본문 바로가기

Windows/_Windows Programming

윈도우 관리 메시지

입력 처리의 중심에는 메시지가 있다. 이런 명시적인 입력 외에 윈도우에 관한 기본적인 관리도 메시지로 한다. 윈도우의 상황 변화시에 보내지는 메시지들도 응용 프로그램의 입장에서 보면 일종의 입력이며 프로그램은 이를 적절하게 처리해야 한다.

1. 생성 및 파괴 :

윈도우와 관련된 메시지중 가장 간단한 메시지는 윈도우가 생성될 때 보내지는 WM_CREATE
와 파괴될 때 보내지는 WM_DESTROY 두 가지가 있다.

WM_CREATE 는 윈도우가 생성될 때 보내지므로 각종 초기화를 하기에 적합하며
WM_DESTROY 는 종료처리를 하기에 적합하다.

이 메시지들 대신해 사용할 수 있는 방법은 WinMain 에서 직접 초기화와 종료처리를 하는 것이다.

WM_CREATE 메시지는 CreateWindow 함수에 의해 메인 윈도우가 생성된 직후에 보내지므로 CreateWindow 함수 호출문 다음에 초기화 코드를 작성해도 결과는 같다.
WM_DESTROY 메시지는 메인 윈도우가 파괴되기 직전에 보내지는데 메인 윈도우 파괴 후에는 메시지 루프가 끝나게 되므로 메시지 루프 다음에 종료 처리 코드를 작성해도 결과는 같다.
(참고 : WinMain 에서 하는 초기화와 종료 처리는 WM_CREATE, WM_DESTROY 메시지가 발생했을 때 하는 것과는 엄밀하게 따지면 다르다. 두 메시지에서의 처리는 특정한 윈도우에 관련된 처리를 하는데 사용하는것이 좋고 WinMain 에서는 프로그램 전역적인 처리를 하는것이 좋다)


2.  작업영역 :

윈도우는 작업영역(Client Area)과 비작업영역(Non Client Area) 두 부분으로 구성되어 있다. 작업영역이란 윈도우 중앙의 흰 부분을 말하며 비작업영역이란 그 외의 영역을 말한다.
(예 : 비작업영역에 속하는 부분은 타이틀  바, 경계선, 메뉴 등이 속한다)
(참고 : 작업/비작업영역의 구분은 윈도우를 이해하는데 중요한 비중을 차지하는데 프로그래머에게 프로그래밍 대상이 되는 것은 작업영역에 한정되기 때문이다. 비작업영역은 프로그래밍 대상이 아니며 운영체제가 알아서 관리해 주도록 되어 있다)

출력의 기준은 작업영역이다. 좌표 (10,10)을 지정하면



1번이 아닌 2번을 원점으로 해서 (10, 10) 좌표가 지정된다.
따라서 원하는 위치에 정확하게 출력하려면 작업영역의 좌표를 조사해야 한다.

BOOL GetClientRect(HWND hWnd, LPRECT lpRect);

Client가 차지하고 있는 Rect를 Get 하는 함수다. 첫 번째 파라미터로 대상 윈도우 핸들을
넘겨주고 두 번째 파라미터로 리턴값을 돌려받기 위한 RECT 구조체의 포인터를 넘겨준다.
호출 후 RECT 구조체의 left, top 은 항상 0이며 right, bottom 에 우하단의 좌표가 대입된다.



2. WM_SIZE :

윈도우의 크기가 변경될 때 보내진다. lParam 의 하위 워드에는 변경된 후의 윈도우 폭이,
상위 워드에는 높이가 전달된다.
wParam 에는 이 메시지가 발생한 이유를 나타내는 플래그가 전달된다.

 플래그  의미 
 SIZE_MAXHIDE  다른 윈도우가 최대화되어
 이 윈도우가 가려졌다.
 SIZE_MAXIMIZED  최대화되었다.
 SIZE_MAXSHOW  다른 윈도우가 원래 크기로 복구되어
 이 윈도우가 드러났다.
 SIZE_MINIMIZED  최소화되었다.
 SIZE_RESTORED  크기가 변경되었다.

WM_SIZE 메시지를 사용하여 윈도우 크기가 변경될 때마다 문자열 위치를 수정하도록 WndProc 을 작성하면
(윈도우 프로그램 기본틀에 수정을 하면 된다 http://dakuo.tistory.com/entry/1)


LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage,
                                              WPARAM wParam, LPARAM lParam);
{
      HDC hdc;
      PAINTSTRUCT ps;
      static RECT rt;
      switch(iMessage)
      {
            case WM_PAINT:
                    hdc = BeginPaint(hWnd, &ps);
                    SetTextAlign(hdc, TA_CENTER);
                    TextOut(hdc, rt.right/2, rt.bottom/2, "Center", 6);
                    EndPaint(hWnd, &ps);
                    return 0;
            case WM_SIZE:
                    CetClientRect(hWnd, &rt);
                    InvalidateRect(hWnd, NULL, TRUE);
                    return 0;
            case WM_DESTROY:
                    PostQuitMessage(0);
                    return 0;
       }
       return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

WM_SIZE 에서 윈도우 크기가 변경될 때마다 작업영역의 크기를 다시 계산하고 화면을 다시 그리므로 문자열은 윈도우의 크기에 상관없이 항상 가운데에 위치하게 된다.
(참고 : 크기가 변경되면 WM_SIZE 메시지가 발생하고 작업영역을 계산한 후 lnvalidateRect 의해 WM_PAINT 메시지가 발생하고 다시 그려지게 된다)

lParam 으로도 작업 영역 크기가 전달되므로 다음과 같이 작성해도 된다.
case WM_SIZE:
     rt.right=LOWORD(lParam);
     rt.bottom=HIWORD(lParam);
     lnvalidateRect(hWnd, NULL, TRUE);
     return 0;

WM_SIZE 메시지는 윈도우 크기에 상관없이 일정한 레이아웃을 유지하기 위해 사용된다.



3. WM_MOVE :

윈도우의 위치가 변경될 때마다 보내진다
lParam 의 하위 워드에 윈도우의 새 x좌표, 상위 워드에는 새 y좌표가 전달된다.

(참고 : 윈도우(Window)와 윈도우즈(Windows)라는 말은 다르다. 윈도우는 창을 가리키고
윈도우즈는 운영체제 자체를 이르는 말이다)

'Windows > _Windows Programming' 카테고리의 다른 글

리소스(Resource)  (0) 2009.12.24
윈도우 프로그램 기본 틀  (0) 2009.12.23
타이머(Timer)  (0) 2009.12.23
입력하기  (0) 2009.12.01
출력하기  (2) 2009.11.28