Sdílet prostřednictvím


TN006: Mapy zpráv

Tato poznámka popisuje funkci Mapa zpráva knihovny MFC.

Problém

Microsoft Windows implementuje virtuální funkce v okně třídy, které slouží svému zařízení pro zasílání zpráv.Z důvodu velkého počtu zpráv, které poskytují samostatné virtuální funkce pro každou zprávu systému Windows byste měli vytvořit prohibitively velké vtable.

Protože počet zpráv definované systémem Windows v průběhu času mění, a vzhledem k tomu, že aplikace můžete definovat své vlastní zprávy systému Windows, zpráva mapuje zajišťují určitou úroveň dereference, který zabraňuje poškození existující kód změny rozhraní.

Přehled

Knihovna MFC poskytuje alternativu k příkazu switch, který byl použit v tradiční programy založené na systému Windows pro zpracování zpráv odeslaných do okna.Mapování zpráv metod, které lze definovat tak, že po obdržení zprávy pomocí okna vhodná metoda je volána automaticky.Tuto mapu zpráv zařízení navrženy tak, aby vypadala jako virtuální funkce, ale má další výhody, které není možné pomocí virtuálních funkcí jazyka C++.

Definování mapu zpráv

DECLARE_MESSAGE_MAP Makro deklaruje tři členy třídy.

  • Soukromé pole AFX_MSGMAP_ENTRY položky nazvané _messageEntries.

  • Chráněné AFX_MSGMAP strukturu s názvem messageMap odkazující _messageEntries pole.

  • A chráněné virtuální funkce nazývá GetMessageMap , který vrací adresu messageMap.

Toto makro měly být umístěny v libovolné třídy pomocí zprávy mapy prohlášení.Podle konvence je na konci deklarace třídy.Příklad:

class CMyWnd : public CMyParentWndClass
{
    // my stuff...

protected:
    //{{AFX_MSG(CMyWnd)
    afx_msg void OnPaint();
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
};

Jedná se o Formát generovaných AppWizard a ClassWizard při vytváření nové třídy./ / {{A / nebo}} závorky jsou potřebné pro ClassWizard.

Tabulka mapování zpráv je definován pomocí sady maker, které rozbalí do položek mapování zpráv.Tabulka začíná BEGIN_MESSAGE_MAP volání makra, které definuje třídu, která je zpracována zpráva mapa a nadřazené třídy, které jsou předány nezpracované zprávy.Končí v tabulce END_MESSAGE_MAP volání makra.

Mezi tato volání dvě makra je záznam pro každou zprávu zpracovat tuto mapu zpráv.Všechny standardní zprávy systému Windows obsahuje makra formuláře ON_WM_MESSAGE_NAME , která generuje položku pro tuto zprávu.

Standardní funkci podpisu byla definována pro rozbalení parametry jednotlivých zpráv systému Windows a poskytují typovou bezpečnost.Tyto podpisy mohou najít v souboru Afxwin.h v prohlášení z CWnd.Každý z nich je označen klíčovým slovem afx_msg pro snadnou identifikaci.

[!POZNÁMKA]

ClassWizard vyžaduje použití afx_msg klíčové slovo v deklaracích zpráva mapování obslužné rutiny.

Tyto funkce identifikace byly získány pomocí jednoduchého úmluvy.Název funkce je vždy spuštěn s "On".Následuje název zprávy systému Windows s "WM_" odebrán a první písmeno každého slova velkými písmeny.Pořadí parametrů je wParam a LOWORD(lParam) pak HIWORD(lParam).Nepoužité parametry nejsou předány.Všechny popisovače, které jsou zabaleny třídou tříd knihovny MFC jsou převedeny na odkazy na příslušné objekty knihovny MFC.Následující příklad ukazuje, jak zpracovat WM_PAINT zpráva a způsobit, že CMyWnd::OnPaint zavolat funkci:

BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
    //{{AFX_MSG_MAP(CMyWnd)
    ON_WM_PAINT()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

Tabulka mapování zpráv musí být definována mimo rámec jakékoli funkce nebo definice třídy.Nesmí být umístěny v bloku extern "C".

[!POZNÁMKA]

ClassWizard změní položky mapování zpráv, ke kterým dochází mezi / / {{a / nebo}} komentář závorka.

Uživatelem definované zprávy systému Windows

Uživatelem definované zprávy mohou být zahrnuty v mapě zpráv pomocí ON_MESSAGE makra.Toto makro je možné zadat počet zpráv a metoda formuláře:

    // inside the class declaration
    afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);

    #define WM_MYMESSAGE (WM_USER + 100)

BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
    ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)
END_MESSAGE_MAP()

V tomto příkladu jsme vytvořit obslužnou rutinu pro vlastní zprávu, která má odvozen od standardní ID zprávy systému Windows WM_USER základní zpráv definované uživatelem.Následující příklad ukazuje, jak volat tuto obslužnou rutinu:

CWnd* pWnd = ...;
pWnd->SendMessage(WM_MYMESSAGE);

Oblast zpráv definované uživatelem, používající tento přístup musí být v rozsahu od WM_USER k 0x7fff.

[!POZNÁMKA]

ClassWizard nepodporuje zadávání ON_MESSAGE rutiny rutiny z uživatelského rozhraní ClassWizard.Je nutné ručně zadat z editoru Visual C++.ClassWizard bude analyzovat tyto položky a umožňují jim procházet stejně jako kterýchkoli jiných položek, mapu zpráv.

Zprávy systému Windows registrované

RegisterWindowMessage funkce se používá k definování nové zprávy okna, která je zaručena jedinečné v celém systému.Makro ON_REGISTERED_MESSAGE se používá ke zpracování těchto zpráv.Toto makro je možné zadat název UINT NEAR proměnná, která obsahuje ID registrované windows zprávy.Například

class CMyWnd : public CMyParentWndClass
{
public:
    CMyWnd();

    //{{AFX_MSG(CMyWnd)
    afx_msg LRESULT OnFind(WPARAM wParam, LPARAM lParam);
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
};

static UINT NEAR WM_FIND = RegisterWindowMessage("COMMDLG_FIND");

BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
    //{{AFX_MSG_MAP(CMyWnd)
    ON_REGISTERED_MESSAGE(WM_FIND, OnFind)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

Musí být registrované proměnné (WM_FIND v tomto příkladu) ID zprávy systému Windows NEAR proměnné vzhledem ke způsobu ON_REGISTERED_MESSAGE je implementována.

Rozsah zprávy uživatelem definované pomocí tento přístup bude v rozsahu 0xC000 až 0xFFFF.

[!POZNÁMKA]

ClassWizard nepodporuje zadávání ON_REGISTERED_MESSAGE rutiny rutiny z uživatelského rozhraní ClassWizard.Je třeba ručně zadat z textového editoru.ClassWizard bude analyzovat tyto položky a umožňují jim procházet stejně jako kterýchkoli jiných položek, mapu zpráv.

Zprávy příkazů

Zprávy příkazu z nabídky a akcelerátory jsou zpracovány v mapách zprávu s ON_COMMAND makra.Toto makro přijímá ID příkazu a metody.Pouze zvláštní WM_COMMAND zprávu, která má wParam rovna zadaný příkaz ID je zpracována podle metody uvedené v položce mapu zpráv.Příkaz obslužné rutiny členské funkce žádné parametry a vrátí void.Makro má následující tvar:

ON_COMMAND(id, memberFxn)

Příkaz update zprávy směrovány na stejný mechanismus, ale použít ON_UPDATE_COMMAND_UI makro místo.Příkaz update obslužné rutiny členské funkce trvat jeden parametr ukazatel CCmdUI objektu a vrátí void.Makro má tvar

ON_UPDATE_COMMAND_UI(id, memberFxn)

Pokročilí uživatelé mohou použít ON_COMMAND_EX makro, které je rozšířená forma příkazu obslužné rutiny zpráv.Makro obsahuje nadmnožinou ON_COMMAND funkce.Rozšířený příkaz popisovač členské funkce vzít jeden parametr, UINT , obsahuje ID příkazu a vrátíte se BOOL.Vrácená hodnota by měla být TRUE označíte, že byla zpracována příkazu.Jinak směrování bude pokračovat další příkaz cílové objekty.

Příklady z těchto forem:

  • Uvnitř Resource.h (obvykle vytvořen pomocí Visual C++)

    #define    ID_MYCMD      100
    #define    ID_COMPLEX    101
    
  • Uvnitř deklarace třídy

    afx_msg void OnMyCommand();
    afx_msg void OnUpdateMyCommand(CCmdUI* pCmdUI);
    afx_msg BOOL OnComplexCommand(UINT nID);
    
  • Uvnitř definice mapování zpráv

    ON_COMMAND(ID_MYCMD, OnMyCommand)
    ON_UPDATE_COMMAND_UI(ID_MYCMD, OnUpdateMyCommand)
    ON_COMMAND_EX(ID_MYCMD, OnComplexCommand)
    
  • Do implementačního souboru

    void CMyClass::OnMyCommand()
    {
        // handle the command
    }
    
    void CMyClass::OnUpdateMyCommand(CCmdUI* pCmdUI)
    {
        // set the UI state with pCmdUI
    }
    
    BOOL CMyClass::OnComplexCommand(UINT nID)
    {
        // handle the command
        return TRUE;
    }
    

Pokročilé uživatele může zpracovat řadu příkazů pomocí jediného příkazu rutiny: ON_COMMAND_RANGE nebo ON_COMMAND_RANGE_EX.Další informace o těchto makrech v dokumentaci produktu.

[!POZNÁMKA]

ClassWizard podporuje vytváření ON_COMMAND a ON_UPDATE_COMMAND_UI obslužné rutiny, ale nepodporuje vytváření ON_COMMAND_EX nebo ON_COMMAND_RANGE obslužné rutiny.Průvodce třídou však bude analyzovat a umožňují procházet všechny varianty čtyři příkaz obslužné rutiny.

Řídicí zprávy oznámení

Položka mapování zpráv odesílaných z podřízených ovládacích prvků do okna mají další bit informací ve zprávě: ID ovládacího prvku.Zpracování zpráv podle zprávy načítání se nazývá pouze v případě, že jsou splněny následující podmínky:

  • Kód oznámení ovládacího prvku (vysoké slovo lParam), jako je například BN_CLICKED, odpovídající kód upozornění zadaný v položce mapu zpráv.

  • ID ovládacího prvku (wParam) odpovídá ID ovládacího prvku, který je zadán v položce mapu zpráv.

Použít vlastní ovládací prvek zprávy s oznámením ON_CONTROL makro definovat položku mapy zpráva s kódem vlastní oznámení.Toto makro má tvar

ON_CONTROL(wNotificationCode, id, memberFxn)

Pro pokročilého využití ON_CONTROL_RANGE lze zpracovat oznámení určitého ovládacího prvku z oblasti ovládacích prvků se stejným obslužné rutiny.

[!POZNÁMKA]

ClassWizard nepodporuje vytváření ON_CONTROL nebo ON_CONTROL_RANGE rutinu v uživatelském rozhraní.Je nutné ručně zadat pomocí textového editoru.ClassWizard bude analyzovat tyto položky a umožňují jim procházet stejně jako kterýchkoli jiných položek mapování zpráv.

Běžné ovládací prvky systému Windows použít výkonnější WM_NOTIFY pro komplexní řízení oznámení.Tato verze knihovny MFC má přímou podporu pro tuto novou zprávu pomocí ON_NOTIFY a ON_NOTIFY_RANGE makra.Další informace o těchto makrech v dokumentaci produktu.

Viz také

Další zdroje

Technické poznámky podle čísel

Technické poznámky podle kategorií