1. Windows应用程序操作系统,计算机硬件之间的相互关系
Windows程序设计是一种完全不同于传统的DOS方式的程序设计方法,它是一种事件驱动方式的程序设计模式,不由事件的顺序来控制,由事件的发生来控制,所有的事件都是无序的,事件驱动程序设计是密切围绕消息的产生于处理而展开的,一条消息是关于发生的事件的消息。在程序提供给用户的界面中有许多可操作的可视对象。用户从所有可能的操作中任意选择,被选择的操作会产生某些特定的事件,这些事件发生后的结果是向程序中的某些对象发出消息,然后这些对象调用相应的消息处理函数来完成特定的操作。WINDOWS应用程序最大的特点就是程序没有固定的流程,而只是针对某个事件的处理有特定的子流程,WINDOWS应用程序就是由许多这样的子流程构成的。
WINDOWS应用程序在本质上是面向对象的。程序提供给用户界面的可视对象在程序的内部一般也是一个对象,用户对可视对象的操作通过事件驱动模式触发相应对象的可用方法。程序的运行过程就是用户的外部操作不断产生事件,这些事件又被相应的对象处理的过程。
向下的箭头③表示应用程序可以通知操作系统执行某个具体的动作,如操作系统能够控制声卡发出声音,但它并不知道应该何时发出何种声音,需要应用程序告诉操作系统该发出什么样的声音。这个关系好比有个机器人能够完成行走的功能,但是,如果人们不告诉它往哪个方向上走,机器人是不会主动行走的。这里的机器人就是操作系统,人们就是应用程序。
向上的箭头④表示操作系统能够将输入设备的变化上传给应用程序。如用户在某个程序活动时按了一下键盘,操作系统马上能够感知到这一事件,并且能够知道用户按下的是哪一个键,操作系统并不决定对这一事件如何作出反应,而是将这一事件转交给应用程序,由应用程序决定如何对这一事件作出反应。好比有个蚊子叮了我们一口,我们的神经末梢(相当于操作系统)马上感知到这一事件,并传递给了我们的大脑(相当于应用程序),我们的大脑最终决定如何对这一事件作出反应,如将蚊子赶走,或是将蚊子拍死。对事件作出反应的过程就是消息响应。
2. Windows程序的入口函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTRlpCmdline, int nCmdShow);掌握WinMain函数前面的类型以及里面的参数
int : 函数的返回类型
WINAPI: 表明是一个API函数,由操作系统调用
HINSTANCEhInstance: 应用程序实例句柄
HINSTANCEhPrevInstance:应用程序实例句柄
LPSTR lpCmdline: 命令行参数
int nCmdShow: 窗口显示状态
3. 消息
l Windows发出的一个通知,或者产生的一个信号,告诉应用程序某个事情发生了,这种信号代表某种操作,把这种信号称为“消息”。Windows是靠消息来驱动的,Windows操作系统是一个基于消息的操作系统,其程序总要同消息打交道,这正是Windows程序同DOS程序不同的地方。实际上,Windows系统通过Windows消息告诉所有应用程序发生了什么事件,例如用户点击了鼠标、用户点击了键盘的哪个键等,每个应用程序都有消息处理或一组消息响应函数,用于对消息进行响应。
Windows操作系统中定义了900余个Windows消息,系统将用户的输入传给应用程序,然后又为每个输入产生消息。此外,系统还为应用程序的变化产生消息,如窗口的尺寸发生了变化等。应用程序自已也可能产生消息,用于对应用程序内部发生的特殊事件进行处理或其它应用程序之间的通信。
l 消息分类
标准消息:除WM_COMMAND外,以WM开头的
命令消息:来自菜单,工具条,加速键的消息
通告消息:由控件产生的消息。
l Win32中的消息循环
while(GetMessage (&msg, NULL, 0, 0)) //从消息队列中获取消息
{
TranslateMessage(&msg) ; //转换某些键盘消息,按键时系统产生虚拟键消息(VK_TAB)
DispatchMessage (&msg) ; //将消息发送给窗口过程
}
GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINTwMsgFilterMax);检索消息队列,把消息放入lpMsg指向的MSG结构中
lpMsg:指向MSG结构的指针
hWnd:接受消息的窗口句柄,通常设置为NULL,检索当前程序的窗口消息
wMsgFilterMin:检索的最小消息值,一般情况下设置为0
wMsgFilterMax:检索的最大消息值,设置为0,两个都设置为0,说明检索所有消息。
该函数知道检索到WM_QUIT消息时返回FALSE,
TranslateMessage(&msg);用于将虚拟键消息转换为字符消息。字符消息被投递到调用线程的消息队列中,当下一次调用GetMessage函数时被取出。当我们敲键盘某个字符时,系统将产生WM_KEYDOWN和WM_KEYUP消息。这两个消息的附加参数包含的是虚拟键代码和扫描等信息。一般我们在程序中需要得到某个字符的ASCII码时,TranslateMessage就可以将WM_KEYDOWN和WM_KEYUP消息的组合转换成一条WM_CHAR消息(该消息的wParam参数包含字符的ASCII),并将转换后的消息投递到调用线程的消息队列中,它不会修改原有的消息,只是产生新的消息。
DispatchMessage(&msg); 派发一个消息到窗口过程,由窗口过程对消息进行处理。(实际上是将消息传回给操作系统,由操作系统调用窗口过程函数对消息进行处理或响应)
l 消息的简单传递过程:
发生用户输入事件,系统专职函数对其加工形成消息,再由这些函数投递到系统消息队列。在系统消息队列进行的消息循环中,消息取操作按照时间先后次序读取消息,根据消息hWnd参数,将消息投递到进程消息队列。在进程的消息循环中,消息的取操作也是按照时间次序读取消息,呼叫DisPatchMessage,根据消息hWnd参数,将消息投递给具体窗口。窗口事件发布函数在接到消息后,根据消息的message参数,进行解析,选择代码段进行执行。
对一些特定的窗口函数呼叫,系统产生消息,这些消息被发送到对应窗口,窗口事件发布函数在接到消息后,根据消息的message参数,进行解析,选择功能函数(或者代码段)执行。
对一些比较特别的消息的处理:例如WM_PAINT,系统在处理WM_PAINT时,同一个窗口的多个 WM_PAINT被合并成为一个 WM_PAINT 消息, 合并所有的无效区域成为一个无效区域,合并WM_PAIN的目的是为了减少刷新窗口的次数,窗口刷新一次是要消耗很多系统资源的。
l 消息的发送
Windows提供了三个API函数用于发送消息,这三个函数是:SendMessage、PostMessage和SendDlgItemMessage。
4. API
应用程序是如何通知操作系统执行某个功能的呢?有过编程经验的读者都应该知道,在应用程序中要完成某个功能,都是以函数调用的形式实现的,同样,应用程序也是以函数调用的方式来通知操作系统执行相应的功能的。操作系统所能够完成的每一个特殊功能通常都有一个函数与其对应,也就是说,操作系统把它所能够完成的功能以函数的形式提供给应用程序使用,应用程序对这些函数的调用就叫做系统调用,这些函数的集合就是Windows操作系统提供给应用程序编程的接口(Application Programming Interface),简称Windows API。如CreateWindow就是一个API函数,应用程序中调用这个函数,操作系统就会按照该函数提供的参数信息产生一个相应的窗口。
Win32 API 即为Microsoft 32位平台的应用程序编程接口。所有在Win32平台上运行的应用程序都可以调用这些函数。使用Win32 API,应用程序可以充分挖掘Windows的32位操作系统的潜力。Mircrosoft的所有 32 位平台都支持统一的API,包括函数、结构、消息、宏及接口。使用Win32 API不但可以开发出在各种平台上都能成功运行的应用程序,而且也可以充分利用每个平台特有的功能和属性。
5. 消息及消息队列
操作系统是怎样将感知到的事件传递给应用程序的呢?这是通过消息机制(Message)来实现的。操作系统将每个事件都包装成一个称为消息的结构体MSG来传递给应用程序,参看MSDN。
MSG结构定义如下:
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;
6. 句柄
资源的标识,操作系统要管理和操作这些资源,都是通过句柄来找到对应的资源。可以相当于C语言中的指针。按资源的类型,又可将句柄细分成图标句柄(HICON),光标句柄(HCURSOR),窗口句柄(HWND),应用程序实例句柄(HINSTANCE)等等各种类型的句柄。操作系统给每一个窗口指定的一个唯一的标识号即窗口句柄。
7. 窗口的创建
Ø 窗口创建:
A 设计一个窗口类 WNDCLASS
B注册窗口类 RegisterClass
C创建窗口 CreateWindow
D显示以及更新窗口 ShowWindow UpdateWindow
Ø 窗口类型:在我们的程序中经常要用到一类变量,这个变量里的每一位(bit)都对应某一种特性。当该变量的某位为1时,表示有该位对应的那种特性,当该位为0时,即没有该位所对应的特性。当变量中的某几位同时为1时,就表示同时具有几种特性的组合。一个变量中的哪一位代表哪种意义,不容易记忆,所以我们经常根据特征的英文拼写的大写去定义一些宏,该宏所对应的数值中仅有与该特征相对应的那一位(bit)为1,其余的bit都为0。我们使用goto definition就能发现CS_VREDRAW=0x0001,CS_HREDRAW=0x0002,CS_DBLCLKS =0x0008,CS_NOCLOSE=0x0200。他们的共同点就是只有一位为1,其余位都为0。如果我们希望某一变量的数值既有CS_VREDRAW特性,又有CS_HREDRAW特性,我们只需使用二进制OR(|)操作符将他们进行或运算相组合,如style=CS_VREDRAW | CS_HREDRAW | CS_NOCLOSE。如果我们希望在某一变量原有的几个特征上去掉其中一个特征,用取反(~)之后再进行与(&)运算,就能够实现,如在刚才的style的基础上去掉CS_NOCLOSE特征,可以用style & ~CS_NOCLOSE实现。
8. 窗口过程函数
窗口的过程函数,也称回调函数。回调函数的原理是这样的,当应用程序收到给某一窗口的消息时(还记得前面讲过的消息通常与窗口相关的吗?),就应该调用某一函数来处理这条消息。这一调用过程不用应用程序自己来实施,而由操作系统来完成,但是,回调函数本身的代码必须由应用程序自己完成。对于一条消息,操作系统到底调用应用程序中的哪个函数(回调函数)来处理呢?操作系统调用的就是接受消息的窗口所属的类型中的lpfnWndProc成员指定的函数。每一种不同类型的窗口都有自己专用的回调函数,该函数就是通过lpfnWndProc成员指定的。 并且,对于消息队列中的WM_PAINT是放在消息队列的最后来处理的。
9. MFC单文档框架简介
在MFC的单文档中创建好后有以下几个类:CAboutDlg、CMainFrame:是CXXXView的父类,也就是说视窗VIEW显示在主框窗MAINFRAME的客户区中。CXXXApp :主要的作用是用来处理消息的,它统一管理程序收到的所有的消息,然后把消息分配到相应的对象、CXXXDoc、CXXXView:作用是显示数据,而数据的来源是类CMYDOC,在MFC程序中,程序的数据是放在文档当中的,而显示数据则是利用视窗方式,文档与视窗分离带来的好处就是一个文档可以同时具有多个视窗,每个视窗只显示文档中的一部分数据,或者以特定的风格显示文档中的数据。文档与视窗分离的另一个好处就是在程序中可以处理多个文档,通过对不同的视窗的处理达到对不同的文档分别处理的目的。
l 类CXXXApp
类CXXXApp是应用程序运行的基础,由class CSIDApp : public CWinApp 可以看出这个类是由MFC中的类CWinApp派生来的。在这个类中除了有一般类都有的构造函数,一个重要的成员函数就是InitInstance(),我们知道,在Windows环境下面可以运行同一程序的多个实例,函数InitInstance()的作用就是在生成的一个新的实例的时候,完成一些初始化的工作。CWinApptheApp;作用就是生成一个CWinApp类型的对象,生成的时候系统会主动调用InitInstance()函数完成一些必要的初始化工作。
Ø InitInstance()
下面研它所做的事情,CSingleDocTemplate* pDocTemplate;它定义了一个文档模板对象指针pDocTemplate,通过new操作符,系统动态生成了这个文档模板对象,然后使用AddDocTemplate()函数把这个文档模板对象加入到应用程序所维护的文档模板链表当中,这个文档模板pDocTemplate的作用就是把程序用到的框架窗口CMainFrame,文档CXXXDoc,视窗CXXXView与应用对象CXXXApp联系起来。CXXXApp类提供了用户与Windows应用程序之间进行交流的界面。在生成这个类的对象后,这个对象自动地把自身与Windows系统建立联系,接收Windows传送的消息,并交给程序中相应的对象去处理,这就免去了程序员许多的工作,使得开发C++的Windows程序变得简单方便。
l 类CMainFrame
类CMainFrame是由MFC中的CFrameWnd派生来的,所以它也是一个框架窗口。前面已经指出,CMainFrame是类CXXXView的父类,也就是说CXXXView类的对象显示在主框架窗口的客户区中。在类CMainFrame中,系统已经从类CFrameWnd那里继承了处理窗口的一般事件的Windows消息,比如:改变窗口的大小,窗口最小化等等的成员函数,因此编程的时候程序员不需要再关心此类消息的处理,从而减轻了程序员的负担。当然,如果确实需要重新编写处理此类消息的成员函数,则需要对原有的成员函数进行重载。
在MFC程序中,我们并不需要经常对CMainFrame类进行操作,更多的是对视窗类进行操作,达到对程序中的数据进行编辑和修改的目的。
最后要指出的是,在MFC方式的程序中,当程序的一个实例被运行的时候,系统根据前面在CXXXApp类中介绍的文档模板对象自动生成类CMainFrame,CXXXView,CXXXDoc的对象,而不需要程序员主动地去创建这些类的对象。
l 类CXXXView与CXXXDoc
之所以把CXXXView类和CXXXDoc类一起介绍是因为这两个类是密切相关的,文档是由文档模板对象生成的,并由应用程序对象管理,而用户则是通过与文档相联系的视窗对象来存储、管理应用程序的数据,用户与文档之间的交互则是通过与文档相关联的视窗对象来进行的。
生成一个新的文档的时候,MFC程序同时生成一个框架窗口,并且在框架窗口的客户区中生成一个视窗对象作为框架窗口的子窗口,这个子窗口以可视化的方式表现文档中的内容。视窗的重要功能就是负责处理用户的鼠标、键盘等操作,通过对视窗对象的处理达到处理文档对象的目的。
要指出的一点是,Windows应用程序分单文档界面SDI和多文档界面MDI两种,在单文档界面中,文档窗口与主框架窗口是同一概念。而这时的视窗对象则是显示在文档窗口的客户区当中,此时文档窗口是主框架窗口,即类CMainFrame的对象。
文档类是用来存放程序中的数据的,一个文档可以对应多个视窗。
10. MFC
微软基础类库(MFC)是微软为Windows程序员提供的一个面向对象的Windows编程框架。 MFC就是利用面向对象的思想(面向对象分析能力。面向对象的分析要求搞清楚一个系统中有哪些类、各个类之间有哪些联系,尤其是在编写基于文档/视图结构的应用程序时),将Windows大部分API函数封装起来的一个浩瀚的类库,利用MFC编写程序本质上就是选择该类库中合适的类,并调用其下相应成员函数来完成某个功能。MFC只是用类的形式封装了SDK函数。MFC库采用的则是自底向上的设计方法。所谓的框架是指为某一特定目的实现一个基本的、可执行的架构。框架中已经包含了应用程序从启动到运行的主要流程,流程中那些无法预先确定的步骤留给用户来实现。程序运行时,框架系统自动调用用户实现的功能组件。
MFC实际上是微软提供的,用于在C++环境下编写应用程序的一个框架和引擎,VC++是WinOS下开发人员使用的专业C++ SDK(SDK,StandardSoftWare Develop Kit,专业软件开发平台),MFC就是挂在它之上的一个输助软件开发包,MFC作为与VC++血肉相连的部分(注意C++和VC++的区别:C++是一种程序设计语言,是一种大家都承认的软件编制的通用规范,而VC++只是一个编译器,或者说是一种编译器+源程序编辑器的IDE,WS,PlatForm。
MFC类库可分为两个主要部分:(1)基础类(2)宏和全程函数。约定:以“Afx”为前缀除了数据库类函数和DDX(Dialog Data Exchange)函数外为全局函数。所有全程变量都是以“afx”为前缀,宏不带任何特别前缀,但是全部大写。
11. MFC六大关键技术
·MFC程序的初始化过程 ·运行时类型识别(RTTI)
·动态创建 ·永久保存
·消息映射 ·消息传递
12. MFC程序执行流程
一个MFC程序运行的一般过程如下:
(1)生成CWinApp的一个实例(调用CwinApp的构造函数),初始化全局对象;
(2)Win32入口程序函数WinMain调用函数AfxWinMain;
(3)AfxWinMain调用函数CWinApp的成员函数InitInstance;
(4)AfxWinMain调用函数CWinApp的成员函数Run;
(5)AfxWinMain函数返回到WinMain,WimMain结束,程序结束。
13. MFC中的类以及的层次关系
打开MSDN,选中窗口左半部分的“搜索”选项卡,在待搜索的编辑框中输入“hierarchy chart”后按回车,MSDN就把MFC的层次结构图显示在窗口的右半部分。
l 根类CObject
CObject是MFC中一个非常重要的类,绝大部分MFC类都是以CObject做为基类,它是CCmdTarget类和CWnd类的父类。自己所编写的类一般以其作为基类,了解它们对于深入理解MFC具有重要意义。CObject类是MFC的抽象基类(不能派生对象),是MFC中多数类和用户自定义类的根类,它为程序员提供了许多公共操作和基本服务。主要包括:对象的动态建立与删除、序列化(即串行化)的支持、对象诊断输出、运行时信息以及集合类的兼容等。它的作用是,使得MFC以及基于MFC的应用程序更加稳固和易于调试。
l 消息映射类CCmdTarget
该类是CObject的子类,是MFC类库中所有具有消息映射属性的基类,消息映射规定了当对象接到命令消息时,应调用哪一个函数对该消息进行处理。命令消息是来自菜单项、命令按钮和加速键的信息,由CCmdTarget派生出的主框架类包括CView、CWinApp、CDocument、CWnd和CframeWnd都可处理命令消息。程序员若需要一个新类来处理消息时,可以从CCmdTarget派生出一个新类。一般程序员很少从CCmdTarget类中直接派生出新类,而是从其子类CView、CWinApp来派生。
l 窗口应用程序类CWinApp
每一个使用MFC的应用程序只能包含一个从CWndApp派生的应用程序对象,当VC的其它全局对象被构造时,这个对象也同时被构造,当Windows调用WinMain()函数时,产生的对象已经有效了。从CWinApp实例化的应用程序对象是一个全局变量,在程序运行中该对象可以与其它对象相互。
Ø 访问CWinApp对象以及全局函数。
1) AfxGetApp():获得一指向CWinApp对象的指针。
2) AfxGetResourceHabdle():获得一应用程序资源的句柄。
3) AfxGetAppName():获得一指针,它指向一个包含应用程序名的字符串。相反,如果有一个指向CWinApp对象的指针,使用m_pszExename可以取得应用程序的名称。
Ø CWinApp的公共数据成员
1) m_pszAppName:指定应用程序的名称。
2) m_nCmdShow:指定窗口最初将如何显示。
3) m_pMainWnd:包含一个指针,它指向一个应用程序的主窗口。
Ø CWinApp的公共成员函数
1) LoadCursor:调取光标资源。
2) LoadStandardCursor:调取Windows预定义光标,在windows.h中指定IDC常量。
3) LoadIcon:调取一个图标资源。
4) LoadStandardIcon:调取Windows预定义的图标,在windows.h中 指定IDI常量。
5) OpenDocumentFile:框架调用此函数打开一个指定的文档。
Ø CWinApp的可超载(overload)的函数
1) InitApplication:重载以执行任何应用程序层次上的初始化。
2) InitInstance:重载以执行Windows对象实例的初始化,诸如建立用户窗口对象等。
3) Run:运行缺省的消息循环,重载该函数以自定义消息循环。
4) OnIdle:重载以执行任何应用程序指定的空闲时间处理。
5) PreTranslateMessage:在窗口消息被TranslateMessage()和DispatchMessage()处理之前过滤它们。
l 应用程序线程类CWinThread
该类为线程的基类,CWinApp是从CWinThread派生而来。该对象描述程序线程的执行,主线程的执行通常由一个CWinApp的派生对象提供。
Ø CWinThread的公共数据成员
1) m_hThread:当前线程的句柄
2) m_nThreadID:当前线程的ID值
3) m_pMainWnd:指向程序主窗口指针。
Ø CWinThread的公共成员函数
1) GetMainWnd:获取一个指向此线程的的主窗口指针。
2) GetThreadPriority:获取当前线程的优先权。
3) ResumeThread:减小一个线程的挂起计数。
l 文档/视图类
文档对象由文档模板对象创建,管理应用程序的数据。视图对象表示一个窗口的客户区,它显示文档数据并允许用户与之交互。
1) CDocTemplate类:文档模板的基类。它负责协调文档、视窗和框架窗口的创建。
2) CMultiDocTemplate类:多文档界面(MDI)的文档模板。
3) CSingleDocTemplate类:单文档界面(SDI)的文档模板。
4) CDocument:应用程序所用文档的基类。
5) CView:显示文档数据的应用程序专用视图的基类。
l 窗口类CWnd
CWnd类提供了MFC中所有窗口类的基类。CWnd与Windows窗口有所不同,但他们又是紧密相连的。CWnd对象是由CWnd的构造函数和析构函数建立和取消的,而Windows窗口与此不同,它是Windows的一个结构,是由create成员函数建立的,DestroyWindow函数破坏Windows窗口而不是破坏对象。
Ø CWnd类的公共数据成员
1) m_hWnd:标识连接到该CWnd对象上的HWND。
Ø CWnd类的初始化函数
1) Create:创建并初始化与该CWnd对象相联系的子窗口。
2) PreCreateWindow:在建立连接到这个CWnd对象的Windows窗口之前调用此函数。
3) GetStyle:返回当前窗口的风格。
4) SubclassWindow:将一个窗口连接给一个CWnd对象并使其通过该CWnd的消息映射传递消息。
5) FromHandle:给出一个窗口句柄时,返回一个CWnd对象的指针。
6) GetSafeHwnd:返回m_hWnd;若此指针为NULL,则返回NULL。
Ø CWnd类的窗口状态函数
1) EnableWindow:允许或禁止鼠标和键盘输入。
2) GetActiveWindow:获取活动的窗口。
3) SetActiveWindow:激活窗口。
4) SetFocus:要求输入焦点。
5) GetFocus:获取当前具有输入焦点的CWnd。
Ø 窗口的大小和位置函数
1) GetWindowPlacement:获取一个窗口显示状态及正常、最小化的和最大化的窗口位置
2) SetWindowPlacement:设置一个窗口显示状态及正常、最小化的和最大化的窗口位置。
3) MoveWindow:改变CWnd的位置和大小。
4) SetWindowPos:改变子窗口、弹出式窗口和顶层窗口的大小、位置和次序。
5) GetWindowRect:获取CWnd的屏幕坐标。
6) GetClientRect:获取CWnd客户区的大小。
Ø 访问窗口函数
1) FindWindow:返回由窗口类和窗口名标识的窗口句柄。
2) GetTopWindow:返回属于CWnd的第一个子窗口。
3) GetParent:获取CWnd的父窗口。
4) GetDlgItem:由指定的对话框获取具有指定ID的控件。
5) GetDescendantWindow:查询所有的派生窗口,并返回具有指定ID的窗口。
6) CenterWindow:将一窗口相对于其父窗口中心定位。
Ø 更新/绘制函数
1) GetDC:获取一个客户区的设备描述表。
2) GetWindowDC:获取整个窗口的,包括标题栏,菜单和滚动条的设备描述表。
3) ReleaseDC:释放客户区和窗口的设备描述表。
4) Invalidate:使整个客户区无效。
5) InvalidateRect:这个函数将给定的客户区矩形加入CWnd更新区域,使该区域无效。
6) ShowWindow:显示或隐藏窗口。
Ø 窗口文本函数
1) SetWindowText:将窗口的标题设置为指定的文本。
2) GetWindowText:返回窗口的标题。
3) SetFont:设置当前的字体。
4) GetFont:获取当前的字体。
Ø 滚动函数
1) GetScrollPos:获取滚动条的当前位置。
2) ScrollWindow:卷滚客户区的内容。
3) SetScrollPos:设置一个滚动框的当前位置,若指定新位置,则重画滚动条。
4) SetScrollRange:设置给定滚动条的最小和最大位置值。
Ø 菜单函数
1) GetMenu:获取指向指定菜单的指针。
2) SetMenu:将菜单设置为指定的菜单。
3) HiliteMenuItem:在一顶层菜单上高亮度显示或除去高亮度显示。
Ø 剪贴板函数
1) OpenClipboard:打开剪贴板。
2) GetClipboardOwner:获取指向剪贴板的当前拥有者的指针。
3) GetOpenCilpboardWindow:获取指向当前打开剪贴板窗口的指针。
l CFrameWnd类
1) CFrameWnd:SDI应用程序的主框架窗口的基类,它是其它框架窗口类的基类。
2) CMDIFrameWnd:MDI程序的主框架窗口的基类。
3) CMDIChildWnd:MDI程序的文档框架窗口的基类。
l 视图类
1) CView:查看文档数据的应用程序视图的基类。
2) CScrollView:具有滚动功能的视图的基类。从其派生的视图类可以自动实现滚动。
3) CFormView:从其派生的类用于实现基于对话模板资源的用户界面。
4) CRecordView:提供直接链接到ODBC记录集的表单视图。
5) CEditView:包含Windows标准编辑控件的视图。
l 对话框类
由于对话框是一个特殊窗口,所以该类是从CWnd类中派生出来的。对话框子层次结构包括通用对话框类CDialog以及支持字体选择、打印、替换文本等公共对话框子类。
1) CDialog:所有对话框(模态或者非模态)的基类。
2) CCommonDialog:所有通用对话框类的基类。
3) CFileDialog:打开或保存文件的标准对话框。
4) CColorDialog:用于选择颜色的的标准对话框。
5) CFontDialog:选择字体的标准对话框。
6) CPrintDialog:用于打印文件的标准对话框。
l 控件类
控件子层次包含若干个可视控件,使用这些类可建立静态文本、命令按钮、位图按钮、列表框、组合框、滚动条和编辑框等,这些可视控件为Windows应用程序提供了各种输入和显示界面。
1) CStatic:静态文本控件窗口。用于标注、分隔对话框和窗口中的其他控件。
2) CButton:按钮控件窗口。该类为对话框或窗口中的按钮、检查框或单选按钮提供一个总的接口。
3) CEdit:编辑控件窗口。编辑控制用于接收用户的文字输入。
4) CScrollBar:滚动条控件窗口。该类提供控制条的功能,用做对话框或窗口中的一个控件,可通过它在某一范围内定位。
5) CSliderCtrl:滑动条控件窗口,包含一个可移动的滑标,用户可以移动滑标选择一个值或一个范围。
6) CListBox:列表框控件窗口。列表框用于显示一组列表项,用户可以进行观察和选择。
7) CComboBoxl:组合框控件窗口,它由一个编辑控制和一个列表框组成。
8) CBitmapButton:以位图而非文字作为标题的按钮。
9) CAnimateCtrl:动画显示控件,以Windows标准视频/音频格式显示AVI剪辑。
10) CTreeCtrl:树形查看控件,显示项的层次列表结构。
11) CListCtrl:管理由图标和标签组成的列表项,可以4种方式(图标、小图标、列表和详细资料)显示列表项内容。
l 控件栏类
控件栏类为工具条、状态条、对话条和分割窗口建立模型,它负责管理工具条、状态条、对话条的一些成员函数。控制条指的是连接在窗口框架顶部或底部的小窗口。
1) CControlBox:MFC控件栏的基类。
2) CToolBar:包含位图按钮的工具栏控件窗口。
3) CStatusBar:状态栏控件窗口的基类。
4) CDialogBar:基于对话框模板资源的控件栏。
5) CStatusBarCtrl:分成多个面板的水平窗口,用于显示应用程序和状态信息。
6) CToolBarCtrl:Windows工具栏控件,包含按钮和可选空间的窗口。
14. 预定义的宏
Windows库中包含了大量支持CObject类及其子类的宏。
l 消息映射宏
Windows是一个消息驱动的操作系统,VC提供了与消息有关的宏,它们是:
1) DECLARE_MESSAGE_MAP(初始化消息映射表),在类的声明中
2) BEGIN_MESSAGE_MAP(开始用户消息映射),在类的定义中
3) END_MESSAGE_MAP(结束用户消息映射),在类的定义中
l 确定对象所属类的信息的宏
每一个从CObject派生的类都和一个对应的CRuntimeClass结构相联系,在程序运行时,用户可以根据该结构掌握对象的信息以及该类的基类的信息。另外,通过CObject中的成员函数IsKindOf可确定某对象是否属于一个指定的类或由指定的类派生。
为了使从CObject派生的类的对象能够在程序运行时动态创建,VC提供了动态创建对象的宏,它们是:
1) DECLARE_DYNCREATE (放在类的声明文件中,声明动态创建对象)
2) IMPLEMENT_DYNCREATE(放在类的实现文件中,表明实现对象的动态创建)。
l 实时运行类结构信息宏
该宏的结构是RUNTIME_CLASS(),在应用程序使用该宏,可以在运行时由类“名称”获得有关类结构的信息。方法为通过CObject的成员函数IsKindOf()来确定。
l 串行化宏
从一个文件中读出或向某一文件中写入某对象的过程叫串行化。若想使从CObject派生的类可串行化,应该按下列步骤使用宏:
1) 在从CObject派生的类的定义中使用DECLARE_SERIAL宏
2) 在从CObject派生的类的实现文件中使用IMPLEMENT_SERIAL 宏
3) 在从CObject派生类中重载Serialize成员函数。
MFC 中还包含了许多完成其它功能的宏,如:可用于诊断服务、异常处理、应用信息与管理等。
15. MFC应用程序架构
l MFC是一种应用程序架构。
应用程序架构就是在特定的领域中程序之间的共同结构,它是某领域中的程序员,依照共同结构来开发程序,使得程序之间具有一致性,增加了程序的清晰度,以此来降低程序的设计和维护费用。从应用方面讲,架构就是整个或部分系统的可复用设计,表现为一组抽象组件及其实例间交互的方法;从目的方面讲架构就是可被应用程序开发者定制的应用骨架。可以说,一个应用程序架构就是一个可复用的设计组件。它规定了应用程序的体系结构,阐明了整个设计、协作组件之间的依赖关系、责任分配和控制流程。应用程序架构包括应用程序的总体组织和全局控制、通讯协议、同步、数据存取,给设计元素分配特定功能,设计元素的组织,规模和性能,以及在各个设计方案间进行选择。
l 软件复用
软件复用是指在两次或多次不同的软件开发过程中重复使用相同或相近软件元素的过程。软件元素包括程序代码、测试用例、设计文档、设计过程、需求分析文档甚至领域知识。通常,把这种可复用的元素称作软构件,可复用的软件元素越大,复用的粒度越大。不管是多大粒度的复用,它们都是软件复用。
根据复用的程度,可以将软件复用分为以下几类:
1) 源代码复用。该方式是应用最为广泛的复用方式,它不仅表现在复用现有的代码,例如已经开发完的类、源文件、LIB库,还表现在每一代码的实现过程中。
2) 模块复用。典型的例子是Windows下的动态链接库程序DLL,当前模块复用比较活跃的技术有COM组件技术,每个COM组件有自己的属性和操作,是一个相对独立运行的实体,使用该技术构造应用程序就像是搭积木一样,搞清楚每个程序这个“建筑”有哪些积木块组成。
3) 接口复用。在一个程序定义好一套接口,而另一个应用程序可以依据这套接口来详细设计,接口复用在VC下表现为一些类的虚函数。微软的Visual Studio的IDE编程、IE扩展编程、屏幕保护程序等都是接口复用的例子。接口的定义使得软件的开发可以扩展到用户一级,由用户进行软件功能的深化或定制。
4) 应用程序复用。在一个应用程序中调用另一个程序,创建一个新的进程就是应用程序复用的典型例子。在Win32平台下,一般通过CreateProcess这个API函数和SHELL方面的API函数ShellExecute来创建新的进程。
5) 应用程序架构复用。
MFC就是实现了一种应用程序架构复用的类库。
应用程序架构本质上是一种软件高层次复用,它可以在具有相似需求的多个系统中得到复用,这比代码级的复用具有更大的意义。
应用程序架构有利于形成完整的软件生产线和软件工厂,并共享公共的架构,应用程序架构的可复用性使得我们可以使用第三方应用程序架构。
16.MFC应用程序的执行过程
l MFC程序的启动
第一、AFX内部初始化,包括应用程序对象状态初始化和主线程初始化
第二、执行由MFC框架提供的标准函数WinMain()
第三、调用CWinApp类的虚函数InitInstance(),初始化应用程序的当前实例
第四、调用CWinApp的Run()函数,运行消息循环和空闲处理
第五、当收到WM_QUIT消息,调用ExitInstance()函数,退出消息循环,并做应用程序退出时的清理工作
l MFC程序的退出
第一、用户单击主窗口的“关闭”按钮,发送MFC标准命令消息ID_APP_EXIT。
第二、主窗口处理WM_CLOSE消息。
第三、收到WM_QUIT消息后,退出消息循环,进而退出整个应用程序。
以下说明程序是如何退出的:
使用者选按【File/Close】,于是发出 WM_CLOSE。CMyFrameWnd 并没有设置WM_CLOSE 处理常式,于是交给预设之处理常式。预设函数对于WM_CLOSE 的处理方式是呼叫 ::DestroyWindow, 并因而发出WM_DESTROY。预设之WM_DESTROY 处理方式是呼叫::PostQuitMessage,因此发出WM_QUIT。CWinApp::Run 收到WM_QUIT 后会结束其内部之讯息回路, 然后呼叫ExitInstance,这是CWinApp 的㆒个虚拟函数。如果CMyWinApp 改写了ExitInstance , 那么CWinApp::Run 所呼叫的就是CMyWinApp::ExitInstance,否则就是 CWinApp::ExitInstance。最后回到 AfxWinMain,执行 AfxWinTerm,结束程序。
WM_CLOSE
DestroyWindow(),发出WM_DESTROY
PostQuitMessage发出WM_QUIT
CWinApp::Run调用CWinApp::ExitInstance
AfxWinMain 调用AfxWinTerm
特别注意:如果想手动发送WM_QUIT只能使用postmessage函数,而不能使用sendmessage函数
17.MFC对象和Windows对象的关系
l 应用的数据结构不同
MFC对象是相应C++类的实例,由MFC或者编程者定义
Windows对象是Windows操作系统内部结构的实例,通过句柄来引用
l 所处的层次不同
MFC对象是高层的
Windows对象是低层的
l 创建的机制不同
MFC对象是由程序通过调用类的构造函数直接创建
Windows对象是由相应的SDK函数创建的
l 使用的范围不同
MFC对象只服务于创建它的进城,对系统的其他进城来说是不可见、不可用的
l 销毁的方法不同
MFC对象随着析构函数的调用而消失
Windows对象必须由相应的Windows操作系统函数销毁