WM_QUIT nur Beiträge für den Thread und nicht das Fenster?

8

In der Windows API untersuche ich, wie die Funktion GetMessage tatsächlich funktioniert. Ich habe 3 Implementierungen der Windows-Nachrichtenschleife gesehen und möchte sie erkunden.

1)

Zum Zeitpunkt des Schreibens dieses Posts dies Der MSDN-Artikel beschreibt, was ich für den richtigen Weg zur Implementierung der Nachrichtenschleife halte.

%Vor%

2)

Auf der GetMessage Funktionsseite , Sehe ich diese Implementierung:

%Vor%

3)

Zuletzt hat die Visual Studio-Dokumentation diese Implementierung als Teil ihrer Win32-Anwendungsdemonstration.

%Vor%

Diskussion

Kurz gesagt, die Implementierung # 3 ignoriert Fehler, die von GetMessage zurückgegeben werden, funktioniert aber ansonsten genauso wie die erste Implementierung. Das heißt, sie verarbeiten alle Nachrichten für den aktuellen Thread. Und wenn die Funktion GetMessage 0 zurückgibt, enden die Schleifen.

Da ich Implementierung # 2 vor # 1 gefunden habe, dachte ich, dass sie komplett ist. Ich habe jedoch festgestellt, dass GetMessage nicht 0 zurückgibt, wenn die Nachricht WM_QUIT über PostQuitMessage

Dies führte zu ein wenig Verwirrung, bis ich Implementierung Nr. 1 fand und sie testete. Der Unterschied zwischen den ersten beiden Implementierungen ist der zweite Parameter für GetMessage . In # 2 wird die hWnd angegeben, die gemäß der GetMessage -Dokumentation lautet:

  

Ein Handle für das Fenster, dessen Nachrichten abgerufen werden sollen. Das Fenster muss zum aktuellen Thread gehören.

In # 1 ist NULL , was zu diesem Auszug gehört:

  

Wenn hWnd NULL ist, ruft GetMessage Nachrichten für jedes Fenster ab, das zum aktuellen Thread gehört, und alle Nachrichten in der Nachrichtenwarteschlange des aktuellen Threads, deren Hwnd-Wert NULL ist (siehe MSG-Struktur). Wenn also hWnd NULL ist, werden sowohl die Fenstermeldungen als auch die Threadnachrichten verarbeitet.

Beim Testen mit NULL gibt die Funktion GetMessage 0 zurück, wenn die Nachricht WM_QUIT verarbeitet wird und die Schleife erfolgreich beendet wird.

Fragen

  1. Auch wenn PostQuitMessage von der Callback-Funktion eines bestimmten Fensters aufgerufen wird, gehört WM_QUIT tatsächlich zum Fenster oder dem aktuellen Thread? Basierend auf dem Testen dieser drei Implementierungen scheint es mit dem aktuellen Thread verknüpft zu sein.

  2. Wenn mit dem Thread verknüpft, wenn es sinnvoll oder angebracht ist, ein gültiges hWnd als Parameter für GetMessage zu verwenden? Eine solche Nachrichtenschleife wäre nicht in der Lage, 0 als Reaktion auf WM_QUIT zurückzugeben. Gibt es also eine andere Möglichkeit, die Nachrichtenschleife zu beenden?

Referenzen

Code

%Vor%     
Nick Miller 24.09.2015, 19:00
quelle

2 Antworten

5

Nach dem MSDN-Dokument von WM_QUIT :

  

Die WM_QUIT Nachricht ist nicht mit einem Fenster verknüpft und wird daher   niemals durch eine Fensterprozedur empfangen werden. Es wird abgerufen   nur durch die Funktionen GetMessage oder PeekMessage.

Da WM_QUIT keinem Fenster zugeordnet ist und die Übergabe eines HWND an GetMessage() nur die mit diesem Fenster verknüpften Nachrichten abruft, wird letzteres nie WM_QUIT per Entwurf erhalten.

Wenn Sie ein HWND an GetMessage() übergeben möchten, würden Sie dies in einer allgemeinen Nachrichtenschleife für eine Anwendung nicht tun. Es gibt jedoch Situationen, in denen Sie Nachrichten pumpen möchten, während etwas in der Benutzeroberfläche stattfindet, und sich nur mit Nachrichten befassen, die mit einem bestimmten Fenster verknüpft sind.

    
Andy 24.09.2015, 19:38
quelle
4

WM_QUIT ist relevant für einen Thread, nicht für ein einzelnes Fenster. Beachten Sie das Fehlen eines Parameters hwnd für PostQuitMessage() . Es gibt keine Möglichkeit, dass es window-spezifisch sein kann, da es keine Möglichkeit gibt, zu bestimmen, in welchem ​​Fenster die Nachricht erzeugt werden soll.

WM_QUIT ist eigentlich keine echte Nachricht. Wenn Sie PostQuitMessage() aufrufen, wird im Status der Nachrichtenwarteschlange ein internes Flag gesetzt, dass WM_QUIT angefordert wurde. Dies wird automatisch von GetMessage() oder PeekMessage() zu einem bestimmten Zeitpunkt in der Zukunft generiert (oft sofort, aber wenn die Warteschlange andere gepostete Nachrichten enthält, werden diese zuerst verarbeitet).

Dies wird auf Raymond Chens Blog näher erläutert. Das enthält auch das folgende Zitat:

  

Als weiteres spezielles Verhalten wird die generierte WM_QUIT-Nachricht umgangen   Die Nachrichtenfilter wurden an GetMessage und PeekMessage übergeben   Funktionen. Wenn das interne Flag "Nachricht beenden" gesetzt ist, dann   Sie erhalten eine WM_QUIT-Nachricht, sobald die Warteschlange ruhig wird, unabhängig   welchen Filter du passierst.

Dies deutet darauf hin, dass Ihre Beobachtungen falsch sind, und dass GetMessage() in Ihrem obigen Beispiel # 2 0 zurückgeben soll, nachdem PostQuitMessage() aufgerufen wurde, obwohl ein Filterparameter angegeben wurde.

Im Allgemeinen sollten Sie Nachrichtenfilter nur verwenden, wenn Sie eine bestimmte Notwendigkeit dafür haben (z. B. möchten Sie speziell eine Nachricht abrufen, die in einem bestimmten Fenster veröffentlicht wurde). In den meisten Fällen sollten diese Parameter für die normale Funktion der Benutzeroberfläche auf 0 gesetzt sein.

    
Jonathan Potter 24.09.2015 19:37
quelle

Tags und Links