




已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Win32 API应用程序框架结构(2) 1.3.3 头文件的类型与传统的C程序一样,在程序的开始都会包含头文件,并在程序中会有对调用函数的申明。在每一个用C编写的Windows程序中,都会用到一个头文件WINDOWS.H。其实,WINDOWS.H只是一个包含文件,包含了其他的Windows头文件。当然,在这些被包含的头文件中也可能还包含着其他的Windows头文件。这些头文件中最重要的有如下几种。 WINDEF.H:基本类型的定义。 WINNT.H:支持Unicode的类型定义。 WINGDI.H:图形设备接口的定义。 WINUSER.H:用户接口的定义。 WINBASE.H:内核函数的定义。 WINSOCK.H和WINSOCK2.H:用于网络通信的套接字的定义。在这些头文件中,定义了Windows提供的所有数据类型、常数标识符、函数原型和数据结构等,都是Windows文档中最重要的部分。在Visual C+的Include子目录中可以找到所有的头文件。1.3.4 函数和数据结构在C语言中有一个入口函数main,在Windows应用程序中同样也有一个入口函数WinMain,它的原型在WINBASE.H中声明,如下所示:int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance,LPSTR lpCmdLine, int nShowCmd);其中,第一个参数被称为“实例句柄”,该句柄惟一地标识了该程序,其他Windows函数可以通过将该句柄作为参数来调用该程序;第二个参数只是为了与早期的版本相兼容,在32位Windows程序中,该概念已经不再被采用,所以总是设置为NULL;第三个参数用于运行程序的命令行,可以通过它将文件在程序启动时载入内存;第四个参数表示程序在运行时是以何种方式显示的(从正常、最大化和最小化中选一)。在程序Hello中,除了用到WinMain函数外,还用到了以下的API函数。 LoadIcon:为程序加载图标以供使用。 LoadCursor:为程序加载鼠标指针以供使用。 GetStockObject:获取图形对象。 RegisterClass:为主程序的窗口注册窗口类。 ShowWindow:在屏幕上显示窗口。 UpdateWindow:命令窗口刷新自身。 GetMessage:从消息队列中获取消息。 TranslateMessage:转换某些键盘消息。 DispatchMessage:将消息发送给窗口过程。 BeginPaint:开始在窗口的客户区绘制。 GetClientWindow:获得窗口客户区的尺寸。 SetTextColor:设置文本的颜色。 DrawText:显示文本串。 EndPaint:结束绘制。 InvalidateRect:强制刷新指定的区域,程序Hello刷新整个窗口的客户区。 PostQuitMessage:在消息队列中插入一条“退出”消息。 DefWindowProc:执行默认的消息处理。这些函数在头文件WINDOWS.H中都有原型的申明,具体的信息可以查阅MSDN(Microsoft Developer Network)中SDK平台的部分函数说明。除了用到的这些API函数外,还使用了在Windows头文件中定义的4个数据类型:MSG(消息结构)、WNDCLASS(窗口类结构)、PAINTSTRUCT(绘图结构)和RECT(矩形结构)。1. 消息结构消息结构定义一个用于发送的消息,其中包含消息的具体信息,在程序接收到消息后,根据其中包含的信息做出相应的处理。其结构声明如下:typedef struct tagMSG HWND hwnd; / 获得消息的窗口句柄 UINT message; / 消息标志 WPARAM wParam; / 消息的附加信息 LPARAM lParam; / 消息的附加信息 DWORD time; / 消息的发送时间 POINT pt; / 当消息发送时,鼠标所处的屏幕位置 MSG, *PMSG; 2. 窗口类结构窗口总是在窗口类的基础上创建的,窗口类用来标识处理窗口消息的窗口过程。在一个窗口类的基础上可以创建多个窗口的实例,所以在程序创建窗口之前,必须先调用函数RegisterClass注册一个窗口类。该函数中只带有一个参数,它是一个指向类型为WNDCLASS的结构指针。其结构声明如下:typedef struct _WNDCLASS UINT style; / 窗口类的风格 WNDPROC lpfnWndProc; / 指向窗口过程的指针 int cbClsExtra; / 分派给窗口类的扩展的字节数 int cbWndExtra; / 分派给窗口实例的扩展的字节数 HINSTANCE hInstance; / 窗口的实例句柄 HICON hIcon; / 类图标的句柄HCURSOR hCursor; / 类鼠标指针的句柄HBRUSH hbrBackground; / 刷新背景所用的画刷的句柄 LPCTSTR lpszMenuName; / 窗口类包含的菜单的名称LPCTSTR lpszClassName; / 窗口类名 WNDCLASS, *PWNDCLASS; 现在,结合程序Hello依次来看WNDCLASS结构中的各个域。 第一个域语句:ws.style = CS_HREDRAW | CS_VREDRAW这条语句使用C的按位“或”操作符组合了两个“类风格”标识符。有关的标识符是在WINUSER.H中定义的,可以查看该文件中以CS为前缀的标识符定义集合。在本程序中,使用的这两个标识符的意义是当窗口水平方向尺寸(CS_HREDRAW)发生改变时和当窗口的垂直方向尺寸(CS_VREDRAW)发生改变时,窗口都要完全刷新。这一点在改变窗口的尺寸时,可以明显地看到。无论窗口如何变化,文本总是出现在窗口的中央(因为在客户区输出文本时,定义将其显示在窗口的中央,每一次窗口的刷新都要执行此操作)。 第二个域语句:ws.lpfnWndProc = (WNDPROC)WndProc这条语句的作用是将窗口类的窗口过程设置为WndProc,这是在本程序中定义的第二个函数,用来处理基于这个窗口类创建的所有窗口的全部消息。在类定义中,实际上使用的是一个指向函数的指针,通过该指针调用同名函数。 第三和第四个域语句:wc.cbClsExtra = 0;和wc.cbWndExtra = 0 这两条语句用于为程序预留空间,程序可以根据需要来使用它们。在本程序中没有使用到,所以赋值为零。 第五个域语句:wc.hInstance = hInstance这条语句指定了程序的实例句柄,该句柄可以从WinMain函数的第一个参数处获得。 第六个域语句:wc.hIcon = LoadIcon( NULL, IDI_APPLICATION )这条语句用于为所有基于这个窗口类建立的窗口设置一个图标。图标是一个小的位图图像,将出现在Windows任务栏中和窗口的标题栏的左端。用户可以定义自己的图标加载到程序中,也可以使用系统提供的图标。在本程序中,为简单起见,使用系统提供的应用程序的标准图标(ID为IDI_APPLICATION),使用函数LoadIcon将图标加载到应用程序中。该函数返回一个图表句柄。 第七个域语句:wc.hCursor = LoadCursor(NULL, IDC_ARROW)这条语句表示窗口载入一个预定义命名为IDC_ARROW的鼠标光标(形状为箭头),并返回该光标的句柄。在Win32 API中定义了一系列的鼠标光标,具体内容可以参考MSDN文档中Platform SDK/Windows User Interface/LoadCursor等内容。当程序启动且鼠标的位置处于窗口的客户区时,鼠标变成箭头形状。另外,也可以自定义鼠标光标的形状。 第八个域语句:wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1)这条语句指定了基于这个窗口类所创建的窗口的背景颜色。在Windows API中,用某一种颜色覆盖背景一般都需要用到画刷(brush),以指定的颜色来填充一个区域。在本程序中,使用了比窗口颜色稍亮的颜色作为画刷的颜色。在Windows中还定义了一些标准的画刷,称为“备用画刷”(stock brush)。利用GetStockObject函数可以调用一个备用画刷。例如,hBrush=GetStockObject(WHITE_ BRUSH),其中的WHITE_BRUSH就是一个标准的画刷Win32 API应用程序框架结构(3) 第九个域语句:wc.lpszMenuName = lpszAppName这条语句指定窗口类的菜单,其中,lpszAppName指向存储菜单名字符串的指针。在本程序中没有用到菜单,所以该字段被设置为NULL。 第十个域语句:wc.lpszClassName = lpszAppName最后一个域给出了窗口类的类名。在提供的程序中,类名和窗口类的菜单名相同。3. 矩形结构矩形结构相对简单,它定义了四个LONG域,前两个表示矩形左上点的横坐标和纵坐标(通常用X和Y表示)的值,后两个表示矩形右下点的X,Y值。其结构声明如下:typedef struct _RECT LONG left; / 左上点的X坐标 LONG top; / 左上点的Y坐标 LONG right; / 右下点的X坐标 LONG bottom; / 右下点的Y坐标 RECT, *PRECT;有关绘图结构的具体内容将在讲解GDI(图形设备接口,Graph Device Interface)时重点介绍。下一小节将具体介绍Windows消息机制,整个Windows是以消息(Message)作为传递信息的手段的消息机制可以说是Windows的灵魂。1.3.5 消息机制1. 消息循环在调用了UpdateWindows之后,窗口就会出现在显示器上,此时Windows就为程序维护一个“消息队列”。当Windows侦测到程序的用户键盘和鼠标输入数据时,就将此输入事件转化为一个“消息”,并将此消息放到程序的消息队列中。程序通过执行被称为“消息循环”的代码从消息队列中取出消息。实现循环的程序代码如下:while(GetMessage(&msg, NULL, 0, 0) TranslateMessage(&msg); DispatchMessage(&msg); 其中,变量msg是类型为MSG的结构,在前一小节中已经介绍过这个结构的有关信息。消息循环首先从消息队列中取出一个消息,其方法如下所示:GetMessage(&msg, NULL, 0, 0);它将取到的消息赋给一个指向名为msg的MSG结构的指针。第二、第三和第四个参数分别设置为NULL或者0,表示程序将接收它创建的所有窗口的所有消息。只要从消息队列中取出的消息的message域不为WM_QUIT(其值为0x0012),GetMessage就返回一个非零的值。然后,进行一些键盘消息转换(在讲解有关键盘输入的章节中进行详细讨论),其方法是:TranslateMessage( &msg );最后,消息又将被转回Windows,Windows会将消息发送给适当的窗口过程进行处理,即Windows调用窗口过程(在程序Hello中是WndProc函数),其方法是:DispatchMessage(&msg);当处理完消息后,窗口过程又将控制返回给Windows,此时,Windows仍处在函数DispatchMessage的调用中。当得到返回后,Windows结束DispatchMessage函数的调用,重新开始调用GetMessage函数从消息队列中获取消息。从以上可以看出,消息只是在窗口过程和Windows之间传递,程序并不会直接调用窗口过程。如果要从程序调用自己的窗口过程,就要用到SendMessage函数,这在后续的章节中会重点讨论。并不是所有的消息都会进入消息队列,加入消息循环。一般来说,进队的消息基本上是用户输入的结果(包括鼠标输入和键盘输入)。另外,进队的消息还包括时钟消息(WM_TIMER)、刷新消息(WM_PAINT)和退出消息(WM_QUIT)等。不进队的消息一般来自调用特定的Windows函数。例如,调用CreateWindow时,将直接给窗口过程发送一个WM_CREATE的消息;调用ShowWindow时,将直接给窗口过程发送名为WM_SIZE和WM_SHOWWINDOW的消息。消息的循环和处理十分复杂,但绝大部分的消息处理都由Windows完成,而且是有规律可循的。消息其实只是应用程序与Windows交互的媒介,存在于窗口过程和Windows之中。2. 消息及消息处理窗口过程接收的每一个消息都是用数值标识的,也就是传递给窗口过程msg结构中的message参数。在Windows头文件WINUSER.H中,为每个消息参数定义以“WM”(Window Message)为前缀的标识符。当然,也可以在自己程序的头文件中定义自己的消息参数。一般来说,Windows程序员都会选择使用switch和case的结构来确定窗口过程接收到的是什么消息。窗口过程在处理消息时,必须返回零,所有窗口过程不予处理的消息都应该被传给函数DefWindowProc处理。事实上, DefWindowProc并不是惟一处理其他消息的函数,在接触多文档时,还会碰到用于相似处理内容的函数。从函数DefWindowProc返回的值必须由窗口过程返回,函数只是将消息进行加工,具体工作还是要由Windows来完成。在程序中,WndProc函数只处理三种消息:WM_PAINT,WM_KEYDOWN和WM_DESTROY。窗口过程的总体结构如下:switch(uMsg) / 定义有关变量case WM_PAINT :/ 处理WM_PAINT消息的过程break;case WM_KEYDOWN :/ 处理WM_KEYDOWN消息的过程break;case WM_DESTROY :/ 处理WM_DESTROY消息的过程break;default :return(DefWindowProc(hWnd, uMsg, wParam, lParam);return(0L);在上面结构的定义中,利用“default :”来调用DefWindowProc函数为窗口过程不予处理的消息提供的默认的处理是必需的。 因为在窗口过程中,有很多很重要的工作都要Windows来完成。如果不能将这些消息及时地发送给Windows,则窗口的创建和维护就不会成功。用户可以将此函数去掉后再编译运行,就会发现其问题所在。(1)WM_PAINT消息当客户区的一部分或者全部变为无效时,将由这个消息通知程序“刷新”该区域。在很多情况下,客户区会变得无效,下面介绍经常遇到的几种情况。 在创建窗口时,客户区将变得无效。此时
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 【正版授权】 ISO/IEC GUIDE 21-1:2005 EN Regional or national adoption of International Standards and other International Deliverables - Part 1: Adoption of International Standards
- 快递行业配送服务协议
- 收费站度工作总结
- 守候作文900字15篇
- 艺术鉴赏考试试题及答案
- 胰腺炎考试试题及答案
- 六一公司成人活动方案
- 六一孕妇活动方案
- 六一居家律动活动方案
- 六一拓印活动方案
- 叉车工安全考试
- (2025)发展对象必考试题与答案
- 第一课-入乡随俗《发展汉语-初级综合2》
- 2025年长春市轨道交通集团有限公司校园招聘(693人)笔试参考题库附带答案详解析版
- 建立健全各项管理制度
- 病媒生物试题及答案
- T/CHC 1001-2019植物源高有机硒食品原料
- 农村果园承包合同范本
- 中外石油文化智慧树知到期末考试答案章节答案2024年中国石油大学(华东)
- 二年级数学无纸化监测试题
- 专利培训课件--专利基础知识
评论
0/150
提交评论