打印本文 打印本文 关闭窗口 关闭窗口
VB与Windows API 间的呼叫技巧
作者:武汉SEO闵涛  文章来源:敏韬网  点击数1749  更新时间:2009/4/23 16:40:02  文章录入:mintao  责任编辑:mintao
VB5.0与Windows API 间的呼叫技巧                    

                   
    一般会使用WINDOW API的情况,实在是因为VB本身不提供某些功能,但是,程式所
需又不得不然,例如:读取Registry内的资料,VB只提供SaveSetting、Getsetting 等
系列的指令,但是它只能读取特定地区的值,要读、删、更动其他区域的值时,就无法
使用。再如:仔细看一看Combo Box的Events,其中没有MouseMove,但这是我们经常用
上的一个Event,那该如何呢?是的,那只有透过Winodow API。而VB呼叫Window API一
般不都使用API检视员,直接将相对应的API  COPY到我们的程式中就好,那还用什麽技
巧吗?其实不然,因为VB资料格式的问题,又加上VB本身没有指标,在许多地方需要一
些小技巧才能解决,而且我们经常因应不同的需求,将API 检视员的宣告COPY过来後再
做一些修改,最重要的,如果有一个.DLL档,它不在API 检视员中定义,那时,就只有
自己想办法啦。

一、 整数参数

Windows                          API32位元VB
==============================   =============================
Int,  INT                        ByVal  Long
UNIT,  DWORD                     ByVal  Long
BOOL                             ByVal  Long    ture时为1
WPARAM,  LPARAM,  LRESULT        ByVal  Long
Handle(如HKEY)                   ByVal  Long
WORD,  ATOM,  SHORT              ByVal  Integer
BYTE, CHAR                       ByVal  Byte

Eg.
-----------------------------------------------------------------------------
Windows API 宣告

  SHORT GetKeyState( int  nVirtKey )

对应的VB宣告

Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
-----------------------------------------------------------------------------

    这个API 可用来检视某些KEY (如Insert键、Num Lock、CapsLock等)是on/off。程
式如下:这个例子应该可十分楚的看到各个整数间的宣告对应。

-----------------------------------------------------------------------------
Dim InsertMode as Integer
InsertMode = GetKeyState(vbKeyInsert) And vbShiftMask
If InsertMode = 1 then
  Debug.print "表示 Insert Mode"
Else
  Debug.print "表示 OverWrite Mode"
End If
-----------------------------------------------------------------------------
二、 指向整数的指标

Windows API                   32位元VB
============================  ==========================
LPINT                         (ByRef )  Long
LPUNIT                        (ByRef )  Long
LPBOOL                        (ByRef )  Long
LPDWORD                       (ByRef )  Long
LPHANDLE (如:PHKEY)           (ByRef )  Long
LPWORD                        (ByRef )  Integer
LPSHORT                       (ByRef )  Integer
LPBYTE                        (ByRef )  Byte

      VB内定是使用传址呼叫,所以ByRef 可以省略,也就是说
   Func(ByRef param1 as type)
     与
   Func(param1 as  type)
是相同的,使用传址呼叫的方式,不外乎想将参数传给API 後将结果传回来。然而LONG
型态的传址呼叫在VB中又占了相当大的份量,因为32位元的指标都是LONG的型态,而字
串、自定型态的Structure在Windows API中是以指标来传递的,而指标的传递事实上也
是Long值的传递,只不过传过去的LONG值,於WIN API中会将之当成Address,而再配合
指标运作而得指标所指的内容,这个观念在後面会很重要。

例如:
-----------------------------------------------------------------------------
LONG RegOpenKeyEx(
    HKEY        hKey,           // handle of open key
    LPCTSTR     lpszSubKey,     // address of name of subkey to open
    DWORD       dwReserved,     // reserved
    REGSAM      samDesired,     // security access mask
    PHKEY       phkResult       // address of handle of open key
   );
相对应的VB 宣告
Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" _
        (ByVal hKey As Long, _
         ByVal lpSubKey As String, _
         ByVal ulOptions As Long,  _
         ByVal samDesired As Long, _
         phkResult As Long)  As Long   ’//最後一个参数是ByRef之宣告
-----------------------------------------------------------------------------

    我们经常会想要用程式来读取Registry中的资料,例如:我们想得知Win95的Produ
ct ID该如何做呢?这里有几个观念要先清楚:首先:ProductId在何处呢?在

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVerson下的ProductId。

我们要取得的便是

KEY       为 HKEY_LOCAL_MACHINE
SUBKEY    为 SOFTWARE\Microsoft\Windows\CurrentVerson
ValueName 为 ProductId 的value

    然而要取得ProductId的value可没那麽直接,要先取得SubKey的KeyHandle而Key
Handle的取得便是利用RegQueryKeyEx的API 。程式部份在介绍Win API字串传递时再一
并介绍。

三、 字串参数

    凡是所有字串参数指标都以 ByVal 参数名称 As String 传。如RegOpenKeyEx()的
第二参数 ByVal lpSubKey As String,便是一例。或许会问,这个例子是把subkey值传
给 Win API所以用ByVal,没什麽大不了,其实不然,要Win API传回字串时,也一定要
用ByVal的宣告。这是VB5字串格式(BSTR)与WIN API标准字串格式(LPSTR)不同的因素。
LPSTR 字串格式是NULL Terminate的字串,若有一字串"HaHa !OK!",则格式如下:


-----------------------------------------------------------------------------
Address  0  1  2  3  4  5  6  7  8  9
         -- -- -- -- -- -- -- -- -- --
内容     H  a  H  a  !     O  K  !  \0

而BSTR则在字串的前面还有一个LONG值存字串长度,格式如下:

Address  0.. 3  4  5  6  7  8  9  10 11 12 13
         ------ -- -- -- -- -- -- -- -- -- --
内容        9   H  a  H  a  !     O  K  !  \0
-----------------------------------------------------------------------------

    所以了字串以ByVal的方式来传像不像指到BSTR中第4个位置,如此一来,不就和LP
STR 可以相容了吗?我想也正因为如此以ByVal的方式来传String可以取得Win API的传
回值,(就算不是如此,至少这麽想比较记得住String要用ByVal的方式传)。现在又有一
个问题,Window95 API的字串使用的是ASCII Code但VB是用Unicode,Unicode占两个位
元组,那麽能和WinAPI的字串相?所幸我们可以先不用管它,因为vb本身做了转换,即
vb传给api时,转了一次,传回时又转回 Unicode,所以如果我们用的是Byte Array来
传字串,也可以但是要自己去转码。
。然而32位元的VB 中,字串有种格式,一个是BSTR,另一个是HLSTR,如果我们宣告的
串是非固定长度者,就会是BSTR,反之则为HLSTR。

        DIM  BSTR5   AS  STRING           BSTR
   &nb

[1] [2] [3]  下一页

打印本文 打印本文 关闭窗口 关闭窗口