吉林大学远程教育课件-Windows A P I编程第四十八讲_第1页
吉林大学远程教育课件-Windows A P I编程第四十八讲_第2页
吉林大学远程教育课件-Windows A P I编程第四十八讲_第3页
吉林大学远程教育课件-Windows A P I编程第四十八讲_第4页
吉林大学远程教育课件-Windows A P I编程第四十八讲_第5页
已阅读5页,还剩135页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、吉林大学远程教育课件Windows A P I编 程主讲人主讲人 : 翟慧杰翟慧杰学学 时:时:48(第四十八讲第四十八讲)一、概述 Windows操作系统是当今世界上最为流行的操作系统之一,几乎每个台式机用户都使用过Windows,用过Windows平台下的应用软件。 Windows操作系统同时也是一个大的函数库,其中包含了数以千计的函数,这些函数能完成各种各样的功能,包括窗口管理、图形设备接口、媒体控制、内存管理和系统扩展,这些函数都被封装在一个接口中,这个接口就是Windows应用程序编程接口(Windows Application Progrmming Interface),简称Win

2、dows API 。 Windows API也是认识Windows操作系统的一面镜子,通过它,用户可以深入系统地掌握Windows的方方面面。很难想象,一个程序员在没有掌握Windows API的情况下,能编制出很好的基于Windows的应用程序来。Windows API 程序设计本课件较为全面地介绍了Windows API的编程结构及其在各个方面的具体应用,分析了大量的Windows API数据结构和函数,并结合实际应用,精心安排了大量的程序实例。读者不仅可以通过函数的分析说明来认识 Windows API,而且还可以通过编程实践来认识Windows API。书中所有的例子都在Windows

3、 982000系统平台、 Visual C 6.0编译环境中经过了严格的测试。Windows 应用程序的消息来源有以下 4种: (l)输入消息:包括键盘和鼠标的输入。这一类消息首先放在系统消息队列中,然后由Windows将它们送入应用程序消息队列中,由应用程序来处理消息。 (2)控制消息:用来与Windows的控制对象,如列表框、按钮、检查框等进行双向通信。当用户在列表框中改动当前选择或改变了检查框的状态时发出此类消息。这类消息一般不经过应用程序消息队列,而是直接发送到控制对象上去。 (3)系统消息:对程序化的事件或系统时钟中断作出反应。一些系统消息,像DDE消息(动态数据交换消息)要通过Wi

4、ndows的系统消息队列,而有的则不通过系统消息队列而直接送入应用程序的消息队列,如创建窗口消息。 (4)用户消息:这是程序员自己定义并在应用程序中主动发出的,一般由应用程序的某一部分内部处理。 Windows程序在处理消息时使用了一种叫作回调函数(Callback Function)的特殊函数。回调函数由应用程序定义,但是,在应用程序中并没有调用回调函数的代码,回调函数是供操作系统或者其子系统调用的,这种调用通常在某一事件发生,或者在窗口或字体被枚举时。典型的回调函数有窗口过程、对话框过程和钩子函数。 简单地说,API就是一系列的例程,应用程序通过调用这些例程来请求操作系统完成一些低级服务。

5、在Windows这样的图形用户界面中,应用程序的窗口、图标、菜单和对话框等就是由API来管理和维护的。在DOS应用程序下,可以通过getchar ()等函数直接等待键盘输入,并直接向屏幕输出。而在Windows下,由于允许多个任务同时运行,应用程序的输入输出是由Windows来统一管理的。 Windows 操作系统包括 3个内核基本元件: GDI,KERNEL,USER。其中 GDI(图形设备接口)负责在屏幕上绘制像素、打印硬拷贝输出、绘制用户界面(包括窗口、菜单。对话框)等。系统内核KERNEL支持与操作系统密切相关的功能:如进程加载,文本切换、文件I/O,以及内存管理、线程管理等。USER

6、为所有的用户界面对象提供支持,它用于接收和管理所有输入消息、系统消息并把它们发给相应的窗口的消息队列。消息队列是一个系统定义的内存块,用于临时存储消息;或是把消息直接发给窗口过程。每个窗口维护自己的消息队列,并从中取出消息,利用窗口函数进行处理。二、Windows程序的基本框架 在实际的程序中,窗口、窗口类、窗口过程、消息队列、消息循环和窗口消息是如何相互配合的。这或许对您会有些帮助。创建一个窗口首先需要注册一个窗口类,那需要一个窗口过程来处理窗口消息。这包 括一段几乎出现在每一个Window程序中的固定代码。程序2.1所示的HELLOWIN程序就是一个包括这段固定代码的简单程序。#inclu

7、de LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) static TCHAR szAppName = TEXT (HelloWin) ; HWND hwnd ; MSG msg ; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndPr

8、oc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon=LoadIcon(NULL, IDI_APPLICATION) ; wndclass.hCursor= LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndcla

9、ss.lpszClassName = szAppName ; if (!RegisterClass (&wndclass) MessageBox (NULL, TEXT (This program requires Windows NT!), szAppName, MB_ICONERROR) ; return 0 ; hwnd = CreateWindow (szAppName, / window class name TEXT (The Hello Program), / window caption WS_OVERLAPPEDWINDOW, / window style CW_US

10、EDEFAULT, / initial x position CW_USEDEFAULT, / initial y position CW_USEDEFAULT, / initial x size CW_USEDEFAULT, / initial y size NULL, / parent window handle NULL, / window menu handle hInstance, / program instance handle NULL) ; / creation parameters ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hw

11、nd) ; while (GetMessage (&msg, NULL, 0, 0) TranslateMessage (&msg) ; DispatchMessage (&msg) ; return msg.wParam ;LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) HDC hdc ; PAINTSTRUCT ps ; RECT rect ; switch (message) case WM_CREATE: PlaySound(TEXT(hellowi

12、n.wav),NULL, SND_FILENAME | SND_ASYNC) ; return 0 ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; DrawText (hdc, TEXT (Hello, Windows 98!), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: PostQuitMe

13、ssage (0) ; return 0 ; return DefWindowProc (hwnd, message, wParam, lParam) ; Windows 函数调用函数调用:HELLOWIN至少调用了18个Windows函数。下面以它们在HELLOWIN,C中出现的次序列出这些函数以及各自的简明描述LoadIcon 加载图标供程序使用;LodCursor 加载鼠标指针供程序使用;GetStockObject 获取一个图形对象,在这个例子中,是获取绘制窗口背景的刷子;RegisterClass为程序窗口注册窗口类;MessageBox 显示消息框;CreateWindow 根据窗

14、口类创建一个窗口;ShowWindow 在屏幕上显示窗口;UpdateWindow 指示窗口刷新自身;GetMessage 从消息队列中获取消息;TranslateMessage转换某些键盘消息;DispatchMessage将消息发送给窗口过程;PlaySound 播放一个声音文件;BeginPaint 开始窗口绘制;GetClientRect 获取窗口客户区的尺寸;DrawText 显示文本串;EndPaint 结束窗口绘制;PostQuitMessage 在消息队列中插入一条“退出”消息;DefWindowProc 执行默认的消息处理。三、三、WINDOWS 资源资源 大多数Window

15、s程序都包含一个定制的图标,Windows将该图标显示在应用程序窗口标题栏的左上角。当程序被列在“开始”菜单中,或者被显示在屏幕底部的任务栏中,或者被列在“Windows资源管理器”中,或者作为快捷方式显示在桌面上时,Windows也显示该程序的图标。有些程序诸如 Windows Paint一类的重要的图形绘制工具也使用用户化的鼠标光标来表示程序的不同操作。许多Windows程序还使用菜单和对话框。图标、光标、菜单和对话框都是相互关联的,它们都是Windows的资源类型。资源即数据,它们被存储在程序的EXE文件中,但是它们并非驻留在程序的数据区域中。也就是说,资源不能通过程序源代码中定义的变量

16、直接访问,Windows提供函数直接或间接地把它们加载到内存中以备使用。我们已经遇到了两个这样的函数,即 LoadIcon和 LoadCursor,它们出现在示例程序中定义窗口类结构的赋值语句中。它们从Windows中加载二进制图标和光标图像,并返回该图标或光标的句柄。在本章,我们从创建自己定制的图标开始,这些图标从该程序自己的EXE文件中加载。 资源包括: 图标; 光标; 字符串; 定制资源; 菜单; 键盘加速键; 对话框; 位图。 将图标添加到程序:将图标添加到程序:使用资源的好处之一在于程序的许多组件能够连编进程序的EXE文件中。如果没有资源这一概念,例如图标图像的二进制文件可能会驻留在

17、单独的文件中,.EXE会把它读入内存中使用。或者图标不得不在程序中以字节数组的形式定义(这将不会看到实际的图标图像)。作为资源,图标存储在开发者计算机上的单独的可编辑文件中,但在编译过程中被连编进EXE文件中。 将资源添加到程序中需要 Visual C Developer Studio的一些附加功能。对于图标来说,可以使用“Image Editor”(也称为Graphics Editor”)来绘制图标的图像。该图像被保存在扩展名为ico的图标文件中。 Developer Studio还生成一个资源描述文件(扩展名为RC的文件,有时也称作资源定义文件),它列出了程序的所有资源和一个让程序引用资源

18、的头文件(RESOURCEH)。 如果试图编译该程序,因为在程序开头引用的RESOURCEH文件并不存在,所以会产生错误。然而,您不必直接创建 RESOURCEH文件,而是由 Developer Studio为您创建一个。可以通过将资源描述文件添加到项目中来做到这一点。从File菜单中选择New,选择 Files选项卡,单台 Resource Script,在 File Name域中键人 ICONDEMO,单击OK此时, Developer Studio创建两个文本文件: ICONDEMO.RC(资源描述文件)和RESOURCEH(允许C源代码文件和资源描述文件引用相同的已定义标识符)。不必直

19、接编辑这两个文件,让 Developer Studio来维护它们。如果您想查看资源描述文件和 RESOURCEH,而不与 Developer Studio产生干扰,可以用记事本程序打开它们。除非对您所做的很有把握,否则不要轻易地更改它们。请记住,只有当您有明确的操作命令或重新编译项目时,Developer Studio才会保存这些文件的新版本。资源描述文件是文本文件。它包括这些资源的可用文本形式表达的描述,例如菜单和对话框。资源描述文件也包括对非文本资源的二进制文件的引用,例如图标和自定义的鼠标光标。现在,已经存在RESOURCEH文件,您可以试着重新编译一下ICONDEMO。现在会出现一条报

20、错信息,指出IDI_ICON还没被定义。这个标识符第一次出现在下面的语句中:wndclasshIcon= LoadIcon(hInstance, MAKEINTRESOURCE(IDI-ICON);在前面的程序中这个语句是由下面的语句代替的:wndclass.hIcon=LoadIcon(NULL,IDI-APPLICATION);之所以改变语句是因为,以前我们为应用程序使用的是标准图标,而这里我们的目的是使用自定义图标。创建一个图标,在 Developer Studio的 File View窗口中,您会看到两个文件ICONDEMOC和ICONDEMORC。单击CONDEMOC后,就可以编辑源

21、代码。单击ICONDEMORC后,就可以把资源添加到文件中或编辑已存在的资源。要添加图标,从Insert菜单上选择Resource。单击要添加的资源,也就是图标,然后单击New按钮。现在呈现的是一个空白的 32像素 x 32像素的图标,可以向其中填充颜色。您会看到带有一组绘图工具和可用颜色的浮动的工具栏。注意颜色工具栏中包括两个与颜色无关的选项,它们有时指“屏幕”和“反屏幕”。当像素用“屏幕”着色时,它实际上是透明的。不管图标在什么表面上显示,图标来着色的部分会显示出底色。这样我们就可以创建非矩形的图标。双击围绕图标的区域,会出现Icon Properties对话框,该对话框能够更改图标的ID

22、和文件名。 菜单是 Windows程序提供的一致用户界面的最重要的部分,而在程序中添加菜单是 Windows编程中相对简单的部分。在 Develope Studio中定义菜单。每个选的菜单项被赋予唯一的ID号。在窗口类结构中指定菜单名。当用户选择一个菜项时,Windows给您的程序发送包含该ID号的WM_COMMAND消息。 窗口的菜单条紧接在标题栏的下方显示,这个菜单条有时被称为“主菜单”或“顶层单”。列在顶层菜单的项通常是下拉式菜单,也叫做“弹出式菜单”或“子菜单”。您也以定义多重嵌套的弹出式菜单,也就是说,在弹出式菜单上的项可以访问另一个弹出菜单。有时弹出式菜单上的项调用对话框以获得更多

23、的信息(对话框在标题栏的最左端,很多父窗口都显示程序的小图标,这个图标激活系统某单,这实际上是另一个弹出式菜单。弹出式菜单的各项可以是“被选中的”,这意味着Window在菜单文本的左端显一个小的复选标记,复选标记让用户知道从菜单中选中了哪些选项。这些选项之间以是互斥的,也可以是不互斥的。顶层菜单项不能被选中。 顶层菜单或弹出式菜单项可以被“启用”、“禁用”或“灰化”。“激活”和“不激活”时候被用作“启用”和“禁用”的同义词。标以启用或禁用的菜单项在用户看来是一样的,但是灰化的菜单项是使用灰色文本来显示的。从用户的角度看,启用、禁用和灰化的菜单项都是可以“选择的”加亮的“,也就是说,用户可以使用

24、鼠标选择被禁用的菜单项,或者将反显光标条移动到禁用的菜单上,或者使用菜单项的关键字母来选择该菜单项。然而,从程序员的角度来看,启用、禁用和灰化菜单项的功能是不同的。Window只为启用的菜单项向程序发送WM_ COMMAND消息。对当前不合法的选项,可以禁用和灰化菜单项。如果想使用户知道选择是不合法的,那么您可以灰化它。当您创建或更改程序中的菜单时,把顶层菜单和每一个弹出式菜单想象成各自独立的菜单是有用的。顶层菜单有一个菜单句柄,在顶层菜单中的每一个弹出式菜单也都自己的菜单句柄。系统菜单(也是一个弹出式菜单)也有菜单句柄。菜单中的每一项都有三个特性。第一个特性是菜单中显示什么,它可以是字串或位

25、图。第二个特性是WM_COMMAND消息中Windows发送给程序的菜单ID,或者是在用户选择菜单项时Windows显示的弹出式菜单的句柄。第三个特性是菜单项的属性,包括是否被禁用、灰化或被选中。当您创建或更改程序中的菜单时,把顶层菜单和每一个弹出式菜单想象成各自独立的菜单是有用的。顶层菜单有一个菜单句柄,在顶层菜单中的每一个弹出式菜单也都自己的菜单句柄。系统菜单(也是一个弹出式菜单)也有菜单句柄。菜单中的每一项都有三个特性。第一个特性是菜单中显示什么,它可以是字串或位图。第二个特性是WM_COMMAND消息中Windows发送给程序的菜单ID,或者是在用户选择菜单项时Windows显示的弹出

26、式菜单的句柄。第三个特性是菜单项的属性,包括是否被禁用、灰化或被选中。如果在 Menu Items Properties对话框中复选 Grayed选项,则菜单 项 是 不 能 激 活 的 , 它 的 文 本 是 灰 色 的 , 该 项 不 产 生WM_COMMAND消息。二、在程序中引用菜单二、在程序中引用菜单大多数Windows应用程序在资源描述文件中只有一个菜单。您可以给菜单起一个与程序名相同文字的名称。程序员经常将程序名用于菜单名,以便相同的字符串可以用于窗口类、程序的图标名和菜单名。然后,程序在窗口的定义中为菜单引用该名称: wndclass.lpszMenuName=szAppNam

27、e;虽然访问菜单资源的常用的方法是在窗口类中指定菜单,也可以使用其他方法,Windows 应用程序可以使用LoadMenu函数将菜单资源加载到内存中,如同LoadIcon 和LoadCursor 函数一样。LoadMenu返回一个菜单句柄。如果您在资源描述文件中为菜单使用了名称,语句如下:hMenu= LoadMenu(hInstance,TEXT(“ MyMenu”); 如果使用了数值,那么LoadMenu调用采用如下形式: hMenu= LoadMenu(hInstance,MAKEINTRESOURCE(ID_MENU);然后,您可以将这个菜单句柄作为CreateWindow的第9个参数

28、: 在这种情况下,CreateWindow调用中指定的菜单可以覆盖窗口类中指定的任何菜单。 如果CreateWindow的第9个参数是NULL,那么您可以把窗口类中的菜单看作是基于这个窗口类的窗口默认菜单。这样,您可以为基于同一窗口类的几个窗口使用不同的菜单。 您 也 可 以 在 窗 口 类 中 指 定 N U L L 菜 单 , 并 且 在CreateWindow调用中也指定NULL菜单,然后在窗口被创建后再给窗口指定一个菜单: SetMenu(hwnd,hMenu); 这种形式使您可以动态地修改窗口的菜单。当窗口被清除时,同窗口相关的所有菜单都将被清除。同窗口不相关的菜单在程序结束前通过调

29、用 DestroyMenu被显式地清除。三、菜单和消息三、菜单和消息 当用户选择一个菜单项时,Windows通常向窗口过程发送几个不同的消息。在大多数情况下,您的程序可以忽略大部分消息,只需把它们传递给DestroyWindowProc即可。WM_INITMENU就是这一类的消息,它具有下列参数: wParam:主菜单句柄 lParam: 0wParam 值是主菜单句柄,即使用户选择的是系统菜单中的项。Windows程序通常忽略 WM_INITMENU消息。尽管在选中该项之前的消息已经给程序提供了修改菜单的机会,但是我们觉得此刻改变顶层菜单对用户来说是很为难的。 加速键是产生_消息(有些情况下

30、是_)的键组合。许多时候,程序使用加速键来重复常用菜单项的动作(然而,加速键还可以用于执行非菜单功能)。例如,许多Windows程序在菜单中都包含或Clear选项,这些程序习惯上都将Del键指定为该选项的加速键。用户可以通过Al键从菜单中选择Delete 选项,或者只需按下加速键Del。当窗口过程收到一个_消息时,它不必确定使用的是菜单还是加速键。 对于有多个窗口和多个窗口过程的应用程序来说,加速键是非常重要的。Windows将键盘消息发送给当前活动窗口的窗口过程。然而对于加速键,Windows把_COMMOND消息发送给窗口过程,该窗口过程的句柄在indows 函数TranslateAcce

31、lerator中给出。通常这是主窗口,也是拥有菜单的窗口,这意味着无需每个窗口过程都复制加速键的操作逻辑。如果在主窗口的客户区中使用了非模态对话框或者子窗口,那么这种好处就变得非常重要。如果定义一个特定的加速键,以便在不同的窗口之间移动,那么只需要一个窗口过程有这个逻辑,子窗口不会收到加速键引发的_COMMAND消息。 四、 Windows绘图程序设计 图形设备接口(GDI:Graphics Device Interface)是Windows的子系统,它负责在视频显示器和打印机上显示图形。正如您所认为的那样,GDI是Windows非常重要的部分。不但您为Windows编写的应用系统在显示视觉信

32、息时只使用GDI,就连Windows本身也只使用GDI来显示用户界面对象,诸如菜单、滚动条、图标和鼠标光标。 从程序员的观点来看,GDI由几百个函数调用和一些相关的数据类型、宏和结构组成。 但是在开始讲述这些函数的细节之前,让我们先从宏观上了解一下GDI的整体结构。组成GDI的几百个函数调用可以分为几大类:获取获取或创建或创建和释放(或清除)设备描述表的函数和释放(或清除)设备描述表的函数 在绘图时需要设备描述表句柄。GetDC和RealseDC函数让您在非WM_PAINT 的消息期间来做到这一点,而 BeginPaint和 EndPaint函数(虽然在技术上它们是 USER模块而不是GDI模

33、块的一部分)在进行绘图的WM_PAINT消息期间使用。获取有关设备描述表信息的函数获取有关设备描述表信息的函数 GetTextMetrics函数来获取有关设备描述表中当前所选字体的尺寸信息。绘图函数绘图函数 显然,在所有前提条件都得以满足之后,这些函数是真正重要的部分。我们使用TextOut函数在窗口的客户区显示一些文本。我们将看到,其他GDI函数还可以让您画线、填充区域。在屏幕或打印机上显示的图形类型本身可以被分为几类,通常被称为“图元”,它们是:直线和曲线直线和曲线 线条是所有矢量图形绘制系统的基础。GDI支持直线、矩形、椭(包括椭圆的子集,也就是我们所说的“圆”)、椭圆圆周上的部分曲线即

34、所谓“弧”,以及贝塞尔曲线,我们将在本章中分别对它们进行介绍。所有更复杂的曲线可由折线( polyline)代替,折线通过一组非常短的直线来定义一条曲线。线条用设备描述表中选中的当前画笔绘制。窗体客户区绘图步骤:步骤: 1获取设备环境句柄 2获取绘图工具 3选择绘图工具 4利用选择的绘图工具绘图 5恢复原来的绘图工具并删除选择的绘图工具 6释放设备环境句柄WINDOWS GDI 函数:1GetDC()函数 功能: 用于获取指定窗体客户区的显示器设备描述表句柄。2ReleaseDC () 函数 功能:用于释放设备描述表句柄。3BeginPaint()函数 功能:用于获取窗体客户区绘图的相关信息,

35、并为绘图做好准备。4. EndPaint()函数 功能:用于结束窗体客户区绘图。5. SetPixel()函数 功能:用于在窗体客户区绘制点(像素)。6、RGB()宏 功能: 用于设置颜色。7、CreatePen()函数 功能: 用于建立逻辑笔。8、MoveToEx()函数 功能:用于窗体客户区移动逻辑笔。9、LineTo()函数 功能:用于在窗体客户区当前位置画线。10、Ellipse()函数 功能:用于窗体客户区绘制椭圆。11、SelectObject()函数 功能:用于选择一种绘图工具柄将其装入设备描述表。12、DeleteObject()函数 功能:用于删除一个绘图工具。13、Text

36、Out()函数 功能:用于在窗体客户区输出文本。14、SetBkMode()函数 功能:用于设置窗体客户区背景填充方式。15、SetTextColor()函数16、CreateFont()函数其它函数其它函数 1SetTimer()函数功能:用于建立产生时间消息的时间控件。2、KillTimer()函数 功能:用于取消时间控件。3、GetClientRect()函数 功能:用于获取窗体客户区范围。画点和线:画点和线: 我们已谈论过Windows图形设备接口将图形输出设备的设备驱动程序与计算机连在一起的方式。在理论上,只要提供SetPixel和GetPixel函数,就可以使用图形设备驱动程序绘制

37、一切东西了。其余的一切都可以使用 GDI模块中实现的更高级的例程来处理。例如画线时,只需GDI调用 SetPixel数次,并适当地调整和Y坐标。在实际情况中,也的确可以仅使用SetPixel和GetPixel函数进行您需要的任何绘制。您也可以在这些函数的基础上设计出简洁和构造良好的图形编程系统。唯一的问题是性能。如果一个函数通过几次调用才能到达SetPixel函数,那么它运行起来会非常慢。如果一个图形系统画线和进行其他复杂的图形操作是在设备驱动程序的层次上,它就会更有效得多,因为设备驱动程序对完成这些操作的代码进行了优化。此外,一些视频适配器卡包含了图形协处理器,它允许视频硬件自己绘制图形。

38、五五 文本和字体:文本和字体:文本输出是应用程序经常需要实现的功能。许多程序的运行结果都必须以文本输出形式显示;文字处理程序更是主要以文本作为处理的对象。所以,程序员掌握文本输出的基本原理和技术具有重要的意义。文本输出需要解决的问题是如何修改显示文本的字体、颜色和大小,以及如何协调在不同设备上显示文本的差异。文本的设备描述表属性:设备描述表( Device Context)是一个决定输出的位置和外形的属性集合。在用户编制的应用程序中可以通过设备描述表句柄间接地读取设备描述表。当程序为设备描述表申请一个句柄时,系统就自动生成了一个设备描述表,生成的设备描述表包含了所有属性的默认值。 背景色定义了

39、填充字符,以及填充字符间区域的颜色。背景模式有两种取值:OPAQUE和 TRANSPARENT。默认值为 OPAQUE表示背景颜色有效;如果设定为TRANSPARENT,则表示关闭背景色。字符间距和文本颜色分别表示两个字符间的间隔和字体的颜色。 字体描述了所显示字符的大小、外形和种类,也就是说字体包含了字符集中每个字符属性的抽象描述。字体分为两种基本类型:物理字体和逻辑字体。GDI(图形设备接口)常用的字体如表所示。 六、键盘和鼠标:在Microsoft Windows 中,键盘和鼠标是两个标准的用户输入源,在一些交叠的操作中通常相互补充使用。当然,鼠标在今天的应用程序中比10年前使用得更为广

40、泛。甚至在一些应用程序中,我们更习惯于使用鼠标,例如在游戏、画图程序、音乐程序,以及Web创览器等程序中就是这样。然而,我们可以不使用鼠标,但绝对不能从一般的PC中拆掉键盘。 相对于个人计算机的其他组件,键盘有非常久远的历史,它起源于1874年的第一台Remington打字机。早期的计算机程序员用键盘在Hollerith卡片上打孔,以后在哑终端上用键盘直接与大型主机通讯。PC上的键盘在某些方面进行了扩展,包括了功能键、光标定位键和(通常都带有的)单独的数字键盘,但它们的输入原理基本相同。Windows程序获得键盘输入的方式:键盘输入以消息的形式传递给程序的窗口过程。实际上,第一次学习消息时,键

41、盘就是一个明显的例子:消息应该传递给应用程序的信息类型。Windows用8种不同的消息来传递不同的键盘事件。这好像太多了,但是(就像我们所看到的一样)程序可以忽略其中至少一半的消息而不会有任何问题。并且,在大多数情况下,这些消息中包含的键盘信息会多于程序所需要的。处理键盘的部分工作就是识别出哪些消息是重要的,哪些是不重要的。虽然应用程序在很多情况下可以通过鼠标实现信息的输入,但到现在为止键盘仍然是PC机中不可替代的重要输入设备。 用键盘当作输入设备,每当用户按下或释放某一个键时,会产生一个中断,该中断激活键盘驱动程序KEYBOARD.DRV来对键盘中断进行处理。KEYBOARD.DRV程序会根

42、据用户的不同操作进行编码,然后调用Windows用户模块USER.EXE生成键盘消息,并将该消息发送到消息队列中等候处理。1扫描码和虚拟码 扫描码对应着键盘上的不同键,每一个键被按下或释放时,都会产生一个唯一的扫描码作为本身的标识。扫描码依赖于具体的硬件设备,即当相同的键被 按下或释放时,在不同的机器上可能产生不同的扫描码。在程序中通常使用由Windows系统定义的与具体设无关的虚拟码。在击键产生扫描码的同时,键盘驱动程序KEYBOARD.DRV截取键的扫描码,然后将其翻译成对应的虚拟码,再将扫描码和虚拟码一齐编码形成键盘消息。所以,最后发送到消息队列的键盘消息中,既包含了扫描码又包含了虚拟码

43、。输入焦点: 同一时刻,Windows中可能有多个不同的程序在运行,也就是说有多个窗口同时存在。这时,键盘由多个窗口共享,但只有一个窗口能够接收到键盘消息,这个能够接收键盘消息的窗口被称为拥有输入焦点的窗口。 拥有输入焦点的窗口应该是当前的活动窗口,或者是活动窗口的子窗口,其标题和边框会以高亮度显示,以区别于其他窗口。拥有输入焦点的也可以是图标而不是窗口,此时,Windows也将消息发送给图标,只是消息的格式略有不同。 窗口过程可以通过发送WM_SETFOCUS和 WM_KILLFOCUS消息 使 窗 体 获 得 或 失 去 输 入 焦 点 。 程 序 也 可 以 通 过 捕 获WM_SETF

44、OCUS和WM_KILLFOCUS消息来判断窗体何时获得或失去输入焦点。其中WM_SETFOCUS消息表示窗口正获得输入焦点,WM_ KILLFOCUS消息表示窗口正失去输入焦点。键盘消息:键盘消息分为系统键消息和非系统键消息。系统键消息是指由Aft键和其他键组合而产生的按键消息。当系统键被按下时产生WM_ SYSKEYDOWN消息,当系统键被释放时产生WM_SYSKEYUP消息。 Aft键与其他键形成的组合键通常用于对程序菜单和系统菜单进行选择,或用于在不同的程序之间进行切换。因此,系统键消息应该交由Windows进行处理,用户所编制的程序一般不处理系统键消息,而是将这些消息交由DefWin

45、dowProc函数进行处理。如果用户想对系统键消息进行处理,应该在处理完这些消息后,再将其发送给DefWindowProc函数,使得Windows系统能够正常工作。 某些击键消息可以被转换成字符消息,例如字母键、数字键等。而有些键只能产生按键消息而没有字符消息,例如 Shift键、 Insert键等。消息循环中的 TranslateMessage函数可以实现从击键消息向字符消息的转化。当GetMessage函数捕获一个WM_SYSKEYDOWN消息或WM_KEYDOWN消息后,TranslateMessage函数判断产生该消息的键是否能够被转换成字符消息,如果能,就将该消息转换成字符消息,再通

46、过DispatchMessape函数将转换后的字符消息发送到消息队列中去。Windows的消息一般是通过一个MSG结构体变量传送给消息处理函数的。对于键盘消息, MSG结构体变量的各个域中较重要的是 lParam域和 wParam域。 wParam域用于保存按键的虚拟键代码或字符的ASCII码。对于非字符消息,wParam域保存按键的虚拟健代码;对于字符消息,wParam域不保存字符的ASCII码。lParam域则用于保存击键时产生的附加信息,实际上一个32位的lParam变量被分为六部分,记录了以下相关信息:重复次数、OEM扫描码、扩展键标志、关联键标志、前一击键状态和转换状态。lParam

47、域各位的含义如表所示。对于非字符消息,wParam域保存按键的虚拟健代码;对于字符消息,wParam域不保存字符的ASCII码。lParam域则用于保存击键时产生的附加信息,实际上一个32位的lParam变量被分为六部分,记录了以下相关信息:重复次数、OEM扫描码、扩展键标志、关联键标志、前一击键状态和转换状态。lParam域各位的含义如表所示。随着Windows操作系统的流行,鼠标因为其精确定位和操作方便的优点而成为计算机不可缺少的输入设备。一、鼠标的基础知识 本节将介绍在程序中用鼠标作为输入设备的方法和技巧。1鼠标操作和鼠标消息用户在使用鼠标操作的过程中,经常会使用的主要方式有五种,如表所

48、示。 其中,前三种操作是最为基本的操作,可以产生Windows内部定义的消息,并通过这些消息来判断用户具体执行了哪种操作。 Windows定义的鼠标消息共有20条,其中非编辑区的鼠标消息一般交由系统处理,程序只处理编辑区内的鼠标消息。编辑区内的鼠标消息共有10条,如表所示。 对于前表所列的鼠标操作中的最后两种,不能直接使用Windows定义的消息来判断,只能通过编程,将多种消息和数据组合之后判断。例如,判断用户是否按下鼠标左键之后进行拖动操作可以通过以下程序段来实现,用case语句来实现: case WM_MOUSEMOVE: if (wParam&MK_LBUTTON) /只处理鼠标

49、拖动的消息 / 处理程序 在处理鼠标消息的过程中,消息的wParam参数和lParam参数起了重要的作用。wParam参数中保存了在消息产生时其他操作进行的状态;用户可以通过位屏蔽操作来判断在该消息产生的同时,其余操作是否正在进行。这正是在程序中判断复杂鼠标操作的基本方法。例如,上面判断拖动操作的程序段就用了位操作 wParam MK_LBUTTON, 判断在鼠标移动(WM_MOUSEMOVE)的同时鼠标左键是否同时被接下。如果,鼠标左键同时按下,则位操作的结果为TRUE,说明当前操作为拖动操作,程序可以继续进行下一步处理。 又如需要判断单击鼠标左键时是否同时按下了Ctrl键或Shift键,可

50、以用以下程序段来处理:case WM_ LBUTTONDOWN: if(wParam MK_CTROL) /Ctrl键同时按下 if (wParamMK_ SHIFT) / Ctrl 键和Shift键都同时按下 / 处理程序 else / Ctrl健同时按下,但 Shift键没有被按下 . / 处理程序 else if(wParamMK_ SHIFT) / Shift键同时按下,但 Ctrl键没有被接下 / 处理程序 else / Shift 键和Ctrl键都未按下 / 处理程序 lParam参数保存了消息产生时鼠标所在点的坐标,其中低16位为X坐标,高16位为Y坐标。 在处理鼠标消息的时候,

51、如果需要处理鼠标双击消息,则在注册窗口类时,窗口的风格必须包括CS_DBCLCKS。否则即使执行了双击操作,窗口也只能收到两条WM_ BUTTONUP和 WM_BUTTONDOWN消息。区分双击操作和两次单击操作是以两次击键的时间间隔为标准的。当两次击键的时间间隔小于 500毫秒时, Windows将其视为双击操作:如果两次击键的时间间隔大于500毫秒,Windows将其视为两次单击操作。500毫秒为默认的时间间隔,用户可以通过调用SetDoubleClickTime函数来修改这一时间间隔。SetDoubleClickTime函数的原型定义如下: BOOL SetDoubleClickTime

52、( UINT uInterval / 新的击键时间间隔 );鼠标捕捉 在通常情况下,只有当鼠标位于窗体内时,窗体才能接收到鼠标的消息。如果需要接收所有的鼠标消息而不论鼠标是否在窗口内,这时可以调用SetCapture函数来实现。SetCapture函数的原型定义如下: HWND SetCapture ( HWND hwnd / 窗口句柄 ); 调用SetCapture函数后,所有鼠标操作所产生的消息都直接发送到指定窗口。因为此时鼠标可能位于窗口之外,所以鼠标的坐标可能为负值。由于调用该函数会使其他窗口不能接收到键盘和鼠标的消息,因此在完成操作后应及时调用ReleaseCapture 函数释放鼠

53、标捕获。ReleaseCapture函数的原型定义如下: BOOL ReleaseCapture(VOID); 我们讨论三种窗体,它们分别是“重叠式窗体”(overlapped window)“弹出式窗体”(popup window)与“子窗体”(child window)。第一节 窗体风格1. WS_OVERLAPPED2. WS_OVERLAPPEDWINDOW3. WS_POPUP4. WS_POPUPWINDOW5. WS_CHILD6. WS_CHILDWINDOW利用带有WINDOW窗体风格建立的窗体, 一般具有较为完备的窗体要素;主窗体一般采用层叠式(WS_OVERLAPPED)

54、 窗体风格;子窗体一般采用子窗体(WS_CHILD)风格 或弹出式窗体(WS_POPUP)风格;利用子窗体(WS_CHILD)风格建立的子窗体只能在其父窗体的客户区内;利用弹出式窗体(WS_POPUP)风格或层叠式(WS_OVERLAPPED)窗体风格建立的子窗体可以子左面上任意移动。第二节 相关函数一SetWindowText()函数 1.功能: 用于设置窗体标题条标题。 2.函数声明: BOOL SetWindowText(HWND hWnd, LPCTSTR lpString); 3.参数: hWnd: 窗体句柄; lpString:指向标题字符串指针。 4.返回值: 如果成功,返回TR

55、UE,否则返回FALSE。 二wsprintf()函数 1.功能: 用于内部文件写操作。 2.函数声明: int wsprintf(LPTSTR lpOut, LPCTSTR lpFmt, .); 3.参数: lpOut:内部文件指针; lpFmt:可是说明字符串; .: 变量表。 4.返回值: 如果成功,返回内部文件长度,否则0。图形界面和消息处理是任何一个基于Windows的应用程序必须认真考虑的事情。在前面的章节中已经介绍了Windows应用程序消息处理的机制,这种机制对于所有对象的消息处理都是一致的,即实行客户(用户操作或请求)到操作系统(捕获消息)到应用程序(接收消息并执行处理代码)

56、的机制。而图形界面则包含丰富的内容,主要是指各种各样的控件,不仅包括前面章节中介绍的主窗口,还包括按钮、编辑框、滚动条等具有窗口风格的子窗口。丰富的图形界面元素为建立界面友好的应用程序提供了可能,而完整的消息处理机制则为应用程序的功能提供了高效集成的保证。子窗口的概念包含两方面的含义: 从创建子窗口的过程来看,Createwindow函数为创建各类窗口提供了统一的函数,并且子窗口的类型唯一由第一个参数确定;从窗口的界面风格来看,这些子窗口都拥有窗口的许多性质。 设计含有子窗口的程序都从调用函数 CreateWindow开始,它一共有 11个参数,指定待创建的子窗口的类型、标题、风格等非常重要的

57、性质。CreateWindow函数的原型定义如下:HWND CreateWindow( LPCTSTR lpClassName, / 指定子窗口的类名LPCTSTR lPWindowName, / 指定窗口名称DWORD dwSty1e, / 指定窗口风格int x, / 指定窗口左上角顶点的水平坐标int y, / 指定窗口左上角顶点的垂直坐标int nWidth, / 指定窗口宽度int nHeight, / 指定窗口高度HWND hWndParent, /父窗口句柄,允许为NULLHMENU hMenu, /窗口的菜单句柄或者是子窗口自己的标识符HANDLE hInstance, /应用

58、程序句柄,可以为NULLLPVOID lpParam /指向lParam数值的指针); 当子窗口创建成功后,返回子窗口的句柄,否则返回NULL。在11个参数中 lpClassName、dwStyle和 hMenu是三个最重要的参数。下面分别讲述它们的意义。 lpClassName指定子窗口的类名,它们的取值可以是如表所示的值。 子窗口类型描述dwStyle指定子窗口的风格。这里只讲述一般窗口的风格,表所列的子窗口的风格在后面内容中分别讲述。一般窗口的风格取值如表所示。参数hMenu指定菜单句柄或者子窗口的标识符。例如,已建立的菜单资源标识符为IDM_MENU, 窗口需要加载该菜单,则 hMen

59、u参数可为 IDM_NENU子窗口的标识符可以是字符或者数字,但同一个应用程序中不同子窗口的标识符必须相异,并且前面加上(hMENU)来满足参数类型兼容的要求。应用程序运行后,首先创建主窗口,并发送 WM_CREATE消息,由于在该消息的处理代码中含有创建子窗口的代码,于是就创建了子窗口。当子窗口的WS_VISIBLE风格指定后,子窗口就显示出来。 同前所讲的消息处理机制类似,子窗口的消息也主要依靠参数lParam和wParam来完成。 应用程序创建子窗口后,在主窗口的消息处理函数中一般使用SendMessase向子窗口发送消息。当用户对子窗口进行某种操作后,将向父窗口发送WM_COMMAND

60、类型的通知消息。其中,lParam包含子窗口的句柄;wParam参数的高位字节为通知代码,低位子代表子窗口的标识符。 下面将分别讲述各种子窗口的特有风格以及消息循环,并结合实例介绍子窗口的应用。 一、Button子窗口 Button(按钮)是Windows子窗口的最常用的元素之一。例如安装程序中选择Next或者Back按钮。1. 按钮类型 依据操作的类型可以把按钮分为按键按钮、单选按钮、复选按钮,另外还有存放单选按钮和复选按钮的按钮组合框(GroupBox)。 按键按钮一般执行某项功能,例如弹出新的窗口。在创建子窗口的函数中,如果需要创建按键按钮,则dwStyle参数指定为BS_PUSHBUTTON。 当某些选择相互排斥时,需要用到单选按钮,例如字体或者颜色

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论