命令传递(Command routing)

消息如果是仅仅从派生类流向父类,那就非常简单了。然而MFC用来处理消息的C++类,并不是单线发展的。document/view也具有处理消息的能力。因此,消息应该有横向流动的机会。

MFC对消息循环的规定为:

1:若是一般的windows消息(WM_xx)则一定是由派生类流向基类。

2:如果是WM_COMMAND消息,就非常复杂了。要区分接受者的类型:

1:接受者若为Frame窗口:处理次序为:View-> Frame窗口本身->CWinApp类。

2:接受者若为View :处理次序为:View本身->Document;

3:接受者若为Document:处理次序为:Document本身->Document template

因此,接下来我们的任务就是仿真以上的消息传递路线。

以下为需要添加的函数:

全局函数AfxWndProc,它是整个消息循环的起始点,本来应该在CWinThread::Run中被调用,每调用一次就推送一个消息。模拟windows的disPatch函数。

LRESULT AfxWndPro(HWND hWnd,UINT nMsg,WPARAM

wParam,LPARAM lParam,CWnd *pWnd)

{

cout<<"AfxWndProc()"<<endl;

return  AfxCallWndProc (pWnd,hWnd,nMsg,wParam,lParam);

}

LRESULT AfxCallWndProc(CWnd*pWnd,HWND hWnd,UINT nMsg,

WPARAM wParam,LPARAM lParam)

{

cout<<"AfxCallWndProc"<<endl;

LRESULT lResult=pWnd->windowProc(nMsg,wParam,lParam);

return lResult;

}

全局函数AfxCallWndProc用于调用接受消息的类的消息处理函数。pWnd->WindowProc调用哪个函数,取决于pWnd指向的对象类型。

如果pWnd指向CMyFrameWnd对象,则调用CFrameWnd::WindowProc。因为CFrameWnd斌没有改写WindowProc,因此调用的是CWnd::WindowProc。。

如果pWnd指向CMyView对象,那么调用CView::windowProc。而CMyView没有改写WIndowProc所以调用的是CWnd::WindowProc。

在CWnd::windowProc中,首先判断消息是否为WM_COMMAND消息,

如不是,则传递给父类进行处理。

如果是WM_COMMAND消息,CWnd::windowProc调用OnCommand。此函数为虚函数。有以下几种情况:

1:如果this指向CMyFrameWnd对象,则调用的是CFrameWnd::OnComamnd。

2:如果this指向CMyView对象,那么调用的是CView::OnCommand。因为CView并没有改写OnComamnd所以调用的是CWnd::OnCommand。

bool CFrameWnd::OnComamnd(WPARAM wParam,LPARAM lParam)

{

cout<<"CFrameWnd::OnCommand()"<<endl;

return CWnd::OnCommand(wParam,lParam);

}

bool CWnd::OnComamnd(WPARAM wParam,LPARAM lParam)

{

cout<<"CWnd::OnComamnd()"<<endl;

return OnCmdMsg(0,0);

}

OnCmdMsg仍然是虚函数,

1:如果this指向CMyFrameWnd对象,那么调用的是CFrameWnd::OnCmdMsg。

2:如果this指向CMyView对象,则调用CView::OnCmdMsg。

3:如果this指向CMyDoc对象,则调用CDocument::OnCmdMsg。

4:如果this指向CM与WinApp对象,则调用CWinApp::  nCmdMsg。因为CWinApp没有改写OnCmdMsg因此调用的是CCmdTarget::OnCmdMsg。

Bool CFrameWnd::OnCmdMsg(UINT nID,int nCode)
{

cout<<"CFrameWnd::OnCmdMsg()"<<endl;

CView*pView=GetActiveView();

if(pView->OnCmdMsg(nID,nCode))//处理则返回否则继续传递。

return true;

if(CWnd::OnCmdMsg(nID,nCode))

return true;

CWinApp*pApp=AfxGetApp();

if(pApp->OnCmdMsg(nID,nCode)

return true;

return fasle;

}

bool CView::OnCmdMsg(UINT nID,int nCode)

{

cout<<"CView::OnCmdMsg()"<<endl;

if(CWnd::OnCmdMsg(nID,nCode))

return true;

bool bHandled=false;

bHandled=m_pDocument->OnCmdMsg(nID,nCode);

return bHandled;

}

Bool CDocument::OnCmdMsg(UINT nID,int nCode)

{

cout<<"CDocument::OnCmdMsg()"<<endl;

if(CCmdTarget::OnCmdMsg(nID,nCode))

return true;

return false;

}

真正的消息传递路径是从OnCmdMsg开始的。在每个类的OnCmdMsg函数中,会调用其他类的OnCmdMsg函数,从而决定每个消息的传递路径。

如果消息在前一个OnCmdMsg中被处理,就不会继续传递。如果没有被处理,则会继续沿着路径传递下去。无论如何,最终消息的比对是在CCmdTarget类中进行的,只是调用GetMessageMap的this指针不同,会决定调用哪个类的消息映射表。理解这一点很重要!!!

bool CCmdTarget::OnCmdMsg(UINT nID,int nCode)

{

cout<<"CCmdTarget::OnCmdMsg()"<<endl;

for(pMessageMap=GetMessageMap();pMessageMap;

pMessageMap=pMessageMap->pBaseMessageMap()

{

If(找到)

//执行消息处理函数。

}

}

深入浅出MFC学习笔记(第三章:MFC六大关键技术之仿真:命令传递) .相关推荐

  1. 《Go语言圣经》学习笔记 第三章 基础数据类型

    <Go语言圣经>学习笔记 第三章 基础数据类型 目录 整型 浮点数 复数 布尔型 字符串 常量 注:学习<Go语言圣经>笔记,PDF点击下载,建议看书. Go语言小白学习笔记, ...

  2. 机器人导论(第四版)学习笔记——第三章

    机器人导论(第四版)学习笔记--第三章 3 操作臂运动学 3.1 引言 3.2 连杆的描述 3.3 连杆连接的描述 3.4 连杆坐标系的定义 3.5 操作臂运动学 3.6 驱动空间.关节空间和笛卡尔空 ...

  3. 2022 最新 Android 基础教程,从开发入门到项目实战【b站动脑学院】学习笔记——第三章:简单控件

    第 3 章 简单控件 本章介绍了App开发常见的几类简单控件的用法,主要包括:显示文字的文本视图.容纳视图的常用布局.响应点击的按钮控件.显示图片的图像视图等.然后结合本章所学的知识,演示了一个实战项 ...

  4. Win32学习笔记 第三章 HelloWin 选择自 villager 的 Blog

    Win32学习笔记 作者: 姜学哲(netsail0@163.net) 教材: Windows程序设计(第五版)北京大学出版社  [美]Charles Petzold 著  北京博彦科技发展有限公司 ...

  5. ros2 Navigation 学习笔记 第三章(the construct 网站)

    第三章 如何在环境中给机器人定位 序言 本章包括: 机器人定位的意义(即需要知道它对于环境中的位置和方向) 如何在ROS2中用AMCL定位 如何设置机器人的初始位置(手动.自动与使用ROS API) ...

  6. 信号与系统学习笔记 第三章

    第三章 周期信号的傅里叶级数表示 下面将讨论信号与线性时不变系统的另一种表示,讨论的出发点仍是将信号表示成一组基本信号的线性组合.这是因为,将信号表示成基本信号的线性组合是有利的,如果基本信号具有一下 ...

  7. 仿生学导论学习笔记——第三章

    第三章 仿生学基本要素 3.1 仿生需求 3.1.1 需求驱动 3.1.1.1 生存需求 3.1.1.2 健康需求 3.1.1.3 军事需求 3.1.1.4 发展需求 3.1.1.5 精神需求 3.1 ...

  8. 计算机网络学习笔记——第三章:数据链路层

    目录 第三章:数据链路层 3.1 数据链路层功能概述 3.2 封装成帧和透明传输 3.3 差错控制 3.3.1 检错编码 3.3.2 纠错编码 3.4 流量控制与可靠传输机制 3.4.1 流量控制.可 ...

  9. JavaScript高级程序设计红宝书学习笔记第三章基本概念

    第三章 基本概念 本章内容 语法 数据类型 操作符 语句 函数 3.1 语法 3.1.1 区分大小写,ECMAScript中的一切(变量.函数名和操作符)都区分大小写. 3.1.2 标识符 标识符:变 ...

  10. [吴功宜]计算机网络学习笔记--第三章 数据链路层

    教材:计算机网络(第四版) 作者:吴功宜 吴英 出版社:清华大学 第三章 数据链路层 3.1 差错产生的原因与差错控制方法 物理线路:由传输介质与通信设备组成 设计数据链路层的主要目的:在有差错的物理 ...

最新文章

  1. 南昌计算机专业好的专科,2021年南昌计算机专业学校好不好
  2. ZVM – 记VMP保护代码还原工程
  3. 我用着不舒服的东西, 就TM是不合理的东西!!!
  4. 棍子节快乐~ 顺便转一篇weka源码分析解析~【转自weka中文网】
  5. linux笔记_20150825_linux下的软件工具唠叨下
  6. 如何将markdown转换为wxml
  7. 对今天下午的工作内容的反思
  8. 今晚直播丨Oracle数据库SQL执行计划的取得和解析
  9. java做法_Java方法
  10. 黑莓 QNX 被曝严重的 BadAlloc 漏洞 影响数百万汽车和医疗设备
  11. edittext禁止换行符但能自动换行简书_利用 subfinder 让群辉 NAS 实现自动下载字幕...
  12. 你不知道的Bitmap
  13. 生成指定范围的随机数_JAVA 获取随机数的方式以及应用案例
  14. SC;FC;LC;光纤接口介绍
  15. html三角形下拉列表,select自定义小三角样式代码(实用总结)
  16. 2 errors and 0 warnings potentially fixable with the `--fix` option,vue-cli3中eslint详解(转载)
  17. C++ OJ习题练习(九)定义哺乳动物类Mammal和Dog类
  18. systemd服务详解
  19. Golang 字符串拼接
  20. 华硕z170-p+英特尔i7-6700k+16GB黑苹果EFI引导文件

热门文章

  1. 关于身份证OCR识别,你知道多少?
  2. “做教练”之硬笔书法
  3. MVC架构下,使用NPOI读取.DOCX文档中表格的内容
  4. 北理乐学C语言寻找特殊偶数,北理乐学C语言答案-最新教程.doc
  5. SAP中检查货币代码
  6. 专业的PRD撰写模板
  7. python前端用什么写_Python 竟然也可以写网页前端了
  8. linux rzsz安装
  9. 景观设计常用的SU插件(Sketchup)
  10. 归并排序java代码实现