Nachrichtenwarteschlange und Nachrichtenverarbeitung in der Microsoft MFC-Technologie (ein)

Ich bin Liyuan Breeze. Als Veteran der IT-Branche seit 25 Jahren werde ich heute über die Nachrichtenwarteschlange und die Nachrichtenverarbeitung in der Microsoft MFC-Technologie sprechen.

In einer MFC-Anwendung das Fenster, das das Windows-System in Form einer Nachricht an die Anwendung sendet. Nachdem das Fenster die Nachricht empfangen und verarbeitet hat, gibt es die Kontrolle an Windows zurück. Das Windows-System kann mehrere Fenster gleichzeitig anzeigen. Dieses System nutzt Nachrichtenwarteschlangen, um Nachrichten wie Maus- und Tastatureingaben in entsprechenden Fenstern aufzuzeichnen. Wenn der Benutzer die Maus bewegt oder auf die Tastatur tippt, wandelt der Gerätetreiber für die Maus oder Tastatur die Eingaben in Nachrichten um und stellt sie in die Nachrichtenwarteschlange des Systems. Windows liest Nachrichten einzeln aus der Systemwarteschlange, entfernt sie aus der Warteschlange und verarbeitet sie dann, indem es sie an die entsprechende Fensterprozedur sendet.

Die Nachrichtenwarteschlange ist eine First-In-First-Out-Warteschlangendatenstruktur, bei der es sich tatsächlich um eine interne verknüpfte Liste im Systemkernel handelt. Benutzer können Nachrichten zur Nachrichtenwarteschlange hinzufügen und aus ihr lesen, und Nachrichten werden nacheinander in die Warteschlange eingefügt. Der sendende Prozess fügt die Nachricht am Ende der Warteschlange hinzu und der empfangende Prozess liest die Nachricht vom Kopf der Warteschlange.

Unter dem Gesichtspunkt der Art und Weise, wie die Nachricht gesendet wird, werden Nachrichten in zwei Typen unterteilt: Warteschlangennachrichten und Nicht-Warteschlangennachrichten.

Nachrichten in der Warteschlange und nicht in der Warteschlange

Lassen Sie uns zunächst die Definitionen von Warteschlangennachrichten und Nicht-Warteschlangennachrichten vorstellen. Warteschlangennachrichten sind Nachrichten, die von Windows in die Nachrichtenwarteschlange eines Programms gestellt werden. Nicht in der Warteschlange befindliche Nachrichten sind Nachrichten, die durch bestimmte Windows-Funktionen für direkte Aufrufe von „Fensterprozeduren“ verursacht werden.

Als nächstes werden wir Warteschlangennachrichten und Nicht-Warteschlangennachrichten in drei Aspekten vergleichen und vorstellen.

1. Zu sendendes Ziel

Warteschlangennachrichten: werden zuerst an die Systemnachrichtenwarteschlange und dann an die Thread-Nachrichtenwarteschlange gesendet.
Nicht in der Warteschlange befindliche Nachrichten: werden direkt an die Zielfensterprozedur gesendet.

2. Jeweilige gemeinsame Nachrichten

Warteschlangennachrichten sind Nachrichten, die durch Maus und Tastatur ausgelöst werden, zum Beispiel Mausbewegungsnachrichten (WM_MOUSEMOVE), durch Tasten generierte Zeichennachrichten (WM_CHAR), Tastennachrichten (WM_KEYDOWN, WM_KEYUP) und andere Nachrichten. Darüber hinaus gibt es andere Nachrichten, wie z. B. eine Neuzeichnungsnachricht (WM_PAINT), eine Timer-Nachricht (WM_TIMER), eine Exit-Nachricht (WM_QUIT) usw.

Was Nachrichten betrifft, die nicht in die Warteschlange gestellt werden, stammen sie in vielen Fällen von Anwendungen, die Systemfunktionen aufrufen. Wenn WinMain() beispielsweise CreateWindow() aufruft, erstellt Windows das Fenster und sendet der Fensterprozedur dabei eine WM_CREATE-Nachricht. Wenn WinMain() ShowWindow() aufruft, sendet Windows WM_SIZE- und WM_SHOWWINDOW-Nachrichten an die Fensterprozedur. Wenn WinMain() UpdateWindow() aufruft, sendet Windows eine WM_PAINT-Nachricht.

3. Einführung in Sonderfälle

Mit der Tastatur oder Maus verknüpfte Nachrichten: Wenn ein Menübefehl mit der Tastatur oder der Maus ausgewählt wird, handelt es sich bei der Tastatur- oder Mausnachricht um eine Nachricht in der Warteschlange, während es sich bei der WM_COMMAND-Nachricht möglicherweise um eine Nachricht ohne Warteschlange handelt.

WM_PAINT: Das Windows-System stellt diese Nachricht immer an das Ende der Nachrichtenwarteschlange, sodass das Fenster immer seine Eingabenachrichten empfangen kann.


Wie Nachrichten gesendet werden – Senden, Veröffentlichen und Senden

Angenommen, eine Person lebt an Ort A, möchte aber zu Ort B reisen, sodass es mehrere Möglichkeiten gibt, von A nach B zu gelangen. Zunächst sollte festgestellt werden, dass am Standort A mehrere Transportmittel vorhanden sind. Wenn es keine Transportmittel gibt, können Sie sich beim Reisen nur auf Ihre Füße verlassen. Wenn es nur einen Zug gibt, müssen Sie ein Zugticket kaufen. Und wenn Sie ein Flugzeug haben, können Sie ein Flugticket für die Reise kaufen. Daher ist es nach der Einführung so vieler Nachrichtentypen so, als wüsste man, welche Transportmittel an Ort A verfügbar sind, und dann sollte man wissen, wie man Nachrichten sendet, also wie man zu Ort B gelangt.

Es gibt drei Möglichkeiten, Nachrichten im MFC-Programm zu senden: Senden, Senden und Senden. Im Folgenden werde ich diese drei Methoden anhand spezifischer Funktionen vorstellen.

1. Nachrichtenfunktion SendMessage() senden

Stellen Sie zunächst den Prototyp dieser Funktion vor, um das weitere Studium zu erleichtern. Der Prototyp der SendMessage()-Funktion lautet wie folgt:

LRESULT SendMessage(
  HWND  hWnd,    //指定的消息接收窗口,其窗口事件发布函数将接收和处理消息
  UINT  Msg,     //所发消息的消息ID
  WPARAM   wParam,    //所发消息的字参数
  LPARAM  lParam    //所发消息的值参数
  );

Hinweis: Das Fensterhandle ist in der MFC-Klasse gekapselt, daher kann der folgende Code zum Anwenden dieser Funktion verwendet werden:

SendMessage(WM_COMMAND, ID_NAME, 0)

Der Rückgabewert der Funktion wird von der Fensterfunktion des Fensters zurückgegeben, das die Nachricht empfängt, und der zurückgegebene Wert hängt von der gesendeten Nachricht ab.

Diese Funktion sendet eine Nachricht an ein oder mehrere Fenster und wartet, bis die Nachricht verarbeitet wurde, bevor sie zurückkehrt. Beachten Sie außerdem, dass die Fensterfunktion dieses Fensters sofort als Unterprogramm aufgerufen wird, wenn das Fenster, das die Nachricht empfängt, Teil desselben Programms ist (dh in einem Thread). Und wenn das Fenster, das die Nachricht empfängt, von einem anderen Thread erstellt wird, wechselt das Fenstersystem zunächst zum entsprechenden Thread und ruft dessen Fensterfunktion auf.

2. Nachrichtenfunktion PostMessage() senden

Prototyp der PostMessage()-Funktion:

BOOL PostMessage(
  HWND  hWnd,       //消息的投递方向
  UINT  Msg,      //所发消息的消息ID
  WPARAM    WParam,      //所发消息的字参数
  LPARAM    lParam       //所发消息的值参数
  );

Der Rückgabewert dieser Funktion unterscheidet sich von SendMessage(), der Rückgabewerttyp ist BOOL. Es gibt nur zwei Zustände, einer ist Null und der andere ist ungleich Null. Wenn der Funktionsaufruf erfolgreich ist, ist der Rückgabewert ungleich Null; wenn der Funktionsaufruf fehlschlägt, ist der Rückgabewert Null.

Diese Funktion fügt eine Nachricht in die Nachrichtenwarteschlange ein, die dem vom angegebenen Fenster erstellten Thread zugeordnet ist, und kehrt zurück, ohne darauf zu warten, dass der Thread die Nachricht verarbeitet. PostMessage() kümmert sich nur darum, ob die Nachrichtenzustellung erfolgreich ist. Dies unterscheidet sich vom Senden von Nachrichten. Weniger dringende Ereignisse, die langsam abgepuffert werden können, werden per Post verschickt. Es werden beispielsweise Maus- und Tastaturnachrichten sowie Tastennachrichten gesendet.

3. Broadcast-Nachrichtenfunktion BroadcastSystemMessage()

Funktionsprototyp BroadcastSystemMessage():

long BroadcastSystemMessage(
  DWORD  dwFlags,      //发送消息的方式
  LPDWORD lpdwRecipients,  //消息接收器的信息,消息发送的目标
  UINT  uiMessage,     //系统消息标识符
   WPARAM  wParam,    //消息参数
  LPARAM    lParam     //消息参数  
  );
 

Der Rückgabewert dieser Funktion ist vom Typ Long. Wenn der Funktionsaufruf erfolgreich ist, ist der Rückgabewert eine positive Zahl: Wenn die Funktion die Nachricht nicht senden kann, ist der Rückgabewert -1. Diese Funktion wird selten verwendet. Stellen Sie daher kurz ihre Funktion vor, die eine Nachricht an den angegebenen Empfänger sendet. Der Empfänger kann eine Anwendung, ein Installationstreiber, ein Netzwerktreiber, ein Gerätetreiber auf Systemebene oder eine Kombination dieser Systemkomponenten sein.

Beschreibt Funktionen, die Nachrichten empfangen

Wie im vorherigen Beispiel der Reise von A nach B, wenn die Person einen Freund in B braucht, der sie abholt. Deshalb muss ein Freund bei B im Voraus wissen, wann er bei B ankommt und wie er dorthin kommt. Daher ist der Empfang von Nachrichten sehr wichtig.

Im Folgenden werden die drei Hauptfunktionen GetMessage(), PeekMessage() und WaitMessage() beschrieben, die zum Empfangen von Nachrichten in MFC verwendet werden.

1. GetMessage()

Funktionsprototyp:

BOOL GetMessage
  LPMSG lpMsg,     //检索到的消息
  HWND hWnd,      //窗口指向
  UINT  wMsgFilterMin,    //消息范围的下限参数
  UINT  wMsgFilterMax     /消息范围的上限参数
    );

Der Rückgabewerttyp der Funktion ist BOOL. Wenn die Funktion eine WM_QUIT-Nachricht erhält, ist der Rückgabewert Null; wenn die Funktion eine andere Nachricht als WM_QUIT erhält, gibt sie einen Wert ungleich Null zurück; wenn ein Fehler auftritt, wird -1 zurückgegeben.

Die Funktion GetMessage() dient dazu, eine Nachricht aus der Nachrichtenwarteschlange abzurufen und in die angegebene Struktur einzufügen. GetMessage() empfängt keine Nachrichten, die zu anderen Anwendungen gehören, und empfängt in Multithread-Programmen keine Nachrichten, die zu anderen Threads gehören. Nachdem die Nachricht erfolgreich abgerufen wurde, wird sie aus der Nachrichtenwarteschlange gelöscht und die Funktion wartet, bis eine Nachricht eintrifft, bevor sie einen Wert zurückgibt. Allerdings löscht GetMessage() eine spezielle WM_PAINT-Nachricht erst dann, wenn die WM_PAINT-Nachricht nicht mehr antwortet.

2. PeekMessage()

Funktionsprototyp: 

BOOL PeekMessage(
  LPMSG  lpMsg,    //检索到的消息
  HWND  hWnd,      //窗口指向
  UINT  wMsgFilterMin,    //消息范围的下限参数
  UINT  wMsgFilterMax,    //消息范围的上限参数
  UINT  wRemoveMsg        //消息在被检索之后要如何处理
  );

Der Rückgabewerttyp der Funktion ist BOOL. Wenn die Nachricht abgerufen werden kann, geben Sie einen Wert ungleich Null zurück. Wenn nicht, ist der Rückgabewert 0. Diese Funktion überprüft die Nachrichtenwarteschlange des Threads auf eine Nachricht und fügt die Nachricht in die angegebene Struktur ein, wenn die Nachricht vorhanden ist. PeekMessage() löscht die WM_PAINT-Nachricht normalerweise nicht aus der Warteschlange, die Nachricht bleibt in der Nachrichtenwarteschlange, bis sie verarbeitet wird.

Hinweis: Der Unterschied zwischen PeekMessage() und GetMessage() besteht darin, dass PeekMessage() die WM_PAINT-Nachricht aus der Warteschlange löscht, wenn die WM_PAINT-Nachricht einen leeren Aktualisierungsbereich hat. Ein weiterer Unterschied zu GetMessage() besteht darin, dass die PeekMessage-Funktion nicht wartet, bis eine Nachricht in die Warteschlange gestellt wird, bevor sie zurückkehrt.

3. WaitMessage()

Funktionsprototyp:

BOOL WaitMessage (VOID);

Der Rückgabewerttyp dieser Funktion ist BOOL. Gibt einen Wert ungleich Null zurück, wenn der Funktionsaufruf erfolgreich ist; gibt 0 zurück, wenn der Funktionsaufruf fehlschlägt. Wenn sich keine andere Nachricht in der Nachrichtenwarteschlange eines Threads befindet, übergibt die Funktion die Kontrolle an einen anderen Thread und hält den Thread gleichzeitig an, bis eine neue Nachricht in die Nachrichtenwarteschlange des Threads gestellt wird, bevor sie zurückkehrt.

Lassen Sie uns in der nächsten Vorlesung über ein Beispiel sprechen und uns gemeinsam mit diesem Mechanismus vertraut machen.

Über den Autor: Li Yuan Weifeng, geboren 1981, leitender Ingenieur, Master of Engineering an der Zhejiang-Universität, Software-Engineering-Projektleiter, hat als Programmierer, Software-Designer, Systemarchitekt, früher Windows-Programmierer, treuer Visual Studio-Benutzer, C/ gearbeitet C++-Benutzer Der Autor ist ein Veteran, der 25 Jahre lang in der Computerindustrie studiert, hart gearbeitet und gekämpft hat. Er hat die UNIX-Ära, die Desktop-WIN32-Ära, die Webanwendungsära, die Cloud-Computing-Ära und das Mobiltelefon-Android erlebt Ära, die Big-Data-Ära, die IKT-Ära und die KI-Deep-Learning-Ära, das Zeitalter intelligenter Maschinen. Ich weiß nicht, welche Ära es in der Zukunft geben wird. Ich erinnere mich nur daran, dass diese Reise voller Schwierigkeiten und Gewinne ist. und ich bin bereit, voller Hoffnung mit Ihnen weiterzumachen.

Guess you like

Origin blog.csdn.net/wang2015cn/article/details/131649261