TN061: ON_NOTIFY- und WM_NOTIFY-Meldungen

Hinweis

Der folgende technische Hinweis wurde seit dem ersten Erscheinen in der Onlinedokumentation nicht aktualisiert. Daher können einige Verfahren und Themen veraltet oder falsch sein. Um aktuelle Informationen zu erhalten, wird empfohlen, das gewünschte Thema im Index der Onlinedokumentation zu suchen.

Diese technische Notiz enthält Hintergrundinformationen zu der neuen WM_NOTIFY Nachricht und beschreibt die empfohlene (und am häufigsten verwendete) Methode zum Behandeln von WM_NOTIFY Nachrichten in Ihrer MFC-Anwendung.

Benachrichtigungen in Windows 3.x

In Windows 3.x benachrichtigen Steuerelemente ihre übergeordneten Elemente über Ereignisse, z. B. Mausklicks, Änderungen in Inhalt und Auswahl, und steuern Sie das Hintergrundbild, indem sie eine Nachricht an das übergeordnete Element senden. Einfache Benachrichtigungen werden als spezielle WM_COMMAND Nachrichten mit dem Benachrichtigungscode (z. B. BN_CLICKED) und der in wParam verpackten Steuerelement-ID und dem Handle des Steuerelements in lParam gesendet. Da wParam und lParam voll sind, gibt es keine Möglichkeit, zusätzliche Daten zu übergeben – diese Nachrichten können nur einfache Benachrichtigungen sein. Beispielsweise gibt es in der BN_CLICKED-Benachrichtigung keine Möglichkeit, Informationen über die Position des Mauszeigers zu senden, wenn auf die Schaltfläche geklickt wurde.

Wenn Steuerelemente in Windows 3.x eine Benachrichtigung senden müssen, die zusätzliche Daten enthält, verwenden sie eine Vielzahl von speziellen Nachrichten, einschließlich WM_CTLCOLOR, WM_VSCROLL, WM_HSCROLL, WM_DRAWITEM, WM_MEASUREITEM, WM_COMPAREITEM, WM_DELETEITEM, WM_CHARTOITEM, WM_VKEYTOITEM usw. Diese Nachrichten können wieder auf das Steuerelement zurückgespiegelt werden, das sie gesendet hat. Weitere Informationen finden Sie unter "TN062: Message Reflection for Windows Controls".

Benachrichtigungen in Win32

Bei Steuerelementen, die in Windows 3.1 vorhanden sind, verwendet die Win32-API die meisten Benachrichtigungen, die in Windows 3.x verwendet wurden. Win32 fügt jedoch auch eine Reihe anspruchsvoller komplexer Steuerelemente hinzu, die in Windows 3.x unterstützt werden. Häufig müssen diese Steuerelemente zusätzliche Daten mit ihren Benachrichtigungsnachrichten senden. Anstatt eine neue WM_* Nachricht für jede neue Benachrichtigung hinzuzufügen, die zusätzliche Daten benötigt, haben die Designer der Win32-API entschieden, nur eine Nachricht hinzuzufügen, WM_NOTIFY, die jede Menge zusätzlicher Daten in standardisierter Weise übergeben kann.

WM_NOTIFY Nachrichten enthalten die ID des Steuerelements, das die Nachricht in wParam sendet, und einen Zeiger auf eine Struktur in lParam. Diese Struktur ist entweder eine NMHDR-Struktur oder eine größere Struktur mit einer NMHDR-Struktur als erstes Element. Beachten Sie, dass ein Zeiger auf diese Struktur als Zeiger auf einen NMHDR oder als Zeiger auf die größere Struktur verwendet werden kann, je nachdem, wie Sie es umwandeln.

In den meisten Fällen zeigt der Zeiger auf eine größere Struktur, und Sie müssen ihn umwandeln, wenn Sie ihn verwenden. In nur wenigen Benachrichtigungen, z. B. den allgemeinen Benachrichtigungen (deren Namen mit NM_ beginnen) und der TTN_SHOW und TTN_POP Benachrichtigungen des QuickInfo-Steuerelements wird tatsächlich eine NMHDR-Struktur verwendet.

Die NMHDR-Struktur oder das ursprüngliche Element enthält das Handle und die ID des Steuerelements, das die Nachricht sendet, und den Benachrichtigungscode (z. B. TTN_SHOW). Das Format der NMHDR-Struktur wird unten gezeigt:

typedef struct tagNMHDR {
    HWND hwndFrom;
    UINT idFrom;
    UINT code;
} NMHDR;

Bei einer TTN_SHOW Nachricht wird das Codeelement auf TTN_SHOW festgelegt.

Die meisten Benachrichtigungen übergeben einen Zeiger an eine größere Struktur, die eine NMHDR-Struktur als erstes Element enthält. Betrachten Sie beispielsweise die Struktur, die von der LVN_KEYDOWN Benachrichtigung des Listenansichtssteuerelements verwendet wird, die gesendet wird, wenn eine Taste in einem Listenansichtssteuerelement gedrückt wird. Der Zeiger zeigt auf eine LV_KEYDOWN Struktur, die wie unten dargestellt definiert ist:

typedef struct tagLV_KEYDOWN {
    NMHDR hdr;
    WORD wVKey;
    UINT flags;
} LV_KEYDOWN;

Beachten Sie, dass der Zeiger, den Sie in der Benachrichtigung übergeben haben, zuerst in dieser Struktur enthalten ist, entweder in einen Zeiger auf einen NMHDR oder einen Zeiger auf eine LV_KEYDOWN umgewandelt werden kann.

Benachrichtigungen, die allen neuen Windows-Steuerelementen gemeinsam sind

Einige Benachrichtigungen gelten für alle neuen Windows-Steuerelemente. Diese Benachrichtigungen übergeben einen Zeiger an eine NMHDR-Struktur .

Benachrichtigungscode Gesendet, weil
NM_CLICK Der Benutzer hat im Steuerelement auf die linke Maustaste geklickt.
NM_DBLCLK Benutzer doppelklicken auf die linke Maustaste im Steuerelement
NM_RCLICK Der Benutzer hat mit der rechten Maustaste im Steuerelement geklickt.
NM_RDBLCLK Benutzer doppelklicken mit der rechten Maustaste im Steuerelement
NM_RETURN Der Benutzer hat die EINGABETASTE gedrückt, während das Steuerelement den Eingabefokus hat.
NM_SETFOCUS Das Steuerelement wurde dem Eingabefokus übergeben.
NM_KILLFOCUS Steuerelement hat den Eingabefokus verloren
NM_OUTOFMEMORY Die Steuerung konnte einen Vorgang nicht abschließen, da nicht genügend Arbeitsspeicher verfügbar war.

ON_NOTIFY: Behandeln von WM_NOTIFY Nachrichten in MFC-Anwendungen

Die Funktion CWnd::OnNotify verarbeitet Benachrichtigungen. Die Standardimplementierung überprüft die Nachrichtenzuordnung auf Benachrichtigungshandler, die aufgerufen werden sollen. Im Allgemeinen überschreiben OnNotifySie nicht . Stattdessen stellen Sie eine Handlerfunktion bereit und fügen einen Nachrichtenzuordnungseintrag für diesen Handler zur Nachrichtenzuordnung der Klasse des Besitzerfensters hinzu.

ClassWizard kann über das ClassWizard-Eigenschaftenblatt den ON_NOTIFY Meldungszuordnungseintrag erstellen und Ihnen eine Skeletthandlerfunktion bereitstellen. Weitere Informationen zur Verwendung von ClassWizard, um dies zu vereinfachen, finden Sie unter Zuordnen von Nachrichten zu Funktionen.

Das ON_NOTIFY Nachrichtenzuordnungsmakro weist die folgende Syntax auf:

ON_NOTIFY(wNotifyCode, id, memberFxn)

mit folgenden Parametern:

wNotifyCode
Der Code für die zu behandelnde Benachrichtigung, z. B. LVN_KEYDOWN.

id
Der untergeordnete Bezeichner des Steuerelements, für das die Benachrichtigung gesendet wird.

memberFxn
Die Memberfunktion, die aufgerufen werden soll, wenn diese Benachrichtigung gesendet wird.

Die Memberfunktion muss mit dem folgenden Prototyp deklariert werden:

afx_msg void memberFxn(NMHDR* pNotifyStruct, LRESULT* result);

mit folgenden Parametern:

pNotifyStruct
Ein Zeiger auf die Benachrichtigungsstruktur, wie im obigen Abschnitt beschrieben.

result
Ein Zeiger auf den Ergebniscode, den Sie vor der Rückgabe festlegen.

Beispiel

Um anzugeben, dass die Memberfunktion OnKeydownList1 LVN_KEYDOWN Nachrichten aus der CListCtrl ID IDC_LIST1verarbeiten soll, verwenden Sie ClassWizard, um Der Nachrichtenzuordnung Folgendes hinzuzufügen:

ON_NOTIFY(LVN_KEYDOWN, IDC_LIST1, OnKeydownList1)

Im obigen Beispiel lautet die von ClassWizard bereitgestellte Funktion:

void CMessageReflectionDlg::OnKeydownList1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;

    // TODO: Add your control notification handler
    //       code here

    *pResult = 0;
}

Beachten Sie, dass ClassWizard automatisch einen Zeiger des richtigen Typs bereitstellt. Sie können über pNMHDR oder pLVKeyDow auf die Benachrichtigungsstruktur zugreifen.

ON_NOTIFY_RANGE

Wenn Sie dieselbe WM_NOTIFY Nachricht für eine Reihe von Steuerelementen verarbeiten müssen, können Sie ON_NOTIFY_RANGE anstelle von ON_NOTIFY verwenden. Beispielsweise verfügen Sie möglicherweise über eine Reihe von Schaltflächen, für die Sie dieselbe Aktion für eine bestimmte Benachrichtigung ausführen möchten.

Wenn Sie ON_NOTIFY_RANGE verwenden, geben Sie einen zusammenhängenden Bereich untergeordneter Bezeichner an, für den die Benachrichtigung behandelt werden soll, indem Sie die anfangs- und endenden untergeordneten Bezeichner des Bereichs angeben.

ClassWizard behandelt keine ON_NOTIFY_RANGE; um sie zu verwenden, müssen Sie Ihre Nachrichtenzuordnung selbst bearbeiten.

Der Meldungszuordnungseintrag und Funktionsprototyp für ON_NOTIFY_RANGE sind wie folgt:

ON_NOTIFY_RANGE(wNotifyCode, id, idLast, memberFxn)

mit folgenden Parametern:

wNotifyCode
Der Code für die zu behandelnde Benachrichtigung, z. B. LVN_KEYDOWN.

id
Der erste Bezeichner im zusammenhängenden Bereich von Bezeichnern.

idLast
Der letzte Bezeichner im zusammenhängenden Bereich von Bezeichnern.

memberFxn
Die Memberfunktion, die aufgerufen werden soll, wenn diese Benachrichtigung gesendet wird.

Die Memberfunktion muss mit dem folgenden Prototyp deklariert werden:

afx_msg void memberFxn(UINT id, NMHDR* pNotifyStruct, LRESULT* result);

mit folgenden Parametern:

id
Der untergeordnete Bezeichner des Steuerelements, das die Benachrichtigung gesendet hat.

pNotifyStruct
Ein Zeiger auf die Benachrichtigungsstruktur, wie oben beschrieben.

result
Ein Zeiger auf den Ergebniscode, den Sie vor der Rückgabe festlegen.

ON_NOTIFY_EX, ON_NOTIFY_EX_RANGE

Wenn Sie möchten, dass mehrere Objekte im Benachrichtigungsrouting eine Nachricht verarbeiten, können Sie ON_NOTIFY_EX (oder ON_NOTIFY_EX_RANGE) anstelle von ON_NOTIFY (oder ON_NOTIFY_RANGE) verwenden. Der einzige Unterschied zwischen der EX-Version und der regulären Version besteht darin, dass die member-Funktion, die für die EX-Version aufgerufen wird, einen BOOL zurückgibt, der angibt, ob die Nachrichtenverarbeitung fortgesetzt werden soll. Durch zurückgeben von FALSE aus dieser Funktion können Sie dieselbe Nachricht in mehreren Objekten verarbeiten.

ClassWizard behandelt ON_NOTIFY_EX oder ON_NOTIFY_EX_RANGE nicht; Wenn Sie eine dieser Elemente verwenden möchten, müssen Sie Ihre Nachrichtenzuordnung selbst bearbeiten.

Der Message-Map-Eintrag und Funktionsprototyp für ON_NOTIFY_EX und ON_NOTIFY_EX_RANGE sind wie folgt. Die Bedeutungen der Parameter sind identisch mit den Nicht-EX-Versionen.

ON_NOTIFY_EX(nCode, id, memberFxn)
ON_NOTIFY_EX_RANGE(wNotifyCode, id, idLast, memberFxn)

Der Prototyp für beide oben ist identisch:

afx_msg BOOL memberFxn(UINT id, NMHDR* pNotifyStruct, LRESULT* result);

In beiden Fällen enthält die ID den untergeordneten Bezeichner des Steuerelements, das die Benachrichtigung gesendet hat.

Ihre Funktion muss WAHR zurückgeben, wenn die Benachrichtigung vollständig verarbeitet wurde oder FALSE, wenn andere Objekte im Befehlsrouting die Möglichkeit haben sollten, die Nachricht zu behandeln.

Siehe auch

Technische Hinweise – nach Nummern geordnet
Technische Hinweise – nach Kategorien geordnet