解决子窗口(视图)截获父窗口消息的2个办法(MFC)
2015-08-25 15:48
393 查看
这样的需求:
1.如果想在CView里面截获发给子框架Frame的消息怎么办?
2.假如子窗口拆分视图了, 那还得细分, 是所有视图都想截获消息,还是某个特定的视图想截获某个特定的消息.
对于需求1:
办法1.是重载子框架Frame的WindowProc(UINT message, WPARAM wParam, LPARAM lParam)函数,将自定义的消息(大于WM_USER)转发给自己的视图,可以SendMessage
办法2.是在视图中利用钩子来截获父窗口消息,即SubclassWindow或SetWindowLong方法,具体做法如下:
SubclassWindow:
1.添加一个CWnd窗口子类MessageWnd,在View中定义一个类MessageWnd的成员m_messageWnd用来接收消息;
2.View::OnCreate中 m_messageWnd.SubclassWindow(GetParentFrame()->GetSafeHwnd());
3.View::OnDestroy()中 m_messageWnd.UnsubclassWindow();
SetWindowLong:
其实MFC提供的SubclassWindow并不是很适用于这个场合, SubclassWindow很适用的一个例子是: CEdit只能输入特 定的字符如只能a-z, 此时添加一个类,在OnChar中把非a-z的字符都忽略不处理. 总结一下大概就是说如果原来已经实现该消息的处理方法,但现在需要新的处理方法,这时用SubclassWindow合适. 而在这要定义一个窗口类,在其消息函数截获到消息后还得把消息返回给View来处理. 那么其实用SetWindowLong将更加简单:
1.在View中定义一个窗口处理函数NewWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam), 此函数内将截获到消息.若其他消息则尽量让原窗口函数处理
OnCreate注册新的处理函数 m_oldWndProc = (WNDPROC)SetWindowLong(GetParentFrame()->GetSafeHwnd(),GWL_WNDPROC,(LONG)NewWndProc);
3.不能忘了,在OnDestroy时换成原来的处理函数SetWindowLong(GetParentFrame()->GetSafeHwnd(),GWL_WNDPROC,(LONG)m_oldWndProc);
此外网上也有现成的工具类, 这个工具类提供了不错的接口Hook/Unhook: http://www.cppblog.com/qinqing1984/archive/2011/12/11/161915.aspx.
对于需求2
1.若所有视图都想截获消息,那用办法1较方便.一次性搞定.
2.若个别视图想截获消息,那用办法2较适合.
题外话: 对于上述需求,为何不直接用文档来更新视图?
这个问题也曾考虑过. 先说一下软件情况: 有一个工作线程不停的采集数据并交给文档,文档根据不同类型采取对应方式来更新视图, 直接用UpdateAllView的话对于区分类型做不到. 如果有好的建议欢迎回复.
1.如果想在CView里面截获发给子框架Frame的消息怎么办?
2.假如子窗口拆分视图了, 那还得细分, 是所有视图都想截获消息,还是某个特定的视图想截获某个特定的消息.
对于需求1:
办法1.是重载子框架Frame的WindowProc(UINT message, WPARAM wParam, LPARAM lParam)函数,将自定义的消息(大于WM_USER)转发给自己的视图,可以SendMessage
办法2.是在视图中利用钩子来截获父窗口消息,即SubclassWindow或SetWindowLong方法,具体做法如下:
SubclassWindow:
1.添加一个CWnd窗口子类MessageWnd,在View中定义一个类MessageWnd的成员m_messageWnd用来接收消息;
2.View::OnCreate中 m_messageWnd.SubclassWindow(GetParentFrame()->GetSafeHwnd());
3.View::OnDestroy()中 m_messageWnd.UnsubclassWindow();
SetWindowLong:
其实MFC提供的SubclassWindow并不是很适用于这个场合, SubclassWindow很适用的一个例子是: CEdit只能输入特 定的字符如只能a-z, 此时添加一个类,在OnChar中把非a-z的字符都忽略不处理. 总结一下大概就是说如果原来已经实现该消息的处理方法,但现在需要新的处理方法,这时用SubclassWindow合适. 而在这要定义一个窗口类,在其消息函数截获到消息后还得把消息返回给View来处理. 那么其实用SetWindowLong将更加简单:
1.在View中定义一个窗口处理函数NewWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam), 此函数内将截获到消息.若其他消息则尽量让原窗口函数处理
OnCreate注册新的处理函数 m_oldWndProc = (WNDPROC)SetWindowLong(GetParentFrame()->GetSafeHwnd(),GWL_WNDPROC,(LONG)NewWndProc);
3.不能忘了,在OnDestroy时换成原来的处理函数SetWindowLong(GetParentFrame()->GetSafeHwnd(),GWL_WNDPROC,(LONG)m_oldWndProc);
此外网上也有现成的工具类, 这个工具类提供了不错的接口Hook/Unhook: http://www.cppblog.com/qinqing1984/archive/2011/12/11/161915.aspx.
对于需求2
1.若所有视图都想截获消息,那用办法1较方便.一次性搞定.
2.若个别视图想截获消息,那用办法2较适合.
题外话: 对于上述需求,为何不直接用文档来更新视图?
这个问题也曾考虑过. 先说一下软件情况: 有一个工作线程不停的采集数据并交给文档,文档根据不同类型采取对应方式来更新视图, 直接用UpdateAllView的话对于区分类型做不到. 如果有好的建议欢迎回复.
相关文章推荐
- 回顾交互设计史:回归人性,重拾质朴
- 【水题】【SCOI 2005】【bzoj 1088】扫雷Mine
- 华为上机试题6(时间相加)
- 使用Beautifulsoup去除特定标签
- Spark修炼之道(基础篇)——Linux大数据开发基础:第五节:vi、vim编辑器(一)
- 【数据结构&&等差数列】KMP简介和算法的实现(c++ && java)
- android沉浸式状态栏设置(4.4以上版本)
- Ubuntu12.04重复输入密码也进不去密码
- 零零碎碎写的脚本(六)创建磁盘分区并自动挂载
- Smarty模板的逻辑运算符号稍微做一下总结
- jsp使用ajax技术与后台通信
- spring 框架的xml文件如何读取properties文件数据
- Zabbix微信企业订阅号报警设置 推荐
- 纯手写的 javascript 万年历控件,复制代码就可以用
- 记录与linux的每次邂逅__小白关于mysql脚本安装事前事后的一点感想
- 百度定位Sdk 162错误解决方法之Android Studio
- Visual Studio Compile and Link error LNK2005
- git使用GPG进行签名
- POJ - 2524 Ubiquitous Religions(简单并查集)
- 迭代器——对象行为模式