TN062:Windows控件的消息反映
备注
以下技术声明,则它在联机文档,首先包括了不更新。因此,某些过程和主题可能已过时或不正确。有关最新信息,建议您搜索议题在联机文档的索引。
此方法声明描述消息反映,在 MFC 4.0 的新功能。 它还包含创建使用消息反映了一个简单的可重用控件的方向。
此方法声明不讨论消息反映,则适用于 Activex 控件 (以前称为 OLE 控件)。 请参见中的文章 Activex 控件:的 Subclassing windows 控件。
什么是消息反映?
windows 控件通常发送通知消息到其父窗口。 例如,许多控件发送控件的颜色通知信息 (其变量WM_CTLCOLOR 或之一) 到其父允许父元素提供绘制控件的背景一个画笔。
在窗口和在 4.0 版之前的 MFC,父窗口,通常对话框中,处理这些消息负责。 这意味着消息处理代码需要在父窗口的类,并在需要处理消息的每个类都必须复制。 在上面的情况,需要使用自定义背景的控件都对话框必须处理控件的颜色通知消息。 重用代码更为方便,则会处理自己的背景色的控件类可以编写。
在 MFC 4.0,旧结构仍然起作用 —父窗口可以处理通知消息访问。 此外,但是, MFC 4.0 便于重复使用通过提供称为 “在子控件窗口或父窗口使这些通知消息已处理的消息反映”函数,或者在两个。 在控件背景色的示例中,您现在可以编写通过处理反映的 WM_CTLCOLOR 消息设置自己的背景颜色 —所有不依赖于父控件的类。 (请注意,由于消息反映由 MFC 实现,而不是窗口,必须从消息反映的 CWnd 派生能够工作。) 的父窗口类
MFC 的早期版本执行操作类似于消息反映通过提供虚函数为某些消息,例如所有者描述的消息列表框 (WM_DRAWITEM,等等)。 新的消息反映结构是泛化和一致。
消息反映不同于 MFC 的版本编写的代码向后兼容在 4.0 版之前。
如果提供了处理程序特定的消息,或消息的大小,则该父窗口的类,它将重写同一消息的反射消息处理程序提供了不对您的处理程序的基类处理程序函数。 例如,因此,如果在对话框类中处理 WM_CTLCOLOR ,则过程将重写任何反射消息处理程序。
如果为,则在您的父窗口类,您提供特定 WM_NOTIFY 消息或 WM_NOTIFY 消息大小的处理程序,该处理程序将调用,仅当发送这些信息的子控件未通过 **ON_NOTIFY_REFLECT()**有一个反射消息处理程序。 如果您的消息映射使用 ON_NOTIFY_REFLECT_EX() ,您的消息处理程序可能存在也可能不提供父窗口处理消息。 如果处理程序返回 FALSE,消息将由父进程,,而返回 TRUE 的调用不对父处理它。 请注意反射消息在通知消息之前处理。
当发送时 WM_NOTIFY 信息,控件的句柄提供第一个机会它。 如果发送其他反映的信息,父窗口具有处理它,控件将收到反射消息。 为此,此控件的类消息映射需要处理程序函数和相应的项。
反射消息的消息映射宏用于常规通知一些不同:它具有 _REFLECT 追加到其通常名称。 例如,若要处理在父级,因此的一 WM_NOTIFY 消息在父的消息映射使用宏 ON_NOTIFY 。 处理在子控件的反射消息,则子控件的消息映射使用 ON_NOTIFY_REFLECT 宏。 在某些情况下,参数是不同的,。 请注意类向导可能会将您的消息映射项和提供主干函数实现用正确的参数。
有关新 WM_NOTIFY 消息的信息,请参见 TN061:ON_NOTIFY 和 WM_NOTIFY 消息 。
消息映射项和处理程序函数原型反射消息的
处理反射的控件通知消息,在下表中使用中列出的消息映射宏和函数原型。
类向导可能会将您的这些消息映射项和提供主干函数实现。 有关如何定义反射消息的,处理程序的信息 定义反射消息的消息处理程序 参见。
从邮件名若要转换成反映的宏名称,请预置 ON_ 并追加 _REFLECT。 例如, WM_CTLCOLOR 成为 ON_WM_CTLCOLOR_REFLECT。 (看到哪些消息可反映,请执行宏项相反的转换在下表中。)
上面的规则的三个例外如下所示:
WM_COMMAND 通知的宏是 ON_CONTROL_REFLECT。
WM_NOTIFY 反射的宏是 ON_NOTIFY_REFLECT。
ON_UPDATE_COMMAND_UI 反射的宏是 ON_UPDATE_COMMAND_UI_REFLECT。
在每个上述特殊情况,必须指定处理程序成员函数的名称。 在其他情况下,必须为处理程序函数使用标准名称。
参数的含义和函数返回的值文档的或函数名或与 在 的函数名称加上了前面。 例如, CtlColor 在 OnCtlColor文档。 若干反射消息处理程序在父窗口只是类似的处理程序所需的参数。 请对名称在下表中的形参的名称在文档的。
映射项 |
函数原型 |
---|---|
ON_CONTROL_REFLECT( wNotifyCode, memberFxn ) |
afx_msg void memberFxn ( ); |
ON_NOTIFY_REFLECT( wNotifyCode, memberFxn ) |
afx_msg void memberFxn ( NMHDR * pNotifyStruct, LRESULT* 结果); |
ON_UPDATE_COMMAND_UI_REFLECT( memberFxn ) |
afx_msg void memberFxn ( CCmdUI* pCmdUI); |
ON_WM_CTLCOLOR_REFLECT () |
afx_msg HBRUSH CtlColor ( CDC* pDC, UINT nCtlColor); |
ON_WM_DRAWITEM_REFLECT () |
afx_msg void DrawItem ( LPDRAWITEMSTRUCT lpDrawItemStruct); |
ON_WM_MEASUREITEM_REFLECT () |
afx_msg void MeasureItem ( LPMEASUREITEMSTRUCT lpMeasureItemStruct); |
ON_WM_DELETEITEM_REFLECT () |
afx_msg void DeleteItem ( LPDELETEITEMSTRUCT lpDeleteItemStruct); |
ON_WM_COMPAREITEM_REFLECT () |
afx_msg int CompareItem ( LPCOMPAREITEMSTRUCT lpCompareItemStruct); |
ON_WM_CHARTOITEM_REFLECT () |
afx_msg int CharToItem ( UINT nKey, UINT nIndex); |
ON_WM_VKEYTOITEM_REFLECT () |
afx_msg int VKeyToItem ( UINT nKey, UINT nIndex); |
ON_WM_HSCROLL_REFLECT () |
afx_msg void HScroll ( UINT nSBCode, UINT nPos); |
ON_WM_VSCROLL_REFLECT () |
afx_msg void VScroll ( UINT nSBCode, UINT nPos); |
ON_WM_PARENTNOTIFY_REFLECT () |
afx_msg void ParentNotify ( UINT message, LPARAM lParam); |
ON_NOTIFY_REFLECT 和 ON_CONTROL_REFLECT 宏有提供多个对象的变体 (例如控件及其父级) 处理一给定的消息。
映射项 |
函数原型 |
---|---|
ON_NOTIFY_REFLECT_EX( wNotifyCode, memberFxn ) |
afx_msg BOOL memberFxn ( NMHDR * pNotifyStruct, LRESULT* 结果); |
ON_CONTROL_REFLECT_EX( wNotifyCode, memberFxn ) |
afx_msg BOOL memberFxn ( ); |
处理反射消息:一个可重用控件的示例
此简单示例创建名为 CYellowEdit的可重用控件。 控件的工作方式与常规编辑控件的,但它显示在黄色背景的黑色文本。 添加将允许 CYellowEdit 控件显示不同颜色的成员函数非常容易。
尝试创建一个可重用控件的示例
创建新对话框在现有应用程序。 有关更多信息,请参见 对话框编辑器 主题。
您必须拥有开发可重用控件的应用程序。 如果不需要使用一个现有应用程序,使用 AppWizard,请创建基于对话框的应用程序。
当您的项目加载到 Visual C++,请使用类向导创建调用基于 CEdit的 CYellowEdit 的新类。
添加三个成员的变量赋给您的 CYellowEdit 类。 前两个将是一个文本颜色和背景颜色的 COLORREF 变量。 第三将是一个绘制背景画笔的 CBrush 对象。 ,当销毁时, CBrush 对象使您可以一次创建画笔,仅引用它之后和自动销毁画笔 CYellowEdit 控件。
通过将构造函数初始化成员变量如下所示:
CYellowEdit::CYellowEdit() { m_clrText = RGB( 0, 0, 0 ); m_clrBkgnd = RGB( 255, 255, 0 ); m_brBkgnd.CreateSolidBrush( m_clrBkgnd ); }
使用类向导,添加反映的 WM_CTLCOLOR 消息的处理程序添加到您的 CYellowEdit 类。 监视消息名称前面的等号才能处理消息的列表以指示消息反映。 这在 定义反射消息的消息处理程序所述。
类向导将您的以下消息映射宏和主干功能:
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; }
用下面的代码替换函数体。 代码为其他控件指定文本颜色、文本背景色和背景色。
pDC->SetTextColor( m_clrText ); // text pDC->SetBkColor( m_clrBkgnd ); // text bkgnd return m_brBkgnd; // ctl bkgnd
创建编辑控件的对话框,然后附加到成员变量通过双击编辑控件,并使 ctrl 键在上时。 在添加成员变量的对话框,请完成变量名并选择 “控件” category ",然后 “CYellowEdit”变量的类型的。 不要忘记将对话框的 tab 键顺序。 另外,请确保包括 CYellowEdit 控件的头文件在对话框的头文件。
生成并运行应用程序。 编辑控件将具有一个黄色背景。