📄 05o015.htm
字号:
定义的消息,这样通过在相应层次上安排消息响应函数就可以实现自己的特殊需<br>
要。比如如果我们要在特定的时间间隔内通知所有数据输出视口重新取得新数据,<br>
要依靠菜单命令和按钮命令实现不够理想,比较理想的解决办法是采用定时器事件<br>
进行特定的计算操作,操作完成后再采用SendMessage发送自己的特定消息,只有当<br>
这一消息得到处理后才会返回主控程序进行下一时间计算。通过在文档层次上安排<br>
对消息的响应取得最新计算数据,而后通过UpdateAllViews()成员函数来通知所有<br>
相关视口更新数据的显示。视口通过重载OnUpdate()成员函数就可以实现特定数据<br>
的更新显示。<br>
如果用户能够熟练使用SendMessage()函数和PostMessage()函数,那么要发送自定<br>
义消息并不难,通常有两种选择,其一是发送WM_COMMAND消息,通过消息的WORD
<br>
wParam参数传递用户的命令ID,举例如下:<br>
SendMessage(WM_COMMAND,IDC_GETDATA,0); //MFC主框架发送<br>
然后在文档层次上安排消息映射入口:<br>
ON_COMMAND(IDC_GETDATA, OnGetData)<br>
同时在文档类中实现OnGetData()函数:<br>
void CSimuDoc::OnGetData()<br>
{<br>
TRACE("Now in SimuDoc,From OnGetData\n");<br>
UpdateAllViews(NULL);<br>
}<br>
注意在上中的消息映射入口需要用户手工加入,Visual
C++提供的ClassWizard并不<br>
能替用户完成这一工作。上中例子没有使用PostMessage函数而使用SendMessage函<br>
数的原因是利用了SendMessage函数的特点,即它只有发送消息得到适当处理后方才<br>
返回,这样有助于程序控制。<br>
另一种发送自定义消息的办法是直接发送命令ID,在控制层次上采用ON_MESSAGE来<br>
实现消息映射入口,注意这时的命令控制函数的原型根据Windows本身消息处理的规<br>
定必须如下:<br>
afx_msg LONG OnCaculationOnce(WPARAM wParam,LPARAM
lParam);<br>
相对来讲,这种机制不如上述机制简单,也就不再赘述。<br>
七、使用不带文挡-视结构的MFC应用<br>
文档-视结构的功能是非常强大的,可以适合于大多数应用程序,但是有时我们只需<br>
要非常简单的程序,为了减少最终可执行文件尺寸和提高运行速度,我们没有必要<br>
使用文挡-视结构,典型的有简单SDI应用和基于对话框的应用。<br>
1、简单SDI应用<br>
此时只需要使用CWinApp和CFrameWnd两个类就完全可以了。由于CWinApp类封装了<br>
WinMain函数和消息处理循环,因此任何使用MFC进行编程的程序都不能脱离开该<br>
类。实际上使用CWinApp类非常简单,主要是派生一个用户自己的应用类,如<br>
CMyApp,然后只需重载CWinApp类的InitInstance()函数:<br>
<br>
BOOL CMyApp::InitInstance()<br>
{<br>
m_pMainWnd=new CMainFrame();<br>
ASSERT(m_pMainWnd!=NULL); //error checking only<br>
m_pMainWnd->ShowWindow(m_nCmdShow);<br>
m_pMainWnd->UpdateWindow();<br>
return TRUE;<br>
}<br>
至于所需要的主框架类,则可以直接使用ClassWizard实用程序生成,该类的头文件<br>
与实现代码可以与CMyApp类的头文件和实现代码放在一起。注意,这里由一个技<br>
巧,由于ClassWizard的使用需要有相应的CLW文件存在,而收工建代码时没有对应<br>
的CLW文件,因此不能直接使用,解决办法是进入App
Studio实用工具后使用<br>
ClassWizard,此时系统会发觉不存在相应的CLW文件,系统将提示你重建CLW文件并<br>
弹出相应对话框,这时候你不需要选择任何文件就直接选择OK按钮,这样系统将为<br>
你产生一个空的CLW文件,这样就可以使用ClassWizard实用工具了。为了将CWinApp<br>
和CFrameWnd的派生类有机地结合在一起,只需在CFrameWnd派生类的构造函数中进<br>
行窗口创建即可。典型代码如下:<br>
CMainFrame::CMainFrame()<br>
{<br>
Create(NULL,"DDE Client
Application",WS_OVERLAPPEDWINDOW,rectDefault,<br>
NULL,MAKEINTRESOURCE(IDR_MAINFRAME));<br>
}<br>
采用ClassWizard实用程序生成相关类代码后,所有的类的其它实现和维护就同普通<br>
由AppWizard实用程序产生的代码一样了。<br>
2、基于对话框的程序<br>
有些主要用于数据的输入和输出等的应用在使用时没有必要改变窗口大小,典型的<br>
如各种联机注册程序,这些使用对话框作为应用的主界面就足够了,而且开发此类<br>
应用具有方便快捷的特点,代码也比较短小,如果直接采用各种控制类生成所需要<br>
的控制就特别麻烦。在Visual C++ 4.x版本中使用AppWizard就可以直接生成基于对<br>
话框的应用。在Visual 1.x中没有此功能,因此这类应用需要程序员自己实现。<br>
实际上使用MFC实现基于对话框的应用非常简单,同样只使用两个MFC类作为基类,<br>
这两个类为CWinApp类和CDialog类。所使用的对话框主界面同样可以先用App
<br>
Studio编辑对话框界面,再使用ClassWizard产生相应代码框架,然后修改CMyApp类<br>
的声明,增加一个该对话框类的成员变量m_Mydlg,最后修改CMyApp类的<br>
InitInstance()函数如下:<br>
BOOL CMyApp::InitInstance()<br>
{<br>
m_Mydlg.DoModal();<br>
return TRUE;<br>
}<br>
八、MFC应用的人工优化<br>
使用C/C++编写Windows程序的优点就是灵活高效,运行速度快,Visual
C++编译器<br>
本身的优化工作相当出色,但这并不等于不需要进行适当的人工优化,为了提高程<br>
序的运行速度,程序员可以从以下几方面努力:<br>
1) 减少不必要的重复显示<br>
相对来讲,Windows的GDI操作是比较慢的,因此在程序中我们应该尽可能地控制整<br>
个视口的显示和更新,如果前后两此数据不发生变化,那么就不要重新进行视口的<br>
GDI图形操作,尤其对于背景图显示时非万不得已时不要重绘,同时不要经常五必要<br>
的刷新整个窗口。<br>
2) 在视口极小化时不要进行更新屏幕操作<br>
在窗口处于极小化时没有必要继续进行视口更新工作,这样可以显著提高速度。为<br>
此需要在子窗口一级捕获上述信息(视口不能捕获该类信息),再在视口中进行相<br>
应操作。如下代码片段所示:<br>
首先在子窗口类中添加如下程序段:<br>
void CMyChild::OnSysCommand(UINT nID,LPARAM lparam)<br>
{<br>
CMDIChildWnd::OnSysCommand(nID,lparam);<br>
if(nID==SC_MINIMIZE){<br>
RedrawFlag=0;<br>
}<br>
else<br>
RedrawFlag=1;<br>
}<br>
再在视口更新时中修改如下:<br>
void CMyChart::OnUpdate( CView* pSender, LPARAM lHint,
CObject* pHint )<br>
{<br>
if(pChild->RedrawFlag)<br>
{<br>
InvalidateRect(&r,FALSE);<br>
TRACE("Now In CMyChart::OnUpdate\n");<br>
}<br>
}<br>
至于上中pChild指针可以在视口创建的例程中获取:<br>
pChild=(CMyChild*)GetParent();<br>
3) 使用永久性的资源<br>
在频繁进行GDI输出的视口中,如在监控软件中常常使用的趋势图显示和棒图显示等<br>
等,应该考虑在类层次上建立频繁使用的每种画笔和刷子,这可以避免频繁的在堆<br>
中创建和删除GDI对象,从而提高速度。<br>
4) 使用自有设备描述句柄<br>
亦即在创建视口时通过指定WM_OWNDC风格来拥有自己的显示设备句柄,这虽然会多<br>
消耗一些内存,一个DC大约占800字节的内存,但是这避免了每次进行GDI操作前创<br>
建并合理初始化显示设备句柄这些重复操作。特别是要自定义坐标系统和使用特殊<br>
字体的视口这一点尤其重要。在16M机器日益普遍的今天为了节约一点点内存而降低<br>
速度的做法并不可取。<br>
5) 优化编译时指定/G3选项和/FPix87选项<br>
/G3选项将强迫编译器使用386处理器的处理代码,使用嵌入式协处理器指令对那些<br>
频繁进行浮点运算的程序很有帮助。采用这两种编译开关虽然提高了对用户机型的<br>
要求,但在386逐渐被淘汰,486市场大幅度萎缩,586市场日益普及的今天上述问题<br>
已经不再成为问题了。<br>
九、结束语<br>
总体上讲,使用Visual C++和MFC类库进行Windows编程是非常方便的,本文中所提<br>
到的一些看法只代表本人的观点,经验也只是笔者根据近年使用MFC进行Windows编<br>
程的总结,在此写出来是希望对那些使用VC和MFC进行Windows编程的同行有所帮<br>
助,如有不同看法欢迎与笔者联系讨论。<br>
十、参考文献:<br>
[1]. David J.Kruglinski ,Visual C++技术内幕,清华大学出版社,1995<br>
[2]. 郑雪明,Visual C++基础类库参考大全,学苑出版社,1994<br>
[3]. B.R. Overland,Visual C++程序设计精髓,科学出版社,1995<br>
[4]. Mike Klein,Windows程序员使用指南--DLL和内存管理,清华大学出版社,<br>
1995<br>
[5]. Richard Wilton,Microsoft Windows软件开发环境与技术,
清华大学出版<br>
社,1993<br>
[6]. 芶建兵,倪维斗,Windows下网络DDE的使用,电子与电脑,1997.2<br>
<br>
作者联系地址:清华大学热能系动控教研组<br>
联系电话:(010)-62781739<br>
BP:68213388-50610
</td>
</tr>
<tr>
<td width="100%" height="12" class="font" colspan="2">
</td>
</tr>
<tr>
<td width="100%" height="6" class="font" colspan="2">
</td>
</tr>
<tr>
<td width="100%" height="8" class="font" colspan="2">
</td>
</tr>
<tr>
<td width="100%" height="17" class="font" colspan="2"></td>
</tr>
</table>
</div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -