快速理解MFC代码
MFC程序
MFC是微软基础类库的简称,是微软公司实现的一个c++类库,主要封装了大部分的windows API函数,另外,MFC还是一个框架,在vc++里新建一个MFC的工程,开发环境会自动帮你产生许多文件,同时它使用了mfcxx.dll。xx是版本,它封装了mfc内核,所以你在你的代码看不到原本的SDK编程中的消息循环等等东西,因为MFC框架帮你封装好了,这样你就可以专心的考虑你程序的逻辑,而不是这些每次编程都要重复的东西。
字符编码:Unicode和多字节
MFC有两种编码方式,Unicode和多字节并且可以设置切换。Visual C++6.0用的是多字节编码;Visual Studio 2010 默认使用的是Unicode编码,所以在代码移植的时候经常会提示很多编码方式相关的错误,解决方法是将Unicode编码改为多字节编码即可。这里提示一点,使用 _T 宏有条件地编写字符串的代码,使之可移植到 Unicode。
框架代码文件的结构
一个完整的应用一般由四个类组成:CWinApp应用类,CFrameWnd窗口框架类,CDocument文档类,CView视类。
主要有4个部分组成:
1) 资源文件Resource.h:主要是定义资源的ID。
2) 预编译文件:可以用来解决头文件包含冲突的问题,定义一些需要全局性包含的文件。
3) 应用程序类对应文件:项目名称是TestOne,对应类名为CTestOneApp。
4) 对话框类:项目名称是TestOne,对应类名为CTestOneDlg。
应用程序类
MFC定义了一个应用程序基类CWinApp,所有基于MFC的应用程序都会继承这个类。
其中InitInstance()函数可以看作MFC程序的入口函数,main函数隐藏在这个函数中。在实际的开发中,一般不需要对这个类进行操作,但如果需要在建立主对话框之前处理一些数据或者准备工作,那么就可以把代码添加到这个函数中,主对话框显示之前。
这里有两个比较个典型的应用。
1)启动界面之前弹出登陆界面,需要正确输入用户名和密码才能弹出主界面;
2)启动界面之前,弹出一个项目配置界面,例如操作员,设备编号,项目名称,批次等信息,同时这些信息需要传递到主界面中,主界面根据项目和批次决定某种操作方式。
上面两个应用在实际的项目开发中很常见,需求比较普遍。
第一个需求不涉及数据传递,可以在代码中将用户名和密码固定,如果输入的结果与设定的结果一致,那么就开放此软件的使用权限;稍微复杂一点的,可以比较输入的结果与数据库中存储的用户名和密码是否匹配,如果匹配,才开放此软件的使用权限;再稍微复杂一点的,还可以将界面输入结果与服务器中的信息比较,查看当前用户是否有此软件的使用权限,当然这个还涉及到服务端的处理,与网络通信有关。
第二个需求涉及不同对话框之间的数据传递,应用也比较广泛。
对话框类
MFC主对话框类CTestOneDlg继承CDialogEx类,CDialogEx又继承CDialog类,对话框类负责与用户交互,处理用户消息,接受用户输入。
在这个类中:
1) 控件与数据关联,可以简单地交给框架来实现;
2) 在MFC框架上开发主要是针对消息处理机制。
MFC字符串操作类CString
CString是用来表示可变长度的字符串的类。在MFC中,这个类的使用频率非常高。CString是MFC经过封装后特有的一种字符串类型,较string或iftream或oftream的字符串有更多明显的优点,如使用CString可不指明内存大小,CString会根据需要自行分配,除此之外还可以对字符串进行拼接操作。
忠告:
开发需要读写文件的应用程序并且有简单的输入和输出可以利用单文档视结构。
开发注重交互的应用程序可以使用对话框为基础的窗口。
尽量避免使用多文档多视结构。
尽量避免多重继承并尽量减少一个类中封装过多的功能。
在要求在多个文档间传递数据时使用多文档视结构。
在对多文档要求不强烈时尽量避免多文档视结构,可以利用分隔条产生单文档多视结构
MFC视图和窗口的基本概念
视类窗口
视类窗口是指程序运行后,显示信息的那一部分。对应的类是CXXXView(XXX表示项目名称)类,CXXXView类是派生于CView类,而CView类又派生于CWnd类。视图类CView,拥有窗口的客户区域,负责显示文档数据,接受用户的输入,提供文档与用户的通信。视类窗口只是主框架窗口中空白的部分。
主框架窗口
主框架窗口是指程序运行后,程序的整个界面。对应的类是CMainFrame,CMainFrame类派生于CFrameWnd类,而CFrameWnd类又又派生于CWnd类。
文档
文档类CDcoument负责维护应用程序所需要的数据,提供一系列可对这些数据进行操作的方法,并且能够为视图提供所需的数据。MFC提供的文档/视(Document/View)结构,其中文档是指CDocument类,视类是指CView类。Microsoft在设计基础类库时,考虑到要把数据本身与它的显示分离开,于是就采用文档类和视类结构来实现这一想法。数据的存储和加载由文档类来完成,数据的显示和修改则由视类完成,从而把数据的管理和显示方法分离开来。
MFC文档、视图和框架窗口间的关系和消息传送
在程序运行时CWinApp将创建一个CFrameWnd框架窗口实例,而框架窗口将创建文档模板,然后有文档模板创建文档实例和视图实例,并将两者关联。一般来讲我们只需对文档和视图进行操作,框架的各种行为已经被MFC封装好了,不需人为干预,这也是Microsoft设计文档-视结构的主旨,使界面和逻辑分离,让开发人员将主要的精力放在程序的算法和功能实现上。
在应用中一个视图对应一个文档,但一个文档可以包含多个视图。即为文档和视图是一对多的关系。
接下来看看如何在程序中得到各种对象的指针:
全局函数AfxGetApp可以得到CWinApp应用类指针。
AfxGetApp()->m_pMainWnd为框架窗口指针。
在框架窗口中:CFrameWnd::GetActiveDocument得到当前活动文档指针。
在框架窗口中:CFrameWnd::GetActiveView得到当前活动视图指针。
在视图中:CView::GetDocument得到对应的文档指针。
在文档中:CDocument::GetFirstViewPosition,CDocument::GetNextView用来遍历所有和文档关联的视。
在文档中:CDocument::GetDocTemplate得到文档模板指针。
在多文档界面中:CMDIFrameWnd::MDIGetActive得到当前活动的MDI子窗口。
一般来讲用户输入消息(如菜单选择,鼠标,键盘等)会首先发送视图,如果视图未处理则会发往框架窗口。所以定义消息映射时定义在视图中就可以了,如果一个应用同时拥有多个视图而当前活动视图没有对消息进行处理则消息会发往框架窗口。
MFC中所提供的各种视类介绍
MFC中提供了丰富的视类供开发者使用,下面对各个类进行介绍:
1) CView类是最基本的视类只支持最基本的操作。
2) CScrollView类提供了滚动的功能,你可以利用void CScrollView::SetScrollSizes( int nMapMode, SIZE sizeTotal, const SIZE& sizePage = sizeDefault, const SIZE& sizeLine = sizeDefault )设置滚动尺寸,和坐标映射模式。但是在绘图和接收用户输入时需要对坐标进行转换。
3) CFormView类提供用户在资源文件中定义界面的能力,并可以将子窗口和变量进行绑定。通过UpdateData函数让数据在变量和子窗口间交换。
4) CTreeView类利用TreeCtrl界面作为视界面,通过调用CTreeCtrl& CTreeView::GetTreeCtrl( ) const得到CTreeCtrl的引用。
5) CListView类利用ListCtrl界面作为视界面,通过调用CTreeCtrl& CTreeView::GetTreeCtrl( ) const得到CListCtrl的引用。
6) CEditView类利用Edit接收用户输入,它具有输入框的一切功能。通过调用CEdit& CEditView::GetEditCtrl( ) const得到Edit&的引用。void CEditView::SetPrinterFont( CFont* pFont )可以设置打印字体。
7) CRichEditView类作为Rich Text Edit(富文本输入)的视类,提供了可以按照格式显示文本的能力,在使用时需要CRichEditDoc的支持。
在使用文档/视图体系开发应用程序过程中,涉及的不仅仅是文档与视图。总体来说,涉及4个部分:文档模板、文档、视图和框架窗口。