Sdílet prostřednictvím


TN061: ON_NOTIFY a WM_NOTIFY – zprávy

Poznámka

Následující technická poznámka se od prvního zahrnutí do online dokumentace neaktualizovala. V důsledku toho můžou být některé postupy a témata zastaralé nebo nesprávné. Nejnovější informace doporučujeme vyhledat v online indexu dokumentace, které vás zajímá.

Tato technická poznámka obsahuje základní informace o nové zprávě WM_NOTIFY a popisuje doporučený (a nejběžnější) způsob zpracování WM_NOTIFY zpráv v aplikaci MFC.

Zprávy oznámení ve Windows 3.x

Ve Windows 3.x ovládací prvky upozorňují rodiče na události, jako jsou kliknutí myší, změny obsahu a výběru, a ovládání obrazu na pozadí odesláním zprávy nadřazené sadě. Jednoduchá oznámení se odesílají jako speciální WM_COMMAND zprávy s kódem oznámení (například BN_CLICKED) a ID ovládacího prvku zabalené do wParam a popisovače ovládacího prvku v lParam. Všimněte si, že vzhledem k tomu , že jsou wParam a lParam plné, neexistuje způsob, jak předat žádná další data – tyto zprávy mohou být pouze jednoduché oznámení. Například v oznámení BN_CLICKED neexistuje způsob, jak odeslat informace o umístění kurzoru myši při kliknutí na tlačítko.

Když ovládací prvky ve Windows 3.x potřebují odeslat zprávu s oznámením, která obsahuje další data, používají různé speciální zprávy, včetně WM_CTLCOLOR, WM_VSCROLL, WM_HSCROLL, WM_DRAWITEM, WM_MEASUREITEM, WM_COMPAREITEM, WM_DELETEITEM, WM_CHARTOITEM, WM_VKEYTOITEM atd. Tyto zprávy se dají promítnout zpět do ovládacího prvku, který je poslal. Další informace naleznete v tématu TN062: Message Reflexe ion for Windows Controls.

Zprávy s oznámením ve Win32

U ovládacích prvků, které existovaly ve Windows 3.1, používá rozhraní API Win32 většinu zpráv oznámení, které byly použity ve Windows 3.x. Win32 ale také přidává k těm podporovaným ve Windows 3.x řadu sofistikovaných a složitých ovládacích prvků. Tyto ovládací prvky často potřebují odesílat další data se zprávami s oznámeními. Místo přidání nové WM_* zprávy pro každé nové oznámení, které potřebuje další data, se návrháři rozhraní API Win32 rozhodli přidat pouze jednu zprávu, WM_NOTIFY, která může předávat libovolné množství dalších dat standardizovaným způsobem.

WM_NOTIFY zprávy obsahují ID ovládacího prvku odesílajícího zprávu v wParam a ukazatel na strukturu v lParam. Tato struktura je buď struktura NMHDR , nebo některá větší struktura, která má strukturu NMHDR jako svůj první člen. Všimněte si, že vzhledem k tomu , že je nejprve člen NMHDR , lze ukazatel na tuto strukturu použít buď jako ukazatel na NMHDR , nebo jako ukazatel na větší strukturu v závislosti na tom, jak ji přetypujete.

Ve většině případů ukazatel ukáže na větší strukturu a při použití ho budete muset přetypovat. V několika oznámeních, jako jsou běžná oznámení (jejichž názvy začínají NM_) a ovládací prvek popisku nástroje TTN_SHOW a TTN_POP oznámení, je ve skutečnosti použitá struktura NMHDR .

Struktura NMHDR nebo počáteční člen obsahuje popisovač a ID ovládacího prvku, který odesílá zprávu a kód oznámení (například TTN_SHOW). Formát struktury NMHDR je znázorněn níže:

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

U TTN_SHOW zprávy by byl člen kódu nastavený na TTN_SHOW.

Většina oznámení předává ukazatel na větší strukturu, která jako první člen obsahuje strukturu NMHDR . Představte si například strukturu, kterou ovládací prvek zobrazení seznamu používá LVN_KEYDOWN zpráva s oznámením, která se odešle při stisknutí klávesy v ovládacím prvku zobrazení seznamu. Ukazatel odkazuje na LV_KEYDOWN strukturu, která je definována takto:

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

Všimněte si, že vzhledem k tomu , že člen NMHDR je v této struktuře první, může být ukazatel, který jste předali v oznamovací zprávě, přetypovat na ukazatel na NMHDR nebo ukazatel na LV_KEYDOWN.

Oznámení společná pro všechny nové ovládací prvky Windows

Některá oznámení jsou společná pro všechny nové ovládací prvky Windows. Tato oznámení předávají ukazatel na strukturu NMHDR .

Kód oznámení Odesláno z důvodu
NM_CLICK Uživatel klikl na levé tlačítko myši v ovládacím prvku.
NM_DBLCLK Uživatel poklikáním na levé tlačítko myši v ovládacím prvku
NM_RCLICK Uživatel v ovládacím prvku klikl pravým tlačítkem myši.
NM_RDBLCLK Uživatel poklikáním pravým tlačítkem myši v ovládacím prvku
NM_RETURN Uživatel stiskl klávesu ENTER, zatímco ovládací prvek má fokus vstupu.
NM_SETFOCUS Ovládací prvek dostal vstupní fokus.
NM_KILLFOCUS Ovládací prvek ztratil fokus vstupu.
NM_OUTOFMEMORY Ovládací prvek nemohl dokončit operaci, protože není k dispozici dostatek paměti.

ON_NOTIFY: Zpracování zpráv WM_NOTIFY v aplikacích MFC

Funkce CWnd::OnNotify zpracovává zprávy s oznámeními. Jeho výchozí implementace zkontroluje mapování zpráv, aby obslužné rutiny oznámení volání. Obecně platí, že nepřepíšete OnNotify. Místo toho zadáte funkci obslužné rutiny a přidáte položku mapy zpráv pro tuto obslužnou rutinu do mapy zpráv třídy okna vlastníka.

ClassWizard, prostřednictvím seznamu vlastností ClassWizard, může vytvořit ON_NOTIFY položku mapy zpráv a poskytnout vám funkci kostru obslužné rutiny. Další informace o použití TřídyWizard, aby to bylo jednodušší, naleznete v tématu Mapování zpráv na funkce.

Makro mapy zpráv ON_NOTIFY má následující syntaxi:

ON_NOTIFY(wNotifyCode, id, memberFxn)

kde parametry jsou:

wNotifyCode
Kód zprávy s oznámením, který se má zpracovat, například LVN_KEYDOWN.

id
Podřízený identifikátor ovládacího prvku, pro který je oznámení odesláno.

memberFxn
Členová funkce, která se má volat při odeslání tohoto oznámení.

Členová funkce musí být deklarována pomocí následujícího prototypu:

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

kde parametry jsou:

pNotify – struktura
Ukazatel na strukturu oznámení, jak je popsáno v části výše.

Výsledek
Ukazatel na kód výsledku, který nastavíte před vrácením.

Příklad

Chcete-li určit, že chcete, aby členská funkce OnKeydownList1 zpracovávala LVN_KEYDOWN zprávy z CListCtrl ID je IDC_LIST1, byste pomocí TřídyWizard přidali následující položky do mapy zpráv:

ON_NOTIFY(LVN_KEYDOWN, IDC_LIST1, OnKeydownList1)

Ve výše uvedeném příkladu je funkce poskytovaná classWizard:

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

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

    *pResult = 0;
}

Všimněte si, že ClassWizard poskytuje ukazatel správného typu automaticky. Ke struktuře oznámení můžete přistupovat prostřednictvím pNMHDR nebo pLVKeyDow.

ON_NOTIFY_RANGE

Pokud potřebujete zpracovat stejnou zprávu WM_NOTIFY pro sadu ovládacích prvků, můžete místo ON_NOTIFY použít ON_NOTIFY_RANGE. Můžete mít například sadu tlačítek, pro které chcete provést stejnou akci pro určitou zprávu s oznámením.

Pokud používáte ON_NOTIFY_RANGE, zadáte souvislou oblast podřízených identifikátorů, pro které se má zpráva s oznámením zpracovat zadáním počátečního a koncového podřízeného identifikátoru rozsahu.

TřídaWizard nezpracuje ON_NOTIFY_RANGE; pokud ho chcete použít, musíte mapu zpráv upravit sami.

Položka mapy zpráv a prototyp funkce pro ON_NOTIFY_RANGE jsou následující:

ON_NOTIFY_RANGE(wNotifyCode, id, idLast, memberFxn)

kde parametry jsou:

wNotifyCode
Kód zprávy s oznámením, který se má zpracovat, například LVN_KEYDOWN.

id
První identifikátor v souvislé oblasti identifikátorů.

IdLast
Poslední identifikátor v souvislé oblasti identifikátorů.

memberFxn
Členová funkce, která se má volat při odeslání tohoto oznámení.

Členová funkce musí být deklarována pomocí následujícího prototypu:

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

kde parametry jsou:

id
Podřízený identifikátor ovládacího prvku, který oznámení odeslal.

pNotify – struktura
Ukazatel na strukturu oznámení, jak je popsáno výše.

Výsledek
Ukazatel na kód výsledku, který nastavíte před vrácením.

ON_NOTIFY_EX, ON_NOTIFY_EX_RANGE

Pokud chcete, aby zprávu zpracovával více než jeden objekt směrování oznámení, můžete místo ON_NOTIFY (nebo ON_NOTIFY_RANGE) použít ON_NOTIFY_EX (nebo ON_NOTIFY_EX_RANGE). Jediným rozdílem mezi verzí EX a běžnou verzí je, že členová funkce volaná pro verzi EX vrací boOL , která označuje, zda má zpracování zpráv pokračovat nebo ne. Vrácení NEPRAVDA z této funkce umožňuje zpracovat stejnou zprávu ve více než jednom objektu.

TřídaWizard nezpracuje ON_NOTIFY_EX ani ON_NOTIFY_EX_RANGE; pokud chcete některou z nich použít, musíte mapu zpráv upravit sami.

Položka mapy zpráv a prototyp funkce pro ON_NOTIFY_EX a ON_NOTIFY_EX_RANGE jsou následující. Významy parametrů jsou stejné jako u jiných verzí než EX .

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

Prototyp obou výše uvedených možností je stejný:

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

V obou případech obsahuje ID podřízený identifikátor ovládacího prvku, který oznámení odeslal.

Funkce musí vrátit hodnotu TRUE , pokud byla zpráva oznámení zcela zpracována nebo NEPRAVDA , pokud by jiné objekty ve směrování příkazů měly mít šanci zprávu zpracovat.

Viz také

Technické poznámky podle čísel
Technické poznámky podle kategorií