1 / 92

第一章 Windows 编程基础知识

第一章 Windows 编程基础知识. 1.1 Windows 操作系统的特点 1 直观的图形化用户界面 Windows 应用程序的外观是由诸如 窗口 、 菜单 、 工具栏 、 状态 栏 、 滚动条 、 对话框 等标准图形元素构成的。程序运行中的人 机交互操作也都是通过这些标准图形元素进行的。我们将这样 的用户界面称为图形化用户界面 GUI ( G raphics U ser I nterface )。 GUI 使得应用程序的用户界面统一、友好、美观。. 2 丰富的设备无关操作 Window 程序的输出显示均为图形操作(包括文本操作)。各

qabil
Download Presentation

第一章 Windows 编程基础知识

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第一章 Windows 编程基础知识

  2. 1.1 Windows 操作系统的特点 1 直观的图形化用户界面 Windows 应用程序的外观是由诸如窗口、菜单、工具栏、状态 栏、滚动条、对话框等标准图形元素构成的。程序运行中的人 机交互操作也都是通过这些标准图形元素进行的。我们将这样 的用户界面称为图形化用户界面 GUI(Graphics User Interface)。 GUI 使得应用程序的用户界面统一、友好、美观。

  3. 2 丰富的设备无关操作 Window程序的输出显示均为图形操作(包括文本操作)。各 类复杂的图形操作都是通过与物理设备无关的图形设备接口GDI (Graphics Device Interface)完成的。每个图形操作都是在一个特 定的图形设备上下文(Device Context)中完成的。也就是说,通 过设备上下文句柄,能够调用图形设备接口 GDI所提供的相应 图形操作进行格式统一而具有特定功能的图形绘制操作,而这 些图形操作又可以通过对应的物理图设备驱动的支持,在指定 的设备上实现相应的图形输出。下图形象地示意了这种 GDI图 形接口的实现机制:

  4. 显示器驱动 打印机驱动 绘图仪驱动 GDI 虚拟设备

  5. 3 完善的多任务运行环境 Windows是一个多任务的操作系统。这种多任务表现在多个 不同进程(包括同一程序的多个进程实例)的同时运行和同一 进程中的多个线程的同时运行。这些同时运行的多任务对系统 资源的共享表现在: CPU:通过系统分时实现多任务共享同一 CPU。 屏幕:通过可以重叠或平铺分布的窗口实现多个任务的视窗可 以共享同一屏幕,用户可以通过切换不同任务的窗口为活 动窗口,在不同任务之间进行切换。 内存:通过虚拟内存管理实现多任务共享有限的内存资源。多 任务之间可以进行手工和自动的数据交换和通信。

  6. 其中 Windows虚拟内存管理的实现如下: ⑴ 进程和内存空间 下面给出的图是在 Windows 95平台上,执行同一个 EXE 文 件的两个不同进程时的虚拟内存映射图。

  7. 0xFFFFFFFF 共享内存空间 0xC0000000 0x80000000 0x5F400000 0x10000000 堆 堆 堆 堆栈 堆栈 可读/写全局内存 可读/写全局内存 0x00400000 进程A 硬盘 进程B Windows 系统代码 Windows DLL 内存映射文件 MFC42.DLL 用户.DLL 交换文件 EXE文件

  8. 对于每个进程来说,只有低端的 2GB(0-0x7FFFFFFF) 的 地址空间是真正属于进程私有的。其中最低端的 4MB内存空间 是禁止访问的。进程运行期间所需要的堆栈、堆和可读/写的全 局内存以及应用程序的 EXE 文件和DLL文件都被映射到这 2GB 空间内。而高端的 2GB空间对所有的进程都是一样的,在这一 区间存放着所有进程共享的 Windows核心执行过程,虚拟设备 驱动程序(VxD)和文件系统代码以及一些重要的表(如映射页 表)都被映射到最高端1GB(0xC0000000 - 0xFFFFFFFF)空间中。 Windows DLL和内存映射文件在 0x80000000 - 0xBFFFFFFF 的内存 空间中。

  9. 由于低端的 2GB内存空间分配给特定的进程,所以一个进 程想要改变另一个进程的堆栈、全局内存或者堆空间的内容是 不可能的。 EXE和 DLL代码存放空间都有只读标记,因此,它们被映射 到多个进程是没有问题的。然而在最高端的 1GB空间有重要的 Windows可读数据,因此,这部分内存很容易受到错误程序的攻 击,例如毁坏系统表。在 0x80000000 - 0xBFFFFFFF地址空间中 存放的一个进程的映射文件也可能被另一个进程破坏。

  10. 在 Windows NT 中这些问题不会发生,因为在 Windows NT 中,进程只允许访问低端的 2GB空间,并且这 2GB的最高端和 最低端的 64KB空间是不允许访问的。同时高端的 2GB空间中 所存放的内容完全受保护。这就是为何提倡使用 Windows NT的 原因之一( Windows 2000 和 Windows XP 有类似的安全机制)。 ⑵ 虚拟内存如何工作 ① 为什麽要使用虚拟镜像技术 • 计算机不可能有数百个 GB的 RAM(物理内存)和数百个 GB的磁盘空间能满足多进程(每个进程 4GB)的需要。 • 每个进程的 4GB空间不会全部使用,更不会同时使用。

  11. 32位线性地址 位 31--22 位 21--12 位 11--0 每个进程拥有一个页表目录,它可以保存1024个页表地址 每个页表可保存1024个虚拟内存页地址 4096字节 32位地址 页表地址 标记 32位地址 页表地址 标记 20位 12位 20位 12位 CR3寄存器 Windows在CR3中为当前进程提供一个页表目录地址 ② 如何实现虚拟镜像技术

  12. • 32 位线性地址分三段,页表目录、页表和页内偏移量。 • 每页 4KB空间。 • 页以 4KB 为边界,即页的首地址必须是 4KB 的整倍数。 每个进程可以获得的虚拟内存空间为 4GB,每一个物理 地址的形成可以解析如下: 页表地址 = 页表目录地址+ 偏移量(第 22 - 31位),共 有1K 个页表。 页地址 = 页表地址+ 偏移量(地址第 12 - 21位),共有 1K*1K = 1M页。 物理地址 = 页地址 + 偏移量(地址第 0 - 11位),共有 1M*4KB = 4GB内存单元

  13. 每个页表入口都包含存在位(表示页是否在物理 RAM 中) 和读/写位(表示页中内容是否可读/写或只读)。 当需要访问此页内容时,根据“存在”位确定是否需要将此 页的内容从磁盘读入到此物理页中。如果页中内容有一段 时间未被访问,则根据虚拟管理的优化算法确定是否将页 中内容交换到磁盘中或直接放弃,使物理页空间可以被新 进程的页使用。在收回页面使用时,根据页的“读/写”位来 确定是将页中内容交换到磁盘中(例如,进程中所有可读 /写数据),或直接放弃(例如,程序 EXE代码和 DLL代 码,进程中的常量)。

  14. ③ 用户可以使用的内存操作函数 • 使用VirtualAlloc 进行内存的保留和占用,该函数的原型: LPVOID VirtualAlloc( LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect ) • 使用 VirtualFree 收回 VirtualAlloc 保留和占用的内存空间。 VirtualFree 的原型: BOOL VirtualFree( LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType ); • 使用GlobalAlloc 函数在Windows运行时堆中分配空间。 HGLOBAL GlobalAlloc(UINT uFlags, SIZE_T dwBytes); • 使用GlobalLock锁定GlobalAlloc 分配的内存空间一次, 并获取操作句柄。每锁定一次LockCount+1。 LPVOID GlobalLock(HGLOBALhMem);

  15. • 使用GlobalUnlock 将内存空间解锁一次,LockCount–1, 当LockCount为0时,所分配的内存空间不再被锁定。 BOOL GlobalUnlock(HGLOBALhMem); • 未锁定的内存地址(句柄)可以用GlobalFree 函数释放。 HGLOBAL GlobalFree(HGLOBALhMem ); • 使用new分配内存空间。 • 使用delete释放由new 分配的内存空间。 • 内存映射文件:将一个地址范围直接映射到相应的文件。 当进程访问相应的内存页时,系统将分配 RAM,并从磁盘 中读入数据或将内存中数据写入磁盘,它可以用于进程间 共享。

  16. •访问资源:资源是包含在 EXE 和 DLL代码中的,因此会 占用虚拟内存空间,而且这些空间在进程的生存期内是 不会被改变的,这就使得我们很容易读取一个资源。获 取资源的函数原型: HGLOBAL LoadResource( HMODULE hModule, HRSRC hResInfo); 参数: hModule— 包含所取资源的模块句柄,NULL 表示从进程 中取资源。 hResInfo— 所取资源的句柄。 返回一个全局内存句柄HGLOBAL 可以安全地把它当作访 问存放资源的内存空间的索引。例如:

  17. LPVOID lpvResource = (LPVOID)::LoadResource ( NULL, ::FindResource ( NULL, MAKEINTRESOURCE(IDB_REDBLOCK), RT_BITMAP )); 其中FindResource用于确定一个指定的资源位置,其原型: HRSRC FindResource( HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType ); 参数: hModule — 包含所取资源的模块句柄,NULL 表示从进程中 取资源。

  18. lpName— 所取资源的名字串。本例中是使用宏定义 MAKEINTRESOURCE 将资源标识 IDB_REDBLOCK 转换为资源名。 pType — 所取资源的类型。本例中使用的 RT_BITMAP表示 所取资源是一个位图资源。

  19. 4 灵活的消息处理机制 ⑴ 队列化消息输入 Windows 操作系统将应用程序控制运行所需要各类信息以消 息的形式放在一个消息队列中,这个队列由操作系统管理。应 用程序只通过读取消息队列中的不同消息控制运行。 Windows 操作系统有一个系统消息队列,每个应用程序有一 个自己的消息队列,应用程序的消息来源: ①输入消息:如键盘、鼠标输入。这类消息通过系统消息 队列被送入应用程序消息队列。

  20. ②控件消息:用于与 Windows 的控件对象进行双向通信, 实现控件状态的变化。这类消息不通过系统消息队列, 可以通过应用程序消息队列,也可以直接发送到控件对 象上。 ③系统消息:由系统管理事件(例如系统时钟)引起的消 息。这类消息中有些要通过系统消息队列送到应用程序 消息队列,如 DDE(Dynamic Data Exchange)消息;而另 一些消息直接送入应用程序消息队列,如创建窗口消息。 ④用户消息:由程序员自己定义在应用程序中发出,并在 应用程序中响应处理的消息。这类消被直接送入应用程 序消息队列。

  21. ⑵支持队列特征的消息驱动模型 Windows 操作系统主要包括三个基本内核元件: ①GDI(Graphics Device Interface):负责虚拟图形设备的操 作,例如,屏幕绘图和打印。 ②KERNEL:支持与操作系统密切相关的功能(如进程加 载,文本切换,文件I/O,内存管理线程管理等)。 ③USER:为所有的用户界面对象提供接收和管理所有输入 消息、系统消息,并把它们发给相应窗口的消息队列。

  22. ⑶事件驱动的程序设计 MS-DOS应用程序主要是采用顺序的、关联的、过程驱动的 程序设计方法。因此,过程的执行顺序是由程序直接控制,并 强制用户以某种不可更改的模式进行工作,交互性差。 Windows应用程序则是采用了由事件发生来控制程序运行逻 辑的设计方法,由于事件发生是随机的,没有预定的顺序,所 以用户就可以按照各种需要的、合理的顺序来安排程序的流程。 每个事件发生都会在对应的队列中放入一条消息。程序开始运 行后,总是从消息队列中读取消息等待事件的发生,并根据消 息做出相应的响应后,返回等待事件发生的状态,直至响应了 程序退出消息导致程序运行结束退出。

  23. ⑷ 支持应用程序间数据交换 Windows支持应用程序间通过以下途径进行数据交换: ① 动态数据交换 DDE(Dynamic Data Exchange), ② 剪切板(Clipboard), ③ 对象链接和嵌入 OLE(Object Linked and Embeded), ④组件对象模型 COM(Component Object Model)和分布式组 件对象模型 DCOM(Distributed Component Object Model)。

  24. 5简便的动态链接库(DLL)应用 库是为应用程序提供各种功能和资源的最重要的途径,其中 动态链接库对于支持多任务的功能和资源共享和提高内存的使 用效率更为有效。Windows 平台为动态链接库的创建、安装和调 用提供了有效的支持,使得动态链接库的应用更加简便、可 行。所以动态链接库的开发和应用成为应用程序开发的重要手 段之一。

  25. 1.2Windows应用程序的特点 1事件驱动方式的程序设计模式 这种程序是由许多完成特定功能的子流程组成,在程序启动 运行之后,没有一个固定的执行流程,而是由用户的操作的结 果(事件)确定(驱动)子流程的执行,包括程序的结束。 2窗口程序设计模式 Windows 应用程序的基本单位不是过程和函数,而是窗口。 Windows 应用程序一般都具有标准的窗口界面风格。这个具有 标准风格的程序窗口界面都是由一系列的具有标准风格的界面 对象元素(如:窗口、图标、标题栏、菜单、工具栏、滚动 条、状态栏、对话框、控件、消息框等)组合而成的,例如 下图就是一个典型 Windows 程序的窗口界面。

  26. 3面向对象的程序设计模式 Windows 应用程序符合典型的面向对象结构的程序。程序为 用户提供的所有可视操作界面在程序内部都可视为一个 Windows 对象,用户对这些可视对象的操作通过事件驱动模式触发相应 Windows 对象的可调用方法。 Windows 程序的执行过程本身就是窗口和其他对象频繁创建、 处理和消亡的过程。程序执行过程中的消息发送可以理解为一 个窗口对象向别的窗口对象请求对象服务的过程。因此,用面 向对象的方法进行 Windows 程序设计与开发是极其方便、合理 的。

  27. 为了便于设计创建具有风格一致的窗口界面,微软公司在为了便于设计创建具有风格一致的窗口界面,微软公司在 Win32 函数库和 C++ 类库中为创建和操作上述标准界面元素提 供了大量的函数和 C++ 类。 学习和掌握有关这些标准界面元素的描述、创建的数据结 构和程序结构、C++ 类及其关系,是创建一个 Windows 程序的重 要基础之一,对于理解这些标准界面元素封装在类库中的类的 工作原理也是十分必要的,同时也有助于创建自己特殊风格的 界面元素以适应特定程序所需要的特定风格的界面。

  28. 4 资源共享 MS-DOS是单任务操作系统,DOS应用程序在运行时独占系 统的全部资源,如显示器、内存,在程序结束时才释放资源。 Windows 是一个多任务的操作系统,同时运行的各个应用程 序必须共享系统为程序运行提供的资源。系统资源是有限的, 如果使用资源的应用程序在资源使用完毕后不释放,就会造成 系统资源的枯竭,从而导致程序的运行异常,或干扰其他程序 的运行,甚至导致死机。因此 Windows 应用程序共享资源的基 本模式如下: ·向 Windows系统请求资源;

  29. ·使用资源; ·释放资源给 Windows,以供别的程序使用。 对于内存或其他硬件设备(键盘、鼠标、计数器、屏幕、 串/并接口等) 资源,一般不允许应用程序直接管理和访问, 而由 Windows 系统控制,以便向所有的应用程序提供公平的资 源,保证不中断的运行。如果应用程序确实需要对某些硬件进 行直接访问,则应当通过 Windows提供的特定 API函数实现安全 的访问。

  30. 5 程序和资源分开 在 DOS 程序中,界面设计编码工作和功能设计编码都是在 源程序中完成的。 在 Windows 应用程序中,实现界面的可视对象(如菜单、对 话框、位图等)都被从源程序中分离出来,放在资源文件(.rc) 中,并通过资源编译器将这些资源编译后,再链接到应用程序 的可执行文件或动态链接库文件中。程序与资源分离的优点: ⑴ 降低内存需求:资源可以不随着应用程序一起全部装入内 存,只有当这些资源被使用时才被装入自己的数据段,并不 驻留在应用程序的数据段;当内存紧张时,可废弃这些资源 (从内存中退出),待使用时再次自动装入。

  31. ⑵ 便于统一管理和重复利用 ⑶ 应用程序与界面有一定的独立性,有利于软件的国际化

  32. 1.3Win32 程序结构 创建 Windows程序的方法有多种,最常用的方法是选择使用 WindowsAPI函数编程或 MFC编程。其中使用 MFC是完全遵照 面向对象程序设计的编程方法,是本课程的学习重点。而使用 Windows API编程对于理解 Windows程序的特点和运行机制更为 直观,因此,对于初学者首先从 Windows API编程入手是十分 必要的。 使用 Windows API编写的典型的 Windows应用程序是由主函 数和窗口函数两个基本部分组成:

  33. 1Windows 应用程序的主函数 主函数是 Windows 应用程序的入口,相当于控制台应用程序 中的 main函数。主函数名由系统确定,不允许改变。典型的主 函数中一般包括: ⑴定义主窗口类结构变量,并初始化; ⑵使用已经初始化的窗口类结构变量注册主窗口类别; ⑶创建已经成功注册的主窗口; ⑷显示并更新主窗口; ⑸启动消息循环,不断地接收消息,并分发到相应的窗口函数 去判断处理,直至收到关闭主窗口的消息,退出消息循环、 结束程序执行。

  34. 2窗口函数 窗口函数是由用户定义,由系统调用的回调函数。它的用途 是处理窗口消息,以完成程序需求的各种特定的功能。 在 Windows应用程序的运行过程中,通常总是先创建一个主 窗口,然后根据执行功能的需要,可能会有子窗口的创建和撤 消(如用于交互操作的对话框的创建和撤消)。每个窗口都应 有一个对应的窗口函数,用于处理对应窗口消息的响应操作, 因此,在一个 Windows应用程序中通常会有多个窗口函数,但 主窗口函数只有一个,换言之,Windows应用程序至少应有一个 主窗口函数。 主窗口函数必须在创建前通过主窗口类变量进行注册,而子 窗口函数一般是在主窗口函数中被注册、创建和撤消的。

  35. 1.3.1 定义窗口类的结构 窗口是一个具有标准风格的界面对象元素,它使用一个数 据结构来描述窗口样式、窗口消息处理函数、程序句柄、图标、 光标、背景刷、菜单以及描述本窗口类型结构的名称。根据这 个数据结构内容的描述,就可以创建一个具体的窗口。这个数 据结构的类型名为 WNDCLASS,定义如下:

  36. typedef struct _WNDCLASS { UINT style; // 窗口格式 WNDPROC lpfnWndProc; // 窗口函数指针 int cbClsExtra; // 窗口类结构变量后额外分配的字节数 int cbWndExtra; // 窗口实例后额外分配的字节数 HANDLE hInstance; // 窗口实例句柄 HICON hIcon; // 窗口图标句柄 HCURSOR hCursor; // 鼠标位置光标句柄 HBRUSH hbrBackground; // 窗口背景画刷句柄 LPCTSTR lpszMenuName; // 窗口菜单名字串指针 LPCTSTR lpszClassName; // 窗口类名字串指针 } WNDCLASS;

  37. 定义一个窗口类别结构变量,并初始化,例如:定义一个窗口类别结构变量,并初始化,例如: WNDCLASSwndclass; wndclass.style = CS_HREDRAW|CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackgound = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = “MyMenu”; wndclass.lpszClassName = “MyWndClass”;

  38. 扩展的窗口数据结构为 WNDCLASSEX,其定义如下: typedef struct _WNDCLASSEX { UINT cbSize; // 新增成员,指示结构本身长度 UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HANDLE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; HICON hIconSm; // 新增成员,指定窗口的小图标的句柄 } WNDCLASSEX;

  39. 1.3.2窗口类的注册与窗口创建、显示和更新 1窗口类的注册 定义一个窗口类结构变量,并初始化便确定了一个指定的窗 口。由于窗口的创建和窗口函数的回调操作都是由操作系统完 成的,因此,在该指定窗口创建之前,必须在系统中注册:通 过调用窗口类函数 RegisterClass 或 RegisterClassEx 用该窗口类 结构变量确定的窗口属性和其关联的主窗口函数。注册函数的 原型和调用实例如下:

  40. ⑴窗口类注册函数 RegisterClass 原型: ATOM RegisterClass( CONST WNDCLASS *lpWndClass ); 调用实例: WNDCLASS wndcls; … if(!RegisterClass(&wndcls)) { MessageBox(NULL, TEXT(“This program requires Windows!”), SzAppName, MB_ICONERROR); return 0; }

  41. ⑵窗口注册函数扩展版 RegisterClassEx 原型: ATOM RegisterClassEx( CONST WNDCLASSEX *lpwcx ); 调用实例: WNDCLASSEX wndcls; … if(!RegisterClassEx(&wndcls)) { MessageBox(NULL, TEXT(“This program requires Windows NT!”), SzAppName, MB_ICONERROR); return 0; }

  42. 2窗口的创建 对于已经成功注册的窗口类,便可以调用窗口创建函数 CreateWindow 或 CreateWindowEx 在屏幕上显示所注册窗口类描 述的窗口并成为 Windows 应用程序的运行界面。窗口创建函数 的原型和调用实例如下:

  43. ⑴窗口创建函数 CreateWindow 原型: HWND CreateWindow ( LPCTSTR lpClassName, // pointer to registered class name LPCTSTR lpWindowName, // pointer to window name DWORD dwStyle, // window style int x, // horizontal position of window int y, // vertical position of window int nWidth, // window width int nHeight, // window height HWND hWndParent, // handle to parent or owner window HMENU hMenu, // handle to menu HANDLE hInstance, // handle to application instance LPVOID lpParam// pointer to window-creation data );

  44. 调用实例: HWND hWnd = CreateWindow ( “MyWndClass”, // 窗口类名 “The Hello Program”, // 窗口名 WS_OVERLAPPEDWINDOW, // 重叠 WS_OVERLAPPEDWINDOW 或 // 子窗口 WS_CHILD、或弹出窗口WS_POPUP。 CW_USERDEFAULT, // 使用窗口缺省水平位置 x = 0。 CW_USERDEFAULT, // 使用窗口缺省垂直位置 y = 0。 CW_USERDEFAULT, // 使用缺省窗宽,系统根据桌面确定。 CW_USERDEFAULT, // 使用缺省窗高,系统根据桌面确定。 NULL, // 无父窗口 NULL, // 使用窗口类结构变量中指定的菜单。 hInstance, // 窗口所属应用程序的句柄。 NULL // 本窗口无须附加参数。 );

  45. ⑵窗口创建函数扩展版 CreateWindowEx 原型: HWND CreateWindowEx ( DWORD dwStyle, // extended window style LPCTSTR lpClassName, // pointer to registered class name LPCTSTR lpWindowName, // pointer to window name DWORD dwStyle, // window style int x, // horizontal position of window int y, // vertical position of window int nWidth, // window width int nHeight, // window height HWND hWndParent, // handle to parent or owner window HMENU hMenu, // handle to menu HANDLE hInstance, // handle to application instance LPVOID lpParam// pointer to window-creation data );

  46. 调用实例: HWND hWnd = CreateWindowEx ( 0, // 无扩展窗口风格 “MyWndClass”, // 窗口类名 “The Hello Program”, // 窗口名 WS_OVERLAPPEDWINDOW, // 重叠WS_OVERLAPPEDWINDOW 或 // 子窗口WS_CHILD、或弹出窗口WS_POPUP。 CW_USERDEFAULT, // 使用窗口缺省水平位置 x = 0。 CW_USERDEFAULT, // 使用窗口缺省垂直位置 y = 0。 CW_USERDEFAULT, // 使用缺省窗宽,系统根据桌面确定。 CW_USERDEFAULT, // 使用缺省窗高,系统根据桌面确定。 NULL, // 无父窗口 NULL, // 使用窗口类结构变量中指定的菜单。 hInstance, // 窗口所属应用程序的句柄。 NULL // 本窗口无须附加参数。 );

  47. 3 窗口的显示与更新 如果调用 CreateWindow或 CreateWindowEx 函数的返回值不为 0时,表明该窗口已成功创建,即系统已为窗口分配了内存, 并返回窗口的句柄。但此时所创建的窗口还未显示,需要调用 函数 ShowWindow显示窗口,并调用函数 UpdateWindow更新窗 口的客户区。这两个函数的原型和调用如下: BOOL ShowWindow( HWND hWnd, // handle to window int nCmdShow// show state of window ); 调用实例:ShowWindow( hWnd, SW_SHOW ); 其中实参 SW_SHOW表示激活由 hWnd索引的窗口,并以当前的 位置和尺寸显示窗口。

  48. 系统定义了一系列表示窗口显示状态值,祥见MSDN的有关系统定义了一系列表示窗口显示状态值,祥见MSDN的有关 部分 BOOL UpdateWindow( HWND hWnd/* handle of window */ ); 调用实例:UpdateWindow( hWnd );

  49. 1.3.3 启动消息循环 使所创建和显示窗口能够控制程序的运行,接收窗口消息并 做出相应的处理的关键是在 WinMain函数中启动一个消息循环。 正如在前面所述 Windows操作系统把所有驱动程序运行的事 件消息都放入应用程序消息队列,所以应用程序必须不断地从 消息队列中获取消息,并分发给相应的窗口函数,这就是消息 循环所要完成的工作,也是 Windows程序的一个重要特点。最 典型、最简单的消息循环定义如下:

More Related