Windows应用程序的基本结构.ppt
《Windows应用程序的基本结构.ppt》由会员分享,可在线阅读,更多相关《Windows应用程序的基本结构.ppt(135页珍藏版)》请在三一办公上搜索。
1、Windows应用程序框架结构,哈尔滨工程大学,概述,理解Window编程所使用的事件驱动模型Window编程的基本框架,Windows平台下可视化开发工具,可视化开发系统集成了一系列系统可用资源和开发工具1、程序调试工具包括源程序语法检查、可执行程序修改和运行监视等2、源程序编辑器和编译器3、资源管理器,包括图形化窗口及组成元素的多种对象的编辑器4、系统函数库和系统函数开发工具5、可选择并构成具体语句或源程序结构的例程库及Help,Windows程序的特点,大致说来windows编程有两种方法:a.windows c方式(SDK),SDK编程就是直接调用windows的API进行编程;b.c
2、+方式:即对SDK函数进行包装,如VC的MFC,BCB的OWL等。MFC把这些API封闭起来,共有一百多个类组成.API,全称application program interface,意思是应用程序编程接口(说起API并不仅仅指windows而言,windows支持的API叫winapi)。winapi就是应用程序和windows之间通讯的一个编程界面。windows提供了上千个API函数,以方便程序员来编写应用程序。,Windows程序的特点,WinSDK程序设计就是API方式的windows程序设计。SDK,全称Software Developers Kit,意思是软件开发工具箱。MFC
3、,全称Microsoft Foundation Classes,伪软把WinAPI进行封装的类库。它是一个类的集合,通过覆盖WinAPI,为编程提供了一个面向对象的界面。它使windows程序员能够利用C+面象对象的特性进行编程,类似BCB的OWL,Delphi的VCL组件。它把那些进行SDK编程时最繁琐的部分提供给程序员,使之专注于功能的实现。你不妨把它想象成类似TC提供的函数库吧。,SDK编程,利用Windows API函数编写Windows应用程序必须首先了解以下内容:(1)窗口的概念(2)事件驱动的概念(3)句柄(4)消息,Windows的事件驱动机制,Dos的过程驱动与Windows
4、的事件驱动 在讲Window消息循环之前,我想先谈一下Dos与Windows驱动机制的区别:DOS程序主要使用顺序的,过程驱动的程序设计方法。顺序的,过程驱动的程序有一个明显的开始,明显的过程及一个明显的结束,因此程序能直接控制程序事件或过程的顺序。而Windows的驱动方式是事件驱动,就是不由事件的顺序来控制,而是由事件的发生来控制,所有的事件是无序的,作为一个windows程序员,在你编写程序时,你并不知道用户先按哪个按纽,也不知道程序先触发哪个消息。你的任务就是对正在开发的应用程序要发出或要接收的消息进行排序和管理。,过程驱动方法和事件驱动方法,Dos编程和Windows编程不同,dos
5、下的C编程的main()一样,windows下的入口是WinMain()函数。WinMain()所起的作用:初始化,展示窗口,销毁应用程序等。第一个参数:应用程序的当前实例句柄。第二个参数:应用程序的前一个实例句柄,别管它,对于Win32位而言,它一般是NULL.第三个参数:指向任何传给程序的命令行参数。PSTR代表指向字符串的指针。第四个参数:它告诉应用程序如何初始化窗口,如最大化,最小化等状态。,WinMain函数的功能,三个基本的组成部分:函数说明、初始化和消息循环,WinMain函数,注意!Win是多任务管理的,同一应用程序的多个窗口可能会同时存,Win系统对每个窗口的执行称为一个实例
6、,并用一个实例句柄来唯一标识,Windows常见的数据类型,在Windows.h中定义了Windows 应用程序中包含种类繁多的数据类型,重要的数据结构,两者句柄定义的不同,句柄(handle):在标准C库中句柄用来对文件输入输出。在Windows环境中,句柄是用来标识项目的,这些项目包括:*.模块(module)*.任务(task)*.实例(instance)*.文件(file)*.内存块(block of memory)*.菜单(menu)*.控制(control)*.字体(font)*.资源(resource),包括图标(icon),光标(cursor),字符串(string)*.GDI
7、对象(GDI object),包括位图(bitmap),画刷(brush),元文件(metafile),调色板(palette),画笔(pen),区域(region),以及设备描述表(device context)。WINDOWS程序中并不是用物理地址来标识一个内存块,文件,任务或动态装入模块的,相反的,WINDOWS API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。,句柄是什么?,在Win32里,句柄是指向一个无值型对象(void*)的指针,是一个4字节长的数据”。句柄并不是一个真正意义上的指针。从结构上看,句柄的确是一个指针,尽管它没有指向用于存储某个对象的
8、内存位置,而实际上句柄指向的是一个包含了对该对象进行的引用的位置。我们天气热摇扇子的时候只要抓住扇柄便可以控制整个扇子的运动了,在程序中也差不多是这个意思。通常一个句柄就可以传递我们所要做的事情。有经验的开发者肯定清楚,编写程序总是要和各种句柄打交道的,句柄是系统用来标识不同对象类型的工具,如窗口、菜单等,这些东西在系统中被视为不同类型的对象,用不同的句柄将他们区分开来。,句柄,常用句柄类型及其说明,应用程序通过句柄访问相应的对象信息,HWND窗口句柄HDC设备环境句柄HBITMAP位图句柄HCURSOR光标句柄HICON图标句柄HFONT字体句柄HMENU菜单句柄HPEN画笔句柄HFILE文
9、件句柄HBRUSH画刷句柄HINSTANCE当前实例句柄,Windows程序的特点,窗口句柄:系统通过窗口句柄来在整个系统中唯一标识一个窗口,发送一个消息时必须指定一个窗口句柄表明该消息由那个窗口接收。而每个窗口都会有自己的窗口过程,所以用户的输入就会被正确的处理。所有的命名采用了匈牙利表示法。如消息的前缀使用msg.句柄使用h.函数使用fn等。Windows程序则至少两个主程序,一个是WinMain(),int WINAPI WinMain(HINSTANCE hInstance,/handle to current instanceHINSTANCE hPrevInstance,/hand
10、le to previous instance LPSTR lpCmdLine,/command line int nCmdShow/show state);,Windows程序的特点,另一个是窗口过程函数WndProc,它的函数原型为:long FAR PASCAL WndProc(HWND hWnd,WORD message,WORD wParam,LONG lParam);窗口函数与回调函数:在Windows中,应用程序通过要求Windows完成指定操作,而承担这项通信任务的API函数就是Windows的相应窗口函数WndProc。应用程序不直接调用任何窗口函数,而是等待Windows调
11、用窗口函数,请求完成任务或返回信息。为保证Windows调用这个窗口函数,这个函数必须先向Windows登记,然后在Windows实施相应操作时回调,所以窗口函数又称为回调函数。WndProc是一个主回调函数,Windows至少有一个回调函数。典型的回调函数有窗口过程、对话框过程和钩子函数。实际上,也许有不止一个的窗口过程。例如,每一个不同的窗口类都有一个与之相对应的窗口过程。实例:在Windows中,能多次同时运行同一个应用程序,即运行多个副本,每个副本叫做一个“实例”。,Windows程序的特点,WinMain()函数的调用约定是PASCAL。在这里PASCAL是一个调用约定,由于这种方式
12、最早由PASCAL采用,所以这么叫。在MSDN中的C+Language Reference中,Calling Conventions这一章都是讲调用约定的。约定:微软重定义了许多约定类型,为的是可以让代码更容易跨平台或者跨编译器。其实,调用约定要解决两个问题,都是针对堆栈操作:1。参数传递的顺序(本质是压栈的顺序)2。谁负责平栈(调用者还是调用对象)一个函数的声明、定义和实现中的调用方式一般都一致。WINAPI标识符的定义是:#define WINAPI _stdcall,_stdcall指Window调用函数的一种方式,也就是如何在堆中存取函数参数的方式。许多Windows Api函数调用声
13、明为_stdcall方式。,调用方式,1、_stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上“”和参数的字节数(堆栈要求分配的字节数)。如:_TestMethod4 2、C调用约定(即用_cdecl关键字说明)按从右至左的顺序压参数入栈,由调用者把参数弹出栈。另外,在函数名修饰约定方面也有所不同。_cdecl是C和C程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方
14、式。VC将函数编译后会在函数名前面加上下划线前缀。是MFC缺省调用约定。如:_TestMethod,调用方式,CALLBACK和WINAPI函数是由你设计的函数,但你不能“显式”的调用它,而是Windows系统自己调用,例如窗口过程函数,枚举函数等,这是由Windows系统的工作机制决定的。至于这些函数为什么要是CALLBACK,且看下面详解:CALLBACK,WINAPI等在windef.h中被如下定义:#define CALLBACK _stdcall#define WINAPI _stdcall#define WINAPIV _cdecl#define APIENTRY WINAPI#d
15、efine APIPRIVATE _stdcall#define PASCAL _stdcall,调用方式举例,CALLBACK就是要VC编译器在编译时采取非默认(_cdecl)的方式(_stdcall),_stdcall和_cdecl最大的不同就是我前面说的“堆栈指针恢复的责任归属”-C编译器默认(_cdecl)是主函数来恢复stack指针SP,若指定关键字_stdcall,则编译器生成的码是由被调函数自己恢复SP,看看下面的例子:假如有一个函数声明如int _stdcall getMax(int a,int b);返回两者中较大值。在主函数中被调用,调用时VC造出的码如下:(其它编译器可能
16、不同)0040102B push 38h;参数b0040102D push 60h;a0040102F call ILT+15(_getMax)(0 x0040100f);call getMax().为 getMax()造出的汇编语句是00401020 push ebp00401021 mov ebp,esp.;其它指令00401026 pop ebp00401027 ret 8;在返回时修改堆栈指针,调用方式举例,若声明及定义时无 _stdcal,VC造出的码如下:0040102B push 38h 0040102D push 60h 0040102F call ILT+15(_getMax
17、)(0 x0040100f)00401034 add esp,8;esp由主函数恢复.为 getMax()造出的汇编语句是00401020 push ebp00401021 mov ebp,esp.;其它指令00401026 pop ebp00401027 ret;返回现在你该知CALLBACK 与不加CALLBACK 的函数在调用以及返回上有什么区别了吧。,Windows程序的特点,用位的“或”操作(操作符“|”)把若干个常数组合起来控制消息窗口显示的按钮和图标等。在Windows.h中,以CS_开头的类样式(Class Style)标识符被定义为16位的常量,这些常量都只有某1位为1。在V
18、C+开发环境中,可以看到CS_VREDRAW=0 x0001,CS_HREDRAW=0 x0002,CS_DBLCLKS=0 x0008,CS_NOCLOSE=0 x0200,将这些16进制数转换为2进制数,就可以发现它们都只有1位为1,并且为1的位各不相同。用这种方式定义的标识符称为“位标志”,我们可以使用位运算操作符来组合使用这些样式。例如,要让窗口在水平和垂直尺寸发生变化时发生重绘,我们可以使用位或()操作符将CS_HREDRAW和CS_VREDRAW组合起来,如style=CS_HREDRAW|CS_VREDRAW。假如有一个变量具有多个样式,而我们并不清楚该变量都有哪些样式,现在我们
19、想要去掉该变量具有的某个样式,那么可以先对该样式标识符进行取反()操作,然后再和这个变量进行与(&)操作即可实现。例如,要去掉先前的style变量所具有的CS_VREDRAW样式,可以编写代码:style=style&CS_VREDRAW。在Windows程序中,经常会用到这种位标志标识符,后面我们在创建窗口时用到的窗口样式,也是属于位标志标识符。,Windows程序的特点,在Windows应用程序中,每一个窗口都必须从属于一个窗口类,窗口类定义了窗口所具有的属性,如它的样式、图标、鼠标指针、菜单名称及窗口过程名等。窗口种类是定义窗口属性的模板,这些属性包括窗口式样,鼠标形状,菜单等等,窗口种
20、类也指定处理该类中所有窗口消息的窗口函数.只有先建立窗口种类,才能根据窗口种类来创建Windows应用程序的一个或多个窗口.创建窗口时,还可以指定窗口独有的附加特性.窗口种类简称窗口类,窗口类不能重名.在建立窗口类后,必须向Windows登记.建立窗口类就是用WNDCLASS结构定义一个结构变量。,窗口的创建过程,窗口的创建过程需要四个步骤,下面列出了创建步骤和这个过程中涉及的类和函数:1.设计一个窗口类/很多特征(光标,图标,背景)WNDCLASS2.注册窗口类/RegisterClass3.创建窗口/首先定义句柄 如:HWND hwnd;CreateWindow4.显示及更新窗口/显示窗口
21、:ShowWindow,更新窗口:UpdateWindow,理解Window编程所使用的事件驱动模型,事件,消息,消息队列和消息循环Windows应用程序是遵循事件驱动模型,通常Windows程序启动后只是等待某些事件的发生(当然应用程序也可以进行空闲处理-当没有事件发生时(WM_IDLE)执行某些特定的任务)。事件有多种产生途径,包括:键盘中某些键按下,鼠标单击,当窗口创建时,尺度发生变化时(Windows系统发给你的),发生移动,被关闭,最小化,最大化或变为可见状态时等。当某一个事件发生时,Windows会为该事件所针对的应用程序发送一条消息,表明该事件发生了,并在该应用程序的消息队列中增
22、加一条消息,该消息队列只是保存了应用程序所接受的消息的一个优先队列(会根据消息的优先级排列)。应用程序要做的事,就是在一个消息循环中不断地检查消息队列,当接收到一条消息时,便将其分派给接收该消息的特定窗口的窗口过程。一个应用程序可能含有很多的窗口,窗口过程是一个与应用程序各窗口相关的特殊函数。(每一个窗口都有一个窗口过程,但多个窗口可以共用一个窗口过程),他就是我们实现的用于处理消息的函数。,事件驱动编程模型,事件,Window操作系统检测到某一个事件的发生。作为响应,Windows将给特定程序的消息队列发送一条消息,应用程序A消息队列,应用程序B消息队列,应用程序C消息队列,当一条消息到来时
23、,消息队列会一直将该消息保存到应用程序准备对其进行处理为止。所以,如果应用层序正处在忙碌状态,该消息便不会立即被处理。此外,优先级较高的消息会在优先级较低的消息之前优先得到处理。,应用程序A的消息循环,应用程序B的消息循环,应用程序C的消息循环,窗口过程C,窗口过程C,窗口过程C,应用程序的消息循环不断地检查消息是否到来,当“获取”一条消息时,该消息便被发送给窗口过程WndProc,该函数为消息的传递的目的地。,窗口过程是一个由应用程序开发人员定义的函数。该函数由windows系统自动调用。注意,一个单个应用程序允许有多窗口函数,Case WM_CREATE:Case WM_KEYDOWN:C
24、ase WM_DESTROY:在窗口处理函数内部,编写消息处理操作,消息?,消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉。一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向Windows发出一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如,对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标。这个记录类型叫做MSG,MSG含有来自windows应用程序消息队列的消息信息。消息可以由
25、系统或者应用程序产生。系统在发生输入事件时产生消息。举个例子,当用户敲键,移动鼠标或者单击控件。系统也产生消息以响应由应用程序带来的变化,比如应用程序改变系统字体改变窗体大小。应用程序可以产生消息使窗体执行任务,或者与其他应用程序中的窗口通讯。,消息中有什么?,它在Windows中声明如下:typedef struct tagMsg HWND hwnd;接受该消息的窗口句柄 UINT message;消息常量标识符,也就是我们通常所说的消息号 WPARAM wParam;32位消息的特定附加信息,确切含义依赖于消息值 LPARAM lParam;32位消息的特定附加信息,确切含义依赖于消息值
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Windows 应用程序 基本 结构
链接地址:https://www.31ppt.com/p-5304603.html