コンピューターでは、ウィンドウ、ダイアログ ボックス、画像、すべてのテキストを含む、画面に表示されるほぼすべてのものが描画され、これらの オブジェクト ニュースを描画するときに、システムによって WM_PAINT メッセージがトリガーされます。コンピューター上で実行するほぼすべての操作でこのメッセージが表示されますが、これは Windows で最も重要なメッセージの 1 つでもあります。この記事では、包括的な研究のためにこのメッセージを実験することに焦点を当てています。
#define WM_PAINT 0x000F
メッセージを送信するために sendmessage/postmessageを使用する場合、多くの場合、WPARAM と LPARAM の 2 つのパラメータが伝達されることがわかっています。 GetMessage を使用するか、PeekMessage がメッセージを受信するときに、これら 2 つのパラメーターも受け取ります。これらのメッセージの一部には、マウスの位置、ウィンドウの長さと幅など、必要な情報がパラメータとして含まれています。 WM_PAINT のこれら 2 つのパラメータは空であり、メッセージは含まれません。
このメッセージのトリガータイミングを取得するために、まずテストオブジェクトとして 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_PAINT のトリガーのタイミングをそれぞれ確認してみましょう:
1. プログラムが開始されると、ウィンドウが描画されるときにトリガーされます。
プログラムを開始すると、ウィンドウを描画する必要があるため、WM_PAINT メッセージがトリガーされます。2 でウィンドウのサイズが変更されると、次の文字列が表示されます。マウスを操作すると、継続的にトリガーされます:
ウィンドウのサイズが変更されるとウィンドウを継続的に再描画する必要があるため、WM_PAINT メッセージは常にトリガーされます:3。WM_PAINT メッセージは次の場合にはトリガーされません。最小化していますが、最小化から復元されます
下の図は、ウィンドウを 2 回最小化して復元する過程です4 WM_PAINT メッセージを最大化するとトリガーされます
次の図に示すように、画像が最大化されて復元されると、WM_PAINT メッセージが 1 回トリガーされます:
以下のスクリーンショットは、ウィンドウが画面に引き戻されると、ウィンドウは常に再描画され、WM_PAINT メッセージがトリガーされます。 A6、wm_paintメッセージの活用を利用して、Inval、Idaterectの推論関数を使用します。 NULL の場合、システムは関数が戻る前にすべてのウィンドウを再描画し、その後 WM_ERASEBKGND と WM_PAINT をウィンドウ プロシージャ処理関数に送信します。 lpRect: 無効な領域の長方形表現。これは、長方形のサイズを格納する
構造体ポインターです。 NULL の場合、ウィンドウのクライアント領域全体が更新領域に追加されます。bErase: 無効な四角形が有効としてマークされた後、再描画するときに事前定義されたブラシを使用するかどうかを示します。 TRUE を指定した場合は再描画が必要です。 戻り値:
関数が成功した場合はゼロ以外の値を返し、そうでない場合はゼロの値を返します。
InvalidateRect 関数の機能を検証するには、ウィンドウ処理関数に WM_LBUTTONDOWN メッセージの処理を追加し、マウスの左ボタンがクリックされるたびに InvalidateRect を呼び出す必要があります。
//窗口处理函数 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); }
下图为执行结果,点击了3次鼠标左键,触发了3次WM_PAINT消息。
总结:
触发WM_PAINT消息的本质是改变窗口对应的显存的大小就触发一次,我们进行的每一次窗口最大化、最小化并恢复都是因为改变了窗口的显存而触发了该消息。在我们向屏幕外面拖动窗口时,这点比较特殊,窗口的显存是在一点点被擦除的,此时不会触发WM_PAINT,但是拉回窗口后,显存需要将擦除的部分重新绘制,这就又会触发一次该消息。而InvalidateRect函数,就是通过强制的清除并重绘显存来实现触发WM_PAINT消息。
我们尝试处理WM_PAINT消息,并在窗口上绘制一个矩形,绘图步骤如下:
1、开始绘图处理
HDC BeginPaint( HWND hwnd,//绘图窗口 LPPAINTSTRUCT lpPaint );
我们利用BeginPaint获取绘图设备的句柄---一个HDC对象,然后在改绘图设备上进行绘制。
2、利用HDC对象进行绘图
3、结束绘图处理
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 中国語 Web サイトの他の関連記事を参照してください。