컴퓨터에서는 창, 대화 상자, 그림 및 모든 텍스트를 포함하여 화면에 표시되는 거의 모든 것이 그려지며 이러한 개체 뉴스를 그릴 때 시스템에 의해 WM_PAINT 메시지가 트리거됩니다. 우리가 컴퓨터에서 수행하는 거의 모든 작업은 이 메시지를 트리거하며 이는 Windows에서 가장 중요한 메시지 중 하나이기도 합니다. 이 기사에서는 포괄적인 연구를 위해 이 메시지를 실험하는 데 중점을 둡니다.
#define WM_PAINT 0x000F
우리는 sendmessage/postmessage를 사용하여 메시지를 보낼 때 WPARAM과 LPARAM 두 매개변수가 종종 전달된다는 것을 알고 있습니다. GetMessage가 사용됩니다. 또는 PeekMessage가 메시지를 수신하면 이 두 매개변수도 수신하게 됩니다. 이러한 메시지 중 일부는 마우스 위치, 창 길이 및 너비 등과 같은 매개변수에 필요한 정보를 전달합니다. WM_PAINT의 이 두 매개변수는 비어 있으며 메시지를 전달하지 않습니다.
이 메시지의 트리거 타이밍을 얻기 위해 먼저 Win32 창 프로젝트를 테스트 개체로 만듭니다. 창 처리 함수 는 다음과 같이 정의됩니다.
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 break; case WM_PAINT: { WriteConsole(hOutput,"WM_PAIN\n",10,NULL,NULL); } break; default: break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }WM_PAINT 처리 문에서 "WM_PAINTn"의
문자열 이 콘솔의 표준 출력에 기록되어 WM_PAINT 메시지가 트리거되는지 확인합니다. WM_PAINT의 트리거 타이밍을 각각 확인해 보겠습니다.
1 프로그램이 시작되면 창이 그려질 때 트리거됩니다.
프로그램을 시작하면 창을 그려야 하기 때문에 WM_PAINT 메시지가 실행됩니다.2.
창 크기가 조정될 때 창을 계속 다시 그려야 하기 때문에 WM_PAINT 메시지가 지속적으로 트리거됩니다.3 WM_PAINT 메시지는 다음과 같은 경우에 트리거되지 않습니다. 최소화했지만 최소화에서 복원됩니다.
아래 그림은 창을 최소화하는 과정에서 두 번 더 문자열이 인쇄되는 것을 볼 수 있습니다4 . WM_PAINT 메시지를 최대화하면 트리거됩니다.
그림이 최대화되고 복원되면 아래 그림과 같이 WM_PAINT 메시지가 한 번 트리거됩니다.5. 화면에 들어가면 WM_PAINT 메시지가 트리거되지 않지만 뒤로 당겨지면 WM_PAINT 메시지가 계속해서 트리거됩니다.
아래 스크린샷은 창이 화면으로 다시 당겨지면, 창은 지속적으로 다시 그려져 WM_PAINT 메시지를 트리거합니다. A6, wm_paint 메시지의 변형을 사용하여 Inval 、IdateRect의 추론 함수를 사용합니다. NULL이면 시스템은 함수가 반환되기 전에 모든 창을 다시 그린 다음 WM_ERASEBKGND 및 WM_PAINT를 창 프로시저 처리 함수에 보냅니다.
lpRect: 유효하지 않은 영역의 직사각형 표현입니다. 직사각형의 크기를 저장하는구조 포인터입니다. NULL인 경우 전체 윈도우 클라이언트 영역이 업데이트 영역에 추가됩니다.
bErase: 잘못된 직사각형이 유효한 것으로 표시된 후 영역을 다시 그릴지 여부를 나타냅니다. 다시 그릴 때 미리 정의된 브러시를 사용합니다. TRUE가 지정된 경우 다시 그리기가 필요합니다.
함수가 성공하면 0이 아닌 값을 반환하고, 그렇지 않으면 0 값을 반환합니다. InvalidateRect 함수의 기능을 확인하려면 창 처리 함수에 WM_LBUTTONDOWN 메시지 처리를 추가하고 마우스 왼쪽 버튼을 클릭할 때마다 InvalidateRect를 호출해야 합니다. 下图为执行结果,点击了3次鼠标左键,触发了3次WM_PAINT消息。 总结: 触发WM_PAINT消息的本质是改变窗口对应的显存的大小就触发一次,我们进行的每一次窗口最大化、最小化并恢复都是因为改变了窗口的显存而触发了该消息。在我们向屏幕外面拖动窗口时,这点比较特殊,窗口的显存是在一点点被擦除的,此时不会触发WM_PAINT,但是拉回窗口后,显存需要将擦除的部分重新绘制,这就又会触发一次该消息。而InvalidateRect函数,就是通过强制的清除并重绘显存来实现触发WM_PAINT消息。 我们尝试处理WM_PAINT消息,并在窗口上绘制一个矩形,绘图步骤如下: 1、开始绘图处理 我们利用BeginPaint获取绘图设备的句柄---一个HDC对象,然后在改绘图设备上进行绘制。 2、利用HDC对象进行绘图 3、结束绘图处理 绘制过程参考下面的代码: 执行结果如下,我们成功绘制了一个矩形://窗口处理函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage返回0
break;
case WM_PAINT:
{
WriteConsole(hOutput,"WM_PAIN\n",10,NULL,NULL);
}
case WM_LBUTTONDOWN:
{
InvalidateRect(hWnd,NULL,true);
}
break;
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
三、WM_PAINT消息的处理
HDC BeginPaint(
HWND hwnd,//绘图窗口
LPPAINTSTRUCT lpPaint
);
Bool EndPoint(
HWND hWnd,
CONST PAINTSTRUCT *lpPaint
);
//窗口处理函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage返回0
break;
case WM_PAINT:
{
PAINTSTRUCT pt;
HDC hdc;
hdc=BeginPaint(hWnd,&pt);
Rectangle(hdc,0,0,100,100);
EndPaint(hWnd,&pt);
}
case WM_LBUTTONDOWN:
{
//InvalidateRect(hWnd,NULL,true);
}
break;
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
위 내용은 Win32 SDK 기본 사항 (12) WM_PAINT 메시지 처리(그림)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!