TN006:消息映射
此注释说明 MFC 消息映射功能。
问题
Microsoft Windows 中使用实现设备其消息的窗口类中的虚函数。 由于涉及大量的消息,提供单独虚函数为每个 Windows 消息将创建一禁止将大 vtable。
由于系统定义的窗口消息的数量随时间更改,因此,应用程序所以能定义自己的窗口消息,消息映射提供防止中断现有代码的接口更改的间接寻址。
概述
MFC 提供替代在传统 Windows 程序处理发送到 Windows 的 switch 语句。 映射从消息给方法中定义,这样,当信息由窗口时,收到相应的方法自动调用。 此消息映射功能设计类似于虚函数,但对 C++ 虚拟函数无好处。
定义消息映射
DECLARE_MESSAGE_MAP 宏声明类的三个成员。
某些私有 AFX_MSGMAP_ENTRY 项调用 _messageEntries。
指向 _messageEntries 数组的受保护的 AFX_MSGMAP 结构调用 messageMap。
返回 messageMap地址的受保护的虚函数调用 GetMessageMap。
在任何类中声明应将使用消息映射,则此宏。 按照约定,其在类声明结尾处。 例如:
class CMyWnd : public CMyParentWndClass
{
// my stuff...
protected:
//{{AFX_MSG(CMyWnd)
afx_msg void OnPaint();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
在创建新类时,这是 AppWizard ClassWizard 和生成的格式。 //{和}括号 ClassWizard 为//需要的。
消息映射中的表是使用扩展到的一组消息映射项宏。 使用 BEGIN_MESSAGE_MAP 宏调用的开始时间表,定义类。此消息映射和父类中处理消息传递。 表与 END_MESSAGE_MAP 宏调用结束。
在这两宏调用之间是此消息映射要处理的每条消息的项。 每个标准 Windows 消息具有生成该消息的项窗体 ON_WM_MESSAGE_NAME 的宏。
一种标准函数签名用于打开每个 Windows 消息参数并提供类型安全定义。 这些签名在 CWnd声明的文件 Afxwin.h 能找到。 每个标记轻松标识的关键字 afx_msg。
备注
ClassWizard 需要您在消息映射处理程序声明中使用 afx_msg 关键字。
通过使用简单的约定,这些函数签名中派生的。 始终函数开头的名称用 "On”。 这后跟窗口消息。“WM_”中移除和大写的每个单词的首字母。 排序参数为 LOWORD之后的 wParam (lParam) 和 HIWORD(lParam)。 未使用的参数进行传递。 由 MFC 类包装的任何处理转换为对相应的 MFC 对象的指针。 下面的示例演示如何处理 WM_PAINT 消息并导致 CMyWnd::OnPaint 函数调用:
BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
//{{AFX_MSG_MAP(CMyWnd)
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
必须定义在任何函数或类定义的范围外,消息映射表。 在外部“C”块不应放置它。
备注
ClassWizard 将修改发生在//的消息映射项//{和}注释括号之间。
用户定义的窗口消息
使用 ON_MESSAGE 宏,用户定义消息中可能包含消息映射。 此宏接受一个消息号和窗体的方法:
// 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()
在此示例中,我们为与用户定义消息的标准 WM_USER 基派生的 Windows 消息 ID 的自定义消息处理程序。 下面的示例演示如何处理事件。
CWnd* pWnd = ...;
pWnd->SendMessage(WM_MYMESSAGE);
使用此方法的用户范围定义消息必须在范围的 WM_USER。0x7fff。
备注
ClassWizard 不支持在 ON_MESSAGE 从 ClassWizard 用户界面处理程序的实例。必须手动输入其从 Visual C++ 编辑器。ClassWizard 将分析这些输入可浏览他们任何其他消息映射项。
已注册窗口消息
Windows RegisterWindowMessage 函数用于定义确保为唯一的整个系统中的新的 Windows 消息。 ON_REGISTERED_MESSAGE 宏来处理这些消息。 此宏接受包含已注册窗口消息标识 UINT NEAR 的变量名称 例如
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()
已注册窗口消息标识变量 (在此示例中为) WM_FIND 必须是 NEAR 变量因实现 ON_REGISTERED_MESSAGE 的方式。
使用此方法的用户范围定义消息在范围 0x C000 到 0xFFFF。
备注
ClassWizard 不支持在 ON_REGISTERED_MESSAGE 从 ClassWizard 用户界面处理程序的实例。必须手动输入他们从文本编辑器。ClassWizard 将分析这些输入可浏览他们任何其他消息映射项。
命令消息
从菜单和快捷键的命令消息与 ON_COMMAND 宏的消息映射进行处理。 此宏接受命令 ID 和方法。 存在 wParam 等于指定的命令 ID 的特定消息由 WM_COMMAND 在消息映射项指定的方法处理。 命令处理程序成员函数不采用任何参数且返回 void。 宏具有以下形式:
ON_COMMAND(id, memberFxn)
命令更新消息通过相同机制传送,但使用 ON_UPDATE_COMMAND_UI 宏。 命令更新处理程序成员函数采用单个参数、指向 CCmdUI 对象并返回 void。 宏有窗体
ON_UPDATE_COMMAND_UI(id, memberFxn)
高级用户可以使用 ON_COMMAND_EX 宏,是命令消息处理程序扩展的窗体。 宏提供 ON_COMMAND 功能的扩展。 扩展命令处理程序函数采用成员包含命令 ID 的单个参数,UINT,并返回 BOOL。 返回值应为 TRUE 指示已处理过该命令。 为路由继续将其他命令目标对象。
这些成员包括:
内 Resource.h (通常发生 Visual C++)
#define ID_MYCMD 100 #define ID_COMPLEX 101
在类声明内部
afx_msg void OnMyCommand(); afx_msg void OnUpdateMyCommand(CCmdUI* pCmdUI); afx_msg BOOL OnComplexCommand(UINT nID);
在消息映射中定义
ON_COMMAND(ID_MYCMD, OnMyCommand) ON_UPDATE_COMMAND_UI(ID_MYCMD, OnUpdateMyCommand) ON_COMMAND_EX(ID_MYCMD, OnComplexCommand)
在类实现文件中:
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; }
使用单个命令处理程序,高级用户可以处理范围命令:ON_COMMAND_RANGE 或 ON_COMMAND_RANGE_EX。 有关这些属性的更多信息,请参见 ADO 文档。
备注
ClassWizard 支持创建 ON_COMMAND 和 ON_UPDATE_COMMAND_UI 处理程序,不过,它不支持创建 ON_COMMAND_EX 或 ON_COMMAND_RANGE 处理程序。但是,类向导"将分析并可以浏览所有四个命令处理程序的变量。
控件通知消息
从子发送的消息可向窗口都有多余位信息在他们的消息映射项:控件 ID 的 . 只有在以下条件为真时,在消息映射项指定的消息处理程序添加调用:
控件通知代码 ( lParam高位字中。),如 BN_CLICKED,与消息映射项指定的通知代码。
控件 ID (wParam) 与消息映射项指定的控件 ID。
自定义控件通知消息可以使用 ON_CONTROL 宏定义具有自定义通知代码的消息映射项。 此宏具有窗体
ON_CONTROL(wNotificationCode, id, memberFxn)
对于高级使用 ON_CONTROL_RANGE 可用于处理从范围的特定控件通知具有同一处理程序的控件。
备注
类向导不支持创建用户界面 (UI) 的 ON_CONTROL 或 ON_CONTROL_RANGE 处理程序。必须手动输入他们从文本编辑器。ClassWizard 将分析这些输入可浏览他们任何其他消息映射项。
Windows 公共控件执行复杂控件通知使用更强大的 WM_NOTIFY。 通过使用 ON_NOTIFY 和 ON_NOTIFY_RANGE 宏,此 MFC 版本具有该新的消息直接支持。 有关这些属性的更多信息,请参见 ADO 文档。