;H20000 Const STANDARD_RIGHTS_READ = (READ_CONTROL) Const KEY_QUERY_VALUE = &H1 Const KEY_ENUMERATE_SUB_KEYS = &H8 Const KEY_NOTIFY = &H10 Const SYNCHRONIZE = &H100000 Const KEY_READ = ((STANDARD_RIGHTS_READ Or _ KEY_QUERY_VALUE Or KEY_ENUMERATE_SUB_KEYS Or _ KEY_NOTIFY) And (Not SYNCHRONIZE))
Dim key5 As String, ValueName as String, strBuff as String, ResultStr as String Dim leng1 As Long, resul As Long, hkey As Long Dim tp As Long, i As Long
key5 = " SOFTWARE\Microsoft\Windows\CurrentVerson " resul = RegOpenKeyEx(HKEY_CLASSES_ROOT, key5, 0, KEY_READ, hkey) ''''hkey便是subkey (key5)的KeyHandle,先取得它才能存取Subkey内的ValueName ValueName= "ProDuctId " tp = REG_SZ strBuff = String(255, 0) leng1 = Len(strBuff) + 1 resul = RegQueryString(hkey, ValueName, 0, tp, strBuff, leng1) ''''注意,第三个参数传0,leng1传回copy 到strBuff的字元个数(anci) leng1 = InStr(1, strBuff, Chr(0), vbBinaryCompare) ''''重新算个数(UniCode) ResultStr = Left(StrBuff,leng1-1) ''''这便是ProductId的值 ***************************************************************************** 在这里有另外一件事要特别说明,范例三程式中有一行leng1=Len(strBuffer)+1, 这行可省不得,很奇怪吧,为什麽明明是一个传回值,却一定要设定给它一个strBuff 的大小呢?这是因为许多WIN API 不会聪明到找strBuff的Null Char在哪里,所以需要 程式传进去,而後它再依这个栏位传回填入strBuff 的数目。
五、Array参数的传递
我们知道Win API 的阵列传递是传阵列的起始位址,所以了,在VB中唯一要注意的 是起始位置的写法。以另一个取得Window目录所在路径的API为 例: ----------------------------------------------------------------------------- UINT GetWindowsDirectory( LPTSTR lpBuffer, // address of buffer for Windows directory UINT uSize // size of directory buffer ); // 若成功,则传回目录的字元数 VB的宣告(API检视员) Declare Function GetWindowsDirectory Lib "kernel32" Alias _ "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) _ As Long 我们将之更改为 Declare Function GetWindowsDirectory Lib "kernel32" Alias _ "GetWindowsDirectoryA" ( lpBuffer As Byte, ByVal nSize As Long) As Long
----------------------------------------------------------------------------- 范例四 ***************************************************************************** Dim n as Long Dim Buff() as Byte Dim StrA as String
Buff = space(256) n=GetWindowsDirectory(Buff(0), 256) Buff = Leftb(Buff, n) StrA = StrConv(Buff, vbUniCode) ''''StrA便是Windows所在目录 *****************************************************************************
在范例四中,GetWindowsDirectory()传入的第一个参数Buff(0)便是这阵列的起始 Byte ,因VB 宣告成lpBuffer As Byte,故传过去的是ByRef Buff(0)的位址,当然了 ,你也可以呼叫成n=GetWindowsDirectory(Buff(1), 256),只是传回值是填在Buff(1) to Buff(n),而Buff(0)则仍为起始的Space Character(32),因为该API传回值是字 元个数,再加上存於Buff中的是Byte Array故,使用Leftb()去除多出的byte,再用 StrConv将Byte Array转成Unicode的字串。比照范例二的作法,我们也可以将Byte Array 改成以String的方式来做,二者可做一比较,谁比较好或比较顺畅,那见人见智 ,不过可以肯定的是,如果传的值是Binary的值,那麽使用Byte Array来做才对,因用 String来传的话,会经过转换成UniCode的步骤,这中间会发生什麽事,没人知道。
六、CallBack Function的作法
VB的使用者通常对於这个名词有著多多少少的疑惑,或称之为"哭爸"Function,而 VB5使用手册使用Window Procedure来说明,除非对Window 系统有一些了解,否则可能 令人更不知所云;我使用另一个例子来说明,那便是KeyBoard Hook。什麽是KeyBoard Hook 呢,简言之便是按键盘时,便会自动执行某一段Function的功能,就好比Dos时代 的拦截中断向量一般。让我们先看一下设定Hook的宣告吧。
----------------------------------------------------------------------------- HHOOK SetWindowsHookEx( int idHook, // type of hook to install HOOKPROC hkprc, // address of hook procedure HINSTANCE hMod, // handle of application instance DWORD dwThreadID // identity of thread to install hook for );
Declare Function SetWindowsHookEx Lib "user32" Alias SetWindowsHookExA" _ (ByVal idHook As Long, _ ByVal lpfn As Long, _ ByVal hmod As Long, _ ByVal dwThreadId As Long) As Long
----------------------------------------------------------------------------- Hook有很多种,如KeyBoard Hook, Mouse Hook, JournalRecord Hook等,所以第 一个参数指明了要哪一种Hook,第二个参数便是Hook Procedure所在,也就是方才所说 "自动执行某一段Function的功能"中的那一个Function,这个Function的名称可以随意 给定,但有一定的参数传递规则,例如: hnexthookproc = SetWindowsHookEx(WH_KEYBOARD, _ AddressOf MyKBHFunc, App.Hinstance, 0) 如此设定则每当按任一个键时,程式自动会去执行 MyKBHFunc。这个Hook Function 是由我们所定义,但是它是由Window自动去呼叫,而不是由我们的程式呼叫,这类的 Function就叫CallBack Function。
以上面的例子来说,这个CallBack Function定义如下: ----------------------------------------------------------------------------- Public Function MyKBHFunc(ByVal iCode As Long, _ ByVal wParam As Long, ByVal lParam As Long) As Long MyKBHFunc = 0 If iCode < 0 Then MyKBHFunc = CallNextHookEx(hnexthookproc, iCode, wParam, lParam) Exit Function End If ''''侦测 有没有按到PrintScreen键 If wParam = vbKeySnapshot Then MyKBHFunc = 1 Debug.Print "haha" End If End Function -----------------------------------------------------------------------------
这个KeyBoard Hook Function的目的主要是想拦截有没有按到Print Screen这个键 ,这个键不会在Form的KeyDown, KeyPress, KeyUp Event中作用,所以只好透过KeyBoa rd Hook去拦截。而CallBack Function放的位置有规定,一个是要与呼叫SetWindowsHo okEx() 的地方在同样的一个Project,另外,它只能存在於.BAS档,不能放在其他地方 。KeyBoard Hook的程式於范五。
范例五 ***************************************************************************** ''''以下程式於Hook.bas Declare Function SetWindowsHookEx Lib "user32" Alias _ "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, _ ByVal hmod As Long, ByVal dwThreadId As Long) As Long Declare Function UnhookWindowsHookEx Lib "user32" _ (ByVal hHook As Long) As Long Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _ ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Public hnexthookproc As Long Public Const HC_ACTION = 0 Public Const WH_KEYBOARD = 2
Public Sub UnHookKBD() If hnexthookproc 0 Then UnhookWindowsHookEx hnexthookproc hnexthookproc = 0 End If End Sub Public Function EnableKBDHook() If hnexthookproc 0 Then Exit Function End If hnexthookproc = SetWindowsHookEx(WH_KEYBOARD, AddressOf _ MyKBHFunc, App.Hinstance, 0) If hnexthookproc 0 Then EnableKBDHook = hnexthookproc End If End Function Public Function MyKBHFunc(ByVal iCode As Long, _ ByVal wParam As Long, ByVal lParam As Long) As Long ''''这三个参数是固定的,不能动,而MyKBHFunc这个名称只要和 ''''SetWindowsHookex()中 AddressOf後的名称一样便可,不一定叫什麽 MyKBHFunc = 0 If iCode < 0 Then MyKBHFunc = CallNextHookEx(hnexthookproc, iCode, wParam, lParam) Exit Function End If If wParam = vbKeySnapshot Then ''''侦测 有没有按到PrintScreen键 MyKBHFunc = 1 Debug.Print "haha" End If End Function ''''以下程式於Form Private Sub Form_Load() Call EnableKBDHook End Sub
Private Sub Form_Unload(Cancel As Integer) Call UnHookKBD End Sub ***************************************************************************** 七、自订型态的传递
因这只要用ByRef的方式来做就没有什麽大的问题,故不做说明。
八、综合应用
我们再以一个实例来说明Win API在VB5中呼叫的技巧。有一个函式叫CopyMemory 的宣告如下:
----------------------------------------------------------------------------- Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" ( _ lpvDest As Any, lpvSource As Any, ByVal cbCopy as Long) -----------------------------------------------------------------------------
这个函式可以将 lpvDest的momory copy 到lpvSource上去,cbCopy则代表要copy 多少个byte。有了这个函式,我们可以知道一个Double值存在Memory中的各个byte到底 是多少。
----------------------------------------------------------------------------- Dim dbl as Double Dim bte(0 to 7) as Byte Dbl = 168.256 CopyMemory dbl, byt(0), 8 -----------------------------------------------------------------------------
如此检视bte阵列便可以知道这Double值的各个byte是多少。再以另一个 JournalRecord Hook为例来说明:
范例六 ***************************************************************************** '''' 以下在Hook.bas Const WM_MOUSELAST = &H209 Const WM_MOUSEFIRST = &H200 Public Const WM_KEYLAST = &H108 Public Const WM_KEYFIRST = &H100 Public Const WH_JOURNALRECORD = 0 Type EVENTMSG message As Long paramL As Long paramH As Long time As Long hwnd As Long End Type Declare Function SetWindowsHookEx Lib "user32" Alias _ "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, _ ByVal hmod As Long, ByVal dwThreadId As Long) As Long Declare Function UnhookWindowsHookEx Lib "user32" _ (ByVal hHook As Long) As Long Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _ ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" _ (lpvDest As Any, ByVal lpvSource As Long, ByVal cbCopy As Long) Public hNxtHook As Long '''' handle of Hook Procedure Public msg As EVENTMSG
Sub EnableHook() hNxtHook = SetWindowsHookEx(0, AddressOf HookProc, App.hInstance, 0) End Sub Sub FreeHook() Dim ret As Long ret = UnhookWindowsHookEx(hNxtHook) End Sub Function HookProc(ByVal code As Long, ByVal wParam As Long, _ ByVal lParam As Long) As Long CopyMemory msg, lParam, Lenb(msg) If (msg.message >= WM_KEYFIRST _ And msg.message <= WM_KEYLAST) Then Debug.Print msg.message, msg.paramH End If HookProc = CallNextHookEx(hNxtHook, code, wParam, lParam) End Function ''''以下程式於Form1 Private Sub Form_Load() Call EnableHook End Sub
Private Sub Form_Unload(Cancel As Integer) Call FreeHook End Sub *****************************************************************************
详细的流程不多做说明,我们只把重点放在HookProc这个Hook Procedure,如果我 们查JournalRecord Hook的Hook Procedure可得定义如下:
----------------------------------------------------------------------------- LRESULT CALLBACK JournalRecordProc( int code, // hook code WPARAM wParam, // undefined LPARAM lParam // 为一个EVENTMSG Structure的address值 );
这个JournalRecordProc 对应到我们的HookProc便是
Function HookProc(ByVal code As Long, ByVal wParam As Long, _ ByVal lParam As Long) As Long
-------------------------------------------------------------上一页 [1] [2] [3] 下一页 |