在VB中使用API函数什么是API--API的描述API声明--如何声明API--API函数--函数的类型消息句柄,坐标,数据结构,...API参数类型--VB中的等价类型Any参数传递--按值调用(ByVal),按引用调用(ByRef),结构,字符串,数组...回调WinProc子类处理--获取错误结果--组合标志位处理参数如何认识API函数?--一个例子结束语什么是API?API(AdvancedProgrammersInterface,高级程序员接口)(注:API实际是指ApplicationProgrammingInterface,应用程序编程接口;此处疑为原文错误,不过在VB中也可以这么说吧!)是一套用来控制Windows的各个部件(从桌面的外观到位一个新进程分配的内存)的外观和行为的一套预先定义的Windows函数.用户的每个动作都会引发一个或几个函数的运行以Windows告诉发生了什么.这在某种程度上很象Windows的天然代码.其他的语言只是提供一种能自动而且更容易的访问API的方法.VB在这方面作了很多工作.它完全隐藏了API并且提供了在Windows环境下编程的一种完全不同的方法.这也就是说,你用VB写出的每行代码都会被VB转换为API函数传递给Windows.例如,Form1.Print...VB将会以一定的参数(你的代码中提供的,或是默认参数)调用TextOut这个API函数.同样,当你点击窗体上的一个按钮时,Windows会发送一个消息给窗体(这对于你来说是隐藏的),VB获取这个调用并经过分析后生成一个特定事件(Button_Click).API函数包含在Windows系统目录下的动态连接库文件中(如User32.dll,GDI32.dll,Shell32.dll...).API声明正如在什么是API中所说,API函数包含在位于系统目录下的DLL文件中.你可以自己输入API函数的声明,但VB提供了一种更简单的方法,即使用APITextViewer.要想在你的工程中声明API函数,只需运行APITextViewer,打开Win32api.txt(或.MDB如果你已经把它转换成了数据库的话,这样可以加快速度.注:微软的这个文件有很多的不足,你可以试一下本站提供下载的api32.txt),选择声明,找到所需函数,点击添加(Add)并复制(Copy),然后粘贴(Paste)到你的工程里.使用预定义的常量和类型也是同样的方法.你将会遇到一些问题:假设你想在你的窗体模块中声明一个函数.粘贴然后运行,VB会告诉你:编译错误...Declare语句不允许作为类或对象模块中的Public成员...看起来很糟糕,其实你需要做的只是在声明前面添加一个Private(如☆★☆★技术文档★☆★☆2.针对API初学者的教程第二篇【返回首页】【上一章】【下一章】Windows的一些特别之处这个主题是要告诉你Windows的一些与在VB中的不同的细节PrivateDeclareFunction...).--不要忘了,可是这将使该函数只在该窗体模块可用.在有些情况下,你会得到不明确的名称这样的提示,这是因为函数.常量或其他的什么东西共用了一个名称.由于绝大多数的函数(也可能是全部,我没有验证过)都进行了别名化,亦即意味着你可以通过Alias子句使用其它的而不是他们原有的名称,你只需简单地改变一下函数名称而它仍然可以正常运行.你可以通过查看VB的Declare语句帮助主题来获取有关Alias的详细说明.消息(Messages)好了,现在你已经知道什么是API函数了,但你也一定听说过消息(如果你还没有,你很快就会)并且想知道它是什么.消息是Windows告诉你的程序发生了哪些事件或要求执行特定操作的基本方法.例如,当用户点击一个按钮,移动鼠标,或是向文本框中键入文字时,一条消息就会被发送给你的窗体.所有发送的消息都有四个参数--一个窗口句柄(hwnd),一个消息编号(msg)还有两个32位长度(Long)的参数.hwnd即要接受消息的一个窗口的句柄,msg即消息的标识符(编号).该标识符是指引发消息的动作类型(如移动鼠标),另外两个参数是该消息的附加参数(例如当鼠标移动时光标的当前位置)但是,当消息发送给你时你为什么看不到呢--就象有人在偷你的信一样?请先别恼火,让我告诉你.小偷其实是VisualBasic.但它并没有偷走你的信,而是在阅读了之后挑出重要的以一种好的方式告诉你.这种方式就是你代码中的事件(Event).这样,当用户在你的窗体上移动鼠标时,Windows会发送一条WM_MOUSEMOVE消息给你的窗口,VB得到这条消息以及它的参数并运行你在事件MouseMove中的代码,同时VB会把这条消息的第二个32位数(它包含了x,y坐标,单位为像素(Pixel),每个位16位)转换为两个单精度数,单位为缇(Twip).现在,如果你需要光标坐标的像素表示,然而VB已经把它转换成了缇,因此你需要重新把它转换为以像素为单位.在这里,Windows给了你所需要的,但VB好意地进行了转换而使你不得不重新转换.你可能会问--我难道不能自己接收消息吗?答案是肯定的,你可以使用一种叫做子类处理(Subclass)的方法.但你除非必须否则最好不要使用,因为这与VB的安全程序设计有一点点的违背.(注:子类处理确实有很大的风险,但如果使用得当,是很有用处的.不过有一点一定要注意,即千万不要使用VB的断点调试功能,这可能会导致VB崩溃!)需要补充说明的是:你可以发送消息给你自己的窗口或其他的窗口,只需调用SendMessage或PostMessage(SendMessage会使接受到消息的窗口立刻处理消息,而PostMessage是把消息发送到一个称为消息队列的队列中去,等候处理(它将会在该消息处理完后返回,例如有些延迟)).你必须制定接受消息的窗口的句柄,欲发送消息的编号(所有的消息的编号均为常量,你可以通过APITextViewer查得)以及两个32位的参数.Windows通过句柄(Handle)识别每个窗体,控件,菜单,菜单项或其他任何你能想得到的东西.当你的程序运行时,它所包含的每个部件都有一个唯一确定的句柄用来同其他的部件相区别.例如,某个按钮得句柄就与其他部件不同,当你想要通过API来执行有关该按钮的某种操作时就必须使用这个句柄.从哪儿得到它呢?VB为每个拥有Windows句柄的控件都提供了Hwnd属性来表示其句柄.Windows使用像素(Pixel)而不是缇(Twip).因此,把涉及API函数调用的控件的ScaleMode属性设为3--(Pixel)是个不错的主意,这样你可以通过ScaleXXX属性得到它们的国际单位值.尽管这样,你可能有时仍需要进行从Twip到Pixel的转换(反之亦然),你可以通过Screen对象的TwipsPerPixelX和TwipsPerPixelY来实现.举例如下:PixelXValue=TwipXValue\Screen.TwipsPerPixelXPixelYValue=TwipYValue\Screen.TwipsPerPixelYTwipXValue=PixelXValue*Screen.TwipsPerPixelXTwipYValue=PixelYValue*Screen.TwipsPerPixelY我并没有在实际中见到过TwipsPerPixelX和TwipsPerPixelY的值有什么不同,但你最好是把它们区别开来而不是混用,这至少是一种好的程序设计风格.另外需要注意的是,这里用的是\(整除)而不是/,这是因为像素值必须是整数.另外需要提到的是,Windows函数中用到了不同的坐标系统,因此需要注意.最后要注意的是,一旦你使用了API函数,VB就可能不再可靠了---API调用中一个简单的语法错误就会导致VB崩溃!(请经常保存您的工程).VB并不能识别API调用中的错误,因此一旦你的程序出现异常,要先检查API调用---是否缺少ByVal,或者是错误的类型,参数等等.从哪里得到有关函数的说明?这个主题不会告诉你如何通过API函数改变按钮文字或如何快速查找一个文件.这不是一个API函数文档.为了得到有关函数的说明,你需要SDK帮助或微软的SDK文档(至少有40M---我怎么可能放在这里?).这些SDK帮助通常都包含在BorlandDephli3.0开发包或者MSVisualC++中.到网上去或找您的朋友要一个,版本越新越好注意Win3.x的SDK帮助对你并没有用,因为很多函数已经过于陈旧甚至废弃不用,尽管他们中的大多数由于与Windows95兼容而依然存在.API参数类型如果你已经有了一个SDK帮助,你肯定主意到了函数的返回之或参数有很多奇怪的类型如VOID,LPCSTR,和DWORD.如果你对C语言比较熟悉的话,那你肯定明白它们的意思.对于其他不熟悉C语言的人,这里有一张摘自VBBooksOnline(标题是:C语言声明到VisualBasic的转换)C语言数据类型在VB中的声明CallwithATOMByValvariableAsIntegerAnexpressionthatevaluatestoanIntegerBOOLByValvariableAsLongAnexpressionthatevaluatestoaLongBYTEByValvariableAsByteAnexpressionthatevaluatestoaByteCHARByValvariableAsByteAnexpressionthatevaluatestoaByteCOLORREFByValvariableAsLongAnexpressionthatevaluatestoaLongDWORDByValvariableAsLongAnexpressionthatevaluatestoaLongHWND,HDC,HMENU,etc.(Windowshandles)ByValvariableAsLongAnexpressionthatevaluatestoaLongINT,UINTByValvariableAsLongAnexpressionthatevaluatestoaLongLONGByValvariableAsLongAnexpressionthatevaluatestoaLongLPARAMByValvariableAsLongAnexpressionthatevaluatestoaLongLPDWORDvariableAsLongAnexpressionthatevaluatestoaLongLPINT,LPUINTvariableAsLongAnexpressionthatevaluatestoaLongLPRECTvariableAstypeAnyvariableofthatuser-definedtypeLPSTR,LPCSTRByValvariableAsStringAnexpressionthatevaluatestoaStringLPVOIDvariableAsAnyAnyvariable(useByValwhenpassingastring)LPWORDvariableAsIntegerAnexpressionthatevaluatestoanIntegerLRESULTByValvariableAsLongAnexpressionthatevaluatestoaLongNULLAsAnyorByValvariableAsLongByValNothingorByVal0&orvbNullStringSHORTByValvariableAsIntegerAnexpressionthatevaluatestoanIntegerVOIDSubprocedureNotapplicableWORDByValvariableAsIntegerAnexpressionthatevaluatestoanInt