当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 如何发送命令到文档对象

VC++
为你的程序换个皮肤
程序启动画面
实现标题条的显示与隐藏
在EVC3.0中创建MDI程序
无模式对话框的创建与使用
界面专家简介
再谈客户区对话框拖动操作
Windows 2000/XP中对窗口进行透明化
用线程实现动态改变图标
不规则对话框的又一实现
用SkinMagic工具包创建换皮肤程序
最简单的界面增强库EasySkin
在VC++.net中制作启动屏幕的新方法
椭圆窗体的实现
编写多文档应用程序
SkinLoad程序界面换肤工具
如何在标题栏中显示动态图标
自绘对话框
VC启动窗口画面制作方法研究
MFC应用程序中指针的使用

VC++ 中的 如何发送命令到文档对象


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 195 ::
收藏到网摘: n/a

如何发送命令到文档对象
赵湘宁
本文范例代码:Doctime1.zip Doctime2.zip
问题:
我编了一个类似Windows 2000 上性能监视器的程序。在这个程序中,我创建了一个文档对象和几个视图。文档对象负责有规律地采集数据,然后通知相关的视图以不同的格式显示这些数据。文档对象为了有规律地采集数据,它需要一个定时(time)事件。但是,文档不是一个基于窗口的对象,所以它没有这样的定时事件。我权衡了三种解决方案:
  1. 在其中的一个视图中创建定时器。当事件发生时通知文档对象获取数据。
  2. 为每一个文档(或在每个文档内)创建一个单独的线程,以便这个线程能有规律地创建时间事件。
  3. 在CMainFrame中创建一个定时器并从中调用文档函数
这三种方法我都不满意。能否给出一种更好的解决方案?
解答:
在你列出的解决方案中,将定时器放入视图是最糟的想法,因为那样的话你就得为每个视图建一个定时器,你应该将定时器视为一种相对有限的资源(这一点在过去尤其如此,现在这个问题考虑得较少)。创建单独的线程对于定时器这样简单的东西又有牛刀弑鸡之嫌。线程无疑使事情复杂化。那么还有第三个方案:在主框架中创建定时器并从中调用文档函数。我会告诉你如何用这个方案直截了当地实现所要的功能,然后我还会展示另外一种你没有想到的方法。
假设你不愿意用第三种方案的原因是它需要从主框架中调用文档,这样做有点丑陋。(为什么框架要掺乎到文档中去呢?)但有一种直截了当的方法来做,不用直接调用CMyDoc::DoTimerThing,你可以将WM_TIMER消息转换成一个ID为ID_APPTIMER的WM_COMMAND,并用通常的方式广播这个命令以便文档能用ON_COMMAND处理它,文档无法处理所有的窗口消息,但它们可以处理WM_COMMAND。事实上,这是MFC命令处理例程体系结构的主要创新之一,它使非窗口对象可以处理命令。所以这样看来,你要做的事情就是:
//CMainFrame::OnTimer(...){ SendMessage(WM_COMMAND, ID_APPTIMER);}//
也就是说,当主框架得到定时器信号的同时,也向自己发送了一个ID_APPTIMER命令。MFC会将这个命令发送到系统,任何具有ON_COMMAND处理器并能处理ID_APPTIMER命令的对象都可以处理这个事件。你可以用ON_COMMAND_EX来对付多个对象处理相同事件的情况。
这样做虽然能行得通,但有一个问题。MFC只把命令发送到活动视图/文档。如果其它文档处于打开状态,但没有被激活,则它们不会得到WM_COMMAND消息。虽然你可以修改程序把命令广播到非激活文档,但那样的话,像“文件|保存”这样普通的命令会被发送到所有的文档——很狼狈!因为我们只需要定时器命令到达所有文档。怎么办呢?如何发送WM_COMMAND到所有的文档?
MFC将命令发送到文档这样的非窗口对象,其方法是通过虚函数CCmdTarget::OnCmdMsg来实现的。当窗口获得WM_COMMAND消息时,它要运行许多CWnd代码和虚函数。最终,控制到达CWnd::OnCommand,由它调用OnCmdMsg。
// in CWnd::OnCommandOnCmdMsg(nID, CN_COMMAND, NULL, NULL);//
这里,nID是命令ID,编码CN_COMMAND告诉OnCmdMsg这是个命令事件——与更新UI事件相对(此时编码应该是CN_UPDATE_COMMAND_UI)。其它参数对于CN_COMMAND没用。
因此,如果你有一个文档指针,并想要发送一个命令到该文档,那么你要做的全部工作就是调用:
//pDoc->OnCmdM