ImageVerifierCode 换一换
格式:DOCX , 页数:34 ,大小:72.77KB ,
资源ID:20344110      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/20344110.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(第三章 Win32应用程序设计Word格式文档下载.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

第三章 Win32应用程序设计Word格式文档下载.docx

1、Windows应用程序是事件驱动(或称作消息驱动)的应用程序。Windows是一个多任务的操作系统,也就是说,在同一时刻,在Windows中有着多个应用程序的实例正在运行,比如说这时我正在打开字处理软件Word来编写这本书的书稿,同时,还打开了Visual C+的集成开发环境Microsoft Developer Studio来调试书中的示例程序,而且,后台还在放着歌曲。在这样的一个操作系统中,不可能像过去的DOS那样,由一个应用程序来享用所有的系统资源,这些资源是由Windows统一管理的。那么,特定的应用程序如何获得用户输入的信息呢?事实上,Windows时刻监视着用户的一举一动,并分析用

2、户的动作与哪一个应用程序相关,然后,将用户的动作以消息的形式发送给该应用程序,应用程序时刻等待着消息的到来,一但发现它的消息队列中有未处理的消息,就获取并分析该消息,最后,应用程序根据消息所包含的内容采取适当的动作来响应用户所作的操作。举一个例子来说明上面的问题,假设我们编了一个程序,该程序有一个File菜单,那么,在运行该应用程序的时候,如果用户单击了File菜单,这个动作将被Windows (而不是应用程序本身!)所捕获,Windows经过分析得知这个动作应该由上面所说的那个应用程序去处理,既然是这样,Windows就发送了个叫做WM_COMMAND的消息给应用程序,该消息所包含的信息告诉

3、应用程序:“用户单击了File菜单”,应用程序得知这一消息之后,采取相应的动作来响应它,这个过程称为消息处理。Windows为每一个应用程序(确切地说是每一个线程)维护了相应的消息队列,应用程序的任务就是不停的从它的消息队列中获取消息,分析消息和处理消息,直到一条接到叫做WM_QUIT消息为止,这个过程通常是由一种叫做消息循环的程序结构来实现的。Windows所能向应用程序发送的消息多达数百种,但是,对于一般的应用程序来说,只是其中的一部分有意义,举一个例子,如果你的应用程序只使用鼠标,那么如WM_KEYUP、WM_KEYDOWN和WM_CHAR等消息就没有任何意义,也就是说,应用程序中事实上

4、不需要处理这些事件,对于这些事件,只需要交给Windows作默认的处理即可。因此,在应用程序中,我们需要处理的事件只是所有事件中的一小部分。图3.1给出了一般Windows应用程序的执行流程。图3. 1 Windows应用程序的基本流程因此,从某种角度上来看,Windows应用程序是由一系列的消息处理代码来实现的。这和传统的过程式编程方法很不一样,编程者只能够预测用户所利用应用程序用户界面对象所进行的操作以及为这些操作编写处理代码,却不可以这些操作在什么时候发生或者是以什么顺序来发生,也就是说,我们不可能知道什么消息会在什么时候以什么顺序来临。Windows程序在处理消息时使用了一种叫做回调函

5、数(callbackfunction)的特殊函数。回调函数由应用程序定义,但是,在应用程序中并没有调用回调函数的代码,回调函数是供操作系统或者其子系统调用的,这种调用通常发生在某一事件发生,或者在窗口或字体被枚举时。典型的回调函数有窗口过程、对话框过程和钩子函数。其中的窗口过程和对话框过程将在本章后面的内容中讲述。第二节 Win32 API和SDK说到Windows编程,就不能不谈到Windows API (WindowsApplication Programming Interface,Windows应用程序编程接口),它是所有Windows应用程序的根本之所在。简单的说,API就是一系列的

6、例程,应用程序通过调用这些例程来请求操作系统完成一些低级服务。在Windows这样的图形用户界面中,应用程序的窗口、图标、菜单和对话框等就是由API来管理和维护的。Windows API具有两种基本类型:Win16 API和Win32 API。两者在很多方面非常相像,但是Win32 API除了几乎包括了Win16 API中的所有内容以外,还包括很多的其它内容。Windows API依靠三个主要的核心组件提供Windows的大部分函数,在Win16和Win32中,它们具有不同的名称,如表3.1所示。Win16 APIWin32 API说明USER.EXEUSER32.DLL负责窗口的管理,包括消

7、息、菜单、光标、通信、计时器和其它与控制窗口显示GDI.EXEGDI32.DLL提供图形设备接口,管理用户界面和图形绘制,包括Windows元文件、位图、设备描述表和字体等KRNL386.EXEKERNEL32.DLL处理存储器低层功能、任务和资源管理等Windows核心服务表3. 1 Win16和Win32的核心组件虽然Win16 API组件带有.EXE的扩展名,但是它们事实都是动态链接库(.DLL),不能单独运行。其它一些非核心的Windows API由其它组件所提供的DLL来实现,这些组件包括通用对话框、打印、文件压缩、版本控制以及多媒体支持等。Windows SDK (Windows

8、Software Development Kit,Windows软件开发工具包)和Windows API紧密联系,它是一套帮助C语言程序员创建Windows应用程序的工具,在Windows SDK中包括了以下几个组成部分:l 大量的在线帮助,这些帮助描述了Windows编程所可能用到的函数、消息、结构、宏及其它资源l 各种编程工具,如对话框编辑器及图象编辑器等l Windows库及头文件l 使用C语言编写的示例程序该工具包的最新版本就是我们正在使用的Win32 SDK,在安装了Visual C+的同时,Win32 SDK也安装到你的计算机上了。尽管MFC提供了对Win32 API的比较完整的封

9、装,但是,在某些情况下,我们更倾向于直接调用Win32 API,因为这有时候可以获得更高的效率,并且有着更大的自由度。而且,使用MFC编写的新风格的Windows应用程序的工作方式基本上与使用SDK编写的同一程序一样,它们往往有着很多的共同之处,只是使用MFC更加的方便,因为它隐藏了大量的复杂性。前面提到过,面向对象的编程方式是当前最流行的程序设计方法,但是,Win32 API本身却是基于C语言的过程式编程的,SDK和MFC的最主要的不同之处也就是以C与C+之间的差别,使用MFC进行Windows应用程序设计需要面向对象的编程思想和方法,好在我们已经在前面这此进行了大量的铺垫。第三节 使用SD

10、K编写Windows应用程序传统的DOS程序以main函数作为进入程序的初始入口点,在Windows应用程序中,main函数被WinMain函数取而代之,WinMain函数的原型如下:int WINAPI WinMain (HINSTANCE hInstance, / 当前实例句柄HINSTANCE hPrevInstance, / 前一实例句柄LPSTR lpCmdLine, / 指向命令行参数的指针int nCmdShow) / 窗口的显示状态这里出现了一个新的名词“句柄”(handle),所谓的句柄是一个标识对象的变量,或者是一个对操作系统资源的间接引用。在上面的函数原型中,我们看到了一

11、些“奇怪”的数据类型,如前面的HINSTANCE和LPSTR等,事实上,很多这样的数据类型只是一些基本数据类型的别名,表3.2列出了一些在Windows编程中常用的基本数据类型的别名,表3.3列出了常用的预定义句柄,它们的类型均为void *,即一个32位指针。表3. 2 Windows基本数据类型Windows的数据类型对应的基本数据类型BOOLInt布尔值BSTRunsigned short *32位字符指针BYTEunsigned char8位无符号整数COLORREFunsigned long用作颜色值的32位值DWORD32位无符号整数,段地址和相关的偏移地址LONGLong32位带

12、符号整数LPARAM作为参数传递给窗口过程或回调函数的32位值LPCSTRconst char *指向字符串常量的32位指针LPSTRchar *指向字符串的32位指针LPCTSTRconst char *(注1)指向可移植的Unicode和DBCS字符串常量的32位指针LPTSTRchar *(注1)指向可移植为Unicode和DBCS字符串的32位指针LPVOIDvoid *指向未定义类型的32位指针LRESULT来自窗口过程或回调函数的32位返回值UINTunsigned int32位无符号整数WNDPROC long(_stdcall *)(void*,unsignedint,unsi

13、gnedint,long)(注2)指向窗口过程的32位指针WORDunsigned short 16位无符号整数WPARAMunsigned int 当作参数传递给窗口过程或回调函数的32位值注1: 这是在DBCS版本下的情况,在Unicode版本下LPCTSTR和LPTSTR将代表其它的数据类型。注2: 事实上,WNDPROC被定义为LRESULT (CALLBACK*)(HWND, UINT,WPARAM, LPARAM),这个定义最终被编译器解释为long (_stdcall *)(void*,unsigned int,unsigned int,long)。表3. 3 Windows公用

14、句柄类型句柄类型HBITMAP保存位图信息的内存域的句柄HBRUSH画刷句柄HCTR子窗口控件句柄HCURSOR鼠标光标句柄HDC设备描述表句柄HDLG对话框句柄HFONT字体句柄HICON图标句柄HINSTANCE应用程序的实例句柄HMENU菜单句柄HMODULE模块句柄HPALETTE颜色调色板句柄HPEN在设备上画图时用于指明线型的笔的句柄HRGN剪贴区域句柄HTASK独立于已执行任务的句柄HWND窗口句柄查看Win32 SDK文档或者浏览Windows头文件(如windef.h、ctype.h以及winnt.h等)可以获得关于其它数据类型的定义,这些定义往往使用了#define和typ

15、edef等关键字。这里解释什么是应用程序的一个实例(instance)。最简单的理解可以用下面的例子来说明:比如说已经在Windows中打开了一个“写字板”(可以在“开始”菜单中的“程序|附件”下面找到它的快捷方式),现在你需要从另一篇文章里复制一部分内容到你正在写的这篇文章中,那么,你可以再打开一个“写字板”(注意写字板不是一个多文档应用程序,不能像在Word中那样打开多个不同的文件),然后从该写字板中复制文件的内容到在前一个写字板内打开的文章中。这里,我们多次运行了同一个应用程序,在这个例子中,我们将所打开的两个写字板叫做该应用程序的两个实例。对于实例的更精确(当然也要比上面的例子要更难懂

16、得多)的定义,在Win32 SDK中是这样给出的:实例就是类中一特定对象类型的一个实例化对象(instantiation),如一个特定的进程或线程,在多任务操作系统中,一个实例指所加载的应用程序或动态链接库的一份拷贝。刚开始时我们也许看不懂这一定义,不过没有关系,慢慢的就理解了。l 注意:l 尽管在前面给出的WinMain函数的原型中包括了一个名为hPrevInstance的HINSTANCE类型的参数,按照其字面上的意义,它所传递的是应用程序的前一个实例的句柄,但是,在Win32平台下,该参数的值总是为NULL,而不管是否有当前应用程序的实例在运行。在过去的Windows 3.x环境下编程,

17、我们常常使用下面的代码来检查应用程序是否已有一个实例在运行:l if (!hPrevInstance)l l / 在此添加没有应用程序实例在运行时的所需执行的代码。l / 对于大多数应用程序,我们常在这里注册窗口类。l 然而,在Win32操作系统Windows 95、Windows NT以及其后续版本中,上面的if条件体中的代码总会被执行,因为hPrevInstance总是为NULL,因此!hPrevInstance恒为真。之所以这样,是因为在Win32环境下,每一个应用程序的实例都有自已独立的地址空间,因此,它们之间互相独立,互不干涉。但是,对于一些应用程序,只需要而且只应该有一个实例在运行

18、。什么情况下会是这样呢?假设我们编写了一个应用程序,在默认情况下,该应用程序将在后台运行,通过按下程序所定义的某一个热键,应用程序将被激活。对于这样的应用程序,在同一时该只应该有一个实例在运行。另外,像Windows NT下在任务管理器,在同一时刻也只可以有一个实例在运行。使用下面的技巧可以保证在同一时刻只有应用程序的一个实例:l #include windows.hll #define VK_X 0x58l int WINAPI WinMain (HINSTANCE hInstance,l HINSTANCE hPrevInstance,l LPSTR lpCmdLine,l int nCm

19、dShow)CreateMutex(NULL,TRUE,No Previous Instance!)l MessageBox(NULL,创建Mutex失败!,NoPrev,MB_OK|MB_SYSTEMMODAL);l return FALSE;l if (GetLastError()=ERROR_ALREADY_EXISTS)已有NoPrev的一个实例在运行, 当前实例将被终止!,l l if(!RegisterHotKey(NULL,0x0001,MOD_CONTROL|MOD_SHIFT,VK_X)注册热键Ctrl+Shift+X失败!NoPrev已启动!nn按下热键Ctrl+Shift

20、+X将终止NoPrev.l MSG msg;l while (GetMessage(&msg,NULL,0,0)l switch (msg.message)l case WM_HOTKEY:l if (int(msg.wParam)=0x0001)l if (MessageBox(NULL,终止NoPrev?,MB_YESNO|MB_SYSTEMMODAL)=IDYES)l return TRUE;上面的代码是一个功能完整的Windows应用程序,其中用到了一些到目前为止我们还未讲述到的内容。程序定义了热键Ctrl+Shift+X,当按下该热键时将终止该程序。由于程序中没有包括任何窗口,因此这

21、是唯一的一种正常终止应用程序的方法。当程序NoPrev正在后台运行时,如果用户按下了组合键Ctrl+Shift+X,Windows将向程序主线程的消息队列中发送一条称为WM_HOTKEY的消息,当程序收到这条消息时,即弹出了消息框询问是否终止NoPrev。上面的说明将有助于你理解以上代码,但是我们目前对止并不做要求。这里,只需要注意下面的代码:在上面的代码中,我们先调用CreateMutex创建一个名为“NoPrevious Instance”的命名互斥对象(named mutexobject),如果该对象名已存在(注意这时函数CreateMutex仍返回真值TRUE),则随后调用的GetLa

22、stError函数将返回ERROR_ALREADY_EXISTS,由此得知已有一个应用程序的实例正在运行。从而弹出消息框提醒用户,然后终止应用程序的当前实例。在上面的WinMain函数原型中的另一个奇怪的标识符为WINAPI,这是一个在windef.h头文件中定义的宏,在当前版本Win32 SDK中,WINAPI被定义为FAR PASCAL,因此,使用FAR PASCAL同使用WINAPI具有同样的效果,但是,我们强烈建议你使用WINAPI来代替以前常用的FAR PASCAL,因为Microsoft不保证FAR PASCAL能够在将来的Windows版本中正常工作。在目前情况下,和FAR PA

23、SCAL等价的标识符还有CALLBACK (用在如窗口过程或对话框过程之类的回调函数前)和APIENTRY等。它们对编译器而言都是一回事,最终将被解释为_stdcall。在Windows环境下编程,会遇到很多这样的情况,注意不要混淆它们。一般情况下,我们应该在WinMain函数中完成下面的操作:1. 注册窗口类;2. 创建应用程序主窗口;3. 进入应用程序消息循环。接下来我们将依次讨论这些内容。在Windows应用程序中,每一个窗口都必须从属于一个窗口类,窗口类定义了窗口所具有的属性,如它的样式、图标、鼠标指针、菜单名称及窗口过程名等。在注册窗口类前,我们先创建一个类型为WNDCLASS的结构

24、,然后在该结构对象中填入窗口类的信息,最后将它传递给函数RegisterClass,整个过程如下面的代码所示:WNDCLASS wc;/ 填充窗口类信息wc.style=CS_HREDRAW|CS_VREDRAW;wc.lpfnWndProc=WndProc;wc.cbClsExtra=0;wc.cbWndExtra=0;wc.hInstance=hInstance;wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);wc.hCursor=LoadCursor(NULL,IDC_ARROW);wc.hbrBackground=GetStockObject(WHITE_BRUSH);wc.lpszMenuName=NULL;wc.lpszClassName=SdkDemo1;/ 注册窗口类RegisterClass(&wc);下面解释一下结构WNDCLASS中各成员的含义:style: 指定窗口样式。该样式可以为一系列屏蔽位的按位或,在前面的例子中,CS_HREDRAW表示当窗口用户区宽度改变时重绘整个窗口,而CS_VREDRAW则表则表示当窗口用户区高度改变时重绘整个窗口。对于其它的窗口样式,请参阅SDK中关于WNDCLASS的联机文档。(顺便说一句,请注意该成员的大小写,它是小写的

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1