MFC 프로그래밍 시 GUI를 만들기 위해서 CBitmapButton으로 버튼에 이미지를 씌우는 작업을 한다.


m_btnXXXX.LoadBitmaps(IDB_비트맵ID);

m_btnXXXX.SizeToContent();


문제는 SizeToContent() 함수를 사용했을 때 버튼의 크기가 무조건 비트맵 이미지 

크기와 같게 수정된다는 점이다. 

또, SizeToContent() 함수를 사용하지 않을 때에는 비트맵 이미지 크기가 버튼보다 클 

경우 비트맵의 좌측상단 기준으로 일부분만 나오게 된다.


이를 해결 하기 위해 CBitmapButton을 상속하는 새로운 비트맵 버튼 클래스를 만들고,

일부 함수를 오버라이드 하여 수정한다.


새로운 클래스명은 심플하게 CMyBitmapButton 으로 정하며, 각 h, cpp 파일의 이름은

MyBitmapButton.h, MyBitmapButton.cpp로 한다.


CMyBitmapButton 클래스는 CBitmapButton 클래스를 상속한다.

CBitmapButton 클래스 중 BOOL AutoLoad(UINT nID, CWnd* pParent) 함수와

void DrawItem(LPDRAWITEMSTRUCT lpDIS); 함수를 오버라이드 한다.


AutoLoad() 함수 안에서 리턴문 바로 위의 SizeToContent(); 함수호출부를 주석처리 하고,

DrawItem() 함수 안에서 StretchBlt()을 사용하여 이미지를 버튼 크기에 맞춘다.


물론, 작업 다 해놓은 파일을 첨부하니 이 작업을 매번 할 필요는 없다.



MyBitmapButton.cpp

MyBitmapButton.h



두 파일을 프로젝트 소스코드가 있는곳에 복사해 넣고, CBitmapButton 변수가 있는 곳에서

#include "MyBitmapButton.h" 로 헤더를 포함시켜준다.


그리고 CBitmapButton 변수명 으로 되어 있을 것을 CMyBitmapButton 변수명 으로 수정한다.


혹시나 버튼 이미지 구현부에 SizeToContent(); 문이 있다면 지우던가 주석처리 해버린다.


이제 이미지 크기에 맞춰 버튼크기가 수정되는 것이 아니라, 버튼 크기에 맞춰 이미지 크기가 수정된다.




참조사이트 : https://support.microsoft.com/ko-kr/kb/134421





관련링크 : http://mypi.ruliweb.daum.net/mypi.htm?id=yoo060



AutoReboot.exe


① 실행시키고

② 재부팅시킬 시간 입력한 후

③ 원할경우 '윈도우 시작시 자동실행'에 체크 후 설정완료 클릭.

 - 레지스트리를 통해 시작프로그램에 자동 등록. 체크 해제 후 다시 설정완료 클릭하면 시작프로그램 해제됨.


④ 알림영역으로 숨기기 클릭 시 시스템 트레이로 숨겨짐.

⑤ 시스템 트레이의 아이콘 왼쪽버튼 클릭한 후 보이기 누르면 프로그램 다시 뜸.

⑥ 3번에서 '윈도우 시작시 자동실행' 체크 설정했다면 윈도우 시작시마다 뜸.


# 첫 실행 후 설정을 마치면 같은 폴더에 config.conf 파일 생성. 설정한 시간을 기억하기 위한 설정파일.



+ 추가


루리웹 백수백숙님 요청으로 프로젝트 통째로 압축한걸 첨부합니다.


AutoReboot.zip


MS Access DB사용을 편하게 하기 위한 모듈입니다.

CloudTree 레퍼런스 클래스에 넣을까 했는데.. 일이 바쁘다보니 DB Search 에 필요한 쿼리문을 범용으로 구성할 아이디어도 잘 안떠오르고.. 결정적으로 DB 설계에 따라 소스 자체를 건드려야될 것 같아서 MS Access DB Module은 따로 빼기로 했습니다.


주의하실 점으로.. XP에서 사용하기 위해 제작된 모듈이며, 7에서는 ADO 관련 dll에서 문제가 생기는 점을 발견했습니다.


① 함께 첨부하는 ADO_XP.zip 을 C:\Program Files\Common Files\System 안에 ADO_XP라는 폴더에 풀어주시고, 

② AccessDBModule.h 상단에 dll import 구문에 C:\Program Files\Common Files\System\ADO 를 C:\Program Files\Common Files\System\ADO_XP로 바꾸면 잘 동작합니다.(import 문 세줄 다 해주셔야 됩니다.)


CloudTree 레퍼런스 클래스와는 다르게 편의성이 썩 좋지는 못합니다.

우선 DB 설계는 각 프로젝트마다 필요성에 의해 다를테니 어쩔수 없는 부분이라 생각됩니다.


본 레퍼런스에서 사용하는 DB는 sample.mdb 파일을 사용하며, 'Data_table' 이라는 단일 테이블에 어트리뷰트로 r_Date, r_Level, r_Name, r_IDNumber, r_Belong1, r_Belong2, r_Score, r_Etc를 사용하고 있습니다.


사용 목적에 따라 mdb 파일을 새로 구성하시거나 변경하시고, 각 함수에서의 내용도 거기에 맞춰 변경하시면 됩니다.


구성 함수는 다음과 같습니다.


void DBConnect(void);    // DB 파일 접속.

void DBDisConnect(void);    // DB 접속 해제.

list<stRecord>* DBSerch(void);    // DB 내용 전체 검색.

void InsertData(stRecord data);    // DB에 자료 입력.

list<stRecord>* SearchData(int category, CString word);    // 특정 카테고리에서 특정 검색어로 자료 검색.



아.. 쓰다보니 귀찮네요.. 

어제 송년회가 있어서 소주를 달렸더니 숙취가..

AccessDBModule.cpp, AccessDBModule.h 와 함께 샘플 프로그램을 첨부하겠습니다.



AccessDBModule.cpp


AccessDBModule.h


sample.zip


ADO_XP.zip



아마 샘플코드 보시면 아.. 대강 이렇게 쓰면 되는구나 하실 정도로 쉽게 코딩되어 있습니다.


저도 DB에 대한 개념이 제대로 잡히지 않은 상태에서 급하게 필요해서 만든 자료라 매우 초보적인 구성이거든요 ㅋㅋ

뭐 최소한 저처럼 DB는 잘 모르는데 급하게 관련 레퍼런스가 필요하신 분이 한분이라도 있고, 조금이라도 도움이 됐다면 그걸로 만족입니다 ^^;;

자주 쓰는데 쓸때마다 치기도 귀찮고, 한동안 안쓰다 또 쓰려면 까먹고 귀찮아서 자주 쓰는 모듈들을 개인용 클래스 하나로 묶어버렸습니다. 라이브러리로 뽑을까도 싶은데.. 매우 귀찮..;;




PreDefined.h

 

 각 모듈에서 그때그때 필요에 따라 재정의할 것들만 밖으로 빼놓은 헤더.


CloudTree.h


 CloudTree 클래스와 각 모듈에서 필요한 클래스 정의가 들어있는 헤더. 

 

CloudTree.cpp


 CloudTree 클래스와 각 모듈이 구현되어 있는 소스파일.


소스코드가 있는 폴더에 위 세파일 복사하고, class view에서 각 파일 등록해준 후 쓰면 됨.

당연한 말이지만, Cloudtree 클래스 포인터 선언할 곳에 #include "CloudTree.h" 포함하는건 기본 센스아니겠음?!


version : 0.01

date : 2012. 11. 22

class CloudTree // 개인용 레퍼런스 클래스

{
public:
CloudTree(void);
~CloudTree(void);

// 자주쓰는 수학 모듈
double EuclideanDistance(double src_xdouble src_ydouble dest_xdouble dext_y);
// x-y 2차원 좌표간 거리 반환.

double EuclideanDistance(double src_xdouble src_ydouble src_z
double dest_xdouble dest_ydouble dest_z); // x-y-z 3차원 좌표간 거리 반환.

double Gaussian(double meandouble stdev); // mean을 기준으로 stdev를 표준편차로 하는 가우시안 랜덤값 반환.

// 공유 메모리 할당과 해제 모듈
void *CreateSharedMem(HANDLE hMappingint sizechar * str); // 공유메모리 할당.
void DestroySharedMem(HANDLE hMappingvoid * mapptr); // 공유메모리 해제.

// 간편하게 쓰도록 만들어둔 공유 메모리 모듈
// PreDefined.h에 정의된 stShareData 구조체와 stShareData* m_pShared를 사용.
void CreateSharedMemSimple(); // stShareData* m_pShared 에 연동되는 공유메모리 자동 할당.
void DestroySharedMemSimple();  // stShareData* m_pShared 에 연동되는 공유메모리 자동 해제.
// 클럭타이머를 이용한 경과시간 체크 모듈
double GetDuration(clock_t start_time); // 입력 인자 start_time 으로부터 몇초가 지났는지를 반환.

// TCP/IP 서버 모듈
void CreateTCPServer(); // TCP 서버 생성.
void AddRecieveCallbackServer(void* chvoid* parent); // 서버 리시브 콜백함수 설정.
void DestroyTCPServer(); // TCP 서버 해제.

// TCP/IP 클라이언트 모듈
void CreateTCPClient(); // TCP 클라이언트 생성.
void AddRecieveCallbackClient(void* chvoid* parent); // 클라이언트 리시브 콜백함수 설정.
void DestroyTCPClient(); // TCP 클라이언트 해제.

private:
// 생략 데헷~♡



이렇게까지 설명해줬는데 행여라도 어떻게 쓰는지 모른다는 사람이 있을까봐 써보는 간단한 활용 예제.


  CloudTree * cloudtree = new CloudTree ();
  cloudtree->CreateSharedMemSimple();
  cloudtree->DestroySharedMemSimple();


Cloudtree형 클래스 포인터 하나 만들어서 각 모듈 불러오면 됩니다.

공유메모리 모듈의 경우 두가지가 있는데, 일반 모듈은 직접 정의해서 쓰고 싶을때 쓰시고 Simple 붙은 모듈은 그냥 호출만 하시면 PreDefined.h에 정의된 stShareData 구조체의 포인터 m_pShared를 통해 공유 메모리에 접근할 수 있습니다.

stShareData 구조체는 필요에 따라 각자 알아서 수정해서 쓰시면 됩니다.



TCP/IP 서버와 클라이언트 모듈의 경우 각 Send() 모듈을 만드는 중인데, 어떻게 만들어야 누가 써도 편할까 고민중이라..

뭐 어쨋든 조만간 업데이트 예정입니다.



ps. 추후 활용빈도에 따라 모듈을 첨삭하며 버전업할 예정입니다.

정상적인 코드를 만들어놓고 이상하게 안된다 싶었는데 FTGL이 폰트를 조금 가리네요.

윈도우에 기본으로 있는 굴림.ttc 로 바꾸니 해결되었습니다.

 

이전 포스팅에 이어 제대로 세팅하고 코딩했는데도 한글이 깨질때 생각해 볼 수 있는 문제점.

 

1. 폰트

 - 이전에 쓰던 무료배포 폰트에서c:\Windows\Fonts 폴더에 있던 기본 폰트로 교환하자 최종적으로 제대로 된 한글이 출력되었습니다. 다른 문제점이 더이상 보이지 않는데도 한글이 안나오실땐 폰트를 바꿔보시길 추천해 드립니다.

 

2. 동적할당

 - FTFont형 포인터를 new로 생성하실때, FTFont를 상속하는 여러가지 클래스로 생성이 가능한데요, 제 경우 FTPixmapFont 외에는 한글 출력에 문제가 조금 있었습니다. 저 개인의 문제인지 아님 원래 이런건지는 모르겠지만 입체로 출력하실게 아니라면 FTPixmapFont(폰트경로) 로 생성해보시기 바랍니다.

 

3. 출력 문자열

 - 그냥 캐릭터배열로 쓰면 안되더라구요. 아마 FTGL 검색하셔서 레퍼런스를 많이 훑어보신 분들이면 다들 아시겠지만서도^^;;

저는 MultiByteToWideChar()를 이용해 멀티바이트를 와이드캐릭터로 변환하여 출력했습니다.

 

 Application.h

...

 

#define FONT_FILE "C:\\Windows\\Fonts\\gulim.ttc"

 

 ...

 

public:

  char m_strMsg[256];

  FTFont* m_String;
  wchar_t* m_wszString;

...

 


 Application.cpp

 ...

  // glInit() 함수 내부.. 사실 어디있든 별 상관은 없음;;

  m_String = new FTPixmapFont(FONT_FILE);

  m_wszString = new wchar_t[260];

 

...

 

  // DrawGLScene() 함수 내부

 

  strcpy(m_strMsg,"한글 나와라 뿅!!");

  int nLen = MultiByteToWideChar(0, 0, m_strMsg, -1, NULL, NULL);
  MultiByteToWideChar(0, 0, m_strMsg, -1, m_wszString, nLen)

 

  m_String->FaceSize(20);
  glColor4f(1.0, 1.0, 1.0, 1);
  glRasterPos3f( 0.0, 0.0, 0.12f );
  m_String->Render(m_wszString );

 

...

 

 

진작에 제대로 돌아가는 소스코드는 다 만들어놓고 폰트파일이 병맛일꺼라곤 생각도 못했습니다 =ㅂ= ;;

저처럼 바보같은 실수 안하시길 빕니다 여러분ㅎㅎ;;

 

- 샘플코드 수정해서 한글폰트 넣었을 경우 한글이 깨지는 현상 발견.

- DC inside 프로그래밍 갤러리에서 나와 같은 현상을 갖는 유져의 글 발견.

- '아, L붙여서 16비트 문자열로 바꾸면 되는거였네' .. 라고 함.

- 확인 후 샘플코드 수정시도 예정.

 

 

FTGL 환기 링크