MFC电子课件:实践教程第三章第二版_第1页
MFC电子课件:实践教程第三章第二版_第2页
MFC电子课件:实践教程第三章第二版_第3页
MFC电子课件:实践教程第三章第二版_第4页
MFC电子课件:实践教程第三章第二版_第5页
已阅读5页,还剩175页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第三章 MFC程序设计,本章的内容,简洁而不失完整性:由应用程序向导建立程序框架,由资源编辑器建立用户界面,由类向导建立成员变量、消息映射和处理函数,加上文档序列化和注册 MFC包含了所有与系统相关的类(包括图形用户界面相关的类),其中封装了大多数的API函数,提供了应用程序框架和开发应用程序的工具如应用程序向导、类向导、可视化资源设计等高效工具,用消息映射处理消息响应,大大简化了Windows应用程序的开发工作,使程序员可以从繁重的编程工作中解脱,提高工作效率。,3.1.MFC程序设计简介 3.2.MFC 程序设计 3.3.用户界面资源的应用 3.4.对话框的应用 3.5.基于对话框的应用程

2、序设计实例 3.6.文本和图形输出 3.7.文档的保存 3.8. MDI应用程序设计,目录,3.1 MFC程序设计简介,MFC类库 基础类 (已在第二章中介绍) 宏、全局变量及全局函数 应用程序框架,3.1.1 MFC定义的宏、全局函数及全局变量,类库,1. MFC提供的主要宏:,消息映射宏:声明消息映射表宏DECLARE_MESSAGE_MAP、消息映射定义宏BEGIN_MESSAGE_MAP和END_MESSAGE_MAP消息映射表入口宏ON_消息名。(本章只介绍消息映射宏),3.1.1 MFC定义的宏、全局函数及全局变量,动态MFC对象宏 DECLARE_DYNAMIC和IMPLEMEN

3、T_DYNAMIC 动态创建对象宏 DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE 运行时类宏: RUNTIME_CLASS 序列化宏: DECLARE_SERIAL和IMPLEMENT_SERIAL 诊断服务宏: ASSERT、VERIFY 跟踪服务宏: TRACE 异常处理宏: THROW,3.1.1 MFC定义的宏、全局函数及全局变量,MFC提供一些不属于任何类的全局函数,函数名以Afx开头,可以被应用程序中的所有类和函数所调用。如:AfxAbort(),无条件终止一个应用程序的执行;AfxGetAppName(),返回指向应用程序名的字符串指针;AfxWin

4、Init(),由WinMain()调用,对MFC应用程序进行图形用户界面(GUI)的初始化等等。,3. 全局变量,全局变量名以afx开头,如afxTraceFlag、afxDump等,主要与异常处理有关。,2. 全局函数,3.1.2 MFC命名规则,匈牙利命名法规定:,变量名以一个或多个小写字母开头作为前缀,标识变量的数据类型;,类型标识后是若干个单词,标识变量含义,每个单词以大写字母开头,其余字母小写;,MFC中所有类及自定义类都以C开头;,类成员变量以m_为前缀,下划线后是变量名等等。,表3.1 命名规则,h,MFC提供了构造Windows应用程序的框架,它不仅为应用程序建立标准的结构,生

5、成一系列起动文件,还提供标准的图形用户界面如菜单、工具栏、状态条等供开发人员在程序中补充完善,开发人员只需要完成针对特定应用的代码。使用应用程序框架的应用程序代码小,运行速度快,它提供的工具也降低了编码的难度。,3.1.3 应用程序框架介绍,程序的数据储存在文档类中(作为文档类的数据成员),是对数据的抽象表示。数据显示由视图负责,视图是程序窗口的客户区,框架窗口是客户区的框架,程序数据显示在窗口,用户通过视图与程序交互。 一个文档可以对应多个不同视图;而一个视图一般只对应一个文档。当文档数据发生变化时,视图显示的状态也会随之变化;对于多个视图的情况,基于同一文档的多个视图的显示同步变化。,1.

6、文档-视图结构,文档视图结构提供一种连续处理数据的方式,使应用程序的数据与数据的显示分开处理。,文档、视图及框架的关系:,图3.1,2. 单文档界面应用,单文档界面应用程序简称SDI(Single Document Interface),只允许一个框架窗口存在,每次只能创建和拥有一个文档对象,也只允许打开一个文档。 SDI各类 关系图,可将文档比作一个文件袋,专门用于保存文件数据,需要看时需从文件袋(文档)中取出来,放到桌面(视图)上看。,表3.2 基于文档/视图关系的SDI应用中的类,返回,应用程序类,框架类( 窗口框架),资源(决定用户 界面的显示),视图类 (显示数据并 与用户交互),文

7、档类 (保存数据),单文档模板,返回,应用程序类 CDocManager* m_pDocManager,框架类( 窗口框架),资源(决定用户 界面的显示),m_pDocument 视图类(显示数据 并与用户交互),文档类(保存数据) m_pDocTemplate m_viewList,返回,单文档模板 CRuntimeClass*m_pDocClass CRuntimeClass*m_pFrameClass CRuntimeClass*m_pViewClass UINT m_nIDResource,多文档界面应用简称MDI(Multiple Document Interface),允许有多个文

8、档类、视图类和多个文档模板CMultiDocTemplate(建立多种文档-视图-子框架关系)存在,运行时允许打开多个MDI子框架窗口,拥有各自的文档和视图对象。示例 关系图,在打开的多个子窗口中,只有一个活动窗口,应用程序菜单和工具栏的所有的命令都是针对活动窗口的。,3.多文档界面应用,主 框 架, 其它文档模板,返回,CDocManager,应用程序类 CDocManager* m_pDocManager,文档/视图结构可以充分发挥应用程序框架和MFC的优势,是MFC应用程序的核心,但使用它也要付出运行效率和代码增大的代价。,文档/视图结构对应用程序来说并不是必不可少的,有两种常见的非文档

9、/视图结构应用。,4. 非文档/视图结构应用,常见非文档/视图结构应用:,(1).基于对话框的应用,它包含一个CWinApp对象和一个模态对话框,对话框负责数据的存储和显示 。关系图,(2).SDI或MDI应用,都可以不包含文档对象,SDI包含一个CWinApp对象,一个框架窗口对象和一个从CWnd派生的CChildView视图对象,视图对象负责数据的显示,MDI应用还包括一个子框架窗口。,对话框类 作为应用程序主窗口 负责保存和显示数据,应用程序类,返回,Dialog-based Application,主框架,应用程序主窗口,CChildView视图类 负责保存和显示数据,应用程序类,SD

10、I Application, None Doc/View,返回,子框架, 视图框架窗口,CChildView 视图类,应用程序类,子框架, 视图框架窗口,CChildView 视图类,主框架,应用程序主框架窗口,MDI Application, None Doc/View,返回,图3.2 MFC应用程序开发过程,类向导,集成开发环境,应用程序向导,资源编辑器,Create,.def,.cpp .h,.dsw .dsp,.ico,.rc,.bmp,源文件,资源文件,编译,.obj,Build,资源编译,.res,应用程序,5. MFC应用程序创建,6.最简单的MFC应用程序示例,对于一个MFC应

11、用程序来说,只有CWinApp的派生对象是必不可少的,其它类均可视情况进行取舍。下例是一个最简单的MFC应用程序。 例:显示一个消息框。 (1).创建工程,工程类型选择Win32 Application,工程名为Ex3_0; (2).创建C+源文件,文件名Ex3_0.cpp,内容如下:,#include class CEx3_0App: public CWinApp /CWinApp派生类 public: virtual BOOL InitInstance() MessageBox(NULL,”SimplistMFC Application.”, ”Ex3_0”,MB_OK); return

12、TRUE; ; CEx3_0App theApp; /全局变量,代表应用程序本身,CWinApp:InitInstance()虚函数完成应用程序的初始化工作,派生的应用程序类都要重载此函数进行初始化,如完成主框架窗口的构造,窗口定义显示等工作。,(3).设置使用MFC。 选择Project|Settings菜单项,选择General页面,在Microsoft Foundation Classes组合框中选择Use MFC in a shared DLL。 (4).编译生成并运行此工程,结果显示一个消息框,如下图:,图3.3 最简单MFC应用示例,3.2.MFC 程序设计,MFC应用程序的执行过

13、程(参见图3.4):,1.构造全局对象CWinApp派生类对象;,2.运行由应用程序框架提供的WinMain函数;,图3.4 MFC应用程序的执行过程,3.在WinMain中,通过afxGetApp()获得全局对象的指针pApp,调用全局函数AfxWinInit() ,为CWinApp的成员 变量m_hInstance, m_hPrevInstance, m_lpCmdLine, m_nCmdShow赋初值; 然后调用pApp-InitApplication() ,这是CWinApp的虚函数,一般不需要改写; 调用 pApp-InitInstance() ,每个程序都必需改写这个函数,进行应用

14、程序初始化;,4.在InitInstance()函数中,先用new构造一个CFrameWnd派生类对象,其构造函数又调用Create(),创建主窗口,MFC依此自动为应用程序注册窗口类; 调用ShowWindow()显示窗口,调用UpdateWindow(),发出WM_PAINT消息;,5.回到WinMain中,调用pApp-Run,进入消息循环,通过API函数GetMessage()获得消息,TranslateMessage()处理消息,DispatchMessage()派送消息到CWnd:DefWindowProc() ,DefWindowProc()按照消息映射表的定义将消息分发到各相应

15、消息处理函数; 如消息队列为空,则Run调用CWinApp:OnIdle()进行空闲处理,重载OnIdle()可以去处理后台程序(低优先级);,6.若用户选择菜单File/Close,则程序收到WM_COLSE消息,调用:DestroyWindow()发出WM_DESTROY消息,然后调PostQuitMessage() ,发出WM_QUIT消息,此时Run会结束其内部消息循环,调用ExitInstance() ;,7.最后,返回WinMain() ,执行WinTerm() ,结束程序运行。,几点解释:,(1).每个MFC应用都有stdafx.h头文件,由应用程序向导自动生成;,(2).每个M

16、FC应用都应包含头文件afxwin.h,其内部又包含了其他头文件。,(3).每一个MFC应用程序都包含唯一的CWinApp派生类对象,代表应用程序本身。,(4).MFC应用程序中看不到WinMain()入口函数,它被 封装在应用程序框架里,运行时自动调用;,3.2.2.MFC消息映射,消息映射(Message Map)机制: 消息映射机制规定每个要响应消息的类定义自己的消息映射表,将消息与处理消息的函数联系在一起;当事件发生产生消息时,在程序中各个类的消息映射表中查找,当找到消息处理函数时,便将消息送至对应的消息处理函数进行处理。每个从CCmdTarget所派生的类都可以接收消息,都可以定义自

17、己的消息映射表Message Map。,消息映射表:,1.消息 消息是Windows用来通知MFC应用程序事件发生的主要方式,应用程序的行为取决于对消息的响应方式。 MFC把消息分为三大类: (1).标准Windows消息(窗口消息)(WM_XXX), (2).命令消息(WM_COMMAND), (3).控件通知消息。,2.消息映射 消息映射将消息与应用程序提供的处理该消息的成员函数联系在一起,一组消息映射构成消息映射表。 消息映射表由BEGIN_MESSAGE_MAP和END_MESSAGE_MAP 这一对宏作开始和结束,中间是若干消息映射入口 每一个入口由特定的消息宏ON_XXX组成,将一

18、个消息与与之对应的处理函数联系在一起。,定义和使用消息映射表的步骤:, 在头文件的类声明中添加DECLARE_MESSAGE_MAP宏声明消息映射;例如, 在类的定义文件(.cpp)定义消息映射表,方法是在 文件的开始处添加BEIGN_MESSAGE_MAP和END_MESSAGE_MAP 这一对宏,在它们之间放置消息映射宏,定义并初始化消息映射表,在消息与处理消息的函数之间建立联系;例如, 在类的定义文件(.cpp)中添加消息处理函数。例如,消息宏: (1).对标准Windows消息(窗口消息)的响应,消息宏ON_WM_XXX定义对标准Windows消息WM_XXX的响应,所有派生自CWnd

19、的类均可响应这类消息,系统默认的响应函数为OnXxx,对应关系见下面的表3.3:,由于有系统默认的消息和处理函数,在消息映射表中只写宏名,如: ON_WM_CREATE(),(2).对命令消息的的响应 。,ON_COMMAND宏定义对命令消息的响应,格式为 ON_COMMAND(命令ID,响应函数) 举例如下: ON_COMMAND ( IDM_ABOUT, OnAbout ) /表示IDM_ABOUT消息由OnAbout()响应 ON_COMMAND ( IDM_FILENEW, OnFileNew) ON_COMMAND ( IDM_FILEOPEN, OnFileOpen) 所有由用户定

20、义的命令消息也由ON_COMMAND定义 消息映射关系。,(3).对控件消息的响应,控件消息由按钮(BN_)、编辑框(EN_)、组合框(CBN_)、列表框(LBN_)等产生,在消息名前加上ON_即构成宏名, 举例如下: ON_BN_CLICKED (按钮ID,响应函数) ON_CBN_DBCLK (组合框ID,响应函数) ON_EN_SETFOCUS (编辑框ID,响应函数) ON_LBN_DBCLK (列表框ID,响应函数) 分别表示选择各个控件后,产生的消息由其后面定义 的函数进行处理。,3.消息处理 消息一般由应用程序中对象的成员函数来响应。当某个事件发生后,系统向应用程序消息队列放入一

21、个消息,CWinApp对象取得消息并按照消息映射表的定义将消息派送到某个类的相应的消息处理函数进行处理。 使用ClassWizard(见第五章菜单中View菜单介绍)定义消息映射关系,添加消息处理函数,系统会自动生成函数原型和函数框架,开发人员只要添加函数体代码,可以避免一些常见错误的产生。,程序中类响应windows消息的优先顺序: 取决于消息传递的顺序。 对于标准Windows消息(窗口消息),由产生这些消息的对象响应,如窗口的创建WM_CREATE,窗口的移动WM_MOVE,由产生消息的窗口类响应。如果找不到相应的处理函数,则将消息传递到其父类,一般情况都有缺省的响应函数; 对于命令消息

22、WM_COMMAND,可由拥有菜单资源的所有类来处理,传递的顺序是视图类、文档类、文档模板类、框架类、应用程序类,即这些类处理命令消息的优先顺序。 详见第2章。,例如,当用户在视图窗口中按下鼠标左键时,Windows发送WM_LBUTTONDOWN消息到应用程序,假设视图类需要响应这些消息,在类的头文件(.h)中有函数声明和消息映射表的声明: Class CMyView: public CView afx_msg void OnLButtonDown(UINT nFlags,CPoint point); /函数原型声明 DECLARE_MESSAGE_MAP() /消息映射表声明 返回,afx

23、_msg标识消息映射函数,所有由ClassWizard生成的消息处理函数原型说明前都有这一标识。,注,视图类的定义文件(.cpp)中必须有消息映射定义: BEIGN_MESSAGE_MAP(CMyView,CView) /消息映射表定义 ON_WM_LBUTTONDOWN() /函数名为OnLButtonDown /其它消息映射入口 END_MESSAGE_MAP() 以及对应的消息响应函数定义: void CMyView:OnLButtonDown(UINT nFlags, CPoint point) /处理消息的操作代码,程序中具体实现 返回,将CMyView的基类CView也包含进去,当

24、在派生类中没找到处理函数时,允许在基类中继续查找。,注,3.2.3.文档/视图结构,1.文档类 在基于文档/视图结构的应用程序中,CDocument的派生对象负责读入、保存和管理应用程序的数据。每个文档类可能与多个视图类关联,而每个视图包含一个指向与其相关的文档的指针。 文档类允许向其中增加数据成员,应用程序的数据可以是任何类型的,或者是任何自定义的数据结构,如结构体,类或链表等。,3.2.3.文档/视图结构,文档类的常用成员函数(带的表示是可重定义的虚函数),表3.4,2.视图类,视图类对象代表了应用程序的窗口客户区,是文档信息的一个显示窗口(视口),它同时也是用户与程序之间信息交互的桥梁,

25、用户对数据的编辑和修改需要通过键盘或鼠标进行,这些消息都由视图类接受后再反映到文档类。,视图类的派生关系:,图3.5,CView类提供了向视图或打印机进行输出的基本框架,决定了视图的基本特性,派生的视图类可以重载基类的函数,或增加新的函数以决定特定视图的特性。 CView的派生类可以多种方式显示文档类的信息,每个视图类根据显示的方式各自定义其显示代码。 MFC提供了一系列这样的类,如 CTreeView 树型视图 CListView 列表型视图 CFormView 显示基于对话框模板的视图CScrollView 带滚动条的视图。,1)视图类实现特定视图的特性的虚函数,表3.5,CEx3_1Do

26、c* pDoc = GetDocument(); 通过GetDocument获得与视图关联的文档类指针,通过指针pDoc访问文档类的数据成员和函数成员,在视图(窗口)中显示文档对象,当用户通过视图改变文档数据时,可设置自动更新文档内容。 文档/视图结构已经把应用程序所需要的数据处理与显示(虚函数)的框架构造好,程序设计人员只需要将具体应用的数据添加到文档类,并根据数据类型在视图类的虚函数OnDraw()中完成数据的显示。,2) 视图类的成员函数访问与其关联的文档类的方式,3.文档模板类,CDocTemplate类将框架、视图、文档对象及应用 程序的资源捆绑在一起。应用程序每打开一个文件,至少创

27、建一个文档对象、一个视图对象和一个框架窗口,而文档模板对象负责管理所有这些对象,并将各种相关资源与之联系在一起。 在大多数情况下,程序不需要对这个类进行修改。,对于SDI应用,使用CSingleDocTemplate文档模板。 对于MDI应用,使用CMultiDocTemplate文档模板。MDI允许有多个文档模板,将不同文档-视图类联系在一起,实现不同文档视图显示关系。,4.文档/视图结构应用程序创建过程,使用AppWzard,根据实际需要,选择创建合适的应用程序框架(是否使用文档/视图结构,使用SDI或MDI等) 在文档类中添加程序所处理的数据,作为文档类数据成员; 在视图类中取得文档数据

28、,以合适的方式在窗口中显示出来,5.应用实例,例3_1:创建一个包含文档/视图结构单文档界面应用的实例,为文档类添加一个字符串数据,在视图窗口显示出来。 步骤如下: (1).在File菜单中选择New,如图3.,在Project页面选择MFC AppWizard(exe),在Project name中输入Ex3_1,并选择合适的路径按OK按钮。,(2).在AppWizard Step 1中,如图3.,选择Single Document单 选按钮,并选中Document/ View architechure Support复选框, 表示使用文档/视图结构,按Finish按钮。显示New Proj

29、ect Information信息框,显示新创建的工程的有关信息按OK按钮,这样工程创建完毕。,图3. New Project对话框,图3. AppWizard Step1,在VC集成开发环境中看到,新工程生成了五个类,如图3.在class view页面上可看到这些类。 CAboutDlg 派生自CDialog,一个About对话框。 CEx3_1App 派生自CWinApp,其全局对象theApp 代表应用程序本身。 CEx3_1Doc 派生自CDocument,文档类。 CEx3_1View 派生自CView,视图类。 CMainFrame 派生自 CFrameWnd,程序框架类。,文档、

30、视图及应用程序类名都以工程名开头,后接对应的类型名,这有助于在程序中有多个文档视图类时区分主视图与其它视图,区分主文档与其它文档类。 应用程序向导AppWizard为每个类生成了一个头文件和一个.cpp文件,还自动生成了stdafx.h和stdafx.cpp,图3.,AppWizard还生成了缺省的用户界面资源文件,在Resource view页面显示。,图3. ClassView,图3.FileView,(3).为文档类增加数据成员。在编辑窗口打开文档类的头文件Ex3_1Doc.h,手工添加一个字符数组成员m_StrName;或在Workspace的ClassView页面,右击 CEx3_1

31、Doc类,在弹出式菜单中选择Add Member Variables,在对话框中输入变量类型和名称。 class CEx3_1Doc : public CDocument /Ex3_1Doc.h / Attributes public: char m_StrName80; ;,在文档类构造函数中对新增加的变量进行初始化。 CEx3_1Doc:CEx3_1Doc() /Ex3_1Doc.cpp / TODO: add one-time construction code here strcpy(m_StrName,A Simple Document/View Application.); (4)

32、.显示字符串.在CEx3_1View的OnDraw()函数显示字符串。 void CEx3_1View:OnDraw(CDC* pDC) CEx3_1Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); / TODO: add draw code for native data here pDC-TextOut(0,0,pDoc-m_StrName); /Ex3_1View.cpp,图3.10 例3.1第一步主界面,3.3.用户界面资源的应用,资源是windows应用程序的一种特殊数据,包括菜单、加速键、光标、位图、图标、对话框、字符串、工具栏、状态栏等

33、,资源一般放在exe或DLL文件中。 当windows将程序装入内存时,一般不将资源同时装入,而是当需要某个资源时才将相应资源装入。 资源定义在资源脚本(resource scirpt)文件中。 以.rc为文件扩展名,文件名与工程名相同。 资源脚本文件中定义了各种资源的相关数据,Windows通过使用不同的资源标识符前缀来区分不同资源类型(如表3.所示),这样做虽然不是必须的,但遵循这样的规则 有利于提高程序的通用性和可读性。,表3. 资源类型及其标示,资源标识前缀 IDM_ ID_ IDI_ IDB_ IDD_ IDR_ IDC_ IDS_,资源类型 菜单项ID 菜单命令ID 图标ID 位图

34、ID 对话框ID 菜单栏、工具栏、加速键 控件ID 字符串,返回,Visual C+ 6.0中提供了资源编辑器,对资源进行可视化编辑,并自动生成资源脚本文件;脚本文件可用文本编辑器进行编辑,但其可读性较差,容易出错,一般情况下尽量不要进行编辑。 用户定义的资源标识符号常量定义在resource.h文件中。 本节为例题3_1添加一些内容。,3.3.用户界面资源的应用,3.3.1.菜单,分类: 顶层菜单 : 一般位于应用程序主窗口或顶层窗口 弹出式菜单: 选择某个菜单项后弹出的子菜单,1.菜单的编辑,如果是AppWizard产生的程序,系统已为框架创建了一个标准的主菜单,包括文件、编辑、视图、窗口

35、帮助等标准菜单,定义了各菜单项的ID及相应的命令处理函数。在Resource View页面,打开工程资源,选择Menu,然后双击主菜单资源IDR_MAINFRAME标示,可打开菜单编辑器。,添加新的菜单资源,选择Insert Resource菜单项,在Insert Resource对话框中,选择Menu资源类型,单击New按钮,缺省新菜单名为IDR_MENU1。,a) 增加一个顶层菜单,在菜单属性对话框中,选中Pop-up选项,可以定义一个顶层菜单,在Caption编辑框中输入菜单名,菜单名即显示在菜单上。若在菜单名的某个字符前加一个 /可以向数组中增加ID以增加状态栏上显示栏。,3.3.3

36、状态栏,图3.16 例3.1主界面,3.4.对话框的应用,3.4.1 对话框的工作方式、种类和创建方法,1. 对话框在应用程序中的工作方式,对话框是一个读入或写出数据的图形界面对象,由集成开发环境中的对话框模板提供,可以向模板添加各种控件(如按钮,编辑框,单选复选按钮等),构成程序的对话框资源;,应用程序要使用对话框还需定义一个CDialog派生类的对话框类与资源相连接,并在这个对话框类中定义一些成员变量与对话框中的控件相对应,提供对话框控件的缺省数据值;,程序运行时需要用到对话框时依据对话框资源激活对话框,接收用户输入后通过成员函数更新文档类数据成员,如图3.17示。,图3.17对话框与文档

37、的数据交换,构造对话框并更新 文档数据,数据交换,对话框模板 controls,public: data members,文档类: application datas,对话框类对象,2. 对话框的种类,Windows有两种对话框,模态对话框和非模态对话框,构造两种对话框的大多数工作都相同,只是两者的显示和数据处理有些不同。,模态对话框(Modal Dialog Boxes)工作时使其父类窗口无效,直到对话框结束。也就是说,该对话框打开后, 程序等待用户输入,在关闭对话框后才执行其它任务。 调用DoModal()函数可以显示模态对话框。如: CMyDialog dlg; dlg.DoModal(

38、); DoModal返回用户单击的按钮的ID值(如IDOK或IDCANCEL),单击OK或CANCEL按钮后,自动调用CDialog:EndDialog()关闭对话框。,非模态对话框( Modeless Dialog Boxes)在打开期间,允许用户切换到程序其它部分,不一定要关闭对话框。如WinWord中的Find and Replace对话框。 对系统而言,一个非模态对话框相当于另一个线程,可以说是执行中的另外一个程序。调用Create函数创建并显示非模态对话框: CMyDialog dlg; dlg.Create(); 用户按下OK或CANCEL按钮不会关闭对话框,可重定义OnOK和On

39、Cancel函数,调用DestroyWindow关闭对话框(即后文建立对话框的方法是针对模态对话框的): void CMyDialog:OnOK() DestroyWindow(); void CMyDialog:OnCancel() DestroyWindow();,3. 对话框的创建与编辑,a)对话框的创建,选择Insert|Resource.,在Insert Resource对话框中选择Dialog类型,按New按钮,打开对话框编辑器,缺省情况下,对话框模板提供了OK和Cancel两个按钮,同时打开了对话框工具栏和控件工具栏,如下图。,图3.18对话框模板及编辑工具,在对话框模板内右击鼠

40、标,在弹出的菜单中选择Properties,打开Dialog Property对话框。,图3.19对话框属性对话框,b)控件属性,将控件工具栏中的任一种控件拖至对话框模板中,在控件上右击鼠标,选择Properties打开控件属性对话框,如图3.20。这是为例3_1添加的输入学生信息的对话框。 各种控件属性对话框基本相似,在ID框中输入标识控件的唯一ID值,在Caption中输入控件上显示的字符(Edit控件没有这一属性),Visible表示该控件在对话框创建时是否显示,Group用来控制控件分组,Disabled使控件不可用,Tab stop表示是否用Tab键选择控件。,图3.20 控件属性设

41、置对话框,c)控制Tab顺序,当打开对话框编辑器后,集成开发环境的菜单上多了一个Layout菜单,其中主要是对话框工具栏上显示的一些命令,其中有一个命令Tab Order,定义当用户用Tab键移动输入焦点时各控件接受焦点的顺序。假如编辑一个如图3.20的对话框,选择Layout|Tab order,对话框编辑器显示定义时的顺序,这时用鼠标点击各个控件,则Tab顺序就定义为鼠标点击的顺序,如图3.21所示。对于静态文本框,由于不需要输入焦点,就放在最后。,d)分组控制,VC提供了根据控件功能将控件进行分组的工具,使用户更易于理解对话框的结构。在分组框中使用最多的是单选按钮(radio butto

42、ns),一组单选按钮允许用户在组内多个相互排他的选项内选择一项。,图3.21设置Tab Order,e)组合框Combo Box,将组合框拖至对话框中后,按向下箭头,显示运行时下拉组合框的大小,调整到合适大小。组合框的属性对话框比其它控件多一个Data页面,用于输入组合框中的数据项,每一行是一项,输完一项按Ctrl+Enter键换行。,f)列表框List Box,在对话框编辑器中只能设置列表框大小、位置和ID,数据的初始化需要通过编程实现。一般在拥有列表框控件的对话框的OnInitDialog函数中,调用CListBox:AddString(无序)或CListBox:InsertString(

43、有序)插入字符串。,g)测试对话框,当所有控件都布置好并定义属性后,可以选择对话框工具栏上的测试按钮,测试对话框工作情况,必要的话做适当调整。,3.4.2 将对话框与程序连结,1.对话框类及数据成员的定义,a)创建对话框类,对话框资源建立好后,在对话框中右击鼠标,选择ClassWizard菜单项,会出现提示框,说明新建的对话框资源是新资源,是否需要建立一个新类或选择一个已存在的类。 若选择新类,出现图3.23示的New class对话框 。 选定后,在WorkSpace中可看到新增加的类,自动生成的StudentDlg.h头文件和StudentDlg.cpp源文件。,图3.23新建类对话框,b

44、)增加数据成员,要使对话框能与程序通讯,还需给对话框类增加数据成员,以保存各控件的初始值,并从控件读取数据。 与控件对应的数据成员可以是变量或控件类型,如表3.9所示。,表3.9对话框与控件对应的变量或控件数据成员,在ClassWizard的Member Variables页面,选择对话框类,在Control IDs中列出了对话框中所有控件ID,如图3.24,选择某个ID,按Add Variable按钮,弹出Add Member Variable对话框,可输入成员名,在Category中选择值(value)变量或控件(controls)类型,在Variable type列表框中,若是Value

45、类,选择变量数据类型,若是Controls,选择控件类,按OK,成员添加成功。 对学生信息输入框的数据成员变量表如图3.25。 数据成员定义后,在对话框第一次显示时需对其初始化。有两种初始化成员变量的方法:一是在对话框类的构造函数中初始化,由ClassWizard自动生成;二是构造对话框对象后进行初始化。为使用方便,对话框变量成员一般定义成public访问权限,因此可以在使用对话框的地方初始化。,ClassWizard自动在构造函数中初始化变量,代码放在/AFX_ 和/AFX_括号中间,一般不需要对其改动。 CStudentDlg:CStudentDlg(CWnd* pParent /*=NU

46、LL*/):CDialog(CStudentDlg:IDD, pParent) /AFX_DATA_INIT(CStudentDlg) m_sDepart = _T(); m_dComputer = 0.0; m_dEnglish = 0.0; m_nID = 0; m_dMath = 0.0; m_sName = _T(); m_dPhysics = 0.0; m_nSex = -1; /AFX_DATA_INIT ,ClassWizard还为对话框生成了DDX(Dialog Data Exchange)函数成员DoDataExchange(),此函数不应被显式调用,而由UpdateData

47、()函数调用,它可以实现在对话框控件与对话框数据成员之间的双向数据交换。 UpdateData(FALSE),将对话框对象的成员变量值复制至对话框控件,用于向用户显示数据。 UpdateData(TRUE)将对话框控件中数据复制至对话框对象成员变量,默认值是TRUE。 如果选择对话框的OK按钮关闭对话框,会自动调用UpdateData()。 对分组的单选按钮,在ClassWizard中只出现组内第一个单选按钮的ID。为区分不同的按钮,需增加一个成员变量,其类型只能是int。选中第一个按钮,其值为0,选中第二个按钮,其值为1,依此类推。,图3.24为对话框添加数据成员,图3.25对话框的变量和控

48、件数据成员,2.对话框的显示,模态对话框 调用DoModal()函数显示对话框, 并做相应数据处理。 按OK或Cancel按钮关闭对话框, 非模态对话框 调用Create()函数创建并显示对话框, 调用DestroyWindow()函数关闭 对话框。 模态对话框和非模态对话框在创建资源时是一致的,仅在显示对话框调用的函数不一样。 对话框与文档数据的交互是双向的。参见下例:,定义CStudent类,其数据成员与学生信息输入对话框内容对应;其成员函数SetStu()以对话框输入的内容为数据成员赋值。在文档类中定义CStudent对象stu。视图类响应输入命令(如增加一个菜单命令Input,响应函数

49、为OnInput(),为输入学生信息打开对话框,则下面代码为对话框按OK按钮后,用对话框成员变量更新文档数据。 void CEx3_1View:OnInput() / TODO: Add your command handler code here CEx3_1Doc* pDoc = GetDocument(); CStudentDlg dlg;/构造对话框对象 if(dlg.DoModal()=IDOK) /显示对话框并选择OK按钮后 pDoc-stu.SetStu(dlg); /将对话框数据赋给文档数据成员 ,也可以通过菜单命令,调用函数ShowData(),用对话框输出文档数据。方法是先

50、构造对话框变量,然后用文档数据为对话框数据成员赋值,再显示对话框,代码如下: void CEx3_1View:ShowData() / TODO: Add your command handler code here CEx3_1Doc* pDoc = GetDocument(); CStudentDlg dlg; /构造对话框对象 dlg.Setdata(Doc-stu); /将文档数据成员赋给对话框数据成员 dlg.DoModal(); /显示对话框,控件显示文档数据 ,3.为控件添加或修改消息响应函数,打开ClassWizard,在Message Map页面,可以为控件添加响应函数。如图

51、3.26。为OK按钮添加默认的响应函数OnOK()。 Class Wizard在类的声明中添加函数声明,并在类的cpp文件中添加空的函数体,由程序设计人员完成函数代码。这样单击OK按钮,就会调用OnOK函数。 void CStudentDlg:OnOK() / TODO: Add extra validation here UpdateData(); /首先使数据传送至对话框成员变量 CDialog:OnOK(); /调用基类OnOK并关闭对话框 ,图3.26为控件添加响应函数,图3.27 例3.1 新主界面,3.5.基于对话框的应用程序设计,AppWizard提供了基于对话框(Dialog

52、based)的应用程序框架,程序可以简单到只有CWinApp派生类和一个对话框类,对话框就是程序框架,负责数据输入输出和存储,以及消息处理;对话框可以有最小化按钮,甚至可以连接一个菜单。,基于对话框的应用程序结构简单,只要正确选择控件及定义成员变量,设计正确的算法。 适合开发数据不多,功能简单的程序。,【例3.2】基于对话框的应用程序,在主框架窗口对话框上有三个组合框,分别选择某年某月某日,按下”Show Weekday”按钮,在Weekday列表框中显示这天是星期几。,步骤如下: 1.创建Dialog based工程Ex3_2 工程创建完毕后,除了CAboutDlg,AppWizard还生成

53、了两个类: CEx3_2App 代表应用程序的CWinApp派生类; CEx3_2Dlg 以IDD_EX3_2_DIALOG为模板的对话框,是程序主框架。 2.编辑对话框资源 为IDD_EX3_2_DIALOG对话框模板添加控件,如图3.28所示。对话框控件ID及添加的相应数据成员见表3.10。 组合框数据在Combo box properties对话框的Data选项卡输入,输入数据为Year 19902010, Month 112, Date 131。,图3.28对话框模板,表3.10 例Ex3_2对话框控件及变量定义,3.定义列表框 数据不能在控件属性对话框中输入,必须为列表框定义一个CL

54、istBox控件类型变量,在对话框的OnInitDialog()函数中为其插入内容。,BOOL CEx3_2Dlg:OnInitDialog() CDialog:OnInitDialog(); m_listWeekday.InsertString(0,Sunday); /向列表框插入字符串 m_listWeekday.InsertString(1,Monday); /字符串编号必须从0开始,并应该顺序排列 m_listWeekday.InsertString(2,Tuesday); m_listWeekday.InsertString(3,Wednesday); m_listWeekday.I

55、nsertString(4,Thursday); m_listWeekday.InsertString(5,Friday); m_listWeekday.InsertString(6,Saturday); return TRUE; ,4. 程序涉及的算法 要计算某年某月某日是星期几,应有一个基准日,然后算出某日离基准日的天数,即可算出星期几。1990年1月1日是星期一,以这天为基准。 为计算闰年与非闰年天数差异,在Ex3_2Dlg.cpp文件中定义一个全局二维数组: char daytab213 = 0,31,28,31,30,31,30,31,31,30,31,30,31, 0,31,29,

56、31,30,31,30,31,31,30,31,30,31;,为对话框添加两个成员函数,其一响应按钮Show Weekday命令,通过ClassWizard对话框添加。另一为计算指定日期为当年的第几天,在Workspace中右击对话框类名,选择Add member functions进行添加。 int CEx3_2Dlg:DayOfYear(int y, int m, int d) /计算某日在当年的第几天 int i,leap; leap = y%4 =0 ,void CEx3_2Dlg:OnShow() UpdateData(); /读入对话框控件数据,接受输入 int year,mont

57、h,date,days=0, i,weekday; year = atoi(m_csYear); /将年月日字符串转换为整数便于计算 month = atoi(m_csMonth); date = atoi(m_csDate); for(i = 1990; i year; i+) /for循环计算9093这四年整的天数 if(i%4=0/使对话框无效,重画 ,3.6.文本和图形输出,Windows设备描述表DC(device contexts),是对各种不同设备的抽象,应用程序只要向DC输出,由DC负责处理不同设备的差异。,DC是一个数据结构,描述了图形设备接口GDI进行输出所需要的信息,包括

58、颜色,填充方式,画笔宽度等。在Windows中,DC允许应用程序使用输出设备,DC在应用程序、设备驱动程序、与输出设备之间建立联系,并提供绘图信息。,在MFC中,CDC类封装了设备描述表DC,该类的核心是 m_hDC,代表一个指向窗口DC的句柄。,1.CDC类及其派生类,CDC类派生自CObject,它具有CObject类的共同特性,如可以动态创建,可进行序列化操作。,(a).设置颜色,windows使用一个32位无符号整型值来表示图形和文本的颜色,其数据类型为COLORREF,它包含4个字节,第一字节未使用,不要改变其值;后面三个字节分别表示红、绿、蓝三种基本色的成分,每一种颜色用一个0-255之间的数字表示。,设备描述表最常见的使用是在视图类的OnDraw函数中进行图形和文本输出,2.CDC类的使用,宏RGB定义颜色值,宏 RGB 定义一个颜色的三种基本色成分,返回COLORREF值 GetRValue 返回一个CO

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论