VB與Windows API 間的呼叫技巧 (入门必看)[5]

[入库:2005年8月18日] [更新:2007年3月24日]

本文简介:选择自 turbochen 的 blog

        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,  _

本文关键:API,
  相关方案
Google
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top