首页
论坛
专栏
课程

分享:
现在很多讲程序设计的书都是基于MFC库和OWL库的Windows设计,对Windows实现的细节鲜有讨论,而调试程序是和系统底层打交道的,所以很有必要掌握一些API函数的知识。 对初学者来说,API函数也许是一个时常耳闻却感觉有些神秘的东西。API的英文全称为“Application Programming Interface”(应用程序编程接口)。对这个定义的理解,需要追溯操作系统的发展历史。当Windows操作系统开始占据主导地位的时候,开发Windows平台下的应用程序成为人们的需要。而在Windows程序设计领域发展的初期,Windows程序员能够使用的编程工具唯有API函数。这些函数提供应用程序运行所需要的窗口管理、图形设备接口、内存管理等各项服务功能。这些功能以函数库的形式组织在一起,形成了Windows应用程序编程接口(API),简称“Win API”。Win API子系统负责将API调用转换成Windows操作系统的系统服务调用。所以,可以认为API函数是构筑整个Windows框架的基石,它的下面是Windows的操作系统核心,而它的上面则是Windows应用程序,如图1.3所示。对应用程序开发人员而言,所看到的Windows操作系统实际上就是Win API,操作系统的其他部分对开发人员来说是完全透明的。 ![图片描述](/upload/attach/201710/201710030941_x84f1vhbz379dw8.png) 用于16位版本Windows的API(Windows 1.0到Windows 3.1)称作“Win16”,用于32位版本Windows的API(Windows 9x/NT/2000/XP/2003)称作“Win32”。64位版本Windows API的名称和功能基本没有变化,还是Win32的函数名,只不过是用64位代码实现的。API函数调用在从Win16到Win32的转变中保持兼容,并在数量和功能上不断增强——Windows 1.0支持不到450个函数调用,现在已有几千个函数。 所有32位版本的Windows都支持Win16 API(以确保和旧的应用程序兼容)和Win32 API(以运行新的应用程序)。非常有趣的是,Windows NT/2000/XP与Windows 9x的工作方式不同。在Windows NT/2000/XP中,Win16函数调用通过一个转换层被转化为Win32函数调用,然后被操作系统处理。在Windows 9x中,该操作正好相反:Win32函数调用通过转换层转换为Win16位函数调用,再由操作系统处理。 Windows运转的核心是一个称作“动态链接”的概念。Windows提供了应用程序可利用的丰富的函数调用,这些函数采用动态链接库(即DLL)实现。在Windows 9x中,通常位于WINDOWSSYSTEM子目录中。在Windows NT/2000/XP中,通常位于系统安装目录的SYSTEM和SYSTEM32子目录中。 在早期,Windows的主要部分只需要在3个动态链接库中实现,代表了Windows的3个主要子系统,分别叫作Kernel、User和GDI。 + Kernel(由16位的KRNL386.EXE和32位的KERNEL32.DLL实现):操作系统核心功能服务,包括进程与线程控制、内存管理、文件访问等。 + User(由16位的USER.EXE和32位的USER32.DLL实现):负责处理用户接口,包括键盘和鼠标输入、窗口和菜单管理等。 + GDI(由16位的GDI.EXE和32位的GDI32.DLL实现):图形设备接口,允许程序在屏幕和打印机上显示文本和图形。 除了上述模块以外,Windows还提供了其他DLL以支持另外一些功能,包括对象安全性、注册表操作(ADVAPI32.DLL)、通用控件(COMCTL32.DLL)、公共对话框(COMDLG32.DLL)、用户界面外壳(SHELL32.DLL)、图形引擎(DIBENG.DLL)和网络(NETAPI32.DLL)。 虽然Win API是一个基于C语言的接口,但是Win API中的函数可以由用不同语言编写的程序调用,只要在调用时遵循调用的规范即可。 Unicode影响着计算机工业的每个部分,对操作系统和编程语言的影响最大。NT系统是使用Unicode标准字符集重新开发的,其系统核心完全是用Unicode函数工作的。如果希望调用任何一个Windows函数并给它传递一个ANSI字符串,系统首先要将字符串转换成Unicode,然后将Unicode传递给操作系统。相反,如果希望函数返回ANSI字符,系统就会首先将Unicode字符串转换成ANSI字符串,然后将结果返回给应用程序。也就是说,在NT架构下,Win32 API能接受Unicode和ASCII两种字符集,而其内核则只能使用Unicode。所有这些操作对用户来说都是透明的,但这些字符串的转换需要占用系统资源。 在Win32 API函数字符集中,“A”表示ANSI,“W”表示Widechars(即Unicode)。前者就是通常使用的单字节方式,后者是宽字节方式,以方便处理双字节字符。用字符串作参数的每个Win32函数在操作系统中都有这两种方式的版本。例如,编程时使用MessageBox函数,而在USER32.DLL中却没有32位MessageBox函数的入口点。实际上,有两个入口点,一个名为“MessageBoxA”(ANSI版),另一个名为“MessageBoxW”(宽字符版)。幸运的是,程序员通常不必关心这个问题,代码中只需要使用MessageBox,开发工具中的编译模块就会根据设置来决定是采用MessageBoxA还是MessageBoxW。 这里以MessageBox为例讨论一下。此函数是在USER32.DLL用户模块中创建和显示信息框,函数原型如下。 ``` int MessageBox( HWND hWnd, // 父窗口句柄 LPCTSTR lpText, // 消息框文本地址 LPCTSTR lpCaption, // 消息框标题地址 UINT uType // 消息框样式 ); ``` 现在来看一看Windows 2000里MessageBoxA函数的内部结构。 ``` int MessageBoxA( MessageBoxExA{ // 调用MessageBoxExA函数 MBToWCSEx( ) // 将MessageBoxA消息框的主体文字转换成Unicode字符串 MBToWCSEx( ) // 将MessageBoxA消息框标题栏上的文字转换成Unicode字符串 MessageBoxExW( ) // 调用MessageBoxExW函数 HeapFree( ) // 释放内存 } ); ``` 这个试验结果表明,MessageBoxExA函数其实是一个替换翻译层,用于分配内存,并将ANSI字符串转换成Unicode字符串,系统最终调用Unicode版的MessageBoxExW函数执行。当MessageBoxExW返回时,它便释放内存缓存。在这个过程中,系统必须执行这些额外的转换操作,因此,ANSI版的应用程序需要更多的内存,占用更多的CPU资源。而Unicode版的程序在NT架构下的执行效率就高多了。 由于Win32程序大量调用系统提供的API函数,而Win32平台上的调试器(如OllyDbg等)恰好有针对API函数设置断点的强大功能,因此掌握常用的API函数具体用法会给程序的跟踪调试带来极大的方便,详细的Win32 API参考文档可以从MSDN中获得。建议读者掌握一定的Win32编程知识(如阅读《Windows程序设计》一书),这会对合理选择API函数有很大的帮助。

上一篇 :
下一篇 :
讨论 (3)
我是本饭 2018-2-19
 举报
相当不错!!!
陈jack 2018-7-31
 举报
学习一下
Aplace 2018-11-22
 举报
楼主加油
沪ICP备16048531号-1
沪公网安备 31011502006611号