. ShowMsg

ApiEdit는 테스트용 프로젝트로 쓰기에는 이제 덩치가 너무 커져 버렸다. 그래서 컨트롤화 방법을 연구해보기 위한 재료로는 부적당한 것 같아 좀 더 간단한 예제를 통해 각 방법을 비교해 본 후 ApiEdit에 적용하도록 할 것이다. 다음 ShowMsg 예제는 지정된 위치에 문자열 메시지를 보여주는 간단한 기능을 가지고 있는데 읽어만 보면 쉽게 분석이 될 것이다.

 

#include <windows.h>

 

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

HINSTANCE g_hInst;

HWND hWndMain;

LPCTSTR lpszClass=TEXT("ShowMsg");

 

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance

       ,LPSTR lpszCmdParam,int nCmdShow)

{

     HWND hWnd;

     MSG Message;

     WNDCLASS WndClass;

     g_hInst=hInstance;

    

     WndClass.cbClsExtra=0;

     WndClass.cbWndExtra=0;

     WndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);

     WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);

     WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);

     WndClass.hInstance=hInstance;

     WndClass.lpfnWndProc=(WNDPROC)WndProc;

     WndClass.lpszClassName=lpszClass;

     WndClass.lpszMenuName=NULL;

     WndClass.style=CS_HREDRAW | CS_VREDRAW;

     RegisterClass(&WndClass);

 

     hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,

          CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,

          NULL,(HMENU)NULL,hInstance,NULL);

     ShowWindow(hWnd,nCmdShow);

     hWndMain=hWnd;

    

     while(GetMessage(&Message,0,0,0)) {

          TranslateMessage(&Message);

          DispatchMessage(&Message);

     }

     return (int)Message.wParam;

}

 

int x;

int y;

TCHAR *str;

 

void ChangeString(TCHAR *nstr)

{

     lstrcpy(str,nstr);

     InvalidateRect(hWndMain,NULL,TRUE);

}

 

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

     HDC hdc;

     PAINTSTRUCT ps;

     RECT crt;

 

     switch(iMessage) {

     case WM_CREATE:

          x=50;

          y=50;

          str=(TCHAR *)malloc(128);

          lstrcpy(str,"String");

          return 0;

     case WM_SIZE:

          if (wParam != SIZE_MINIMIZED) {

              x=min(x,LOWORD(lParam)-50);

              y=min(y,HIWORD(lParam)-10);

          }

          return 0;

     case WM_KEYDOWN:

          GetClientRect(hWnd,&crt);

          switch (wParam) {

          case VK_LEFT:

              if (x > 0)

                   x--;

              break;

          case VK_RIGHT:

              if (x < crt.right-50)

                   x++;

              break;

          case VK_UP:

              if (y > 0)

                   y--;

              break;

          case VK_DOWN:

              if (y < crt.bottom-10)

                   y++;

              break;

          }

          InvalidateRect(hWnd,NULL,TRUE);

          return 0;

     case WM_LBUTTONDOWN:

          if (lstrcmp(str,"String") == 0) {

              ChangeString("문자열");

          } else {

              ChangeString("String");

          }

          return 0;

     case WM_PAINT:

          GetClientRect(hWnd,&crt);

          hdc=BeginPaint(hWnd, &ps);

          Rectangle(hdc,0,0,crt.right,crt.bottom);

          TextOut(hdc,x,y,str,lstrlen(str));

          EndPaint(hWnd, &ps);

          return 0;

     case WM_DESTROY:

          free(str);

          PostQuitMessage(0);

          return 0;

     }

     return(DefWindowProc(hWnd,iMessage,wParam,lParam));

}

 

세 개의 전역변수를 가지고 있는데 x, y 좌표에 문자열 str을 출력한다. str 변수는 일종의 문자열 버퍼인데 WM_CREATE에서 동적으로 할당되고 WM_DESTROY에서 해제된다. 문자열 출력 기능 외에 커서이동키로 문자열의 위치를 조정할 수 있으며 마우스 왼쪽 버튼을 클릭하여 문자열의 내용을 바꿀 수 있다. 문자열 변경을 위해 ChangeString이라는 일반함수도 하나 정의되어 있는데 이 함수를 일부러 외부로 분리해놓은 이유는 컨트롤화 방법에 따라 일반함수의 형태가 조금씩 바뀌는 것을 살펴보기 위해서이다. 실행중의 모습은 다음과 같다.

실용적 가치라고는 전혀 없는 간단한 기능의 윈도우인데 이 윈도우를 컨트롤로 만들어 보도록 하자. 컨트롤이 되면 다른 윈도우의 차일드가 되므로 재활용에 유리하다. 이 윈도우를 컨트롤로 만드는 방법은 ApiEdit에도 그대로 적용된다.