:来自MSDN
消息的发送和接收
请看该过程的发送部分以及框架的响应方式。
大多数消息因用户与程序之间的交互而产生。命令通过鼠标单击菜单项或工具栏按钮或通过敲击快捷键生成。用户也通过其他方式生成 Windows 消息,例如移动窗口或调整窗口大小。当发生诸如程序启动或终止、窗口获取或失去焦点等事件时,将发送其他 Windows 消息。控件通知消息由鼠标单击或用户与某一控件(如对话框中的按钮或列表框 (ListBox) 控件)的其他交互生成。
CWinApp 类的 Run 成员函数检索消息并将其调度到适当的窗口。大多数命令消息被发送到应用程序的主框架窗口。由类库预定义的 WindowProc 获取消息并以不同的方式传送消息,传送方式取决于所接收的消息类别。
现在请看该过程的接收部分。
消息的初始接收器必须是窗口对象。Windows 消息通常直接由该窗口对象处理。通常产生于应用程序主框架窗口的命令消息被传送到命令传送中描述的命令目标链。
每一种能够接收消息或命令的对象都有各自的消息映射,该消息映射使消息或命令与其处理程序名配对。
当命令目标对象收到消息或命令后,它在其消息映射中搜索匹配项。如果找到该消息的处理程序,则调用此处理程序。有关如何搜索消息映射的更多信息,请参见框架搜索消息映射的方式。请再次参照图框架中的命令。
非命令消息到达其处理程序的方式
与命令不同,标准 Windows 消息不传送到命令目标链,而是通常由 Windows 将消息发送到的窗口处理。该窗口可能是主框架窗口、MDI 子窗口、标准控件、对话框、视图或其他某种子窗口。
运行时,每一个 Windows 窗口附加到一个窗口对象(由 CWnd 直接或间接派生),此窗口对象有自己的关联消息映射和处理函数。框架像对待命令一样,使用消息映射将传入的消息映射到处理程序。
命令传送
使用命令时您的责任仅限于创建命令和其处理函数之间的消息映射连接。使用“属性”窗口来完成此任务。您还必须编写大多数的命令处理程序。
通常将 Windows 消息发送到主框架窗口,而将命令消息传送到其他对象。框架通过命令目标对象的标准序列传送命令,而在这些对象中,有一个应具有该命令的处理程序。每一个命令目标对象检查其消息映射,查看是否能处理传入的消息。
不同的命令目标类在不同的时间检查各自的消息映射。通常,类将命令传送到某些其他对象,给它们首先处理命令的机会。如果这些对象都不能处理此命令,则原始类检查自己的消息映射。然后,如果它自己也无法提供处理程序,则可能将此命令传送到更多的命令目标。下表标准命令路由显示了每一种类构造该序列的方法。命令目标传送命令的一般顺序是:
- 传送到当前活动的子命令目标对象。
- 传送到本身。
- 传送到其他命令目标。
该传送机制的成本多高?与处理程序为响应命令所做的工作相比,传送的成本较低。记住只有当用户与用户界面对象交互时框架才生成命令。
当此类型的对象收到命令时... | 按此顺序为其本身以及其他命令目标对象提供处理命令的机会: |
---|---|
MDI 框架窗口 (CMDIFrameWnd) |
|
文档框架窗口 (CFrameWnd, CMDIChildWnd) |
|
视图 |
|
文档 |
|
对话框 |
|
上表第二列中的编号项提到其他对象(如文档)的地方,请参见第一列中的相应项。例如,当在第二列中读到视图将命令转发到其文档时,请参见第一列中的“文档”项以进一步跟踪传送。
命令传送示例
为举例说明,请看 MDI 应用程序“编辑”菜单中的“全部清除”菜单项的命令消息。假定该命令的处理函数恰好是应用程序文档类的成员函数。以下描述当用户选择此菜单项后该命令是如何到达其处理程序的:
- 首先,主框架窗口接收到命令消息。
- 主 MDI 框架窗口为当前活动的 MDI 子窗口提供处理该命令的机会。
- 在检查自己的消息映射之前,MDI 子框架窗口的标准路由为其视图提供处理该命令的机会。
- 视图首先检查自己的消息映射,如果未发现处理程序,则将该命令传送到关联的文档。
- 该文档检查自己的消息映射并找到处理程序。调用该文档成员函数,然后传送停止。
如果此文档没有处理程序,则会将命令传送到其文档模板。然后命令将返回到视图,再返回到框架窗口。最后,框架窗口检查自己的消息映射。如果此次检查再次失败,则命令将被传送回主 MDI 框架窗口,再传送回应用程序对象,这是未经处理的命令的最终目的地。
OnCmdMsg 处理程序
为完成命令传送过程,序列中的每一个命令目标依次调用下一个命令目标的 OnCmdMsg 成员函数。命令目标使用 OnCmdMsg 确定是否能处理某一命令,如不能处理,则将命令传送到下一个命令目标。
每一个命令目标类可以重写 OnCmdMsg 成员函数。通过重写,每一类将命令传送到下一个特定目标。例如,框架窗口总是将命令传送到其当前子窗口或视图,如表标准命令路由所示。
OnCmdMsg 的默认 CCmdTarget 实现使用命令目标类的消息映射,为接收到的每一个命令消息搜索处理函数。其方法与搜索标准消息的方法相同。如果发现匹配项,则调用此处理程序。框架搜索消息映射的方式中对消息映射搜索进行了解释。
重写标准命令传送
在很少情况下,必须实现标准框架传送的某些变体,这时可以重写传送。其概念是重写一个或多个类中的 OnCmdMsg 来更改这些类中的传送。按下列步骤执行:
- 在打断顺序以传递到非默认对象的类中。
- 在新的非默认对象中或在可能将命令依次传送到的命令目标中。
如果在路由中插入某个新对象,则新对象的类必须是命令目标类。在 OnCmdMsg 的重写版本中,确保调用正在重写的版本。请在“MFC 参考”中参阅 CCmdTarget 类的 OnCmdMsg 成员函数,并在所提供的源代码中参阅 CView 和 CDocument 这些类中的版本以获得示例。