Heim > Artikel > Betrieb und Instandhaltung > Win32 SDK-Grundlagen (12) Verarbeitung der WM_PAINT-Nachricht (Bild)
In einem Computer wird fast alles, was auf dem Bildschirm angezeigt wird, gezeichnet, einschließlich Fenstern, Dialogfeldern, Bildern und sämtlichem Text, und die Meldung WM_PAINT wird ausgelöst vom System beim Zeichnen dieser Objekte. Fast jede Operation, die wir am Computer ausführen, löst diese Meldung aus und sie ist auch eine der wichtigsten Meldungen in Windows. Dieser Artikel konzentriert sich auf das Experimentieren mit dieser Botschaft für eine umfassende Studie.
#define WM_PAINT 0x000F
Das wissen wir bei der Verwendung von sEnde Wenn message/postmessage eine Nachricht sendet, trägt sie oft zwei Parameter, WPARAM und LPARAM, und wenn sie GetMessage oder PeekMessage zum Empfangen einer Nachricht verwendet, empfängt sie auch diese beiden Parameter. Einige dieser Nachrichten enthalten einige notwendige Informationen in Form von Parametern, wie z. B. Mausposition, Fensterlänge und -breite usw. Diese beiden Parameter von WM_PAINT sind leer und enthalten keine Nachricht.
Um das Trigger-Timing dieser Nachricht zu erhalten, erstellen wir zunächst ein Win32-Fensterprojekt als Testobjekt. Die Fensterverarbeitungsfunktion ist wie folgt definiert:
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); }
In unserer WM_PAINT-Verarbeitungsanweisung wird eine Zeichenfolge „WM_PAINTn“ in die Standardausgabe der Konsole geschrieben um zu überprüfen, ob die WM_PAINT-Nachricht ausgelöst wurde. Überprüfen wir jeweils den Auslösezeitpunkt von WM_PAINT:
1. Wenn das Programm startet, wird es ausgelöst, wenn das Fenster gezeichnet wird.
Wenn wir das Programm starten, wird die WM_PAINT-Nachricht ausgelöst, da wir das Fenster zeichnen müssen, und die obige Zeichenfolge wird gedruckt:
2. Wenn die Größe des Fensters mit der Maus geändert wird, wird Folgendes kontinuierlich ausgelöst:
Da das Fenster beim Ändern der Fenstergröße kontinuierlich neu gezeichnet werden muss, was ist Zu diesem Zeitpunkt wird eine kontinuierliche Auslösung angezeigt:
3 Die WM_PAINT-Nachricht wird nicht beim Minimieren ausgelöst, sondern beim Wiederherstellen von der Minimierung
Das Bild unten zeigt den Prozess der Minimierung bis zur zweifachen Wiederherstellung des Fensters. Sie können sehen, dass zwei weitere Zeichenfolgen gedruckt werden
4. Die WM_PAINT-Nachricht wird beim Maximieren ausgelöst
Wenn das Bild maximiert und wiederhergestellt wird, wird jeweils die WM_PAINT-Nachricht ausgelöst, wie in der Abbildung unten gezeigt:
5. Beim Herausziehen des Fensters aus dem Bildschirm wird die WM_PAINT-Meldung nicht ausgelöst, beim Zurückziehen in den Bildschirm jedoch die WM_PAINT Die Meldung wird weiterhin ausgelöst
Der Screenshot unten zeigt, dass beim Zurückziehen des Fensters auf den Bildschirm das Fenster ständig neu gezeichnet wird, wodurch die Meldung WM_PAINT ausgelöst wird.
6. Verwenden Sie die InvalidateRect-Funktion, um die WM_PAINT-Nachricht
auszulösen Prototyp von InvalidateRect Wie folgt löst jeder Aufruf eine WM_PAINT-Nachricht aus:
BOOL InvalidateRect( HWND hWnd, // handle of window with changed update region CONST RECT *lpRect, // address of rectangle coordinates BOOL bErase // erase-background flag );
hWnd: Das Handle des Formulars, in dem der Clientbereich, in dem aktualisiert werden soll, ist. Wenn es NULL ist, zeichnet das System alle Fenster neu, bevor die Funktion zurückkehrt, und sendet dann WM_ERASEBKGND und WM_PAINT an die Fensterprozedurverarbeitungsfunktion.
lpRect: Die rechteckige Darstellung des ungültigen Bereichs. Es handelt sich um einen Strukturzeiger, der die Größe des Rechtecks speichert. Bei NULL wird der gesamte Fenster-Client-Bereich zum Aktualisierungsbereich hinzugefügt.
bErase: Gibt an, ob das ungültige Rechteck neu gezeichnet werden soll, nachdem es als gültig markiert wurde. Verwenden Sie beim Neuzeichnen einen vordefinierten Pinsel. Bei Angabe von TRUE ist ein Neuzeichnen erforderlich.
Rückgabewert:
Wenn die Funktion erfolgreich ist, gibt sie einen Wert ungleich Null zurück, andernfalls gibt sie einen Wert von Null zurück.
Um die Funktion der InvalidateRect-Funktion zu überprüfen, müssen wir eine Verarbeitung der WM_LBUTTONDOWN-Nachricht in der Fensterverarbeitungsfunktion hinzufügen und InvalidateRect jedes Mal aufrufen, wenn mit der linken Maustaste geklickt wird:
//窗口处理函数 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); }
执行结果如下,我们成功绘制了一个矩形:
Das obige ist der detaillierte Inhalt vonWin32 SDK-Grundlagen (12) Verarbeitung der WM_PAINT-Nachricht (Bild). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!