应用程序编程接口api-全文可读_第1页
应用程序编程接口api-全文可读_第2页
应用程序编程接口api-全文可读_第3页
应用程序编程接口api-全文可读_第4页
应用程序编程接口api-全文可读_第5页
已阅读5页,还剩61页未读 继续免费阅读

下载本文档

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

文档简介

Visual

C++第5章Windows应用程序编程接口教学要点本章内容主要包括API的概念及分类,从API的使用看操作系统所提供的服务,操作系统内核中的文件操作API的使用,网络服务API函数的使用,利用图形设备接口API编写图形用户界面程序的方法。要求了解API的分类及其对应的磁盘上的物理文件.DLL的名称、网络服务API的含义和网络编程的一些基本概念、进程概念及建立新进程的方法、WM_PAINT消息

含义。握握API概念和其与操作系统提供的程序员接口的关系、内核中文件操作API的调用,熟悉API编写图形用户界面程序的步骤,熟练掌握API编写的图形用户界面程序的主要组成模块及含义。Visual

C++第5章目录API概述内核服务API函数的使用网络接口服务Win32

API编写图形界面程序图形设备接口与用户接口服务

习题本章以一些API设计的控制台程序和具有图形界面的Win32程序为例,阐述了利用API函数开发程序的过程,重点在于理解操作系统所提供的各种服务以及程序员如何进行调用。Visual

C++5.1

API概述关于Windows

API编程模式API简介Windows核心——三个动态链接库Windows

API分类*5.1.5

操作系统的认识Visual

C++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编程模式Visual

C++5.1.2

API简介Windows操作系统向程序员提供了可以实现开启窗口、绘制图形,使用系统各种设备等的一组函数服务,称之为Application

Programming

Interface(应用程序编程接口),即API函数。利用VC进行Windows应用程序的开发,除了用到各种.h头文件中的库函数及数据结构外,还需要使用WindowsSDK(Software

Development

Kit,软件开发工具包)提供的使用于Windows应用程序的特殊库函数和数据结构、语句、文件结构。所有这些内容组成了Windows应用程序设计接口API。使用Win32 API,应用程序可以充分挖掘出Windows 32位操作系统的潜力,Microsoft的所有32位平台都支持统一的API,包括函数、结构、消息、宏及接口。使用Win32

API,不但可以开发出在各种平台上都能运行的应用程序,而且还可以充分利用每个平台上特有的功能和属性。Visual

C++5.1.3

Windows核心——三个动态链接库Windows操作系统核心有三个动态链接库(Kernel32.dll,User32.dll,Gdi32.dll),这些动态链接库构成了Win32

API函数。Windows内核库(Kernel32.dll)内核库中的函数用于处理操作系统功能的所有核心工作,例如多任务管理、内存管理等。另外内核库还管理系统注册表。Windows用户界面管理库(User32.dll)用户界面管理库包括了Windows管理、菜单、光标、定时器和通信等有关的函数。在Windows中,窗口的标识被称为“句柄”。Windows图形设备界面库(Gdi32.dll)图形设备界面库提供了用于管理系统支持的所有图形设备函数,包括屏幕、打印机等设备的管理。GDI库中的函数为应用程序提供与设备无关的绘图内容。应用程序中通过GDI库中的函数绘图,不是直接面向硬件操作,而是通过“设备描述表”来进行操作,它通过句柄hDC来跟踪。Windows三个核心库中的API函数的原型声名在windows.h中有说明,这就是我们在编写Win32应用程序时要在程序开头放#include“windows.h”语句的原因。Visual

C++5.1.4

Windows

API分类

根据Windows

API函数完成的功能,可以将其分为如下的类别:1.内核服务通过内核服务函数,应用程序可以使用计算机中的资源和操作系统的特性,例如内存,文件系统、设备、进程、线程等。拿一个简单的文件输入输出函数来说,通过这些函数,程序员可以存取本地计算机或网络中某台计算机中的文件、目录、输入输出设备,并且这些文件函数支持各种各样的文件系统,包括FAT、NTFS的文件系统。内核服务体现了Windows操作系统“服务”的观点。作为一个程序员我们应该利用这些服务函数来充分发挥操作系统的功能。对于这部分API函数的使用,我们可以在基于控制台的应用程序中编写,因为这些函数都是一些与Windows图形用户界面无关的,在字符方式下操作比较简单。后面有关这方面函数的操作就是在基于控制台的应用程序中使用的。内核服务的函数大部分包含在Windows内核库——Kernel32.dll中。Visual

C++5.1.4

WindowsAPI分类(续)2.图形设备接口■■■图形设备接口是Windows最原始的图形输出库(最原始意味着除了GDI外,还有工业界用的OpenGl和游戏界用的DirectX,VC都对他们提供支持)。当看到图形或文本显示在屏幕上时,这就是GDI的功劳。它提供了在显示器、打印机或其它设备

上生成图形的函数与相关的数据结构。利用GDI函数,你可以画直

线、曲线、文本、位图等。你还可以使用各种各样的绘图对象如笔、画刷、字体等,使得所绘制的图形更加丰富多彩。另外,Windows本身也是通过GDI来绘制其用户界面,包括窗口、菜单和对话框。顾名思义,图形设备接口是与图形界面有关的,因此这些函数的使用要在图形用户界面下操作。即必须建立基于Win32的应用程序,建立的步骤如4.4节所示。图形设备接口的函数是包含在Windows图形设备界面库——

Gdi32.dll中。Visual

C++5.1.4

Windows

API分类(续)用户接口服务用户接口服务函数可以创建和使用Windows来显示输出、提示用户输入和执行与用户交互的任务。用户接口服务是通过一些常见的Windows对象来实现的,例如按钮、组合框、编辑框、菜单、键盘输入、定时器等。用户接口服务的函数是在Windows用户界面管理库——User32.dll中。网络服务网络服务允许分布在网络中不同计算机上的应用程序进行通讯。通过这些函数可以创建和管理共享资源,例如共享目录和网络打印机。网络服务的函数是在网络接口函数库——Mpr.dll、Wininet.dll和Winsock32.dll中。多媒体服务多媒体技术是指利用计算机综合处理多媒体信息——文本、图形、图象和声音等,使多种信息建立逻辑连接,集成为一个系统并具有交互性。多媒体服务提供了数字音频、视频、图形、图象等服务。该服务的函数主要包含在多媒体函数库——Winmm.dll中。Visual

C++5.1.4

WindowsAPI分类(续)客户/服务方式存取服务在客户/服务方式存取模式中,客户可以连接到服务器上以使用服务器的功能和数据,服务器通过客户端的标识和权限来决定客户端可以使用的功能。Win2K提供了一套函数来限制和允许客户端对服务端的访问。这些函数扩展了Win2k的存取控制模型来使用服务端的私有对象和使用服务端的功能。客户/服务方式存取服务又称操作系统高级编

程接口,这些函数包含在高级编程接口函数库——Advapi32.dll中。版本服务版本服务主要提供有关文件的版本信息。这些服务所对应的函数包含在版本函数库——Version.dll中。公共对话框服务公共对话框,又叫通用对话框,是Windows预定义的对话框,可以使用通用对话框来执行六种标准操作,选择文件,指定字体、选择颜色、打印设置、查找文本、保存文件。这些服务所对应的函数包含在公共对话框函数库——Comdlg32.dll中。Visual

C++5.1.4

WindowsAPI分类(续)打印管理服务在Windows操作系统下,可以实现在各种设备下的打印。打印管理服务提供了完整的函数集支持这些操作,例如检索打印机,准备打印等。这些服务所对应的函数包含在打印管理函数库——Winspool.drv中。解/压缩文件服务该服务提供了对文件的压缩和解压服务。这些服务所对应的函数包含在函数库——Lz32.dll。在VC6.0中提供了一个文件Win32api.csv。它是一个Win16与Win32函数的对照表。通过它读者可以浏览到Windows各种版本下API函数的原型说明。Visual

C++5.1.5

操作系统的认识操作系统有两个接口:一个是用户接口,另一个是程序员接口。VC开发工具的强大,其中很重要的一个方面就是对于WindowsAPI的直接调用,其它任何开发工具中的函数都是对其的一个封装。凡是在Windows工作环境下执行的应用程序,都可以通过某种特定方式调用Woindows

API函数。可以毫不夸张地说,Windows

API函数是构建整个Windows框架的基石,在它下面是Windows操作系统核心,在它上面则是所有华丽的Windows应用程序。事实上,任何开发工具提供的类库和构件都是架构在Win32API函数基础上,是封装了的API函数集合。这些类库和构件简化了程序的开发,但其功能有限。在实际应用中,如果我们希望开发出更灵活、更实用、更具效率的程序时,则必须要涉及直接使用API函数。虽然类库和构件使应用程序的开发简单了,但它们只提供Windows的常用的一般功能,对于比较复杂和特殊的功能来说,使用类库和构件中提供的方法是非常难以实现的,这时就需要直接调用特定的API函数。Visual

C++5.2内核服务API函数的使用内核服务是最能体现API函数威力的地方,通过这些函数,用户能够使用操作系统内核所提供的核心功能。操作系统的进程管理、文件管理、内存管理都是属于内核的功能。文件管理内核服务进程操作计算机系统信息操作Visual

C++5.2.1文件管理内核服务VC下提供了对文件操作的四种方式:使用C语言中的fopen()、fprintf()、fread()等基本的函数进行文件操作;使用C++中的流式文件接口fstream中的函数进行操作;使用面向对象的类CFile进行操作;使用有关的文件API进行操作。文件操作驱动器操作Visual

C++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.文件操作Visual

C++#include<windows.h>//windows操作系统API函数的头文件#include<iostream.h>void

main(){char

SourceFileName[MAX_PATH];char

DestFileName[MAX_PATH];BOOL

Success;cout<<"请输入待拷贝的源文件的名称\n";cin>>SourceFileName;cout<<"请输入待拷贝的目标文件的名称\n";cin>>DestFileName;Success=CopyFile(SourceFileName,DestFileName,TRUE);//调用API函数CopyFile实现文件拷贝if(!Success)cout<<"拷贝失败,错误的代码为:"<<GetLastError()<<endl;//调用API函数GetLastError()求出错的代码elsecout<<"文件拷贝成功\n";}文件移动和文件删除的API函数是MoveFileEx()和DeleteFile(),详细请查看MSDN的说明。程序Visual

C++(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&1)//看该位是否为1,为1代表有对应的驱动器DiskCount++;DiskInfo>>=1;

//DiskInfo=DiskInfo>>1}2.驱动器操作Visual

C++DWORD

nBufferLength,LPTSTR

lpBuffer//缓冲区的长度//指向所有驱动器字符串的指针);使用该函数一般分两个步骤:①求所有驱动器的字符串信息长度把0传递给API函数GetLogicalDriveStrings()的两个形参,函数的返回值就是所有驱动器的字符串信息长度。语句为:DriveStringLength=GetLogicalDriveStrings(0,NULL);②动态分配内存空间保存所有驱动器的字符串信息通过new函数在栈区申请内存于字符指针变量DriverStr,然后把上一步求的所有驱动器的字符串信息长度DriveStringLength和准备保存所有驱动器的字符串缓冲区地址DriverStr传递给API函数

GetLogicalDriveStrings()的两个形参,2.驱动器操作(续)(2)取所有驱动器字符串信息取所有驱动器字符串信息通过API函数GetLogicalDriveStrings()来完成,其原型为:DWORD

GetLogicalDriveStrings(Visual

C++2.驱动器操作(续)这样求得的所有驱动器的字符串信息就保存到缓冲区DriverStr中,注意每个驱动器字符串的长度为4,假设该机器有A、B、C、D四个驱动器则在缓冲区DriverStr保存的内容是A:\<NULL>B:\<NULL>C:\<NULL>D:\<NULL><NULL>,其中<NULL>表示的是空字符,各个驱动器之间靠<NULL>来分隔,最后以<NULL>结束。典型的代码为:DriverStr=new

char[DriveStringLength+1];GetLogicalDriveStrings(DriveStringLength,(LPTSTR)DriverStr);③取驱动器类型倘若还要知道每个驱动器标识符各代表什么类型的驱动器时,如A:代表软盘还是硬盘,F:代表光盘还是U盘(可移动盘),就要使用API函数GetDriveType(),该函数的原型为:UINT

GetDriveType(LPCTSTR

lpRootPathName

//驱动器的根目录);函数返回值为驱动器的类型,若值为DRIVE_REMOVABLE,代表的是可移动U盘,若值为DRIVE_FIXED,代表的是固定盘,若值为CDROM,代表的是光盘等。Visual

C++【例5-2】调用驱动器操作API函数的演示实例程序主文件为:DrivesInfo.cpp。#include

<iostream.h>void

main(){DWORD

DiskInfo;char

*DriverStr;UINT

type;short

DriveStringLength;_int8

DiskCount=0;//定义8位的整型变量DiskInfo=GetLogicalDrives();//取机器上的驱动器信息于DiskInfowhile(DiskInfo){if(DiskInfo&1)//看该位是否为1,为1代表有对应的驱动器DiskCount++;DiskInfo>>=1;}Visual

C++【例5-2】(续)cout<<"该机器共有"<<DiskCount<<"个逻辑驱动器n";DriveStringLength=GetLogicalDriveStrings(0,NULL);//求整个驱动器的字符串信息的长度,每个驱动器字符串的长度为4DriverStr=new

char[DriveStringLength+1];GetLogicalDriveStrings(DriveStringLength,(LPTSTR)DriverStr);//求整个驱动器的字符串信息于DriverStrfor(short

i=0;i<(int)(DriveStringLength/4);i++){type=GetDriveType(DriverStr+i*4);//取驱动器的类型是软盘、硬盘、光盘、可移动U盘if(type==DRIVE_CDROM)

//如果是光驱的话cout<<"驱动器"<<DriverStr+i*4<<"是光驱n";}}Visual

C++5.2.2

进程操作Windows是多任务操作系统,它支持两种类型的多任务:一种是多进程,另一种是多线程。进程是应用程序的运行实例,它是应用程序的一

次动态执行。所谓的多进程就是,Windows允许多个程序同时驻留在内存

或同一个应用程序可以在内存中有多个副本。我们知道,进程指独立运行着的应用程序。当启动Word字处理程序,便启动了一个进程。同样,当我们编译并运行我们自己所编写的一个VC程序时,也启动了一个进程。下面的例子就要演示在一个控制台的应用程序中,启动Windows附件中的“记事本”程序,从而启动一个新的进程。进程的创建Windows以对象的方式来管理进程的,它由Win32子系统来创建和维护,并且可以由此进程的句柄来进行管理。进程创建是调用Win32

API函数

CreateProcess()来实现,创建后的进程可以和原进程共享资源(例如句柄和变量)。在Windows中,这两个进程不存在紧密的父子关系,即使原进程终止后,这个新进程仍然可以继续执行。进程创建函数的原型说明Visual

C++BOOL

CreateProcess(LPCTSTR

lpApplicationName,//

name

of

executable

moduleLPTSTR

lpCommandLine,LPSECURITY_ATTRIBUTES//

command

line

stringlpProcessAttributes,LPSECURITY_ATTRIBUTES

lpThreadAttributes,BOOL

bInheritHandles,DWORD

dwCreationFlags,//

handle

inheritance

option//

creation

flagsLPVOID

lpEnvironment,//

new

environment

blockLPCTSTR

lpCurrentDirectory,//current

directory

name

LPSTARTUPINFO

lpStartupInfo,

//startup

informationLPPROCESS_INFORMATION

lpProcessInformation//process

information);3.函数的参数说明(1)参数lpApplicationName

它是一个以NULL结尾的字符串指针,指向待执行的可执行文件名字,它可以为全路径,也可以只是单独一个文件名。如果只是一个单独的文件名,则系统会在当前路径下寻找,然后在系统目录和PATH所指的目录中去查找。5.2.2 进程操作(续)Visual

C++当这个参数为NULL时,这个文件的名称必须是第二个参数lpCommandLine的第一个空格前的字符所代表的文件名。参数lpCommandLine

它是一个以NULL结尾的字符串的指针,指向命令行参数。参数lpApplicationName和参数lpCommandLine不允许同时空,否则系统找不见新进程所对应的可执行程序的文件名。参数lpProcessAttributes和参数lpThreadAttributes用来确定新进程和它的主线程的安全属性,即用来决定所返回的句柄是否可以被这个新进程的子进程继承。它们都是指向SECURITY_ATTRIBUTES结构的指针,若它们为NULL,则不能被继承。参数bInheritHandles用来确定新建进程能否继承产生它的进程的句柄。若它的值为TRUE,则这个进程和线程所建立的句柄都可以被这个进程所建立的新进程所继承,即继承的句柄和原先的句柄有相同的值和存取权限。参数dwCreationFlags该参数决定新进程产生的方式,它可以用逻辑或的方式把下列值组合起来:5.2.2 进程操作(续)Visual

C++5.2.2 进程操作(续)<1>CREATE_NEW_CONSOLE为新进程建立一个新的控制台窗口。<2>DETACHED_PROCESS在默认情况下,新进程使用的是父进程的控制台窗口,而如果指明此标志,则新进程的输出消息将发送到新的控制台窗口。<3>CREATE_NEW_PROCESS_GROUP这个新进程将是一个新进程组的根,进程组包括该进程的所有子进程。<4>CREATE_SUSPENDED这个新进程的主线程在它被创建时处于挂起状态,即不被执行,一直等到调用ResumeThread()时,主线程才开始执行。<5>DEBUG_PROCESS如果该标志设置的话,调用进程被当作调试者,新进程正准备接收调试。系统把在进程被调试时所发生的调试事件通知给父进程。<6>参数lpEnvironment指向环境块内存的指针,若该值为NULL,则新进程和父进程使用相同的环境块。<7>参数lpCurrentDirectory新进程的工作目录和驱动器,若其为NULL,则新进程的工作目录和驱动器与父进程相同。Visual

C++5.2.2 进程操作(续)<8>参数lpStartupInfo这是一个指向STARTUPINFO结构的指针,说明新进程以怎样的形式加以显示。<9>参数lpProcessInformation一个指向PROCESS_INFORMATION结构的指针,用来存放返回值。如果函数CreateProcess成功被调用,则返回TRUE,否则返回FALSE。如果函数返回FALSE,则可以调用函数GetLastError取得进一步的错误信息。【例5-3】调用Windows内核API函数实现多任务的执行实例。程序的主文件为:MultiProcess.cpp。#include

"windows.h"#include

<iostream.h>void

main(){char

InChar;cout<<"输入Y将调用内核函数创建新的进程n";cin>>InChar;if(InChar=="Y"||InChar=="y"){Visual

C++【例5-3】(续)BOOL

IsSuccess;char

NotePadFile[255];//存放记事本程序的路径UINT

uSize=255;GetWindowsDirectory(NotePadFile,uSize);//调用API函数GetWindowsDirectory()取得Windows的系统目录strcat(NotePadFile,“\\notepad.exe”);//取得记事本程序的完整路径PROCESS_INFORMATION

NewProcessInformation;//建立进程信息变量NewProcessInformationSTARTUPINFO

StartUpInformation;//建立进程的启动信息变量StartUpInformationmemset(&StartUpInformation,0,sizeof(StartUpInformation));//将缓冲区StartUpInformation设置为0StartUpInformation.cb=sizeof(StartUpInformation);

StartUpInformation.wShowWindow=SW_SHOW;//新进程的显示方式为正常显示StartUpInformation.dwFlags=STARTF_USESHOWWINDOW;……Visual

C++Windows内核Kernel32.dll中包含了大量有关计算机系统的信息。这些信息包括计算机的硬件配置信息、计算机的名称、用户的名称、操作系统的版本信息等。一个应用程序的可移植性,往往反映在程序运行时,要检测当前程序运行的外部环境,其中获取计算机系统信息是很重要的,Win32

API提供了这些服务。其中:GetComputerName()可以取得本机器的名称,GetSystemInfo()可以取得CPU的信息,GlobalMemoryStatus()可以取得内存的状态信息例5-45.2.3

计算机系统信息操作Visual

C++5.3

网络接口服务当今,计算机网络的发展一日千里,就连蜜蜂这个“空姐”找对象时都想找蜘蛛,原因是蜘蛛好赖是一个搞“网络”的。随着因特网“飞入寻常百姓家”,人们对网络服务应用程序的要求越来越高,如何开发网络应用程序,最基本的是搞清楚Windows操作系统对网络的支持,对程序员来说,要掌握网络编程的一些概念,最终掌握有关网络使用的一些API函数。套接字的使用与Winsock

API因特网服务WinInetVisual

C++5.3.1

套接字的使用与Winsock

API什么是套接字套接字(socket)是一种网络编程接口,它是对通信端点的一种抽象,提供了一种发送数据和接收数据的机制。Winsock是Windows操作系统下的套接字,它是一套Microsoft

Windows下的网络编程接口,使用该接口可以充分利用Windows消息驱动机制进行编程,在应用程序中是通过调用WinSock

API实现相互之间的通讯。Visual

C++5.3.1

套接字的使用与WinsockAPI(续)初始化套接字在使用Winsock进行编程之前,必须对它进行初始化,使用WSAStartup()就可以完成。该函数的原型为:int

WSAStartup(WORD

wVersionRequested,//Socket动态链接库的版本号LPWSADATA

lpWSAData//指向一个WSADATA数据结构,//该数据结构返回Windows

Socket实现的详细信息);第一个参数指明了要调用的Socket动态链接库的版本号;第二个参数为指针类型,指向一个WSADATA数据结构,该数据结构返回Windows

Socket实现的详细信息。该函数通过一个过程调用来完成使用Windows中Socket动态链接库的初始化工作,它调用成功后就可以调用WindowsSocket

API函数。Visual

C++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结构的指针,该结构包含了当前主机的详细信息。该结构定义如下:Visual

C++charFAR*

h_name;//主机的官方名称charFAR*

FAR

*

h_aliases;//主机的别名shorth_addrtype;//地址类型shorth_length;//该数据结构的大小char

FAR*

FAR*

h_addr_list;//主机地址列表,包含了主机的IP};【例5-5】调用Windows网络API函数取计算机的名称和IP地址。程序主文件为MyComputer.cpp。例5-55.3.1

套接字的使用与WinsockAPI(续)struct

hostent

{Visual

C++WinInet是Windows

Internet扩展应用程序的接口,它包含了一个C语言的函数集。使用WinInet可以为应用程序添加向InterNet服务器的连接,而无需考虑基本的通讯协议和底层的数据传输工作。WinInet支持文本传输协议(FTP)、超文本传输协议(HTTP)等。1.利用WinInet检测计算机是否接入因特网及接入方式在开发网络应用程序的时候,如果设计到Internet方面的处理问题,则首先必须要能判断当前计算机是否接入Internet。因为,如果用户当前的计算机没有接入网的话,随后的任何操作过程都必出现错误。我们可以通过软件的方式检测当前计算机是否接入Internet及当前的接入方式。5.3.2 因特网服务WinInetVisual

C++2.WinInet中的API函数InternetGetConnectedState通过API函数InternetGetConnectedState可以检测当前计算机是否接入Internet及接入的方式。该函数原型为:BOOL

InternetGetConnectedState(OUT

LPDWORD

lpdwFlags,IN

DWORD

dwReserved);该函数第一个参数表示网络的接入类型,第二个值保留,一般取0,当函数返回值为真时,代表已经接入因特网。否则,没有接入。【例5-6】调用因特网API函数检测本机是否接入因特网的实例例。5-6程序的主文件为LinkInternet.cpp程序。5.3.2 因特网服务WinInet(续)Visual

C++5.4

Win32API编写图形界面程序本章的前几节利用API函数来操纵操作系统,编写的都是控制台工程,下面讲解利用API函数来编写图形界面的程序,它是本节的重点和难点,读者要花大力气去学习。使用AppWizard生成W32应用程序程序的入口WinMain()定义和注册窗口类初始化实例维护消息循环窗口函数和消息处理常见消息的处理几个重要的结构*5.4.9

WinMain()执行规程描述*5.4.10

利用Win32

API编写图形界面的关键Visual

C++5.4.1 使用AppWizard生成Win32应用程序【例5-7】调用API函数建立一个图形界面的程序Hello。1.建立Hello工程启动Visual

C++的集成开发环境Developer

Studio。选择菜单命令“File|New|Projects|Win32

Application”。在Project

Name的编辑框中输入一个应用程序的名称“Hello”,界面如图5.1

所示。完后单击OK按钮。进入下一个界面,如图5.2所示。选择一个Windows应用程序的类型——A

Typical“HelloWorld!”Application。完后单击Finish按钮。进入下一个界面,单击OK按钮,一个应用程序已经生成。单击WorkSpace视图的ClassView标签下HelloClasses根结点下的子结点Globals。界面如图5.3

所示。双击WinMain()函数结点,进入到程序的主文件

Hello.cpp文件中。我们的主要工作就是剖析该文件的内容。文件的主要内容如2小节所示(作了简单修改)。2.Hello.cpp的主要内容(详细内容请参见程序)Visual

C++图(一)图5.1选择工程类型窗口图5.2选择win32应用程序类型窗口图5.3选择WinMain函数的界面WinMain()函数是所有Windows应用程序的入口,类似于C语言中的Main()函数,其功能是完成一些初始化工作并维持一个消息循环。消息循环是整个程序运行的核心。在WinMain()函数中,要完成以下几步工作:利用自定义函数MyRegisterClass()注册应用程序窗口类利用自定义函数InitInstance()初始化应用程序的实例,该函数主要完成创建和显示窗口,并进行其它必要的初始化处理利用API函数GetMessage()启动应用程序的消息循环,把从应用程序消息队列接收的消息进行翻译,并送到窗口函数中进行处理窗口函数WinProc()是Windows应用程序的消息处理中心,它能够处理所有的消息,当消息循环检索到WM_QUIT消息时,则退出应用程序。如果WinMain()调用成功,那么将会在接收到WM_QUIT时退出。Visual

C++5.4.2程序的入口WinMain()Windows下窗口的生成都是基于窗口类的。每个窗口都有一些基本属性,如标题栏文字、窗口大小和位置、图标、窗

体的背景颜色等,窗口类就是充当定义这些属性的模板。WinMain()函数中,通常要对主窗口定义一个窗口类,即把窗口类的具体属性填入WNDCLASSEX结构的相应成员中。然后进行注册,它是通过调用RegisterClassEx()来完成。窗口创建函数CreateWindows创建窗体。窗口类的注册在函数MyRegisterClass()中完成。

代码Visual

C++5.4.3定义和注册窗口类Visual

C++5.4.4初始化实例在初始化应用程序实例过程中,主要作的工作有:创建窗口;显示窗口;更新窗口。这些步骤的完成是放在向导生成的函数InitInstance()中。BOOL

InitInstance(HINSTANCE

hInstance,

int

nCmdShow){HWND

hWnd;hInst

=

hInstance;

//

Store

instance

handle

in

our

globalvariablehWnd

=

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;}Visual

C++1.创建窗口窗口类定义了窗口的一般特性,而窗口与显示关系比较密切的一些细节尚未指定。因此,基于同一个窗口类可以创建多个不完全相同的窗口,这一工作在

API函数CreateWindow()函数中完成。

创建窗口类所需要的各个信息“打包”在一个WNDCLASS结构中传递给

RegisterClass()函数,而创建具体窗口所需的信息则各自作为单独的参数传递给CreateWindow()函数。5.4.4初始化实例(续)Visual

C++CreateWindow()的参数参数lpClassName是窗口类的名字

参数lpWindowName是指定窗口的标题参数dwStyle是指定窗口的显示风格参数x,y,nWidth,nHeight指定了窗口的位置和大小参数hWndParent为父窗口的句柄参数hMenu为主菜单句柄参数hInstance为应用程序的当前句柄最后一个参数lpParam为创建参数CreateWindow()的返回值CreateWindow()函数返回被创建窗口的窗口句柄。Windows的每一个窗口都有一个句柄,程序通过窗口句柄来引用窗口,许多

Windows函数都需要使用窗口句柄做参数。这样,Windows才知道

操作是针对哪一个窗口的。如果一个程序创建了多个窗口,则每

一个窗口都拥有各自的句柄。Visual

C++显示窗口把窗口显示在屏幕上,得调用函数ShowWindow(),其中,参数hWnd指定要显示的窗口句柄,用来确定显

示哪一个窗口参数nCmdShow指定窗口的显示方式,该值从WinMain()函数传递过来。更新窗口应用程序调用UpdateWindow()函数迫使窗口立即重画客户区域,并发出WM_PAINT消息,如果更新区域是空的,就不发送任何消息。窗口的客户区域是指窗口菜单栏下面的矩形区域,除了客户区域之外,窗口所覆盖的其它区域,包括标题栏、菜单、滚动条、边框等都是属于非客户区域。窗口的显示与更新Visual

C++5.4.5

维护消息循环调用UpdateWindow()函数后,应用程序主窗口就显示在屏幕上,即程序的输入输出界面已经准备好,剩下来要完成的任务是处理消息。Windows应用程序接收以各种形式输入的消息,包括键盘、鼠标、计时器等产生的消息,也可以是其它应用程序发来的消息。Windows监控所有的输入设备,将外部发生的事件转化为对应的消息,并将信息放入消息队列中。最后,应用程序从自己的消息队列中按一定的次序检索消息并将每一个消息发送到相应的窗口函数中进行处理。维护消息循环的主要代码Visual

C++5.4.6窗口函数和消息处理(上)利用WindowsAPI进行Windows图形用户界面程序设计的实质性的工作在于对消息的处理,这个任务是由窗口函数来担当。在该函数中,要定义对各种消息的响应动作,包括内容的显示、对用户输入的响应,只要是属于该窗口的不同的消息都将会得到相应的处理。因此,窗口函数是窗口的核心,函数的原型如下:LRESULT

CALLBACK

WndProc(HWND

hWnd,UINT

message,WPARAMwParam,

LPARAM

lParam)其中CALLBACK表明该函数是一个回调函数。该函数的返回类型为LRESULT,它是一个长整型。窗口函数可以任意命名,只要它和其他窗口函数名称不发生冲突,但它的返回值及参数类型和顺序都必须按照系统的规定来定义。该函数的第一个参数hWnd是窗口句柄,它的值与CreateWindow()的返回值相同。第二个参数message是无符号整数类型(UINT),用来标识接收的消息。最后两个参数提供了有关消息message的进一步的信息,我们将它们统称为“消息参数”。WPARAM与LPARAM表示的都是长整数。该函数的四个参数与MSG结构的前四个域相同。Visual

C++5.4.6 窗口函数和消息处理(下)窗口函数是Windows应用程序的核心,Windows操作系统定义了上千种消息,每种消息的生成条件不一样,消息参数的意义也不一样,处理方式也有很大的差异。因此必须了解在什么样的条件下窗口会收到什么样的消息。所有窗口函数的代码都是非常相似的,都是使用switch和case结构来确定窗口函数接收什么样的消息,以

及如何处理所接收到的消息。如果成功地处理了某个消息,窗口函数应返回一个0;如果不想处理某个消息,就将这个消息传递给系统默认的窗口过程DefWindowProc();如果在处理消息的过程中出现失败,则要返回一个非零值,具体返回什么值要根据特定的消息来决定,窗口函数的返回值类似于DOS应用程序的退出代码。Visual

C++5.4.7

常见的消息处理示例程序代码比较简单,它的窗口函数只处理了三个消息:WM_COMMAND消息、WM_PAINT消息和WM_DESTROY消息。当用户选择一个菜单的选项时,发送WM_COMMAND消息,示例程序中有一个退出选项和帮助选项,该消息的处理暂时不讲。WM_PAINT消息WM_PAINT消息是窗口函数WinProc()需要处理的一个很重要消息,该消息牵涉到应用程序的界面维护。当窗口中的用户区域一部分或全部“无效”而需要“刷新”时,都通过该消息实现界面的清理。消息的生成条件消息的处理方法当窗口收到WM_PAINT消息时,应用程序窗口将该窗口的客户区重绘。Visual

C++WM_DESTROY消息消息的生成条件当窗口被摧毁撤消后(当用户按下ALT+F4键或单击关闭窗口按钮时),Windows向窗口发送WM_DESTROY消息。系统默认的响应是调用DestroyWindow()函数撤消窗口。消息的处理方法响应WM_DESTROY消息时,必须要调用PostQuitMessage()函数。该函数向消息队列中放入WM_QUIT消息,使程序退出消息循环,进而退出应用程序。应用程序可在响应这个消息时做一些收尾工作。典型的代码如下:case

WM_DESTROY:PostQuitMessage(0);break;5.4.7 常见的消息处理(续)Visual

C++■消息的生成条件当Windows应用程序要求重新在窗口客户区域绘图时,要发送该消息,典型的情况有:(1)一个窗口由不活动状态变为活动状态时,如果客户区域有部分被其它窗口覆盖,则被覆盖区域变为无效时,会生成该消息;(2)如果一个窗口由隐藏状态变为显示状态时,整个客户区域都无效,会生成该消息;(3)窗口类的风格设置为CS_HREDRAW或

CS_VREDRAW时,那么当窗口大小在水平或垂直方向发生变化时,会生成该消息;(4)在移动窗口使得它和其它窗口相互重叠时,Windows并不保存被覆盖的内容,它是通过,当被覆盖的部分不再被覆盖时(如移走另一个窗口),Windows将其标志为无效,发送该消息;(5)程序显式地调用Invalidate()、InvalidateRect()或InvalidateRgn()函数将产生WM_PAINT消息。当窗口收到WM_PAINT消息时,相当于操作系统告诉你的应用程序窗口“该窗口的客户区域已经混乱了,请你重新把窗口的客户区域绘制一下”。我们在相应WM_PAINT消息时的作图称为“被动作图”,在任何时候,我们都可以在窗口区域中作图,这种情况被称作“主动作图”。Visual

C++消息的处理方法响应WM_PAINT消息的主要目的是在客户区域作图。典型的代码如下:case

WM_PAINT:hdc

=

BeginPaint(hWnd,

&ps);//准备在hWnd所指的窗口内绘图RECT

rt;//定义矩形变量rtGetClientRect(hWnd,&rt);//取hWnd窗口的客户区域保存在矩形变量rtDrawText(hdc,szHello,strlen(szHello),&rt,DT_CENTER);//在矩形rt中显示文本szHelloEndPaint(hWnd,

&ps);//结束在hWnd所指的窗口内绘图break;上述示例代码中,BeginPaint()与EndPaint()函数必须成对调用,并且当且仅当在响应WM_PAINT消息时调用。所有作图代码都必须位于这对函数调用中间,这对函数的第一参数为程序的窗口句柄,第二个参数是指向PAINTSTRUCT(参见下一节的介绍,它主要用于刷新客户区中的内容)结构的指针。Visual

C++typedef

struct

tagMSG

{

HWND

hwnd;WPARAM

wParam;UINTLPARAMPOINTmessage;lParam;pt;DWORD

time;}

MSG;消息结构MSG的各个成员的含义如下:hwnd:接收消息的窗口句柄,用以检索消息。若此参数为0(NULL),则可以检索所有驻留在消息对列中的消息。message:消息标识符。每个Windows消息都有一个确定的值,该值由windows.h头文件中的宏来识别,以WM_前缀开头。wParam、lParam:32位的消息附加参数,此值随不同的message而有所改变。time:消息进入消息队列时的时间。pt:

消息进入消息队列时鼠标的位置坐标。上述消息结构MSG的各个成员中,最为重要的成员是消息标识符。所有的窗口消息定义为具有指定的宏,并带有WM_前缀,紧随其后的是描述消息名。例如,当窗口重新确定尺寸时,则具有WM_SIZE值的消息被放入消息队列中。5.4.8

几个重要的结构1.消息结构Windows的消息结构MSG,其定义如下Visual

C++5.4.8 几个重要的结构(续)HDC

hdc;BOOL

fErase;RECT

rcPaint;BOOL

fRestore;BOOL

fIncUpdate;//设备环境句柄//是否擦除背景//无效的矩形区域//保留,系统内部使用//保留,系统内部使用BYTE

rgbReserved[32];//保留,系统内部使用}

PAINTSTRUCT,

*PPAINTSTRUCT;参数fErase用于指定应用程序是否需要自己擦除无效区域的背景,若其值为FALSE,则意味着由Windows将利用WNDCLASS结构中hbrBackground域指定的画刷来自动擦除背景。若其值为TRUE,则意味着由应用程序自己来负责无效区域的擦除。2.PAINTSTRUCT结构typedef

struct

tagPAINTSTRUCT

{Visual

C++5.4.9

WinMain()执行规程描述程序的主函数WinMain()首先调用字符串资源函数,

将窗口标题和窗口类的名称取出来。然后注册窗口类,

创建一个窗口。创建窗口是由CreateWindow()函数完成,该函数向窗口发送WM_CREATE消息,通知应用程序要创建窗口。创建窗口后,紧接着要显示窗口,这时会收到WM_SIZE消息,窗口的客户区全部无效,收到WM_PAINT消息。对WM_PAINT消息的响应则是在窗口的客户区域显示

一行字符串。此时窗口已经被正常的显示,主函数也进

入了一个消息循环,开始了应用程序的正常运转。最后

当用户关闭窗口时,窗口函数会收到WM_DESTROY消息,

表明窗口已经被撤消了。应用程序最后调用PostQuitMessage()函数终止主函数中的消息循环。至此,窗口已经被撤消,主函数也退出了,整个应用程序终止。Visual

C++5.4.10利用Win32API编写图形界面的关键用VC进行Windows编程的关键在于明白其消息驱动机制,程序的基本流程交由Windows管理,Windows掌握着一定的主

动权,而程序员只需要集中精力做真正需要做的事情,如设

计函数,编写消息的响应代码,至于消息响应函数如何被调

用的则无须管理,交由Windows去处理。用VC进行Windows编程的一个重要工作就是编写窗口函数。程序员的主要精力是编写自己的窗口函数,将接收到的消息所对应的响应代码编好,而调用工作由Windows进行处理。通过消息循环机制,Windows会全心全意地为“接收到的消息找到对应的处理函数执行”而服务。Visual

C++图形设备接口与用户服务Windows应用程序使用图形设备接口和Windows设备驱动程序来支持与设备无关的图形。图形设备接口(GDI)是构造Microsoft的

Windows操作系统核心的三个动态链接库之一,它的任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。为了适应不同的设备,Windows系统提供应用程序与具体设备分离的功能,由操作系统来管理设备驱动程序,将应用程序的图形输出转化为具体物理设备上的输出。设备描述表文本函数画直线函数用户接口服务综合实例*5.5.6

在VC中使用FileView视图浏览文件Visual

C++5.5.1

设备描述表设备描述表(Device

Context,又称设备环境,设备上下文),它是VC进行绘图操作碰到最多的一个技术名词。“设备描述表”中的设备含义为图形既可以在屏幕上显示,还可以在打印机、绘图仪等上显示,而具体是什么外部设备,应用程序并不需要关心,它是设备无关的。在Windows下程序员对所有绘图功能的调用,都是通

过设备描述表来进行的,在进行绘图之前,必须先获取设备描述表句柄。获取和释放设备描述表句柄在应用程序中,有两种方法来获取和释放设备描述表句柄。■(1)通过BeginPaint和EndPaint函数程序在响应WM_PAINT消息进行绘图操作时,要调用

BeginPaint函数来获取设备描述表句柄,使用完后用EndPaint来释放设备描述表句柄。■(2)通过GetDC和ReleaseDC函数在处理非WM_PAINT消息时,通过调用GetDC函数来获取设备描述表信息。该函数的原型为:Visual

C++//

handle

to

windowHDC

GetDC(HWND

hWnd);该函数中参数hWnd代表窗口函数所属的窗口句柄,它返回所获得的设备描述表句柄。当使用完毕,要调用ReleaseDC函数来释放该设备描述表句柄。其原型为:int

ReleaseDC(//所属窗口的句柄//需要释放的设备描述表句柄HWND

hWnd,

HDC

hDC);两种方法的区别:(1)通过BeginPaint函数获得的操作区域是客户区中的无效矩形区域,随后的绘图操作只能在该无效区域内进行,而该区域之外的操作将被忽略。GetDC函数获得的操作区域是整个客户区域,随后的绘图操作可以在客户区的任意部分进行,而不只是在无效区域内进行;5.5.1 设备描述表(续)Visual

C++5.5.1 设备描述表(续)(2)BeginPaint函数会自动将无效矩形区域变为有效,

GetDC函数不会将任何无效矩形区域变为有效,它必须强行调用ValidateRect函数,并将第二个参数设置

温馨提示

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

评论

0/150

提交评论