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
-----------------------------------------------------------------------------
有沒有注意到第三個參數它是一個 byval的long,指的是存放某一個eventmsg的位址,而先前我們提過,自定型慴的參數傳遞要使用byref的方式才能解泀,天啊!它用byval的方式來做,如果是c誾言,那不成問題,只要如下:
-----------------------------------------------------------------------------
eventmsg *p;
p = (eventmsg *) lparam;
-----------------------------------------------------------------------------
如此便可以用 *p->message 之方式來取得內容,但vb呢?這裡便要用些小技巧了,試想,如果我們能依lparam所指的位址,一個byte一個byte的copy到一個eventmsg的變數上面,不就可以了嗎?所以了, copymomory這個函式派上用場了,但是 copymomory的原始宣告如下,前面兩個參數都是byref的方式,但目前對我們有的是lparam的內容(假詏是lparam = 25600, address of lparam = 100100),如果我們使用底下的宣告,而去呼叫
-- 宣告一 ----------------------------------------------------------------------
declare sub copymemory lib "kernel32" alias "rtlmovememory" ( _
lpvdest as any, lpvsource as any, byval cbcopy as long)
copymomory msg , lparam, lenb(msg)
-----------------------------------------------------------------------------
那黱winapi rtlmovememory會得到第二個參數值=100100,而使指標指到100100的位址,那黱就得不到想要的賧料了 (因賧料在25600的位址上)。所以我們改變原始宣告,將之變成宣告二的樣子,如此vb 第二個參數的作法會傳出25600(因為byval嘛)給rtlmovememory,那不就成功了嗎?
----宣告二 ---------------------------------------------------------------------
declare sub copymemory lib "kernel32" alias "rtlmovememory" ( _
lpvdest as any, byval lpvsource as long, byval cbcopy as long)
copymomory msg , lparam, lenb(msg)
-----------------------------------------------------------------------------
或詓這rtlmovememory您在詓多地方都會用上,前兩個參數時而要byref, 時而需byval,那是否就要定義四個宣告來因應不同之需,其實也不用,上面的例子中,只要宣告成宣告一的樣子,但是呼叫時改成:
copymemory msg, byval lparam, lenb(msg)
在第二個參數前加上byval這樣這可以了啦。
這裡還有另外一個做法,那就是從hook procedure的宣告著手,別忘了,hook procedure是window所呼叫的,所以它傳給我們定義的hookproc()時,第三個參數以先前的舉例來說便是傳入25600,那黱,我們將hookproc()改定義成:
-----------------------------------------------------------------------------
function hookproc(byval code as long, byval wparam as long, _