TN062: Reflexe zprávy pro ovládací prvky Windows
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 popisuje reflexi zprávy, novou funkci v prostředí MFC 4.0. Obsahuje také pokyny pro vytvoření jednoduchého opakovaně použitelného ovládacího prvku, který používá reflexi zpráv.
Tato technická poznámka neprobírá reflexi zpráv, protože se vztahuje na ovládací prvky technologie ActiveX (dříve označované jako ovládací prvky OLE). Přečtěte si článek technologie ActiveX ovládací prvky: Podtřídy ovládacího prvku Windows.
Co je Reflexe zpráv
Ovládací prvky Windows často odesílají zprávy s oznámeními do nadřazených oken. Mnoho ovládacích prvků například odesílá do nadřazeného objektu zprávu oznámení o barvě ovládacího prvku (WM_CTLCOLOR nebo jednu z jejích variant), aby nadřazený prvek mohl poskytnout štětec pro malování pozadí ovládacího prvku.
Ve Windows a v prostředí MFC před verzí 4.0 zodpovídá nadřazené okno, často dialogové okno, za zpracování těchto zpráv. To znamená, že kód pro zpracování zprávy musí být ve třídě nadřazeného okna a že musí být duplikován v každé třídě, která potřebuje zpracovat tuto zprávu. V případě výše by každé dialogové okno, které chtělo ovládací prvky s vlastními pozadími, zpracovávat zprávu oznámení o barvě ovládacího prvku. Pokud by byla třída ovládacího prvku napsaná tak, aby zvládla vlastní barvu pozadí, bylo by mnohem jednodušší kód znovu použít.
V prostředí MFC 4.0 starý mechanismus stále funguje – nadřazená okna můžou zpracovávat zprávy s oznámeními. Knihovna MFC 4.0 ale usnadňuje opakované použití tím, že poskytuje funkci s názvem "reflexe zprávy", která umožňuje zpracování těchto zpráv s oznámeními v podřízené ovládacím okně nebo v nadřazené okně nebo v obou. V příkladu barvy pozadí ovládacího prvku teď můžete napsat třídu ovládacího prvku, která nastaví vlastní barvu pozadí tím, že zvládne WM_CTLCOLOR zprávu – to vše bez nutnosti spoléhat se na nadřazenou položku. (Všimněte si, že vzhledem k tomu, že reflexe zprávy je implementována mfc, nikoli systémem Windows, nadřazená třída okna musí být odvozena od CWnd
, aby reflexe zprávy fungovala.)
Starší verze mfc udělaly něco podobného reflexi zpráv tím, že poskytovaly virtuální funkce pro několik zpráv, jako jsou zprávy pro seznamy nakreslené vlastníkem (WM_DRAWITEM atd.). Nový mechanismus reflexe zpráv je zobecněný a konzistentní.
Reflexe zprávy je zpětně kompatibilní s kódem napsaným pro verze MFC před 4.0.
Pokud jste do třídy nadřazeného okna zadali obslužnou rutinu pro určitou zprávu nebo pro rozsah zpráv, přepíše obslužné rutiny zpráv pro stejnou zprávu za předpokladu, že nevoláte funkci obslužné rutiny základní třídy ve vlastní obslužné rutině. Pokud například zpracováváte WM_CTLCOLOR ve třídě dialogového okna, zpracování přepíše všechny zobrazené obslužné rutiny zpráv.
Pokud v nadřazené třídě okna zadáte obslužnou rutinu pro určitou WM_NOTIFY zprávu nebo rozsah zpráv WM_NOTIFY, bude obslužná rutina volána pouze v případě, že podřízený ovládací prvek odesílající tyto zprávy nemá reflektující obslužnou rutinu zprávy prostřednictvím ON_NOTIFY_REFLECT()
. Pokud používáte ON_NOTIFY_REFLECT_EX()
v mapě zpráv, může obslužná rutina zprávy nebo nemusí povolit nadřazené okno zpracovat zprávu. Pokud obslužná rutina vrátí hodnotu NEPRAVDA, bude zpráva zpracována také nadřazeným objektem, zatímco volání, které vrátí hodnotu PRAVDA , neumožňuje nadřazenému objektu zpracovat. Všimněte si, že reflektovaná zpráva se zpracovává před oznámením.
Když se odešle WM_NOTIFY zpráva, zobrazí se ovládací prvek první šanci na jeho zpracování. Pokud se odešle nějaká jiná reflektovaná zpráva, nadřazené okno má první možnost ji zpracovat a ovládací prvek obdrží reflektující zprávu. K tomu bude potřebovat funkci obslužné rutiny a příslušnou položku v mapě zpráv třídy ovládacího prvku.
Makro mapy zpráv pro reflektované zprávy se mírně liší od běžných oznámení: je _REFLECT připojeno k obvyklému názvu. Pokud chcete například zpracovat WM_NOTIFY zprávu v nadřazené pomůcek, použijete makro ON_NOTIFY v mapě zpráv nadřazeného objektu. Pokud chcete zpracovat reflektovaná zpráva v podřízeného ovládacího prvku, použijte makro ON_NOTIFY_REFLECT v mapě zpráv podřízeného ovládacího prvku. V některých případech se parametry liší. Všimněte si, že ClassWizard může obvykle přidávat položky mapy zpráv za vás a poskytovat implementace kostru funkce se správnými parametry.
Viz TN061: ON_NOTIFY a WM_NOTIFY Zprávy , kde najdete informace o nové zprávě WM_NOTIFY.
Položky mapy zpráv a prototypy funkcí obslužné rutiny pro Reflexe zprávy
Pokud chcete zpracovat reflektované oznámení o ovládacím prvku, použijte makra mapy zpráv a prototypy funkcí uvedené v následující tabulce.
ClassWizard může obvykle přidávat tyto položky mapy zpráv za vás a poskytovat implementace kostru funkce. Informace o tom, jak definovat obslužné rutiny pro reflektované zprávy, najdete v tématu Definování obslužné rutiny pro Reflexe ed Zprávu.
Pokud chcete převést název zprávy na název reflektovaného makra, předpřipravené ON_ a připojte _REFLECT. Například WM_CTLCOLOR se stane ON_WM_CTLCOLOR_REFLECT. (Chcete-li zjistit, které zprávy se dají promítnout, proveďte opačný převod u položek makra v následující tabulce.)
Tři výjimky výše uvedeného pravidla jsou následující:
Makro pro oznámení WM_COMMAND je ON_CONTROL_REFLECT.
Makro pro WM_NOTIFY odrazy je ON_NOTIFY_REFLECT.
Makro pro ON_UPDATE_COMMAND_UI odrazy je ON_UPDATE_COMMAND_UI_REFLECT.
V každém z výše uvedených zvláštních případů je nutné zadat název členské funkce obslužné rutiny. V ostatních případech musíte pro funkci obslužné rutiny použít standardní název.
Významy parametrů a návratových hodnot funkcí jsou zdokumentované pod názvem funkce nebo názvem funkce s předpendedem. Například CtlColor
je dokumentován v OnCtlColor
souboru . Několik odražených obslužných rutin zpráv potřebuje méně parametrů než podobné obslužné rutiny v nadřazeném okně. Stačí, když názvy v následující tabulce odpovídají názvům formálních parametrů v dokumentaci.
Položka mapy | Prototyp funkce |
---|---|
ON_CONTROL_REFLECT(wNotifyCode ,)memberFxn |
afx_msg voidmemberFxn ( ); |
ON_NOTIFY_REFLECT(wNotifyCode ,)memberFxn |
afx_msg voidmemberFxn ( NMHDRpNotifyStruct *; výsledek LRESULT);* |
ON_UPDATE_COMMAND_UI_REFLECT(memberFxn ) |
afx_msg voidmemberFxn ( CCmdUI);*pCmdUI |
ON_WM_CTLCOLOR_REFLECT( ) | afx_msg HBRUSH CtlColor ( CDCpDC *, UINT);nCtlColor |
ON_WM_DRAWITEM_REFLECT( ) | afx_msg void DrawItem ( LPDRAWITEMSTRUCTlpDrawItemStruct ); |
ON_WM_MEASUREITEM_REFLECT( ) | afx_msg void MeasureItem ( LPMEASUREITEMSTRUCTlpMeasureItemStruct ); |
ON_WM_DELETEITEM_REFLECT( ) | afx_msg void DeleteItem ( LPDELETEITEMSTRUCTlpDeleteItemStruct ); |
ON_WM_COMPAREITEM_REFLECT( ) | afx_msg int CompareItem ( LPCOMPAREITEMSTRUCTlpCompareItemStruct ); |
ON_WM_CHARTOITEM_REFLECT( ) | afx_msg int CharToItem ( UINTnKey , UINT);nIndex |
ON_WM_VKEYTOITEM_REFLECT( ) | afx_msg int VKeyToItem (UINTnKey , UINT);nIndex |
ON_WM_HSCROLL_REFLECT( ) | afx_msg void HScroll ( UINTnSBCode , UINT);nPos |
ON_WM_VSCROLL_REFLECT( ) | afx_msg void VScroll ( UINTnSBCode , UINT);nPos |
ON_WM_PARENTNOTIFY_REFLECT( ) | afx_msg void ParentNotify ( UINTmessage , LPARAM);lParam |
Makra ON_NOTIFY_REFLECT a ON_CONTROL_REFLECT mají varianty, které umožňují zpracování dané zprávy více než jeden objekt (například ovládací prvek a nadřazený prvek).
Položka mapy | Prototyp funkce |
---|---|
ON_NOTIFY_REFLECT_EX(wNotifyCode ,)memberFxn |
afx_msg BOOLmemberFxn ( NMHDRpNotifyStruct *; výsledek LRESULT);* |
ON_CONTROL_REFLECT_EX(wNotifyCode ,)memberFxn |
afx_msg BOOLmemberFxn ( ); |
Zpracování Reflexe ed zpráv: Příklad opakovaně použitelného ovládacího prvku
Tento jednoduchý příklad vytvoří opakovaně použitelný ovládací prvek s názvem CYellowEdit
. Ovládací prvek funguje stejně jako běžný ovládací prvek pro úpravy s tím rozdílem, že zobrazuje černý text na žlutém pozadí. Bylo by snadné přidat členské funkce, které by ovládacímu CYellowEdit
prvku umožňovaly zobrazit různé barvy.
Vyzkoušení příkladu, který vytvoří opakovaně použitelný ovládací prvek
Vytvořte nové dialogové okno v existující aplikaci. Další informace najdete v tématu editoru dialogových oken.
Musíte mít aplikaci, ve které se má vyvíjet opakovaně použitelný ovládací prvek. Pokud nemáte existující aplikaci k použití, vytvořte dialogovou aplikaci pomocí AppWizardu.
S projektem načteným do jazyka Visual C++ vytvořte pomocí třídyWizard novou třídu založenou
CYellowEdit
naCEdit
.Přidejte do
CYellowEdit
třídy tři členské proměnné. První dvě budou proměnné COLORREF, které budou obsahovat barvu textu a barvu pozadí. Třetí budeCBrush
objekt, který bude držet štětec pro malování pozadí. ObjektCBrush
umožňuje vytvořit štětec jednou, pouze na něj odkazovat a zničit štětec automaticky přiCYellowEdit
zničení ovládacího prvku.Inicializace členských proměnných zápisem konstruktoru následujícím způsobem:
CYellowEdit::CYellowEdit() { m_clrText = RGB(0, 0, 0); m_clrBkgnd = RGB(255, 255, 0); m_brBkgnd.CreateSolidBrush(m_clrBkgnd); }
Pomocí třídy ClassWizard přidejte obslužnou rutinu pro reflektovanou WM_CTLCOLOR zprávu do třídy
CYellowEdit
. Všimněte si, že symbol rovná se před názvem zprávy v seznamu zpráv, které můžete zpracovat, označuje, že se zpráva odráží. Toto je popsáno v definování obslužné rutiny zprávy pro Reflexe ed Message.ClassWizard přidá následující makro mapy zpráv a kostru funkce za vás:
ON_WM_CTLCOLOR_REFLECT() // Note: other code will be in between.... HBRUSH CYellowEdit::CtlColor(CDC* pDC, UINT nCtlColor) { // TODO: Change any attributes of the DC here // TODO: Return a non-NULL brush if the // parent's handler should not be called return NULL; }
Tělo funkce nahraďte následujícím kódem. Kód určuje barvu textu, barvu pozadí textu a barvu pozadí pro zbytek ovládacího prvku.
pDC->SetTextColor(m_clrText); // text pDC->SetBkColor(m_clrBkgnd); // text bkgnd return m_brBkgnd; // ctl bkgnd
V dialogovém okně vytvořte ovládací prvek pro úpravy a pak ho připojte k členské proměnné tak, že dvakrát kliknete na ovládací prvek pro úpravy a podržíte stisknutou klávesu control. V dialogovém okně Přidat členovou proměnnou dokončete název proměnné a zvolte "Control" pro kategorii a pak "CYellowEdit" pro typ proměnné. Nezapomeňte v dialogovém okně nastavit pořadí ovládacích prvků. Nezapomeňte také zahrnout soubor
CYellowEdit
záhlaví ovládacího prvku do souboru záhlaví dialogového okna.Sestavte a spusťte aplikaci. Ovládací prvek pro úpravy bude mít žluté pozadí.
Viz také
Technické poznámky podle čísel
Technické poznámky podle kategorií