第 3 章 mfc 应用程序概述
DESCRIPTION
第 3 章 MFC 应用程序概述. MFC 应用程序概述. Windows 应用程序概述 MFC 应用程序框架 文档 / 视图结构 消息映射. 3.1 Windows 应用程序概述. 3.1.1 窗口编程基础 窗口 消息和消息队列 事件驱动的程序设计 资源管理. 1. 窗口 (Window). 窗口是应用程序与用户交互的界面 窗口元素以对象方式组织 一个应用程序由多个窗口组成 程序运行过程是窗口之间,窗口与系统,窗口与用户之间交换并处理数据的过程。. 标题栏. 菜单栏. 最小化按钮. 关闭按钮. 最大化按钮. 客户区. 垂直滚动条. - PowerPoint PPT PresentationTRANSCRIPT
第第 33 章 章 MFCMFC 应用程序概应用程序概述述
MFCMFC 应用程序概述应用程序概述 Windows 应用程序概述 MFC 应用程序框架 文档 / 视图结构 消息映射
3.1 Windows 3.1 Windows 应用程序概应用程序概述述
3.1.1 窗口编程基础窗口消息和消息队列事件驱动的程序设计资源管理
1. 1. 窗口窗口 (Window)(Window) 窗口是应用程序与用户交互的界面 窗口元素以对象方式组织 一个应用程序由多个窗口组成 程序运行过程是窗口之间,窗口与系统,
窗口与用户之间交换并处理数据的过程。
2. 2. 窗口的界面元素窗口的界面元素
垂直滚动条
标题栏 菜单栏
关闭按钮
最小化按钮
最大化按钮
水平滚动条窗口边界
客户区
消息消息 (Message)(Message) 和消息队和消息队列 列
消息用于通知某个事件的产生消息机制 MSG消息的类型
消息消息 (Message)(Message) 和消息队和消息队列列
Windows 应用程序是利用消息与其他Windows 应用程序和操作系统进行信息交换的。
消息的作用是通知一个应用程序某个确定的事件的产生。
应用程序对该事件做出响应,即编写相应的消息处理代码。
举例:按下鼠标左键时,系统会产生 WM_LBUTTONDOWN 消息
消息消息 (Message)(Message) 和消息队和消息队列列
Windows 应用程序接受系统队列传递过来的消息的步骤:
(1) 每个 Windows 应用程序都有一个 WinMain( ) 函数 , 在该函数中会定义一个窗口句柄,当应用程序启动时,会使该窗口句柄注册,操作系统使用窗口句柄与Windows 应用程序通信。
消息消息 (Message)(Message) 和消息队和消息队列列
(2)Windows 应用程序创建一个或多个窗口,每个窗口都有一个窗口处理函数 (WndProc) ,负责窗口显示和响应用户输入。
(3) 消息映射 (Message Mapping) :负责从消息队列中取消息,并送回窗口,由窗口处理函数选择合适的消息处理函数响应消息。
派送消息
消息源 1
消息源 2
消息源 n
否
程序开始
程序结束
捕获消息
处理消息 是否退出消息
是
···
消息机制消息机制消息机制是 Windows 应用程序运行的核心工作
机制,用如下结构体 MSG 表示:typedef struct tagMSG { HWND hwnd ; UINT message ; WPARAM wParam ; LPARAM lParam ; DWORD time ; POINT pt ;}MSG ;
MSG 结构体成员说明:(1)hwnd 接收消息的窗口句柄。 (2)Message 消息值,每个 windows 消息都有一个
消息值,该值由 windows.h 头文件的宏定义来标识。
(3) wParam 和 lParam 包含有关消息的附加信息,它随消息的不同而
不同。(4)Time 指定消息送至队列的时间界限。(5)pt 指定消息发送时屏幕光标的位置,结构如下:typedef struct tagPOINT{ LONG x; LONG y; POINT;}
消息的类型消息的类型1. 输入消息 由键盘和鼠标操作产生输入消息。这
类消息首先放在系统消息队列中,后由Windows 操作系统将他们放到应用程序消息队列中,由应用程序处理消息。
2.控件消息 用户操作窗口对象时产生控件消息,这类消息一般不进入应用程序消息队列,而直接发送到控件对象所属的对话框窗口
消息的类型消息的类型3. 系统消息 对程序化的事件或系统时钟中断做出的放
映。一类例如 DDE( 动态数据交换消息 )要通过 Windows 的系统消息队列,送入应用程序的消息队列,另一类直接送入应用程序的消息队列,例如创建窗口消息。
4. 用户消息 是程序员自己定义并在应用程序中主动发出
的,一般由应用程序的某一部分做内部处理。
3. 3. 事件驱动的程序设计事件驱动的程序设计Windows 操作系统下的 Windows 应用
程序采用事件驱动的程序设计,与 Dos操作系统下面向过程有明显不同。
事件驱动的程序的逻辑顺序是按事件的产生而决定的。
事件的产生不是预先定义的,有着随机性 。
3. 3. 事件驱动的程序设计事件驱动的程序设计例 1、一个应用程序的功能是体操全能比赛项目运动成绩管理,体操全能包括 4个项目,在一个驱动中需要如下步骤:
(1) 输入第一项运动员的成绩。(2) 输入第二项运动员的成绩。(3) 输入第三项运动员的成绩。(4) 输入第四项运动员的成绩。(5) 计算每个运动员的总分。 (6) 按总分排名。
开始
输入第一项某运动员的成绩
输入第二项某运动员的成绩
输入第三项某运动员的成绩
输入第四项某运动员的成绩
计算每个运动员的总分
按总分排名
结束
消息循环
事件驱动程序流程示例
4. 4. 资源管理资源管理 资源的类型
用户自定义资源菜单对话框工具栏
系统资源设备上下文画刷画笔字体通信端口
3.1.2 Windows3.1.2 Windows 应用程序组成应用程序组成一个应用程序是如何开始?操作系统创建一个新的进程和一个初始线程
应用程序代码装载到内存动态链接库装载到内存 ( 如果需要使用
DLL)为数据和堆栈分配物理内存,并映射到虚拟内存
应用程序开始执行
3.1.2 Windows3.1.2 Windows 应用程序组成应用程序组成Windows 应用程序必须包含两个基本函数:(1) 应用程序主函数 WinMain( ) WinMain 函数定义了窗口句柄,创建初始化窗口并启动一个消息循环。
(2) 窗口处理函数 WinProc( ) WinProc 函数处理所有从操作系统传递到窗口的消息。每一个窗口都要有一个窗口处理函数。
3.1.2 Windows3.1.2 Windows 应用程序组成应用程序组成1.WinMain( ) 函数 Windows 应用程序是从 WinMain( ) 函数开始和结束的。
在”WINBASE.H”中定义如下:int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSR lpCmdLine, int nCmdShow );
3.1.2 Windows3.1.2 Windows 应用程序组成应用程序组成参数说明如下:(1) hInstance 系统分配的窗口所属的应用程序的实例
句柄,标识当前进程的实例,是进程所占据的地址空间的首地址,是程序的唯一标识。
(2)hPrevInstance 用于检查是否有多个程序实例运行。
3.1.2 Windows3.1.2 Windows 应用程序组成应用程序组成(3)lpCmdLine 是一个指向字符串的指针,用来保存
程序运行时的参数,同 main 函数中的argv[ ]相似。
(4)nCmdShow 用来指明应用程序的主窗口的显示
方式 ( 最大化,最小化,一般显示 ) ,通常被 ShowWindow( ) 函数作为显示窗口的参数。
3.1.2 Windows3.1.2 Windows 应用程序组成应用程序组成WinMain 函数的作用: 注册窗口类,创建并初始化窗口,
创建消息循环 (message loop) 。(1) 注册窗口类 每个窗口都包含一些基本属性,如窗
口边框、标题、大小、位置、鼠标、背景色等,注册的过程是将这些属性报告给系统。
3.1.2 Windows3.1.2 Windows 应用程序组成应用程序组成(2) 创建并初始化窗口 CreateWindow( ) 函数用于创建窗口,
定义了窗口的名称、位置、尺寸等数据,创建成功返回窗口句柄,否则为 0。
创建后创口需要调用 ShowWindow( ) 和 UpdateWindow( )两个函数显示窗口。
3.1.2 Windows3.1.2 Windows 应用程序组成应用程序组成(3) 创建消息循环 使用 While语句创建一个消息循环,负责从
消息队列中获取消息并发送给相应的处理函数。 while(GetMessage (&Msg,NULL,0,0)) { TranslateMessage(&Msg); DispatchMessage(&Msg);} TranslateMessage( ) 函数的作用是将来自键
盘的命令翻译为消息的 ID字符表示。 DispatchMessage( )把每个消息分发给相应
的窗口函数。
3.1.2 Windows3.1.2 Windows 应用程序组成应用程序组成2. 窗口处理函数 决定窗口在它的客户区中显示哪些内容、窗
口如何响应用户输入,窗口函数定义如下:LRESULT CALLBACK WndProc( HWND hwnd, UNIT Message, WPARAM wParam, LPARAM lparam,)
3.1.2 Windows3.1.2 Windows 应用程序组成应用程序组成参数说明如下:(1) LRESULT 表示该函数返回值为长整数,由系统使用。(2)CALLBACK 表示该函数是回调函数,由系统使用。(3)Hwnd 接收消息的窗口句柄 (4)Message用来标示消息的数字(5)wParam 和 lparam两个 32 位的消息参数,用来提供消息的附加信息。
WindowsWindows 的编程模型与的编程模型与 MS-DOSMS-DOS 编编程模型之比较程模型之比较
第一,用 C语言编写基于 MS-DOS 的应用程序时,唯一绝对需要的是一个名为main 的函数。而当 Windows 操作系统启动一个程序时,调用的是 WinMain 函数。
第二,许多 MS-DOS 程序直接写显存和打印机接口。这种技术的不利之处是对每一种设备需要其支持的驱动程序软件。 Windows引入了一个名为图形设备接口( GDI)的抽象化外层,所以用户不必知道有关系统设备的类型。 Windows 程序不是寻址硬件,而是调用 GDI 函数。
WindowsWindows 的编程模型与的编程模型与MS-DOSMS-DOS 编程模型之比较编程模型之比较
第三,要在 MS-DOS环境下进行数据驱动编程,必须或者为把数据编码成为初始化常量或者提供独立的数据文件让程序来读。进行Windows 编程时,使用大量已经确立的格式在资源文件中存储数据。
第四,在 MS-DOS环境下一个程序的所有对象模块在建立过程中是静态连接的。 Windows允许动态链接,这意味着特别创建的库可以在运行时加载和链接。多个应用程序可以共享动态链接库( DLLs),它节省内存和磁盘空间。动态链接增加了程序的模块性。
3.1.3 3.1.3 应用程序举例应用程序举例 分析使用 AppWizard 生成的 Win32
窗口程序示例 Exam3_2 ,并对该程序作以下修改:
(1)修改输出的文本字符串”Hello World”为”Hello C++ !”。
(2) 在视图的中央输出文本” Starting your VC++ learning!”
(3)添加一个对话框,并能使用菜单调用这个对话框。
3.2 MFC3.2 MFC 应用程序框架应用程序框架Visual C++6.0 是一种集成开发环境,
提供了 MFC 类库。MFC(Microsoft 基本类库, Micros
oft Foundation Class Library)MFC 是微软公司对大部分标准的 Wi
n32 API 函数的封装 , 提供了图形环境应用程序的框架及创建应用程序的组件 .
MFC MFC 简 介简 介MFC 是用来写 Windows 应用程序的 VC++类集,该类集以层次结构组织起来。提供的类库对程序设计高度抽象,使代码的可靠性和重用性得到很大的提高。
MFC给Windows 系统开发平台程序员以最好支持的基本类结构,它包含的类分层结构和功能是具有可伸缩性,在功能扩展的同时, MFC还保持了程序的向下兼容性。
MFCMFC 类的层次结构类的层次结构MFC 类库中是以层次结构的方式
组织起来的,每个层次结构都与一具体的 Windows 的实体相对应。
大多数 MFC 类是从 3 个基类( CObject 类、 CCmdTarget 类、 CWnd 类)派生的
MFCMFC 类的层次结构类的层次结构根类: CObject 类CObject 类 CCmdTarget 类CWnd 类从 CObject 类派生的类具有运行时获得对象大小的名字的能力
从 CCmdTarget 类派生的类能够处理命令消息
从 CWnd 类派生的类能够控制窗口
派生 派生
CObjectCObject派生类派生类CObject
CCmdTarget
CWinThread
CWinApp
CWnd
CFrameWndCView
CDocument
MFCMFC 类的层次结构类的层次结构MFC 提供的一些重要的类分为以下几种:应用程序框架结构类 CWinApp程序窗口类 CFramWnd图形打印类 CGdiObject文件类 CFile Internet 类集合类异常和调试支持类
应用程序类应用程序类 CWinAppCWinApp应用程序框架类主要包括应用程序
类、线程类、文档类和文档模板类。应用程序类 CWinApp:每个 MFC
应用程序只能由一个 CWinApp 的派生对象。
CWinApp 是应用程序开始后创建的第一个对象,结束前最后一个执行对象。
文档类文档类 CDocumentCDocument文档类 Cdocument封装了应
用程序的数据管理功能,可以存储和载入用户定义的持久数据提供“容器”
文档类负责将一个文档赋给它的成员变量,并允许视图类编辑这些成员变量。
程序窗口类程序窗口类 CWndCWnd程序窗口类主要包括框架窗口类、对话框类、视图类、控件类等。
类 CWnd提供了MFC 中所有窗口类的基本功能,作为所有类的公共基类。
创建一个 Windows 窗口需二步,首先引入构造函数,构造一个 CWnd对象,然后调用 Create 建立Windows 窗口并将它连接到 CWnd 对象上。
框架窗口类框架窗口类 CFramWndCFramWnd框架窗口类 CFramWnd 是 CWn
d 类的子类,创建和维护窗口的边框、菜单栏、工具栏、状态栏等部分 .
一个 SDI 应用程序,主框架类是从 CMainFrame派生的,对于一个 MDI 应用程序,主框架类是从CMDIFramWnd派生的。
视图类视图类 CViewCView视图类是应用程序中较重要的类,
应用程序返回的结果大多在视图类上进行进行和显示 , CView 是用于让用户通过窗口来访问文档 ,提供人机交互的界面。
视图类负责描述文档的内容,也可以用户编辑文档。
创建应用程序时,创建文档类的一个实例后将创建视图类 Cview 的一个实例。
几种视图类几种视图类CView 类是基本视类,支持基本操作CScrollView 类提供了滚动功能,设置滚
动尺寸和坐标模式。CFormView 类可在资源文件中定义界面的能力,并可将子窗口和变量进行绑定。
CListView 类利用 ListCtrl( 列表框 ) 界面作为视界面
CEditView 类利用 Edit 接收用户输入,具有输入框的一切功能,可实现多行文本的编辑。
对话框类对话框类 CDialogCDialogCDialog 类封装了用来创建对话框
的 Windows API ,在创建时可以用对话框模板中定义的控件来填充。
CDialog 可分别处理无模式和有模式两种类型的对话框 .
几个 MFC 通用对话框类 CColorDialog、 CFileDialog、 CFontDialog、 CPrintDialog 。
控件类和控制栏类控件类和控制栏类常用控件类 CButton 类, CListC
trl 类 ,CProgressCtrl 类 ,CTreeCtrl 类 ,CComboBox 类 ,CEdit 类等。
控制栏类( CControl 类的派生类),从编成的角度看,工具栏只是 CToolBar 类的一个对象,状态栏是 CStatusBar 类的对象。
MFCMFC 应用程序框架分析应用程序框架分析在一个 CHello SDI 应用程序中,向导为我们生成了 4 个主要的类,这些类都是 MFC 类的派生类,分别包含在对应的头文件以及实现文件中。
分析每个类的作用
MFCMFC 应用程序框架分析应用程序框架分析CHelloApp 类——类 CHelloApp 的一个
对象代表一个应用程序。 程序定义了一个全局 CHelloApp 对象 theApp 。 CWinApp 基类决定 theApp 的大多数行为。
CWinApp 类重载函数: InitInstance( ) ,完成应用的初始化以,与 WinMain 函数结构中的初始化处理相对应。
MFCMFC 应用程序框架分析应用程序框架分析典型的一个应用程序将有一个主应用
程序窗口。因此, CHelloApp 应用程序类定义了一个名为 m_pMainWnd 成员变量来指向主窗口。
InitInstance 函数建立了一个 CHelloWindow 事例,并使用 m_pMainWnd 来指向一个新的窗口
MFCMFC 应用程序框架分析应用程序框架分析 CMainFrame 代表的是程序的主框架窗
口。 框架窗口类及其相关的文件框架窗口类
对应应用程序的主窗口 ,他的定义是在头文件 MainFrm.h 中,而实现则是在 MainFrm.cpp 文件中。所有与框架窗口相关的功能都是在这里定义和实现的。
MFCMFC 应用程序框架分析应用程序框架分析文档类及其相关的文件 文档类在应用程序中没有直观的对应关系,但这一点就是 MFC 的框架的一个特点就是文档 / 视图结构。可以抽象一点地来理解,比如说我们在 Word 中打开了一个文件,其实,这个文件就是文档,而我们看到的只不过是这个文件一个视图,所以说文档提供了应用程序显示的支持,但是我们真正看到的应用程序显示的则是一个视图,文档类的定义是在“ CHelloDoc.h”中,而他的实现则是在“ CHello Doc.cpp”文件中。
MFCMFC 应用程序框架分析应用程序框架分析 视图类及其相关的文件 视图类是用来显示文档对象的内容的,我们在 Word 程序中所看到的界面就是一个视图,我们要修改,画图首先操作的对象就是视图,所以,视图类就如他的名称所指出的那样,提供了从用户角度看到的东西。视图类的定义在“ CHelloView.h” 中,实现是在文件“ CHelloView.h”中。
MFCMFC 应用程序框架分析应用程序框架分析 应用程序类及其相关的文件 MFC 应用程序的初始化,启
动运行和结束都是由应用程序对象完成的。他对应的文件是”Hello World.cpp” 和” Hello World.h” 。
MFCMFC 应用程序框架分析应用程序框架分析 大致的看出 MFC 应用程序
对象之间的关系了。应用程序一开始生成应用程序对象,然后,在 InitInstance 中创建中将会创建文档模板对象 , 应用程序就可以通过建立的模板对象来管理文档、视图、和框架窗口。
3.3 3.3 消息映射消息映射 在 Win32 的窗口函数中,采用 swit
ch_case 结构进行消息处理 , 在 MFC 中通过消息映射的方法,将消息映射到各个处理函数。本节内容包括:消息的类别及描述消息映射系统消息处理的路径自定义消息处理
3.3.1 3.3.1 消息的类别消息的类别 MSG 结构描述消息,区别消息一般
是对结构中的主消息 message、附加参数 wParam 和 lParam3 个字段进行判断
在 MFC 中,消息分为窗口消息,命令消息和控件消息三种类型。
窗口消息的描述窗口消息的描述1. 窗口消息 只能被窗口或者窗口对象处理,在 MFC 中油 CView 和 CFrame及其派生类、及自定义窗口类处理窗口消息。描述: message : WM_XXX wParam 和 lParam :随 WM_XXX而变 举例: WM_LBUTTONDOWN 鼠标左键消息 ,w
Param 是一个整数值,标识鼠标按下是哪个键, lParam 的低字节是鼠标的 X坐标,高字节是鼠标的 Y坐标 。
命令消息的描述命令消息的描述2.命令消息 选择菜单项、单击工具栏按钮等都可以
产生命令消息,从基类 CCmdTarget派生的类都能处理命令消息 描述:message : WM_COMMAND wParam :低 16位为命令 ID、高 16位为0
lParam : 0L
控件消息的描述控件消息的描述3.控件消息 当控件事件发生时,如改变文本框控件的内容、选择列表框控件中某一选项产生控件消息,由控件所属的对话框类处理描述:message : WM_NOTIFY wParam :控件 ID lParam :指向 NMHDR的指针, NMH
DR是包含了消息内容的一个结构
消息宏前缀消息宏前缀 前缀 消息分类
BM 按钮控制消息
CB 组合框控制消息
DMEM
默认下压式按钮控制消息编辑控制消息
LBSBMWM
列表框控制消息滚动条控制消息窗口消息
3.3.2 3.3.2 消息映射系统消息映射系统MFC 消息映射由两大块组成:1. CCmdTarget 的派生类
每个子类都能接收和处理消息,并定义了一个消息映射表
2. 消息映射。 MFC提供了 3 个宏管理消息映射。DECLARE_MESSAGE_MAP()BEGIN_MESSAGE_MAP()END_MESSAGE_MAP()
MFCMFC 消息映射原理消息映射原理应用程序开始运行后有一个从 CWinApp派生的对象,等待和处理消息的函数是应用程序类的 RUN() 函数。
RUN() 函数将接收到的消息都交给主窗口的窗口函数 OnWndMsg() ,由 OnWndMsg() 函数负责将消息分类并交予不同的消息处理函数去处理。
消息映射表消息映射表MFC 在每一个能够接收和处理消息类中,
定义一个消息和消息处理函数静态对照表,该表称为消息映射表。该类能够处理的所有的消息及其对应的消息处理函数的地址都列在该表中。
在类中加入静态消息映射表在类中加入静态消息映射表在 .h 文件中加入: DECLARE_MESSAGE_MAP()在 .CPP 文件中加入:
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
ON_WM_PAINT() ......END_MESSAGE_MAp()
消息映射表示例消息映射表示例BEGIN_MESSAGE_MAP(CExam1_1App, CWinApp)
//{{AFX_MSG_MAP(CExam1_1App)ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
//}}AFX_MSG_MAPON_COMMAND(ID_FILE_NEW, CWinAp
p::OnFileNew)ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
消息处理宏格式消息处理宏格式消息类型 宏格式 参数
预定 义 窗 口消息
ON_WM_XXX 无
命令消息 ON_COMMAND
命令 ID ,消息处理函数名
更新命令消息
ON_UPDATE_COMMAND_UI
命令 ID ,消息处理函数名
控件消息 ON_XXX 控件 ID ,消息处理函数名
用 户自定 义消息
ON_MESSAGE
自定义消息 ID ,消息处理函数名
例 3-3 创建一个单文档的 MFC 应用
程序 Exam3_3 ,并实现功能:当在视图中双击鼠标右键时,弹出对话框,显示鼠标的坐标。
如何处理窗口消息如何处理窗口消息
所有基类均没定义该消息的处理函数
窗口类 ::OnWndMsg(...)
是窗口消息
搜索窗口类的消息映射表
找到 ?
继续搜索基类消息映射表
窗口类 ::DefWndProc(...)
执行消息处理函数
命令消息或控件消息处理
找到消息处理函数
yesno
yesno
3.3.3 3.3.3 消息处理路径消息处理路径窗口消息的处理:OnWndMsg()搜索窗口类的消息映射表,
如果找到了匹配的消息处理函数,就执行消息处理函数
如果找不到,继续搜索该窗口类的基类,如果找到了匹配的消息处理函数,就执行消息处理函数;
如果还没有找到,则把消息交给默认窗口函数 DefWindowProc() 处理
如何处理命令消息如何处理命令消息从理论上讲,所有从基类 CCmdTarget
类派生的类均可处理命令消息, MFC 应用程序框架将依次检查基本类的消息映射表。
视图类 文档类 文档模板类
框架窗口类应用程序类界面变灰
命令消息的处理命令消息的处理 OnWndMsg() 函数会将命令消息分发给窗口
类的 OnCommand() 函数 OnCommand() 函数调用成员函数 OnCmdM
sg() 函数,该函数依次搜索视图类、文档类、文档模板类、框架窗口类和应用程序类及其基类中的消息映射表,搜索到消息处理函数,
搜索到消息处理函数则执行消息处理函数 如果全部查找完毕,依然不能处理,则该命令
消息所对应的界面元素变灰。
如何处理控件消息如何处理控件消息
OnWndMsg(...)
OnNotify(...)
控件窗口类处理消息
控件窗口类能处理?
控件的父 窗口类 :: OnWndMsg(...)
yes
no
控件消息的处理控件消息的处理把消息交给控件所属的类,如果能够处
理,执行消息处理函数如果控件所属的类不能处理,调用控件
的父窗口对应类的 OnCmdMsg() ,搜索父窗口对应类的消息映射表,以获得处理该消息的函数