WM_PAINT 메시지에서 처리되는 무효화의 이해
예전에 데브피아에서 어떤 유저가 기고하였던 질문이 있었는데, 거기에 대한 저의 답변입니다.
-------------------------------------------------------------------------------------
(환경 : VS 2005 MFC)
LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
switch( message )
{
case WM_PAINT:
// 페인트 메시지에서 메박을 띄웠습니다.
MessageBox(_T("이상하다"), _T("case WM_PAINT:"), MB_OK);
// 그런데 여기서 실제로 이 메박은 뜨지 않습니다. 쾅쾅거리는 소리만 요란하게 납니다.
// 0.1초 쯤 아주 조금의 시간이 지난 뒤에 실행창은 뜹니다
// 그런데 실행창이 투명처리가 되어 나타납니다.
// 그리고 컴터가 다운은 아니지만 다운 비슷함니다. 다른 메시지가 전혀 먹히지 않습니다.
return 0; // 이런 이유가 무엇인가요?
}
return CFrameWnd::WindowProc(message, wParam, lParam);
}
-------------------------------------------------------------------------------------
원인이 발생하는 가장 큰 이유는 무효화후에 유효화가 일어나지 않기 때문에
커널단에서 무한하게 WM_PAINT 메시지를 발생시키는 겁니다.
다시 설명을 드리자면, WM_PAINT 메시지는 무효화가 일어났을 때 즉,
다시 그려야 할 경우에 발생하는 메시지입니다.
여기서 다시 그려야 할 경우라면 바로 메시지 박스를 의미하겠지요.
메시지 박스를 다시 그려라고 WM_PAINT 메시지를 주었는데, 그곳에는
어디에도 메시지 박스를 다시 그리는 작업(유효화)하는 부분이 존재
하지 않습니다.
님께선 이런 의문을 가지시겠지요.
case WM_PAINT:
MessageBox(_T("이상하다"), _T("case WM_PAINT:"), MB_OK);
return 0;
위의 코드처럼 WM_PAINT에서 MessageBox()를 호출하게 하였는데 무슨 소리냐..고요.
중요한 것은 그리기 작업을 하기 위한 DC를 발급받지 않은 상태에서 어떤 호출은
커널상에서 무시가 된다는 것입니다.
그러니까 커널 내부적으로 무효화된 부분이 다시 그려졌는지 확인해보고
그려져 있지 않으니까 또다시 호출하고 이런 과정이 무수히 반복되는 것입니다.
위의 코드가 님이 의도하신대로 제대로 동작하려면 두가지 방법으로 처리해야 합니다.
CDC *pDC;
PAINTSTRUCT ps;
case WM_PAINT:
pDC = BeginPaint( &ps );
MessageBox(_T("이상하다"), _T("case WM_PAINT:"), MB_OK);
EndPaint( &ps );
return 0;
와 같이 처리하시면 무효화가 발생할 때마다 메시지 박스가 정상적으로 호출될 겁니다.
혹은 부모 클래스 CFrameWnd의 WindowProc()으로 디폴트로 처리해 주신다면
님의 의도대로 호출될 수 있습니다.
case WM_PAINT:
MessageBox(_T("이상하다"), _T("case WM_PAINT:"), MB_OK);
break;
부모 클래스 CFrameWnd의 WindowProc()를 호출해주면 거기에서
다시 DefWindowProc()을 호출하게 되는데요.
DefWindowProc()에서 BeginPaint()와 EndPaint()처리를 기본적으로 해주게 됩니다.
※ WM_PAINT메시지는 Queued Message지만, WM_PAINT 하나의 메시지만 큐에 저장됩니다.
Written By Sim-Hyeon, Choe