Windows应用程序编程接口API.ppt_第1页
Windows应用程序编程接口API.ppt_第2页
Windows应用程序编程接口API.ppt_第3页
Windows应用程序编程接口API.ppt_第4页
Windows应用程序编程接口API.ppt_第5页
已阅读5页,还剩61页未读 继续免费阅读

下载本文档

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

文档简介

第5章 Windows应用程序 编程接口,教学要点 本章内容主要包括API的概念及分类,从API的使用看操作系统所提供的服务,操作系统内核中的文件操作API的使用,网络服务API函数的使用,利用图形设备接口API编写图形用户界面程序的方法。 要求了解API的分类及其对应的磁盘上的物理文件.DLL的名称、网络服务API的含义和网络编程的一些基本概念、进程概念及建立新进程的方法、WM_PAINT消息含义。握握API概念和其与操作系统提供的程序员接口的关系、内核中文件操作API的调用,熟悉API编写图形用户界面程序的步骤,熟练掌握API编写的图形用户界面程序的主要组成模块及含义。,第5章 目录,5.1 API概述 5.2 内核服务API函数的使用 5.3 网络接口服务 5.4 Win32 API编写图形界面程序 5.5 图形设备接口与用户接口服务 习题,本章以一些API设计的控制台程序和具有图形界面的Win32程序为例,阐述了利用API函数开发程序的过程,重点在于理解操作系统所提供的各种服务以及程序员如何进行调用。,5.1 API概述,5.1.1 关于WindowsAPI编程模式 5.1.2 API简介 5.1.3 Windows核心三个动态链接库 5.1.4 Windows API分类 *5.1.5 操作系统的认识,Windows API编程是一种原始的开发Windows应用程序模式,它主要使用的是C语言、少量的C+通用类及“原始”的Windows应用程序编程接口API(Application Programming Interface) 。这些函数都是比较底层的函数,其地位大致相当于字符界面环境下C语言的标准库函数,只不过其运行环境为Windows的图形界面环境。 本篇的后多半部分虽然采用的是相对比较简单的MFC编程,但使用底层的API函数编写程序可以看到许多MFC编程看不到的东西,从而对Windows的内部运作有更深入的了解。进行API编程,要求用户对Windows环境比较熟悉,并且熟悉C语言。在API编程中用到大量的有关操作系统的结构体变量和控制操作系统的函数,当在使用API函数遇到问题时,可以随时查阅Windows 的API文档,它位于MSDN的Platform SDK部分。,5.1.1 关于WindowsAPI编程模式,Windows操作系统向程序员提供了可以实现开启窗口、绘制图形,使用系统各种设备等的一组函数服务,称之为Application Programming Interface(应用程序编程接口),即API函数。 利用VC进行Windows应用程序的开发,除了用到各种.h头文件中的库函数及数据结构外,还需要使用Windows SDK(Software Development Kit,软件开发工具包)提供的使用于Windows应用程序的特殊库函数和数据结构、语句、文件结构。所有这些内容组成了Windows应用程序设计接口API。 使用Win32 API,应用程序可以充分挖掘出Windows 32位操作系统的潜力,Microsoft的所有32位平台都支持统一的API,包括函数、结构、消息、宏及接口。使用Win32 API,不但可以开发出在各种平台上都能运行的应用程序,而且还可以充分利用每个平台上特有的功能和属性。,5.1.2 API简介,5.1.3 Windows核心 三个动态链接库,Windows操作系统核心有三个动态链接库(Kernel32.dll,User32.dll,Gdi32.dll),这些动态链接库构成了Win32 API函数。,1Windows内核库(Kernel32.dll) 内核库中的函数用于处理操作系统功能的所有核心工作,例如多任务管理、内存管理等。另外内核库还管理系统注册表。 2Windows用户界面管理库(User32.dll) 用户界面管理库包括了Windows管理、菜单、光标、定时器和通信等有关的函数。在Windows中,窗口的标识被称为“句柄”。 3Windows图形设备界面库(Gdi32.dll) 图形设备界面库提供了用于管理系统支持的所有图形设备函数,包括屏幕、打印机等设备的管理。GDI库中的函数为应用程序提供与设备无关的绘图内容。应用程序中通过GDI库中的函数绘图,不是直接面向硬件操作,而是通过“设备描述表”来进行操作,它通过句柄hDC来跟踪。,Windows三个核心库中的API函数的原型声名在windows.h中有说明,这就是我们在编写Win32应用程序时要在程序开头放#include “windows.h”语句的原因。,5.1.4 Windows API分类,根据Windows API函数完成的功能,可以将其分为如下的类别:,1内核服务 通过内核服务函数,应用程序可以使用计算机中的资源和操作系统的特性,例如内存,文件系统、设备、进程、线程等。拿一个简单的文件输入输出函数来说,通过这些函数,程序员可以存取本地计算机或网络中某台计算机中的文件、目录、输入输出设备,并且这些文件函数支持各种各样的文件系统,包括FAT、NTFS的文件系统。 内核服务体现了Windows操作系统“服务”的观点。作为一个程序员我们应该利用这些服务函数来充分发挥操作系统的功能。对于这部分API函数的使用,我们可以在基于控制台的应用程序中编写,因为这些函数都是一些与Windows图形用户界面无关的,在字符方式下操作比较简单。后面有关这方面函数的操作就是在基于控制台的应用程序中使用的。 内核服务的函数大部分包含在Windows内核库Kernel32.dll中。,5.1.4 WindowsAPI分类(续),2图形设备接口 图形设备接口是Windows最原始的图形输出库(最原始意味着除了GDI外,还有工业界用的OpenGl和游戏界用的DirectX,VC都对他们提供支持)。当看到图形或文本显示在屏幕上时,这就是GDI的功劳。它提供了在显示器、打印机或其它设备上生成图形的函数与相关的数据结构。利用GDI函数,你可以画直线、曲线、文本、位图等。你还可以使用各种各样的绘图对象如笔、画刷、字体等,使得所绘制的图形更加丰富多彩。另外,Windows本身也是通过GDI来绘制其用户界面,包括窗口、菜单和对话框。 顾名思义,图形设备接口是与图形界面有关的,因此这些函数的使用要在图形用户界面下操作。即必须建立基于Win32的应用程序,建立的步骤如4.4节所示。 图形设备接口的函数是包含在Windows图形设备界面库Gdi32.dll中。,5.1.4 Windows API分类(续),3用户接口服务 用户接口服务函数可以创建和使用Windows来显示输出、提示用户输入和执行与用户交互的任务。用户接口服务是通过一些常见的Windows对象来实现的,例如按钮、组合框、编辑框、菜单、键盘输入、定时器等。 用户接口服务的函数是在Windows用户界面管理库User32.dll中。 4网络服务 网络服务允许分布在网络中不同计算机上的应用程序进行通讯。通过这些函数可以创建和管理共享资源,例如共享目录和网络打印机。 网络服务的函数是在网络接口函数库Mpr.dll、Wininet.dll和Winsock32.dll中。 5多媒体服务 多媒体技术是指利用计算机综合处理多媒体信息文本、图形、图象和声音等,使多种信息建立逻辑连接,集成为一个系统并具有交互性。多媒体服务提供了数字音频、视频、图形、图象等服务。 该服务的函数主要包含在多媒体函数库Winmm.dll中。,5.1.4 WindowsAPI分类(续),6客户/服务方式存取服务 在客户/服务方式存取模式中,客户可以连接到服务器上以使用服务器的功能和数据,服务器通过客户端的标识和权限来决定客户端可以使用的功能。Win2K提供了一套函数来限制和允许客户端对服务端的访问。这些函数扩展了Win2k的存取控制模型来使用服务端的私有对象和使用服务端的功能。客户/服务方式存取服务又称操作系统高级编程接口,这些函数包含在高级编程接口函数库Advapi32.dll中。 7版本服务 版本服务主要提供有关文件的版本信息。这些服务所对应的函数包含在版本函数库Version.dll中。 8公共对话框服务 公共对话框,又叫通用对话框,是Windows预定义的对话框,可以使用通用对话框来执行六种标准操作,选择文件,指定字体、选择颜色、打印设置、查找文本、保存文件。这些服务所对应的函数包含在公共对话框函数库Comdlg32.dll中。,5.1.4 WindowsAPI分类(续),9打印管理服务 在Windows操作系统下,可以实现在各种设备下的打印。打印管理服务提供了完整的函数集支持这些操作,例如检索打印机,准备打印等。这些服务所对应的函数包含在打印管理函数库Winspool.drv中。 10解/压缩文件服务 该服务提供了对文件的压缩和解压服务。这些服务所对应的函数包含在函数库Lz32.dll。 在VC6.0中提供了一个文件Win32api.csv。它是一个Win16与Win32函数的对照表。通过它,读者可以浏览到Windows各种版本下API函数的原型说明。,5.1.5 操作系统的认识,操作系统有两个接口:一个是用户接口,另一个是程序员接口。 VC开发工具的强大,其中很重要的一个方面就是对于Windows API的直接调用,其它任何开发工具中的函数都是对其的一个封装。凡是在Windows工作环境下执行的应用程序,都可以通过某种特定方式调用Woindows API函数。可以毫不夸张地说,Windows API函数是构建整个Windows框架的基石,在它下面是Windows操作系统核心,在它上面则是所有华丽的Windows应用程序。 事实上,任何开发工具提供的类库和构件都是架构在Win32 API函数基础上,是封装了的API函数集合。这些类库和构件简化了程序的开发,但其功能有限。在实际应用中,如果我们希望开发出更灵活、更实用、更具效率的程序时,则必须要涉及直接使用API函数。虽然类库和构件使应用程序的开发简单了,但它们只提供Windows的常用的一般功能,对于比较复杂和特殊的功能来说,使用类库和构件中提供的方法是非常难以实现的,这时就需要直接调用特定的API函数。,5.2 内核服务API函数的使用,内核服务是最能体现API函数威力的地方,通过这些函数,用户能够使用操作系统内核所提供的核心功能。操作系统的进程管理、文件管理、内存管理都是属于内核的功能。,5.2.1 文件管理内核服务 5.2.2 进程操作 5.2.3 计算机系统信息操作,VC下提供了对文件操作的四种方式: (1)使用C语言中的fopen()、fprintf()、fread()等基本的函数进行文件操作; (2)使用C+中的流式文件接口fstream中的函数进行操作; (3)使用面向对象的类CFile进行操作; (4)使用有关的文件API进行操作。,5.2.1 文件管理内核服务,1.文件操作 2.驱动器操作,API为一般的文件操作提供了三个函数:移动、复制和删除。 文件拷贝的API函数如下所示: BOOL CopyFile( /从源文件向目标文件复制内容 LPCTSTR lpExistingFileName, / 源文件名称 LPCTSTR lpNewFileName, / 目标文件名称 BOOL bFailIfExists /目标文件存在时的操作模式,为true时,函数调用失败,为False /时,现有文件将被覆盖 ); 文件移动和文件删除的API函数是MoveFileEx()和DeleteFile()【例5-1】调用API函数CopyFile实现文件拷贝实例。 Windows的内核功能的实现不一定要在Windows的图形界面下完成,在字符方式下也可以。由于目前Windows图形用户接口程序的开发还没有讲(5.4节和5.5节中讲),并且我们目前掌握的重点是利用API函数实现Windows内核功能的演示,所以下面的程序仍然是字符界面下的单文件控制台工程,该程序的主文件的名称为FileCopy.cpp。,1.文件操作,#include / windows操作系统API函数的头文件 #include void main() char SourceFileNameMAX_PATH; char DestFileNameMAX_PATH; BOOL Success; coutSourceFileName; coutDestFileName; Success=CopyFile(SourceFileName,DestFileName,TRUE); /调用API函数CopyFile实现文件拷贝 if (!Success) cout“拷贝失败,错误的代码为:“ GetLastError()endl; /调用API函数GetLastError()求出错的代码 else cout“文件拷贝成功n“; 文件移动和文件删除的API函数是MoveFileEx()和DeleteFile(),详细请查看MSDN的说明。,程序,(1)取驱动器个数 计算机上一般都有软盘、硬盘和光盘,有时候应用程序需要查看系统中一共有多少个逻辑驱动器,这时可以调用API函数GetLogicalDrives()来完成。其函数的原型为: DWORD GetLogicalDrives(VOID); 该函数返回一个DWORD类型的值,这32位的每一位代表某个驱动器是否存在。如果存在A盘,则第0位被设置为1;依次类推,如果存在C盘,则第2位被设置为1。当我们需要知道在该计算机上总共有几个驱动器时,可以用如下的代码完成: DWORD DiskInfo; _int8 DiskCount=0; /定义8位的整型变量 DiskInfo=GetLogicalDrives(); while(DiskInfo) if(DiskInfo,2.驱动器操作,(2)取所有驱动器字符串信息 取所有驱动器字符串信息通过API函数GetLogicalDriveStrings()来完成,其原型为: DWORD GetLogicalDriveStrings( DWORD nBufferLength, / 缓冲区的长度 LPTSTR lpBuffer / 指向所有驱动器字符串的指针); 使用该函数一般分两个步骤: 求所有驱动器的字符串信息长度 把0传递给API函数GetLogicalDriveStrings()的两个形参,函数的返回值就是所有驱动器的字符串信息长度。语句为: DriveStringLength=GetLogicalDriveStrings(0, NULL); 动态分配内存空间保存所有驱动器的字符串信息 通过new函数在栈区申请内存于字符指针变量DriverStr,然后把上一步求的所有驱动器的字符串信息长度DriveStringLength和准备保存所有驱动器的字符串缓冲区地址DriverStr传递给API函数GetLogicalDriveStrings()的两个形参,,2.驱动器操作(续),这样求得的所有驱动器的字符串信息就保存到缓冲区DriverStr中,注意每个驱动器字符串的长度为4,假设该机器有A、B、C、D四个驱动器则在缓冲区DriverStr保存的内容是A:B: C:D:,其中表示的是空字符,各个驱动器之间靠来分隔,最后以结束。典型的代码为: DriverStr=new charDriveStringLength+1; GetLogicalDriveStrings(DriveStringLength,(LPTSTR)DriverStr); 取驱动器类型 倘若还要知道每个驱动器标识符各代表什么类型的驱动器时,如A:代表软盘还是硬盘,F:代表光盘还是U盘(可移动盘),就要使用API函数GetDriveType(),该函数的原型为: UINT GetDriveType( LPCTSTR lpRootPathName / 驱动器的根目录); 函数返回值为驱动器的类型,若值为DRIVE_REMOVABLE,代表的是可移动U盘,若值为DRIVE_FIXED,代表的是固定盘,若值为CDROM,代表的是光盘等。,2.驱动器操作(续),【例5-2】调用驱动器操作API函数的演示实例,程序主文件为:DrivesInfo.cpp。 #include void main() DWORD DiskInfo; char *DriverStr; UINT type; short DriveStringLength; _int8 DiskCount=0; /定义8位的整型变量 DiskInfo=GetLogicalDrives(); /取机器上的驱动器信息于DiskInfo while(DiskInfo) if(DiskInfo ,【例5-2】(续),cout“该机器共有“DiskCount“个逻辑驱动器n“; DriveStringLength=GetLogicalDriveStrings(0,NULL); /求整个驱动器的字符串信息的长度,每个驱动器字符串的长度为4 DriverStr=new charDriveStringLength+1; GetLogicalDriveStrings(DriveStringLength,(LPTSTR)DriverStr); /求整个驱动器的字符串信息于DriverStr for(short i=0;i(int)(DriveStringLength/4);i+) type=GetDriveType(DriverStr+i*4); /取驱动器的类型是软盘、硬盘、光盘、可移动U盘 if(type=DRIVE_CDROM) /如果是光驱的话 cout“驱动器“DriverStr+i*4“是光驱n“; ,Windows是多任务操作系统,它支持两种类型的多任务:一种是多进程,另一种是多线程。进程是应用程序的运行实例,它是应用程序的一次动态执行。所谓的多进程就是,Windows允许多个程序同时驻留在内存或同一个应用程序可以在内存中有多个副本。 我们知道,进程指独立运行着的应用程序。当启动Word字处理程序,便启动了一个进程。同样,当我们编译并运行我们自己所编写的一个VC程序时,也启动了一个进程。下面的例子就要演示在一个控制台的应用程序中,启动Windows附件中的“记事本”程序,从而启动一个新的进程。 1进程的创建 Windows以对象的方式来管理进程的,它由Win32子系统来创建和维护,并且可以由此进程的句柄来进行管理。进程创建是调用Win32 API函数CreateProcess()来实现,创建后的进程可以和原进程共享资源(例如句柄和变量)。在Windows中,这两个进程不存在紧密的父子关系,即使原进程终止后,这个新进程仍然可以继续执行。 2进程创建函数的原型说明,5.2.2 进程操作,BOOL CreateProcess( LPCTSTR lpApplicationName, / name of executable module LPTSTR lpCommandLine, / command line string LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, / handle inheritance option DWORD dwCreationFlags, / creation flagsLPVOID lpEnvironment, / new environment block LPCTSTR lpCurrentDirectory, / current directory name LPSTARTUPINFO lpStartupInfo, / startup information LPPROCESS_INFORMATION lpProcessInformation / process information); 3函数的参数说明 (1)参数lpApplicationName 它是一个以NULL结尾的字符串指针,指向待执行的可执行文件名字,它可以为全路径,也可以只是单独一个文件名。如果只是一个单独的文件名,则系统会在当前路径下寻找,然后在系统目录和PATH所指的目录中去查找。,5.2.2 进程操作(续),当这个参数为NULL时,这个文件的名称必须是第二个参数lpCommandLine的第一个空格前的字符所代表的文件名。 (2)参数lpCommandLine 它是一个以NULL结尾的字符串的指针,指向命令行参数。 参数lpApplicationName 和参数lpCommandLine不允许同时空,否则系统找不见新进程所对应的可执行程序的文件名。 (3)参数lpProcessAttributes和参数lpThreadAttributes 用来确定新进程和它的主线程的安全属性,即用来决定所返回的句柄是否可以被这个新进程的子进程继承。它们都是指向SECURITY_ATTRIBUTES结构的指针,若它们为NULL,则不能被继承。 (4)参数bInheritHandles 用来确定新建进程能否继承产生它的进程的句柄。若它的值为TRUE,则这个进程和线程所建立的句柄都可以被这个进程所建立的新进程所继承,即继承的句柄和原先的句柄有相同的值和存取权限。 (5)参数dwCreationFlags 该参数决定新进程产生的方式,它可以用逻辑或的方式把下列值组合起来:,5.2.2 进程操作(续), CREATE_NEW_CONSOLE 为新进程建立一个新的控制台窗口。 DETACHED_PROCESS 在默认情况下,新进程使用的是父进程的控制台窗口,而如果指明此标志,则新进程的输出消息将发送到新的控制台窗口。 CREATE_NEW_PROCESS_GROUP 这个新进程将是一个新进程组的根,进程组包括该进程的所有子进程。 CREATE_SUSPENDED 这个新进程的主线程在它被创建时处于挂起状态,即不被执行,一直等到调用ResumeThread()时,主线程才开始执行。 DEBUG_PROCESS 如果该标志设置的话,调用进程被当作调试者,新进程正准备接收调试。系统把在进程被调试时所发生的调试事件通知给父进程。 参数lpEnvironment 指向环境块内存的指针,若该值为NULL,则新进程和父进程使用相同的环境块。 参数lpCurrentDirectory 新进程的工作目录和驱动器,若其为NULL,则新进程的工作目录和驱动器与父进程相同。,5.2.2 进程操作(续), 参数lpStartupInfo 这是一个指向STARTUPINFO结构的指针,说明新进程以怎样的形式加以显示。 参数lpProcessInformation 一个指向PROCESS_INFORMATION结构的指针,用来存放返回值。如果函数CreateProcess成功被调用,则返回TRUE,否则返回FALSE。如果函数返回FALSE,则可以调用函数GetLastError取得进一步的错误信息。 【例5-3】调用Windows内核API函数实现多任务的执行实例。程序的主文件为 :MultiProcess.cpp。 #include “windows.h“ #include void main() char InChar; coutInChar; if(InChar=Y|InChar=y) ,5.2.2 进程操作(续),【例5-3】(续),BOOL IsSuccess; char NotePadFile255; /存放记事本程序的路径 UINT uSize=255; GetWindowsDirectory(NotePadFile,uSize); /调用API函数GetWindowsDirectory()取得Windows的系统目录 strcat(NotePadFile,“notepad.exe”); /取得记事本程序的 完整路径 PROCESS_INFORMATION NewProcessInformation; /建立进程信息变量NewProcessInformation STARTUPINFO StartUpInformation; /建立进程的启动信息变量StartUpInformation memset(,Windows内核Kernel32.dll中包含了大量有关计算机系统的信息。这些信息包括计算机的硬件配置信息、计算机的名称、用户的名称、操作系统的版本信息等。一个应用程序的可移植性,往往反映在程序运行时,要检测当前程序运行的外部环境,其中获取计算机系统信息是很重要的,Win32 API提供了这些服务。其中: GetComputerName()可以取得本机器的名称,GetSystemInfo()可以取得CPU的信息,GlobalMemoryStatus()可以取得内存的状态信息,例5-4,5.2.3 计算机系统信息操作,5.3 网络接口服务,当今,计算机网络的发展一日千里,就连蜜蜂这个“空姐”找对象时都想找蜘蛛,原因是蜘蛛好赖是一个搞“网络”的。随着因特网“飞入寻常百姓家”,人们对网络服务应用程序的要求越来越高,如何开发网络应用程序,最基本的是搞清楚Windows操作系统对网络的支持,对程序员来说,要掌握网络编程的一些概念,最终掌握有关网络使用的一些API函数。,5.3.1 套接字的使用与Winsock API 5.3.2 因特网服务WinInet,什么是套接字 套接字(socket)是一种网络编程接口,它是对通信端点的一种抽象,提供了一种发送数据和接收数据的机制。Winsock是Windows操作系统下的套接字,它是一套Microsoft Windows下的网络编程接口,使用该接口可以充分利用Windows消息驱动机制进行编程,在应用程序中是通过调用WinSock API实现相互之间的通讯。,5.3.1 套接字的使用与 Winsock API,初始化套接字 在使用Winsock进行编程之前,必须对它进行初始化,使用WSAStartup()就可以完成。该函数的原型为: int WSAStartup( WORD wVersionRequested,/ Socket动态链接库的版本号 LPWSADATA lpWSAData /指向一个WSADATA数据结构, /该数据结构返回Windows Socket实现的详细信息 ); 第一个参数指明了要调用的Socket动态链接库的版本号;第二个参数为指针类型,指向一个WSADATA数据结构,该数据结构返回Windows Socket实现的详细信息。 该函数通过一个过程调用来完成使用Windows中Socket动态链接库的初始化工作,它调用成功后就可以调用Windows Socket API函数。,5.3.1 套接字的使用与 WinsockAPI(续),用WinsockAPI函数取本机名和IP地址 取本机名称的函数为: int gethostname( char FAR *name, int namelen ); 其中参数name为传出参数,指向接收主机名称的缓冲区;后面的参数为传入参数,它指定了缓冲区的长度。 取主机信息的函数为: struct hostent FAR *gethostbyname( const char FAR *name ); 该函数用来通过主机名称获取主机的详细信息。参数name就是gethostname()函数的返回结果,该函数执行成功后,将返回一个hostent结构的指针,该结构包含了当前主机的详细信息。该结构定义如下:,5.3.1 套接字的使用与 WinsockAPI(续),struct hostent char FAR * h_name; /主机的官方名称 char FAR * FAR * h_aliases; /主机的别名 short h_addrtype; /地址类型 short h_length; /该数据结构的大小 char FAR * FAR * h_addr_list; /主机地址列表,包含了主机的IP ; 【例5-5】调用Windows网络API函数取计算机的名称和IP地址。程序主文件为MyComputer.cpp。,例5-5,5.3.1 套接字的使用与 WinsockAPI(续),WinInet是Windows Internet扩展应用程序的接口,它包含了一个C语言的函数集。使用WinInet可以为应用程序添加向InterNet服务器的连接,而无需考虑基本的通讯协议和底层的数据传输工作。WinInet支持文本传输协议(FTP)、超文本传输协议(HTTP)等。 1利用WinInet检测计算机是否接入因特网及接入方式 在开发网络应用程序的时候,如果设计到Internet方面的处理问题,则首先必须要能判断当前计算机是否接入Internet。因为,如果用户当前的计算机没有接入网的话,随后的任何操作过程都必出现错误。我们可以通过软件的方式检测当前计算机是否接入Internet及当前的接入方式。,5.3.2 因特网服务WinInet,2WinInet中的API函数InternetGetConnectedState 通过API函数InternetGetConnectedState可以检测当前计算机是否接入Internet及接入的方式。该函数原型为: BOOL InternetGetConnectedState( OUT LPDWORD lpdwFlags, IN DWORD dwReserved ); 该函数第一个参数表示网络的接入类型,第二个值保留,一般取0,当函数返回值为真时,代表已经接入因特网。否则,没有接入。 【例5-6】调用因特网API函数检测本机是否接入因特网的实例。程序的主文件为LinkInternet.cpp程序。,例5-6,5.3.2 因特网服务WinInet(续),本章的前几节利用API函数来操纵操作系统,编写的都是控制台工程,下面讲解利用API函数来编写图形界面的程序,它是本节的重点和难点,读者要花大力气去学习。,5.4 Win32API编写 图形界面程序,5.4.1 使用AppWizard生成W32应用程序 5.4.2 程序的入口WinMain() 5.4.3 定义和注册窗口类 5.4.4 初始化实例 5.4.5 维护消息循环 5.4.6 窗口函数和消息处理 5.4.7 常见消息的处理 5.4.8 几个重要的结构 *5.4.9 WinMain()执行规程描述 *5.4.10 利用Win32 API编写图形界面的关键,【例5-7】调用API函数建立一个图形界面的程序Hello。 1建立Hello工程 (1)启动Visual C+的集成开发环境Developer Studio。 (2)选择菜单命令“File|New|Projects|Win32 Application”。 (3)在Project Name的编辑框中输入一个应用程序的名称“Hello”,界面如图5.1 所示。完后单击OK按钮。进入下一个界面,如图5.2所示。 (4)选择一个Windows应用程序的类型A Typical“ Hello World!” Application。完后单击Finish按钮。进入下一个界面,单击OK按钮,一个应用程序已经生成。 (5)单击WorkSpace视图的ClassView标签下Hello Classes根结点下的子结点Globals。界面如图5.3 所示。 (6)双击WinMain()函数结点,进入到程序的主文件Hello.cpp文件中。我们的主要工作就是剖析该文件的内容。文件的主要内容如2小节所示(作了简单修改)。 2Hello.cpp的主要内容( 详细内容请参见程序),5.4.1 使用AppWizard生成 Win32应用程序,图(一),图5.1 选择工 程类型 窗口,图5.2 选择win32应用程序类型窗口,图5.3 选择WinMain函数的界面,WinMain()函数是所有Windows应用程序的入口,类似于C语言中的Main()函数,其功能是完成一些初始化工作并维持一个消息循环。消息循环是整个程序运行的核心。在WinMain()函数中,要完成以下几步工作: 利用自定义函数MyRegisterClass()注册应用程序窗口类 利用自定义函数InitInstance()初始化应用程序的实例,该函数主要完成创建和显示窗口,并进行其它必要的初始化处理 利用API函数GetMessage()启动应用程序的消息循环,把从应用程序消息队列接收的消息进行翻译,并送到窗口函数中进行处理 窗口函数WinProc()是Windows应用程序的消息处理中心,它能够处理所有的消息 当消息循环检索到WM_QUIT消息时,则退出应用程序。 如果WinMain()调用成功,那么将会在接收到WM_QUIT时退出。,5.4.2程序的入口WinMain(),Windows下窗口的生成都是基于窗口类的。每个窗口都有一些基本属性,如标题栏文字、窗口大小和位置、图标、窗体的背景颜色等,窗口类就是充当定义这些属性的模板。 WinMain()函数中,通常要对主窗口定义一个窗口类,即把窗口类的具体属性填入WNDCLASSEX结构的相应成员中。然后进行注册,它是通过调用RegisterClassEx()来完成。 窗口创建函数CreateWindows创建窗体。 窗口类的注册在函数MyRegisterClass()中完成。 代码,5.4.3定义和注册窗口类,在初始化应用程序实例过程中,主要作的工作有:创建窗口; 显示窗口;更新窗口。这些步骤的完成是放在向导生成的函数InitInstance()中。,5.4.4 初始化实例,BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) HWND hWnd; hInst = hInstance; / Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; ,1.创建窗口 窗口类定义了窗口的一般特性,而窗口与显示关系比较密切的一些细节尚未指定。因此,基于同一个窗口类可以创建多个不完全相同的窗口,这一工作在API函数CreateWindow()函数中完成。 创建窗口类所需要的各个信息“打包”在一个WNDCLASS结构中传递给RegisterClass()函数,而创建具体窗口所需的信息则各自作为单独的参数传递给CreateWindow()函数。,5.4.4初始化实例(续),参数lpClassName是窗口类的名字 参数lpWindowName是指定窗口的标题 参数dwStyle是指定窗口的显示风格 参数x,y, nWidth, nHeight指定了窗口的位置和大小 参数hWndParent为父窗口的句柄 参数hMenu为主菜单句柄 参数hInstance为应用程序的当前句柄 最后一个参数lpParam为创建参数,CreateWindow()的参数,CreateWindow()的返回值 CreateWindow()函数返回被创建窗口的窗口句柄。Windows的每一个窗口都有一个句柄,程序通过窗口句柄来引用窗口,许多Windows函数都需要使用窗口句柄做参数。这样,Windows才知道操作是针对哪一个窗口的。如果一个程序创建了多个窗口,则每一个窗口都拥有各自的句柄。,显示窗口,把窗口显示在屏幕上,得调用函数ShowWindow(),其中,参数hWnd指定要显示的窗口句柄,用来确定显示哪一个窗口 参数nCmdShow指定窗口的显示方式,该值从WinMain()函数传递过来。,更新窗口,应用程序调用UpdateWindow()函数迫使窗口立即重画客户区域,并发出WM_PAINT消息,如果更新区域是空的,就不发送任何消息。窗口的客户区域是指窗口菜单栏下面的矩形区域,除了客户区域之外,窗口所覆盖的其它区域,包括标题栏、菜单、滚动条、边框等都是属于非客户区域。,窗口的显示与更新,5.4.5 维护消息循环,调用UpdateWindow()函数后,应用程序主窗口就显示在屏幕上,即程序的输入输出界面已经准备好,剩下来要完成的任务是处理消息。 Windows应用程序接收以各种形式输入的消息,包括键盘、鼠标、计时器等产生的消息,也可以是其它应用程序发来的消息。Windows监控所有的输入设备,将外部发生的事件转化为对应的消息,并将信息放入消息队列中。最后,应用程序从自己的消息队列中按一定的次序检索消息并将每一个消息发送到相应的窗口函数中进行处理。,维护消息循环的主要代码,5.4.6 窗口函数和消息处理(上),利用Windows API进行Windows图形用户界面程序设计的实质性的工作在于对消息的处理,这个任务是由窗口函数来担当。在该函数中,要定义对各种消息的响应动作,包括内容的显示、对用户输入的响应,只要是属于该窗口的不同的消息都将会得到相应的处理。因此,窗口函数是窗口的核心,函数的原型如下: LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 其中CALLBACK表明该函数是一个回调函数。该函数的返回类型为LRESULT,它是一个长整型。窗口函数可以任意命名,只要它和其他窗口函数名称不发生冲突,但它的返回值及参数类型和顺序都必须按照系统的规定来定义。该函数的第一个参数hWnd是窗口句柄,它的值与CreateWindow()的返回值相同。第二个参数message是无符号整数类型(UINT),用来标识接收的消息。最后两个参数提供了有关消息message的进一步的信息,我们将它们统称为“消息参数”。WPARAM 与LPARAM 表示的都是长整数。该函数的四个参数与MSG结构的前四个域相同。,5.4.6 窗口函数和消息处理(下),窗口函数是Windows应用程序的核心,Windows操作系统定义了上千种消息,每种消息的生成条件不一样,消息参数的意义也不一样,处理方式也有很大的差异。因此必须了解在什么样的条件下窗口会收到什么样的消息。 所有窗口函数的代码都是非常相似的,都是使用switch和case结构来确定窗口函数接收什么样的消息,以及如何处理所接收到的消息。如果成功地处理了某个消息,窗口函数应返回一个0;如果不想处理某个消息,就将这个消息传递给系统默认的窗口过程DefWindowProc();如果在处理消息的过程中出现失败,则要返回一个非零值,具体返回什么值要根据特定的消息来决定,窗口函数的返回值类似于DOS应用程序的退出代码。,消息的生成条件 消息的处理方法,5.4.7 常见的消息处理,WM_PAINT消息 WM_PAINT消息是窗口函数WinProc()需要处理的一个很重要消息,该消息牵涉到应用程序的界面维护。当窗口中的用户区域一部分或全部“无效”而需要“刷新”时,都通过该消息实现界面的清理。,当窗口收到WM_PAINT消息时,应用程序窗口将该窗口的客户区重绘。,示例程序代码比较简单,它的窗口函数只处理了三个消息:WM_COMMAND消息、WM_PAINT消息和WM_DESTROY消息。当用户选择一个菜单的选项时,发送WM_COMMAND消息,示例程序中有一个退出选项和帮助选项,该消息的处理暂时不讲。,WM_DESTROY消息,(1) 消息的生成条件 当窗口被摧毁撤消后(当用户按下ALT+F4键或单击关闭窗口按钮时),Windows向窗口发送WM_DESTROY消息。系统默认的响应是调用DestroyWindow()函数撤消窗口。 (2) 消息的处理方法 响应WM_DESTROY消息时,必须要调用PostQuitMessage()函数。该函数向消息队列中放入WM_QUIT消息,使程序退出消息循环,进而退出应用程序。应用程序可在响应这个消息时做一些收尾工作。典型的代码如下: case WM_DESTROY: PostQuitMessage(0); break;,5.4.7 常见的消息处理(续),当Windows应用程序要求重新在窗口客户区域绘图时,要发送该消息,典型的情况有:(1)一个窗口由不活动状态变为活动状态时,如果客户区域有部分被其它窗口覆盖,则被覆盖区域变为无效时,会生成该消息;(2)如果一个窗口由隐藏状态变为显示状态时,整个客户区域都无效,会生成该消息;(3)窗口类的风格设置为CS_HREDRAW 或CS_VREDRAW时,那么当窗口大小在水平或垂直方向发生变化时,会生成该消息;(4)在移动窗口使得它和其它窗口相互重叠时,Windows并不保存被覆盖的内容,它是通过,当被覆盖的部分不再被覆盖时(如移走另一个窗口),Windows将其标志为无效,发送该消息;(5)程序显式地调用Invalidate()、InvalidateRect()或InvalidateRgn()函数将产生WM_PAINT消息。 当窗口收到WM_PAINT消息时,相当于操作系统告诉你的应用程序窗口“该窗口的客户区域已经混乱了,请你重新把窗口的客户区域绘制一下”。我们在相应WM_PAINT消息时的作图称为“被动作图”,在任何时候,我们都可以在窗口区域中作图,这种情况被称作“主动作图”。,消息的生成条件,响应WM_PAINT消息的主要目的是在客户区域作图。 典型的代码如下: case WM_PAINT: hdc = BeginPaint(hWnd, 上述示例代码中,BeginPaint()与EndPaint()函数必须成对调用,并且当且仅当在响应WM_PAINT消息时调用。所有作图代码都必须位于这对函数调用中间,这对函数的第一参数为程序的窗口句柄,第二个参数是指向PAINTSTRUCT(参见下一节的介绍,它主要用于刷新客户区中的内容)结构的指针。,消息的处理方法,5.4.8 几个重要的结构,

温馨提示

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

评论

0/150

提交评论