Windows编程基础.pdf

上传人:qwe****56 文档编号:70014340 上传时间:2023-01-14 格式:PDF 页数:32 大小:401.69KB
返回 下载 相关 举报
Windows编程基础.pdf_第1页
第1页 / 共32页
Windows编程基础.pdf_第2页
第2页 / 共32页
点击查看更多>>
资源描述

《Windows编程基础.pdf》由会员分享,可在线阅读,更多相关《Windows编程基础.pdf(32页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、 第第 1 章章 Windows 编程基础编程基础 学习目标学习目标 1、Windows 编程基本概念(掌握)2、Windows GDI 函数的使用(掌握)3、用消息机制处理用户交互过程(理解)背景知识背景知识 1、C基础 本章要点本章要点 1、Windows GDI 函数 2、Windows 消息机制 引言引言 Windows 是当今主流的操作系统,也是网络游戏主要的开发平台。不论是网络游戏客户端开发还是服务器端开发,都有很多成功的网络游戏作品运行于 Windows 操作系统上。虽然对于服务器端开发来讲,还有 Unix/Linux 以及其他种类的操作系统可以选择,但是相关技术知识相当繁杂,因

2、此本章中重点介绍 Windows 平台下的程序设计,所涉及到的若干 Windows 编程基础概念对于开发者针对DirectX程序设计和 WinSock 程序设计的理解和掌握是相当重要的。Windows 操作系统本身和其上的软件技术发展是相当迅速的,从早期的 Windows 3.1 直到目前的Windows XP 的各个版本,其功能愈加强大和完善。网络游戏客户端设计所关注的 DirectX 技术也在快速发展,当开发者对 DirectX 7.0 版本到 DirectX 9.0 版本,甚至即将推出的 DirectX 10.0 版本间的若干细微变化还应接不暇时,意在整合以 Windows、Xbox、W

3、indows CE 为代表的家用电脑、家用游戏机、移动设备这三种游戏平台的微软新一代“通用软件开发平台”XNA 也已经在如火如荼的宣传之中了,它的含义是 DirectX&Xbox,NextGeneration,Architecture。技术的发展如此迅猛,作为游戏开发者来说,意味着需要投入大量的时间和精力去跟踪学习新的游戏开发技术,这样虽然能够保证游戏的高效开发及技术先进性,但是新技术的学习曲线也是不容忽视的。开发者应该熟知 Windows 平台的底层开发和高级开发包之间的关系和区别,如果对 Windows 编 程基础还掌握得不是很充分很透彻,那么即使开发包、开发工具再先进,也不能保证开发者可

4、以顺利进行游戏开发。Windows 基础方式的编程早在 VC 1.5版本的时候就已经很明显了,那就是基于 Windows API 的 SDK 方式的编程,一种 C 风格的 API 编程。随后出现的微软 MFC 库、FCL 库可以理解为是对Windows API 的重新封装,一种 C+风格的面向对象的编程,从技术学习的角度来看,如果希望掌握Windows 编程的本质,值得深入研究的是 Windows 底层的 API,也就是 SDK 方式的 Windows 编程,而且 DirectX 的绝大多数版本及相关技术资料都是采用这种方式来进行开发的,因此虽然本书中的案例开发采用了 VC.Net 2003

5、的开发环境,但是本章在介绍 Windows 编程基础的时候,将重点介绍 Windows的 SDK 方式的开发、消息机制、相关概念及重要的 API 函数。API 是 Windows SDK 方式开发的基础,Windows 平台上运行的各类软件都可以用 Windows API 来实现。具体的开发方式非常类似于采用 C 语言的标准函数库的面向过程的开发,为程序实现一个入口函数 main,进而实现其他函数,在 main 函数中指定各类函数的调用关系及逻辑。Windows API 同样也是一个非常庞大的函数库,里面汇聚了 Windows 平台上的各种系统调用函数,可以实现 Windows 窗口绘制、网络

6、数据包收发、键盘鼠标的输入获取等等众多游戏设计所关注的功能。既然 API 函数如此庞大,我们的重点又是 Windows SDK 方式的开发,那么对它的学习肯定也不是一蹴而就的。开发者通常要配备 Windows API 大全、Windows 消息大全这样的参考手册,或者结合微软的 MSDN 来开发,原因很简单,几乎没有人能对如此大量的 Windows API 函数和这些函数的参数类型、参数个数、函数返回值、调用方式等熟记于心!本章只拣选对游戏开发比较重要的 Windows API 来介绍,由于开发目的及实现方式的不同会导致所采用的 API 也各不相同,所以这里的介绍可能不够全面,只能靠开发者不断

7、地熟悉及实践来扩大知识积累,这一点犹为重要。当然,在掌握了大量的 Windows API 函数之后,游戏开发者也可以考虑在开发环境上进行变通,比如不采用 VC.Net 2003 来开发,而采用诸如 Borland C+或者 Delphi 这样的开发环境来开发都是可行的,关键取决于游戏开发者的技术熟练程度。1.1 Windows 编程约定编程约定 1.1.1 Windows编程常见缩写编程常见缩写 API:Application Programing Interface,应用程序接口。SDK:Software Development Kit,软件开发包。MFC:Microsoft Foundat

8、ion Class,微软基础类库。MSDN:Microsoft Developer Network,微软开发者网络。GDI:Graphics Device Interface,图像设备接口。MDI:Multiple Documents Interface,多重文档界面。SDI:Simple Document Interface,单文档界面。1.1.2 Windows编程常见数据类型编程常见数据类型 类型定义 含义 BOOL 布尔型(逻辑型)变量(应为 TRUE 或 FALSE)BOOLEAN 布尔型(逻辑型)变量(应为 TRUE 或 FALSE)BYTE 字节(8 位)CCHAR Window

9、s 字符 CHAR Windows 字符 TCHAR 取决于预处理器的符号 UNICODE 是否定义 COLORREF RGB(红绿蓝)颜色值(32 位)CONST 在执行时其值保持不变的变量 DLGPROC 指向应用程序定义的对话框过程回调过程的指针 DWORD 双字(32 位)DWORDLONG 双双字(64 位)FARPROC 指向应用程序定义的指针 FLOAT 浮点型变量 GLOBALHANDLE 全局内存块句柄 HACCEL 加速键表句柄 HANDLE 对象句柄 HBITMAP 位图句柄 HBRUSH 画刷句柄 HDC 设备环境句柄 HFILE 文件句柄 HFONT 字体句柄 HGD

10、IOBJ GDI(图形设备接口)对象句柄 HGLOBAL 全局内存块句柄 HHOOK 钩子句柄 HICON 图标句柄 HINSTANCE 实例句柄 HLOCAL 本地内存句柄 HMENU 菜单句柄 HOOKPROC 指向应用程序定义的钩子的指针 HPALETTE 调色板句柄 HPEN 画笔句柄 HWND 窗口句柄 LOCALHAND 本地内存句柄 LONG 32 位无符号值 LONGLONG 64 位无符号值 LPARAM 32 位消息参数 LPCSTR 指向 Windows 常字符串(以空字符结束)的指针 LPSTR 指向 Windows 字符串(以空字符结束)的指针 LPVOID 指向任意

11、类型的指针 LRESULT 常规函数返回值 MSG Windows 消息 PROC 指向回调函数的指针 SHORT 短整型数 UCHAR 无符号 Windows 字符 UINT 无符号整数 ULONG 无符号长整型数(32 位)USHORT 无符号短整型数(16 位)VOID 任意类型 WINAPI FAR PASCAL 的等价声明方式 WNDPROC 指向在应用程序中定义的窗口过程的指针 WORD 无符号字(16 位)WPARAM 32 位消息参数,早期 Win3.x 中为 16 位 以上列表中包括了字符型、整型、浮点型、布尔型、指针型以及 Windows 应用程序特有的句柄型,表示指针型的

12、数据类型往往以 P 或 LP 作为前缀,而句柄型总是冠以 H。当然上面的列表并非全部,还有诸如CALLBACK回调函数的声明方式,WNDCLASS窗口类的声明方式等繁多的类型定义或宏定义。1.1.3 Windows编程命名规则编程命名规则 介绍了常见的 Windows 数据类型后,不得不提到著名的“匈牙利命名法”。1.属性部分:全局变量:g_ 常量:c_ 类成员变量:m_ 2.类型部分:指针:p 句柄:h 布尔型:b 浮点型:f 无符号:u 3.描述部分:初始化:Init 临时变量:Tmp 目的对象:Dst 源对象:Src 窗口:Wnd 了解这种命名规则对理解常见的 Windows 程序非常有

13、帮助,对于代码调试也用途很大,现在可以结合这种命名规则来理解下面的定义了:hWnd:h 表示句柄,Wnd 表示窗口。g_bFlag:g 表示全局变量,b 表示布尔型,Flag 表示状态标志。结合以上介绍的 Windows 编程常见数据类型,对不同类型的句柄进行理解记忆,在后续的 Windows程序开发中就会受益匪浅。下面我们结合各个项目来具体了解一下这些相关概念。1.2 Windows 编程编程基本基本概念概念 1.2.1 句柄句柄 几乎 Windows 编程涉及的很多内容都和句柄有关联。句柄是用来标识项目的,这些项目包括:窗口(window)资源(resource),包括图标(icon),光

14、标(cursor),菜单(menu),字符串(string)等。GDI 对象(GDI object),包括位图(bitmap),画刷(brush),元文件(metafile),调色板(palette),画笔(pen),区域(region),以及设备环境(device context)。模块(module)实例(instance)文件(file)内存块(block of memory)控件(control)字体(font)注:device context 通常译作设备上下文,这里为了理解方便称为“设备环境”。1.窗口“窗口”是 Windows 程序实现的基础,大多数 Windows 程序都是以窗

15、口的方式运行的。网络游戏客户端编程也要用 DirectX 在窗口基础上实现程序,而网络游戏服务器端编程中,诸如监测工具、GM工具等程序实现也常以窗口方式运行。在 Windows 开发中,可以通过设置参数来决定窗口类型,这样可以实现多样的窗口外观,比如有菜单栏的窗口、有状态栏的窗口、有滚动条的窗口等等。从技术角度上看,每个窗口都具有窗口句柄(HWND 类型的变量),在系统内可以通过窗口句柄定位具体的可见或不可见的窗口。每个窗口又对应着窗口类,同样的窗口类可以用来创建多个具有相同外观和相同特性的窗口,例如 Windows 的文件夹可以是相同外观,也可以同时具有相同的特性,可以使用滚动条 浏览文件等

16、等。2.资源“资源”的概念比较广泛,Windows 的视窗系统又实在是庞大而复杂。在 Windows 程序设计中,对话框、光标、图标、位图、菜单、快捷键、字符串、版本信息等诸多构成窗口的要素都是资源类型。在 VC 6.0 版本的界面中也提供了专门的 Tab 页来方便开发者对资源进行有效管理并能够将资源进行编译,存放在.rc 格式的文件中。每个资源都对应唯一的 ID 值,应用程序通过资源 ID 对资源进行定位。浅显的理解是资源在窗口程序开发中相对固定的窗口要素。实际在窗口程序开发中,不但要通过设计工具来制作、导入各种资源,还要对这些资源实现代码控制,比如对话框这种资源通常是要对用户的输入进行响应

17、的,具体能完成什么功能就要靠开发者具体实现。3.GDI 对象“GDI 对象”在游戏客户端开发中应用比较少,因为游戏界面的众多元素通常都以图像来实现,以突出游戏的画面风格。这里需要强调的就是设备环境,通常在 SDK 方式的开发中,都要涉及 HDC的数据类型,所有的与图形有关的调用将在 HDC 变量初始化后继续进行,所以简单地理解可以认为HDC 是图像显示设备的一种抽象,这样在进行绘图的时候就可以忽略计算机显卡的具体细节。4.模块“模块”在 Windows 编程中实际上就是对应着 DLL 编程。DLL(Dynamic Link Library,动态链接库)是在 Windows 系统中广泛采用的函数

18、封装方式。对应于 C 语言中常见的静态函数库.lib 在生成可执行文件时即参与链接的方式,.dll 可以在可执行文件运行时根据需要将动态链接库加载到内存以继续运行。这样的动态加载方式的优点显而易见,那就是可以大大地减少可执行文件的大小,对于有大量函数可以共用的程序非常有优势。比如,Windows 系统是很庞大的,可共用的函数众多。在系统层面上,早期 windows 版本中采用 user.dll、kernel.dll 和 gui.dll 作为核心的动态链接库,在应用层面上,windows提供网络连接的库为 ws2_32.dll,也是采用动态链接库实现的。5.实例“实例”也是一种重要的句柄,Win

19、dows 系统中创建的各个应用程序都对应着不同的实例句柄。Windows 是一种多用户操作系统,同样的应用程序可以启动多次。每次开启同样的应用程序时,创建的实例是不一样。这里需要注意的是实例句柄和窗口句柄的关系:如果应用程序可以开启窗口,那么一个应用程序可能开启多个窗口,也就是说同样的实例句柄可能关联着多个窗口句柄;如果相同的应用程序再次启动,同样开启了多个窗口,那么新启动的应用程序具有新的实例句柄以及和这个句柄对应的新的窗口句柄。6.文件“文件”句柄在 Windows 编程中实现数据永久存储时很重要。在 Windows 平台发展过程中的文件系统有 FAT、FAT32、NTFS。如果开发者在访

20、问一个文件的时候都要考虑到操作系统存储文件时的数 据组织方式,那么这无疑给开发者带来了很大的负担。因此 Windows API 中封装了与文件操作相关的大量函数,而这些函数的使用,都和文件句柄有关系。因此文件句柄也是重要的句柄类型。7.内存块“内存块”句柄与 Windows 操作系统在内存管理上的实现方式关系密切。在早期的计算机中通常可使用的内存和硬盘是严格区分的,并且内存管理上通常都采用特殊的寻址方式,非常不利于开发者操作内存。而在现代操作系统中,通常都使用了“页”式内存管理,而可寻的地址范围则更大。在 Windows系统中,应用程序可寻址的内存达到 4G,但实际上低 2G 内存是 Wind

21、ows 系统使用的,所以通常可以认为可寻址可使用的内存为 2G。当然,PC 中内存一般没有这么大,此时操作系统会利用硬盘空间“虚拟”出更多的内存供应用程序使用,但是硬盘数据的存取速度和内存数据的存取速度是无法比拟的,所以如果程序要大量使用虚拟出来的内存,那么程序本身的响应速度和系统性能都会下降。为了操作内存就必须使用内存块句柄。8.控件“控件”句柄也是经常使用的一种句柄。现代操作系统往往在软件的可重用性上重点实现。相关的 OLE 技术、ActiveX 技术代表了 Windows 平台上控件技术的发展。虽然在游戏程序开发当中很少采用已有的控件,但是对控件技术的掌握可以使得大量的常规程序开发工作变

22、得简单可以利用大量的控件资源快速地实现程序功能。9.字体“字体”句柄在设计界面信息交互时十分重要。不论是窗口应用开发还是游戏客户端图形图像设计,从用户使用的角度来讲,图形图像对信息传达的力度是远远不够的,面对计算机,用户获取的大量信息还是来自于文字信息。对于游戏客户端设计来说,使用字体句柄来指定所要选择的字体库、字型、字号,可以通过美观的字体来塑造表现力丰富的画面信息,实现玩家与游戏之间、玩家与玩家之间的信息交流。句柄的使用通常通过调用特定的 API 函数来进行,例如:/加载资源 ID 为 IDI_WINLOGO 的图标并返回 HICON 类型的句柄 HICON hIcon=LoadIcon(

23、NULL,IDI_WINLOGO);/加载 Windows 默认的箭头鼠标形状并返回 HCURSOR 类型的句柄 LoadCursor(NULL,IDC_ARROW);/取得 Windows 预定义的黑色刷子用来绘制区域并返回 HBRUSH 类型的句柄 HBRUSH hbrBackground=GetStockObject(BLACK_BRUSH);1.2.2 Windows消息机制简介消息机制简介 1.消息 Windows 是一个消息驱动的操作系统,因此理解 Windows 的消息机制非常重要。消息为应用程序和应用程序间、应用程序和操作系统间提供了信息传递的渠道。在早期的 16 位 Wind

24、ows 系统中,操作系统实现为协同式多任务系统,整个系统只有一个消息队列,所有应用程序都要访问这个消息队列以便检查是否有自己所关心的消息。在后来的 32 位 Windows 系统中,操作系统实现为抢占式多任务系统,系统中每个运行中的应用程序都有一个消息队列,系统不用等到应用程序完成消息处理就可以得到控制权。消息是由消息 ID(UINT)和两个消息参数(WPARAM,LPARAM)构成的。不论是用户和窗口的键盘鼠标交互还是窗口本身状态的改变,系统都会发送特定的消息到当前窗口,而每个窗口都有预先指定的消息处理函数(通常是 WndProc),在消息处理函数中会识别系统所发送的消息,根据消息 ID进行

25、具体处理。typedef struct tagMSG /消息结构体 HWND hwnd;/窗口句柄 UINT message;/消息的类型 WPARAM wParam;/消息的额外信息,含义由消息类型确定 LPARAM lParam;/消息的额外信息,含义由消息类型确定 DWORD time;/投递消息的时间 POINT pt;/投递消息时光标的位置 MSG;比如,当键盘被按下时,WM_KEYDOWN 消息发送到当前窗口,消息的 WPARAM 参数中包含了按键的字符信息;当鼠标左键被按下时,WM_LBUTTONDOWN 消息发送到当前窗口,消息的 LPARAM参数的低 16 位和高 16 位分

26、别封装了鼠标点击时的 x 坐标和 y 坐标;当用户关闭窗口时,WM_QUIT消息发送到当前窗口,可以识别这个消息做些关闭处理;当用户点击窗口菜单项时,WM_COMMAND消息发送到当前窗口,可以通过消息参数继续识别所点击的菜单项来进行处理;当窗口需要重新绘制以显示图形时,WM_PAINT 消息发送到当前窗口,可以在这个消息的处理过程中调用各种绘图 API 来显示图形,Windows SDK 方式的开发实际上就是开发者根据实现目标选择需要处理的 Windows 消息,进而对这些消息进行处理,完成应用程序开发。常见的 Windows 消息参见下面的列表 1.1 常见 Windows消息 消息名称

27、消息含义 WM_CREATE 应用程序创建一个窗口 WM_DESTROY 一个窗口被销毁 WM_MOVE 移动一个窗口 WM_SIZE 改变一个窗口的大小 WM_ACTIVATE 一个窗口被激活或失去激活状态 WM_SETFOCUS 获得焦点后 WM_KILLFOCUS 失去焦点 WM_ENABLE 改变 Enable 状态 WM_SETREDRAW 设置窗口是否能重画 WM_SETTEXT 应用程序发送此消息来设置一个窗口的文本 WM_GETTEXT 应用程序发送此消息来复制对应窗口的文本到缓冲区 WM_GETTEXTLENGTH 得到与一个窗口有关的文本的长度(不包含空字符)WM_PAIN

28、T 要求一个窗口重画自己 WM_CLOSE 当一个窗口或应用程序要关闭时发送一个信号 WM_QUERYENDSESSION 当用户选择结束对话框或程序自己调用 ExitWindows 函数 WM_QUIT 用来结束程序运行或当程序调用 postquitmessage 函数 WM_QUERYOPEN 当用户窗口恢复以前的大小位置时,把此消息发送给某个图标 WM_SHOWWINDOW 当隐藏或显示窗口是发送此消息给这个窗口 WM_DRAWITEM 当控件的可视外观改变时发送此消息给这些控件的拥有者 WM_SETFONT 当绘制文本时程序发送此消息得到控件要用的颜色 WM_GETFONT 应用程序发

29、送此消息得到当前控件绘制文本的字体 WM_SETHOTKEY 应用程序发送此消息让一个窗口与一个热键相关连 WM_GETHOTKEY 应用程序发送此消息来判断热键与某个窗口是否有关联 WM_QUERYDRAGICON 此消息发送给最小化窗口 WM_KEYDOWN 按下一个键 WM_KEYUP 释放一个键 WM_CHAR 按下某键,并已发出 WM_KEYDOWN,WM_KEYUP 消息 WM_SYSKEYDOWN 当用户按住 ALT 键同时按下其它键 WM_SYSKEYUP 当用户释放一个键同时还按着 ALT 键 WM_INITDIALOG 在一个对话框程序被显示前发送此消息 WM_COMMAN

30、D 选择一条菜单命令项或当某个控件发送一条消息给它的父窗口 WM_TIMER 发生了定时器事件 WM_MOUSEMOVE 移动鼠标 WM_LBUTTONDOWN 按下鼠标左键 WM_LBUTTONUP 释放鼠标左键 WM_LBUTTONDBLCLK 双击鼠标左键 WM_RBUTTONDOWN 按下鼠标右键 WM_RBUTTONUP 释放鼠标右键 WM_RBUTTONDBLCLK 双击鼠标右键 WM_MBUTTONDOWN 按下鼠标中键 WM_MBUTTONUP 释放鼠标中键 WM_MBUTTONDBLCLK 双击鼠标中键 WM_MOUSEWHEEL 当鼠标滚轮转动时发送此消息 WM_CAPTU

31、RECHANGED 当失去捕获的鼠标时发送此消息给窗口 WM_MOVING 移动窗口时发送此消息 WM_CUT 发送此消息给一个编辑框或 ComboBox 来删除当前选择的文本 WM_COPY 发送此消息给一个编辑框或 ComboBox 来复制当前选择的文本 WM_PASTE 发送此消息给 EditControl 或 ComboBox 从剪贴板中得到数据 WM_CLEAR 发送此消息给 EditControl 或 ComboBox 清除当前选择的内容 WM_UNDO 发送此消息给 EditControl 或 ComboBox 撤消最后一次操作 WM_USER 此消息能帮助应用程序自定义消息 W

32、indows 以宏的方式预定义了许多系统消息,开发者也可以自定义消息。2.消息循环 Windows 如何处理这些消息呢?这里要重点介绍一下 Windows 系统的消息循环机制。前面提到过,Windows 系统中运行的每个应用程序都拥有自己的消息队列,每个应用程序都通过 while 循环不停地获取消息,当发现应用程序本身关心的消息时就通过 swtich 语句来分别进行处理,否则就让应用处于空闲状态。典型的消息循环语句如下:while(GetMessage(&msg,NULL,0,0)TranslateMessage(&msg);DispatchMessage(&msg);关于消息循环中 API

33、函数的含义将后面结合实际代码来说明,这里先做个了解。1.3 Windows SDK 典型的程序结构典型的程序结构 一个典型的 Win32 窗口应用程序结构从开发逻辑上说是这样的:程序入口点(WinMain函数)注册窗口类(RegisterClass或RegisterClassEx)创建主窗口(CreateWindow或CreateWindowEx)显示主窗口(ShowWindow)进入消息循环GetMessageTranslateMessageDispatchMessage处理各种Windows消息更新主窗口(UpdateWindow)程序出口点(WinMain返回)图 1.1 Win32 窗

34、口应用程序流程图#include#include/窗口类名和窗口标题 TCHAR szWindowClass=_T(演示程序);TCHAR szWindowTitle=_T(主窗口标题);/窗口过程函数 LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)switch(msg)case WM_DESTROY:PostQuitMessage(0);return 0;default:return DefWindowProc(hWnd,msg,wParam,lParam);int WINAPI _tWinMa

35、in(HINSTANCE hInstance,HINSTANCE,LPTSTR lpCmdLine,int nCmdShow)/注册窗口类 WNDCLASSEX wcex;wcex.cbSize =sizeof(WNDCLASSEX);wcex.style =CS_HREDRAW|CS_VREDRAW;wcex.lpfnWndProc=(WNDPROC)WndProc;wcex.cbClsExtra =0;wcex.cbWndExtra =0;wcex.hInstance =hInstance;wcex.hIcon =NULL;wcex.hCursor =LoadCursor(NULL,IDC

36、_ARROW);wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);wcex.lpszMenuName=NULL;wcex.lpszClassName=szWindowClass;wcex.hIconSm =NULL;RegisterClassEx(&wcex);/创建主窗口 HWND hWnd=CreateWindowEx(0,szWindowClass,szWindowTitle,WS_OVERLAPPEDWINDOW,128,96,512,480,HWND_DESKTOP,NULL,hInstance,NULL);if(!hWnd)return FAL

37、SE;/显示并更新主窗口 ShowWindow(hWnd,nCmdShow);UpdateWindow(hWnd);/进入消息循环 MSG msg;while(GetMessage(&msg,NULL,0,0)TranslateMessage(&msg);DispatchMessage(&msg);return msg.wParam;/程序退出 首先要包含 windows.h 头文件。为了兼容 UniCode 字体,包含 tchar.h 头文件。再定义两个字符串szWindowClass 和 szWindowTitle 分别存储窗口类名和窗口标题。WndProc 函数负责处理窗口消息,在上面的

38、程序段中它只处理了一个消息:WM_DESTROY,其余的消息通过调用 DefWindowProc 都交给了 Windows 系统去进行缺省处理。对于一个实际的 Windows应用程序来说,在这个函数中要处理的消息会非常多,然而,很多消息要通过调用 DefWindowProc交给 Windows 系统去进行缺省处理,因为 Windows 消息实在是太多了。注意 WndProc 的参数,HWND 类型的参数 hWnd 是一个窗口句柄,这将告诉 WndProc 处理哪个窗口中的消息,UINT 类型的 msg 是消息 ID,如果有消息发给窗口 hWnd,则消息有可能带着 WPARAM 和 LPARAM

39、 类型的消息参数以便提供具体消息信息。_tWinMain 主函数是整个应用程序的入口。注意主函数的参数,HINSTANCE 类型的变量 hInstance是应用的实例句柄,Windows 设置这个参数的值并把它传递给应用程序,很多 Windows 函数都要用到它;第二个 HINSTANCE 类型是该应用的前一应用的实例句柄 hPreInstance,这里并未给出变量名是因为这个应用并没有父应用,另外这个参数在新版本的 Windows 中已经不再使用,所以不需要关心它;第三个 LPTSTR 类型的参数 lpCmdLine 是启动此应用时可能跟随的命令行参数,只有从 DOS 命令行输入或是从 Ru

40、n 对话框中输入时才起作用,这个也不必关心;第四个整型参数 nCmdShow 是用来控制窗口显示方式的,比如设置为 SW_SHOWNORMAL 表示默认状态,设置为 SW_MAXIMIZE 或SW_MINIMIZE 分别表示最大和最小模式等等。窗口创建之前必须注册窗口类,WNDCLASSEX 类型的变量 wcex 是个很典型的结构体变量,它的分量中存储着有关窗口类的各个参数,其中:cbSize 是整个 wcex 变量的大小,这里是通过 wcex 变量的大小来区分 wcex 到底是扩展结构体类型 WNDCLASSEX 还是基本结构体类型 WNDCLASS,这也是Windows 编程中常见的方式,

41、微软经常把早期开发的数据结构或函数进行增强,而增强后的数据结构或函数通常都会加上个EX后缀;style 是类风格,可以选用 CS_DEFAULT 指定默认风格或者指定CS_HREDRAW 使一旦客户区宽度发生变化就重新绘制窗口,或指定 CS_VREDRAW 使一旦客户区高度发生变化就重新绘制窗口,或通过 CS_OWNDC 等参数指定其他风格;lpfnWndProc 是此类窗口的消息处理函数,在这里指定为 WndProc 函数;cbClsExtra 为额外类空间,可以选择在其中存放窗口类所共有的数据;cbWndExtra 为额外窗口空间,可以选择在其中存放每个窗口所拥有的数据;hInstance

42、 为应用程序的实例句柄,标识这个窗口类和哪个应用程序的实例相关联;hIcon 为窗口类的正常图标,当窗口正常显示或被最大化时,窗口左上角会显示此图标;hCursor 为窗口类的鼠标光标,可以根据需要将此光标设置成默认的鼠标指针形式或者特殊些的十字光标形式;hbrBackground 为缺省的窗口背景颜色,lpszMenuName 为缺省的菜单名,用它关联一个默认菜单;lpszClassName 为此窗口类的名称,这个名字比较重要,因为用这个窗口类实际创建窗口的时候,实际窗口是通过窗口类的名字来指定窗口类的;hIconSm 为窗口类的小图标,当窗口被最小化时,在 Windows 任务栏中会显示此

43、图标;RegisterClassEx(&wcex)是将准备好的 wcex 变量注册到 Windows 系统,只有这样才能用这个窗口类创建实际窗口。实际窗口的创建通过 CreateWindow 函数来完成。在上面的例子中,这个函数为:CreateWindowEx(0,szWindowClass,szWindowTitle,WS_OVERLAPPEDWINDOW,128,96,512,480,HWND_DESKTOP,NULL,hInstance,NULL);传递给这个函数的参数不是很清晰,可以参考下面另一段较清晰的代码来理解 CreateWindow 函数和其各个参数的含义:hWnd=Creat

44、eWindow(lpszClassName,/创建窗口,窗口类名 lpszTitle,/窗口实例的标题名 WS_OVERLAPPEDWINDOW,/窗口的风格 CW_USEDEFAULT,CW_USEDEFAULT,/窗口左上角坐标为缺省值 CW_USEDEFAULT,CW_USEDEFAULT,/窗口的高度和宽度为缺省值 NULL,/此窗口没有父窗口 NULL,/此窗口没有主菜单 hInstance,/应用程序当前句柄 NULL);/不使用该值 如果窗口创建成功,那么此函数将返回一个窗口句柄存放在 hWnd 变量中。if(!hWnd)return FALSE;这条语句是检查窗口创建是否成功,

45、这也是保证应用程序健壮性的一种很好的编程方式。此时,即使窗口创建成功,也还不会在屏幕上显示,只是在内存中准备好了显示此窗口所需要的数据。为了让窗口实际显示,需要调用下面的代码:ShowWindow(hWnd,nCmdShow);UpdateWindow(hWnd);这里 ShowWindow 的第一个参数是指定要显示哪个窗口,hWnd 实际上指的是刚刚所创建的那个窗口;第二个参数是传递过来的决定窗口显示方式的变量。ShowWindow 使窗口显示在屏幕上,而UpdateWindow 将调整窗口,使之完成一次窗口客户区的重绘。进而要实现该窗口的消息循环,否则此应用程序会陷入无响应的状态:MSG

46、msg;while(GetMessage(&msg,NULL,0,0)TranslateMessage(&msg);DispatchMessage(&msg);return msg.wParam;这是很典型的 Windows 消息循环,其中 GetMessage 函数从窗口的消息队列中取出实际的消息,如 果有消息需要处理,则 GetMessage 返回 TRUE,循环需要继续查看有无后续的消息需要处理。对于取得的消息,还要通过 TranslateMessage 函数和 DispatchMessage 函数分别对消息进行翻译和分发。TranslateMessage 主要做一些键盘翻译工作,而 D

47、ispatchMessage 负责将消息传递给该窗口的消息处理函数 WndProc 并调用 WndProc 完成对消息的处理。最后通过 msg.wParam 返回应用的状态。MSG msg;if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)TranslateMessage(&msg);DispatchMessage(&msg);在程序代码中遇到上面的消息获取函数也不要诧异,因为这是等同于 GetMessage 的另一种实现方式,PeekMessage 函数的定义如下,和 GetMessage 函数类似:BOOL PeekMessage(LPMSG lpMsg,/po

48、inter to structure for message HWND hWnd,/handle to window UINT wMsgFilterMin,/first message UINT wMsgFilterMax,/last message UINT wRemoveMsg/removal flags);LPMSG lpMsg:是一个 MSG 类型的指针变量。如果有消息在等待,表示消息信息;HWND hWnd:所要检查的消息队列的窗口句柄;UINT wMsgFilterMin,wMsgFilterMax:索引第一个和最后一个消息,一般都会从第一个消息开始检索,所以通常这两个变量都设置为

49、 0;UINT wRemoveMsg:一般来说,可以是 PM_REMOVE 或 PM_NOREMOVE 的值。使用前者会在消息被读取后从消息队列中删除,后者是继续保留。通常选择前者 PM_REMOVE。以上程序代码展示了如何初始化窗口类,如何注册窗口类,如何创建窗口,如何显示窗口,如何实现消息循环及变通方式实现消息循环,如何在消息处理函数中实现对应用程序所关心的消息的处理。可以注意到,上面的代码只进行了消息的接收和处理,有些时候,应用程序还要在特定时机主动发送消息。有两种方式可以发送消息:调用 PostMessage()函数或 SendMessage()函数。函数定义如下:BOOL PostM

50、essage(HWND hWnd,/handle of destination window UINT Msg,/message to post WPARAM wParam,/first message parameter LPARAM lParam/second message parameter);LRESULT SendMessage(HWND hWnd,/handle of destination window UINT Msg,/message to post WPARAM wParam,/first message parameter LPARAM lParam/second me

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 其他杂项

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁