设为首页收藏本站Access中国

Office中国论坛/Access中国论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

返回列表 发新帖
查看: 3704|回复: 5
打印 上一主题 下一主题

[API] 【转载 / 文章】在VB中使用API函数

[复制链接]
跳转到指定楼层
1#
发表于 2005-8-24 19:22:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
原作来自:水木清华BBS翻译作品

===================================================================

什么是API?

  API(Application Programming Interface应用程序编程接口)是一套用来控制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提供了一种更简单的方法,即使用API Text Viewer。



  要想在你的工程中声明API函数,只需运行API Text Viewer,打开Win32API.TXT(或.MDB如果你已经把它转换成了数据库的话,这样可以加快速度。注:微软的这个文件有很多的不足,你可以试一下本站提供下载的API32.txt),选择“声明”,找到所需函数,点击“添加(Add)”并“复制(Copy)”,然后粘贴“(Paste)”到你的工程里,使用预定义的常量和类型也是同样的方法。



你将会遇到一些问题:



  假设你想在你的窗体模块中声明一个函数,粘贴然后运行。VB会告诉你:编译错误...Declare 语句不允许作为类或对象模块中的 Public 成员...看起来很糟糕,其实你需要做的只是在声明前面添加一个Private(如:Private Declare Function...)……不要忘了,可是这将使该函数只在该窗体模块可用。



  在有些情况下,你会得到“不明确的名称”这样的提示,这是因为函数、常量或其他的什么东西共用了一个名称。由于绝大多数的函数(也可能是全部,我没有验证过)都进行了别名化,亦即意味着你可以通过Alias子句使用其它的而不是他们原有的名称,你只需简单地改变一下函数名称而它仍然可以正常运行。



  你可以通过查看VB的Declare语句帮助主题来获取有关Alias的详细说明。

消息(Messages)



  好了,现在你已经知道什么是API函数了,但你也一定听说过消息(如果你还没有,你很快就会)并且想知道它是什么。消息是Windows告诉你的程序发生了哪些事件或要求执行特定操作的基本方法,例如:当用户点击一个按钮,移动鼠标,或是向文本框中键入文字时,一条消息就会被发送给你的窗体。



  所有发送的消息都有四个参数:一个窗口句柄(hWnd),一个消息编号(Msg)还有两个32位长度(Long)的参数。



  hWnd即要接受消息的一个窗口的句柄,Msg即消息的标识符(编号)。该标识符是指引发消息的动作类型(如移动鼠标),另外两个参数是该消息的附加参数(例如当鼠标移动时光标的当前位置)



  但是,当消息发送给你时你为什么看不到呢?就象有人在偷你的信一样?请先别恼火,让我告诉你,小偷其实是Visual Basic。但它并没有偷走你的信,而是在阅读了之后挑出重要的以一种好的方式告诉你,这种方式就是你代码中的事件(Event)。



  这样,当用户在你的窗体上移动鼠标时,Windows会发送一条WM_MOUSEMOVE消息给你的窗口,VB得到这条消息以及它的参数并运行你在事件MouseMove中的代码,同时VB会把这条消息的第二个32位数(它包含了x,y坐标,单位为像素(Pixel),每个位16位)转换为两个单精度数,单位为缇(Twip)。



  现在,如果你需要光标坐标的像素表示,然而VB已经把它转换成了缇,因此你需要重新把它转换为以像素为单位。在这里,Windows给了你所需要的,但VB“好意地”进行了转换而使你不得不重新转换。你可能会问:我难道不能自己接收消息吗?答案是肯定的,你可以使用一种叫做子类处理(Subclass)的方法.但你除非必须否则最好不要使用,因为这与VB的安全程序设计有一点点的违背。(注:子类处理确实有很大的风险,但如果使用得当,是很有用处的。不过有一点一定要注意,即千万不要使用VB的断点调试功能,这可能会导致VB崩溃!)



  需要补充说明的是:你可以发送消息给你自己的窗口或其他的窗口,只需调用SendMessage或PostMessage(SendMessage会使接受到消息的窗口立刻处理消息,而P
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 分享淘帖 订阅订阅
2#
 楼主| 发表于 2005-8-24 19:24:00 | 只看该作者
从哪里得到有关函数的说明?

  这个主题不会告诉你如何通过API函数改变按钮文字或如何快速查找一个文件,这不是一个API函数文档。



  为了得到有关函数的说明,你需要SDK帮助或微软的SDK文档(至少有40M---我怎么可能放在这里?)。这些SDK帮助通常都包含在Borland Dephli 3.0开发包或者MS Visual C++中。到网上去或找您的朋友要一个,版本越新越好。



  注意Win3.x 的SDK 帮助对你并没有用,因为很多函数已经过于陈旧甚至废弃不用,尽管他们中的大多数由于与Windows95兼容而依然存在。

API参数类型



  如果你已经有了一个SDK帮助,你肯定主意到了函数的返回之或参数有很多奇怪的类型如VOID、LPCSTR和DWORD。如果你对C语言比较熟悉的话,那你肯定明白它们的意思。对于其他不熟悉C语言的人,这里有一张摘自 VB Books Online(标题是:C语言声明到Visual Basic的转换)



<TABLE cellSpacing=0 width="100%" borderColorLight=silver border=1 p>





C 语言数据类型

在VB中的声明

Call with



ATOM

ByVal variable As Integer

An expression that evaluates to an Integer



BOOL

ByVal variable As Long

An expression that evaluates to a Long



BYTE

ByVal variable As Byte   











An expression that evaluates to a Byte











CHAR





ByVal variable As Byte   













           





An expression that evaluates to a Byte















COLORREF





ByVal variable As Long





               An













expression that evaluates to a Long















DWORD





ByVal variable As Long   













           





An expression that evaluates to a Long















HWND, HDC,HMENU,etc.(Windows handles)





ByVal variable As Long   













           





An expression that evaluates to a Long















INT, UINT





ByVal variable As Long





An expression that evaluates to a Long















LONG





ByVal variable As Long





An expression that evaluates to a Long















LPARAM   













               







ByVal variable As Long   













            





An expression that evaluates to a Long















LPDWORD





variable As Long





An expression that evaluates to a Long















LPINT, LPUINT





variable As Long





An expression that evaluates to a Long









<TR>





LPRECT





variable As type
3#
 楼主| 发表于 2005-8-24 19:24:00 | 只看该作者
窗口程序

  Windows并不知道事件,这些是VB特有的隐藏Windows获取你的窗口发生事件的真正方法的一种方式。VB很像是一个将Windows语言翻译成VB语言的解释器。



  但是事实并非如此,你很快就会遇到。设想你想知道用户何时加亮了菜单选项(不是点击,只是加亮即选择了)VB并不提供这种事件,但你可能见到其他的程序,但你浏览它的菜单时状态栏会出现相应的文字。如果他们能,你为何不能?



  OK,这里是大致的真实情况。每个窗口都有一个特殊的程序叫做窗口程序。它实际上是一个回调函数。该函数将在你的窗口发生事件的任何时间发送消息。这样当用户加亮一个菜单项时就会发送一条消息(WM_COMMAND)。



  那为什么我看不到这条消息呢?这是因为是VB创建窗口程序而不是你。当Windows发送消息时,该程序将为之分派特定的事件,并将其参数转换为比较容易用的事件的参数。但是在有些情况下,它会忽略有些消息而不能收到真实的输入。如果你真的想得到这些消息,你必须对你的窗体进行子类处理,我们将在另外一个主题中谈到。



这里是一个回调窗口程序的声明:



Function WindowProc(ByVal Hwnd As Long, ByVal wMsg As Long,ByVal wParam As Long, ByVal lParam As Long) As Long



  第一个参数指定窗口的句柄,第二个参数是消息的标识符(如WM_COMMAND或WM_MOUSEMOVE),wParam和lParam时两个32位的数值,它们的意义依赖于消息的类型。

子类处理



  当你一最大限度利用了VB所给你的并且还想知道更多的东西,或只是想更多地了解你自己的窗口,你将会发现子类处理的优势。



  子类处理是指用一个新的窗口函数来取代当前活动窗口函数。这个用户自定义函数能处理任何需要的消息,并能调用原来的窗口函数,它将在原来的窗口函数之前收到各种消息。但原来的那个窗口处理函数依然存在,并没有消失。如果你不想处理某条消息,你应该让原来的窗口函数去处理它。



  子类处理是通过调用SetWindowLong函数实现的,该函数将改变指定窗口的特殊属性。下面是它的声明:



Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA"(ByVal hwnd As Long, ByVal nIndex As Long,ByVal dwNewLong As Long) As Long



第一个参数代表要进行子类处理的窗口,第二个参数应该是GWL_WNDPROC(-4),第三个参数是新的窗口函数的地址。参见回调和窗口函数一节:



此函数将在窗口取得焦点,发生事件,或其他情况下(如其他进程改变了系统的某些参数)被随时调用:



如果发生错误SetWindowLong函数将返回0,否则将返回原来的窗口函数的地址。这个地址特别重要,你应该把它保存在一个变量中或其他地方。当你不处理某些消息时(实际上,你可能只处理不到1%的消息,其他的都将由原窗口函数处理),调用原来的窗口函数就需要该地址。

  调用原窗口函数将由CallWindowProc来完成。这里是它的声明:



Declare Function CallWindowProc Lib "user32" Alias"CallWindowProcA"(ByVal lpPrevWndFunc As Long,ByVal hWnd As Long,ByVal Msg As Long,ByVal wParam As Long, ByVal lParam As Long) As Long



  第一个参数是原窗口函数的地址,其他的同你接收到的四个参数一样。你可以改变其中的值来控制对消息的处理。例如:当你收到了一条WM_MOUSEMOVE消息时,你从lParam中得到鼠标所在位置的坐标并将其改成了其他的坐标。那么原窗口函数就会认为鼠标位于其他的位置从而做出一些有趣的事如显示其他控件的Tooltip.。



  你指定的返回值也是有意义的,它依赖于发送的消息。



在结束你的程序时将控制权交回给原窗口函数是很重要的,通常在Form_Unload中完成如下:



Ret& = SetWindowLong(Me.Hwnd, GWL_WNDPROC, oldWndProcAddress)



如果你在VB中启动程序时忘掉了这一行,结果将是VB崩溃并会丢失尚未保存的数据,千万要小心。



这里是子类处理的一个简单示例:

Dim oldWndProc As Long



Private Sub Form_Load()

    oldWndProc = SetWindowLong(Me.Hwnd, GWL_WNDPROC, AddressOf MyWndProc)

End Sub



Private Sub Form_Unload()

    Ret& = SetWindowLong(Me.Hwnd, GWL_WNDPROC, oldWndProc)

End Sub



Function MyWndProc(ByVal Hwnd As Long,ByVal wMsg as Long,ByVal wParam As Long,ByVal lParam As Long)

    Debug.Print wMsg & " " & wParam & " " & lParam

    Ret& = CallWindowProc(oldWndProc, Hwnd, wMsg, wParam, lParam)

End Function

处理参数

  有时函数并不以你所需的方式返回信息。一个典型的例子是将
4#
发表于 2005-8-24 19:47:00 | 只看该作者
5#
发表于 2009-7-12 07:15:59 | 只看该作者




6#
发表于 2009-9-27 09:31:21 | 只看该作者
谢谢分享,收藏了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|站长邮箱|小黑屋|手机版|Office中国/Access中国 ( 粤ICP备10043721号-1 )  

GMT+8, 2024-5-17 11:33 , Processed in 0.092264 second(s), 29 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表