MFC 메시지 맵 1 : 순수 C 로 구현된 윈도우 프로그램 MFC 마을



01: #include <windows.h.>
02: #include <tchar.h>
03:
04: LRESULT CALLBACK WndProc ( HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
05: {
06: HDC hdc;
07: RECT rect;
08: PAINTSTRUCT ps;
09:
10: switch ( iMsg )
11: {
12: case WM_CREATE:
13: return 0;
14: case WM_PAINT:
15: hdc = BeginPaint(hwnd, &ps);
16: //hdc = GetDC(hwnd);
17: GetClientRect(hwnd, &rect);
18: DrawText(hdc, _T("Hello, Windows!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER );
19: EndPaint(hwnd, &ps);
20: //ReleaseDC(hwnd, hdc);
21: return 0;
22: case WM_LBUTTONDOWN:
23: hdc = GetDC(hwnd);
24: MoveToEx(hdc, 0, 0, NULL);
25: LineTo(hdc, 100, 100);
26: ReleaseDC(hwnd, hdc);
27: return 0;
28: case WM_CLOSE:
29: // hdc = GetDC(hwnd);
30: // MoveToEx(hdc, 0, 0, NULL);
31: // LineTo(hdc, 100, 100);
32: // ReleaseDC(hwnd, hdc);
33: // Sleep(2000);
34: // return 0;
35: case WM_DESTROY:
36: PostQuitMessage(0);
37: return 0;
38: }
39:
40: return DefWindowProc(hwnd, iMsg, wParam, lParam);
41: }
42:
43: int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd )
44: {
45: static wchar_t szAppName[] = _T("HelloWin");
46: HWND hwnd;
47: MSG msg;
48: WNDCLASSEX wndclass;
49:
50: wndclass.cbSize = sizeof(wndclass);
51: wndclass.style = CS_HREDRAW | CS_VREDRAW;
52: wndclass.lpfnWndProc = WndProc;
53: wndclass.cbClsExtra = 0 ;
54: wndclass.cbWndExtra = 0;
55: wndclass.hInstance = hInstance;
56: wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
57: wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
58: wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
59: wndclass.lpszMenuName = NULL;
60: wndclass.lpszClassName = szAppName;
61: wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
62:
63: RegisterClassEx ( &wndclass );
64:
65: hwnd = CreateWindow ( szAppName, _T("Hello Program"), WS_OVERLAPPEDWINDOW,
66: CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL );
67:
68: ShowWindow(hwnd, nShowCmd);
69: //UpadteWindow(hwnd);
70:
71: // while ( GetMessage(&msg, NULL, 0, 0 ))
72: // {
73: // //TranslateMessage(&msg);
74: // static int i = 0;
75: // wchar_t buffer[80];
76: // _stprintf(buffer, _T("%d\n"), ++i );
77: // OutputDebugString(buffer);
78: // DispatchMessage(&msg);
79: // };
80:
81: while ( 1)
82: {
83: if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE ))
84: {
85: if ( msg.message == WM_QUIT ) break;
86: DispatchMessage(&msg);
87: }
88:
89: static int i = 0;
90: wchar_t buffer[80];
91: _stprintf(buffer, _T("%d\n"), ++i );
92: OutputDebugString(buffer);
93: DispatchMessage(&msg);
94: }
95:
96: OutputDebugString(_T("Hello"));
97:
98: return msg.wParam;
99: }




WM_PAINT 의 주석친 부분을 자세히 보자, 


WM_PAINT 메시지는 클라이언트 영역을 다시 그려야 할 필요성이 있을때 생성된다.  예를들어

- 윈도우가 다른 윈도우 위로 올라왔을때
- 윈도우가 옮겨졌을때
- 윈도우 사이즈가 변경 되었을때

등등.. 이때 DC, 즉 그리기 정보를 담고 있는 구조체인 Device Contexts 를 얻고 해제하기 위해서 사용할 수 있는 함수가 바로

BeginPaintEndPaint 다. 이 함수를 통해 프로그래머는 DC 를 다루는 핸들, 즉 HDC 를 얻을 수 있다.


만약 WM_PAINT 가 아닌 다른 메시지를 받았을때 클라이언트에 그리기 작업을 위해서 DC 를 얻고 해제하려면 GetDCReleaseDC 함수를 호출 해야한다.

왜 이렇게 함수를 나누어 놓았을까? 이유는 윈도우의 메시지 시스템에 있다. 

GetMessage 로 메시지를 얻어올때, 다른 메시지들은 메시지 큐에서 꺼내온 후 제거되지만 WM_PAINT는 제거되지 않는다.

따라서 이 꺼내온 WM_PAINT 메세지를 제거해 주어야 하는데, 이 작업을 BeginPaint 가 해 준다. 

이런이유로 WM_PAINT 에서는 Device Contexts 를 얻기 위해 GetDC 함수를 사용해서는 안된다.

GetDC 함수는 WM_PAINT 메시지를 메시지 큐에서 제거하지 못하기때문에 메시지 큐에 WM_PAINT 가 계속 누적되기 때문이다.





핑백

덧글

댓글 입력 영역


시계

라운드 시계

위키피디아