感谢您使用微软产品。您可以调用 SetWindowsHookEx 函数来设置全局 Hook 来拦截相应的消息。关于 Win32 Hook 的用法,下面是一篇很好的文章:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn_hooks32.asp更多的信息,您可以查阅一下 SetWindowsHookEx 的用法。以下是两篇文章供您参考:http://support.microsoft.com/support/kb/articles/q81/3/32.asphttp://support.microsoft.com/support/kb/articles/q177/9/92.asp-微软全球技术中心  桌面产品技术支持 
本贴子以“现状”提供且没有任何担保,同时也没有授予任何权利。具体事项可参见使用条款(http://support.microsoft.com/directory/worldwide/zh-cn/community/terms_chs.asp)。为了为您创建更好的讨论环境,请参加我们的用户满意度调查(http://support.microsoft.com/directory/worldwide/zh-cn/community/survey.asp?key=(S,49854782))。

解决方案 »

  1.   


    给你一段代码,希望对你有帮助'In a module
    Public Const WH_KEYBOARD = 2
    Public Const VK_SHIFT = &H10
    Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
    Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
    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
    Public hHook As Long
    Public Function KeyboardProc(ByVal idHook As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        'if idHook is less than zero, no further processing is required
        If idHook < 0 Then
            'call the next hook
            KeyboardProc = CallNextHookEx(hHook, idHook, wParam, ByVal lParam)
        Else
            'check if SHIFT-S is pressed
            If (GetKeyState(VK_SHIFT) And &HF0000000) And wParam = Asc("S") Then
                'show the result
                Form1.Print "Shift-S pressed ..."
            End If
            'call the next hook
            KeyboardProc = CallNextHookEx(hHook, idHook, wParam, ByVal lParam)
        End If
    End Function'In a form, called Form1
    Private Sub Form_Load()
        'KPD-Team 2000
        'URL: http://www.allapi.net/
        'E-Mail: [email protected]
        'set a keyboard hook
        hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf KeyboardProc, App.hInstance, App.ThreadID)
    End Sub
    Private Sub Form_Unload(Cancel As Integer)
        'remove the windows-hook
        UnhookWindowsHookEx hHook
    End Sub
      

  2.   

    对于HOOK,我还是会的。我的问题是:我要拦截FORM1的KEYDOWN、FORM2的MOUSEDOWN、……,这些都是不定的,一般HOOK需要一个Public Function HookProc(ByVal idHook As Long, ByVal wParam As Long, ByVal lParam As Long),怎样用一个HookProc,实现对不同HOOK的分类处理,就是怎样判断消息是来自哪个窗体的。
      

  3.   

    Hook简介上Hook简介
     
    Hook这个东西有时令人又爱又怕,Hook是用来拦截系统某些讯息之用,例如说,我们想让系统不管在什麽地方只要按个Ctl-B便执行NotePad,或许您会使用Form的KeyPreview,设定为True,但在其他Process中按Ctl-B呢?那就没有用,这是就得设一个Keyboard Hook来拦截所有Key in的键;再如:MouseMove的Event只在该Form或Control上有效,如果希望在Form的外面也能得知Mouse Move的讯息,那只好使用Mouse Hook来栏截Mouse的讯息。再如:您想记录方才使用者的所有键盘动作或Mosue动作,以便录巨集,那就使用JournalRecordHook,如果想停止所有Mosue键盘的动作,而放(执行)巨集,那就使用JournalPlayBack Hook;Hook呢,可以是整个系统为范围(Remote Hook),即其他Process的动作您也可以拦截,也可以是LocalHook,它的拦截范围只有Process本身。Remote Hook的Hook Function要在.Dll之中,Local Hook则在.Bas中。在VB如何设定Hook呢?使用SetWindowsHookEx()
     
    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
     
    idHook代表是何种Hook,有以下几种
        Public Const WH_CALLWNDPROC = 4
        Public Const WH_CALLWNDPROCRET = 12
        Public Const WH_CBT = 5
        Public Const WH_DEBUG = 9
        Public Const WH_FOREGROUNDIDLE = 11
        Public Const WH_GETMESSAGE = 3
        Public Const WH_HARDWARE = 8
        Public Const WH_JOURNALPLAYBACK = 1
        Public Const WH_JOURNALRECORD = 0
        Public Const WH_KEYBOARD = 2
        Public Const WH_MOUSE = 7
        Public Const WH_MSGFILTER = (-1)
        Public Const WH_SHELL = 10
        Public Const WH_SYSMSGFILTER = 6
     
    lpfn代表Hook Function所在的Address,这是一个CallBack Fucnction,当挂上某个Hook时,我们便得定义一个Function来当作某个讯息产生时,来处理它的Function,这个Hook Function有一定的叁数格式
     
        Private Function HookFunc(ByVal nCode As Long, _
                                ByVal wParam As Long, _
                                ByVal lParam As Long ) As Long
     
            nCode 代表是什麽请况之下所产生的Hook,随Hook的不同而有不同组的可能值。
            wParam lParam 传回值则随Hook的种类和nCode的值之不同而不同。
        因这个叁数是一个 Function的Address所以我们固定将Hook Function放在.Bas中,并以AddressOf HookFunc传入。至於Hook Function的名称我们可以任意给定,不一定叫 HookFunc
     
    hmod 代表.DLL的hInstance,如果是Local Hook,该值可以是Null(VB中可传0进去),而如果是Remote Hook,则可以使用GetModuleHandle(".dll名称")来传入。
     
    dwThreadId 代表执行这个Hook的ThreadId,如果不设定是那个Thread来做,则传0(所以一般来说,Remote Hook传0进去),而VB的Local Hook一般可传App.ThreadId进去。
     
    值回值 如果SetWindowsHookEx()成功,它会传回一个值,代表目前的Hook的Handle,这个值要记录下来。
     
    因为A程式可以有一个System Hook(Remote Hook),如KeyBoard Hook,而B程式也来设一个Remote的KeyBoard Hook,那麽到底KeyBoard的讯息谁所拦截?答案是,最後的那一个所拦截,也就是说A先做keyboard Hook,而後B才做,那讯息被B拦截,那A呢?就看B的Hook Function如何做。如果B想让A的Hook Function也得这个讯息,那B就得呼叫CallNextHookEx()将这讯息Pass给A,於是产生Hook的一个连线。如果B中不想Pass这讯息给A,那就不要呼叫CallNextHookEx()。
     
    Declare Function CallNextHookEx Lib "user32" Alias "CallNextHookEx" _
            (ByVal hHook As Long, _
            ByVal ncode As Long, _
            ByVal wParam As Long, _
            lParam As Any) As Long
     
    hHook值是SetWindowsHookEx()的传回值,nCode, wParam, lParam则是Hook Procedure中的三个叁数。
     
    最後是将这Hook去除掉,请呼叫UnHookWindowHookEx()
     
    Declare Function UnhookWindowsHookEx Lib "user32" Alias "UnhookWindowsHookEx"  _
            (ByVal hHook As Long) As Long
     
    hHook便是SetWindowsHookEx()的传回值。此时,以上例来说,B程式结束Hook,则换A可以直接拦截讯息。
           以上代码来自: 源代码数据库(SourceDataBase)
               复制时间: 2002-04-13 19:17:42
               当前版本: 1.0.580
                   作者: Shawls
               个人主页: Http://Shawls.Yeah.Net
                 E-Mail: [email protected]
                     QQ: 9181729
    Hook简介下KeyBoard Hook的范例
     
    Hook Function的三个叁数
     
    nCode        wParam                     lParam            传回值
    ===========  ========================== ==============    ================
    HC_ACTION    表按键Virtual Key          与WM_KEYDOWN同  若讯息要被处理传0
    或                                                        反之传1
    HC_NOREMOVE
     
     
    Public hHook as Long
     
    Public Sub UnHookKBD()
    If hnexthookproc <> 0 Then
        UnhookWindowsHookEx hHook
        hHook = 0
    End If
    End Sub
     
    Public Function EnableKBDHook()
    If hHook <> 0 Then
        Exit Function
    End If
    hhook = SetWindowsHookEx(WH_KEYBOARD, AddressOf _
                MyKBHFunc, App.hInstance, App.ThreadId)
    End Function
     
    Public Function MyKBHFunc(ByVal iCode As Long, _
        ByVal wParam As Long, ByVal lParam As Long) As Long
      MyKBHfunc = 0 '表示要处理这个讯息
     
      If wParam = vbKeySnapshot Then  '侦测 有没有按到PrintScreen键
        MyKBHFunc = 1 '在这个Hook便吃掉这个讯息
      End If
      Call CallNextHookEx(hHook, iCode, wParam, lParam) '传给下一个Hook
    End Function
     
    至于其他的 Hook的详细资料与nCode,wParam, lParam的意义,请查Win32 Help或Windows 95: A Developer's Guide (Jeffrey Richter著)(中译本:基峰 李书良译 侯俊杰总监 Windows95程式设计指南)
           以上代码来自: 源代码数据库(SourceDataBase)
               复制时间: 2002-04-13 19:17:51
               当前版本: 1.0.580
                   作者: Shawls
               个人主页: Http://Shawls.Yeah.Net
                 E-Mail: [email protected]
                     QQ: 9181729
      

  4.   

    HOOKS说明书上hook是WINDOWS提供的一种消息处理机制,它使得程序员可以使用子过程来监视系统消息,并在消息到达目标过程前得到处理。 
    下面将介绍WINNDOWS HOOKS并且说明如何在WINDOWS 程序中使用它。 关于HOOKS 
    使用HOOK 将会降低系统效率,因为它增加了系统处量消息的工作量。建议在必要时才使用HOOK,并在消息处理完成后立即移去该HOOK。 
    HOOK链 
    WINDOWS提供了几种不同类型的HOOKS;不同的HOOK可以处理不同的消息。例如,WH_MOUSE HOOK用来监视鼠标消息。 
    WINDOWS为这几种HOOKS维护着各自的HOOK链。HOOK链是一个由应用程序定义的回调函数队列,当某种类型的消息发生时,WINDOWS向此种类型的HOOK链的第一个函数发送该消息,在第一函数处理完该消息后由该函数向链表中的下一个函数传递消息,依次向下。如果链中某个函数没有向下传送该消息,那么链表中后面的函数将得不到此消息。(对于某些类型的HOOK,不管HOOK链中的函数是否向下传递消息,与此类型HOOK联系的所有HOOK函数都会收到系统发送的消息) 
    HOOK过程 
    为了拦截特定的消息,你可以使用SetWindowsHookEx函数在该类型的HOOK链中安装你自己的HOOK函数。该函数语法如下: 
    public function MyHook(nCode,wParam,iParam) as long 
    ‘加入代码 
    end function 
    其中MyHook可以随便命名,其它不能变。该函数必须放在模块段。nCode指定HOOK类型。wParam,iParam的取值随nCode不同而不同,它代表了某种类型的HOOK的某个特定的动作。 
    SetWindowsHookEx总是将你的HOOK函数放置在HOOK链的顶端。你可以使用CallNextHookEx函数将系统消息传递给HOOK链中的下一个函数。 
    [注释]对于某些类型的HOOK,系统将向该类的所有HOOK函数发送消息,这时,HOOK函数中的CallNextHookEx语句将被忽略。 
    全局HOOK函数可以拦截系统中所有线程的某个特定的消息(此时该HOOK函数必须放置在DLL中),局部HOOK函数可以拦截指定线程的某特定消息(此时该HOOK函数可以放置在DLL中,也可以放置在应用程序的模块段)。 
    [注释] 建议只在调试时使用全局HOOK函数。全局HOOK函数将降低系统效率,并且会同其它使用该类HOOK的应用程序产生冲突。 
           以上代码来自: 源代码数据库(SourceDataBase)
               复制时间: 2002-04-13 19:18:06
               当前版本: 1.0.580
                   作者: Shawls
               个人主页: Http://Shawls.Yeah.Net
                 E-Mail: [email protected]
                     QQ: 9181729
    HOOKS说明书下HOOK类型 
    WH_CALLWNDPROC 和 WH_CALLWNDPROCRET HOOK 
    WH_C ALLWNDPROC 和WH_CALLWNDPROCRET HOOK可以监视SendMessage发送的消息。系统在向窗体过程发送消息前,将调用WH_CALLWNDPROC;在窗体过程处理完该消息后系统将调用WH_CALLWNDPROCRET。 
    WH_CALLWNDPROCRET HOOK会向HOOK过程传送一个CWPRETSTRUCT结构的地址。该结构包含了窗体过程处理系统消息后的一些信息。 
    WH_CBT Hook 
    系统在激活,创建,消毁,最小化,最大化,移动,改变窗体前;在完成一条系统命令前;在从系统消息队列中移去鼠标或键盘事件前;在设置输入焦点前,或同步系统消息队列前,将调用WH_CBT HOOK。你可以在你的HOOK 过程拦截该类HOOK,并返回一个值,告诉系统,是否继续执行上面的操作。 
    WH_DEBUG HOOK 
    系统在调用与某种HOOK类型联系的HOOK过程前,将调用WH_DEBUG ,应用程序可以使用该HOOK决定是否让系统执行某种类型的HOOK。 
    WH_FOREGROUNDIDLE Hook 
    系统在空闲时调用该HOOK,在后台执行优先权较低的应用程序。 
    WH_GETMESSAGE Hook 
    WH_GETMESSAGE Hook使应用程序可以拦截GetMessage 或 PeekMessage的消息。应用程序使用WH_GETMESSAGE HOOK监视鼠标、键盘输入和发送到队列中的其它消息。 
    WH_JOURNALRECORD Hook 
    WH_JOURNALRECORD Hook使应用程序可以监视输入事件。典型地,应用程序使用该HOOK记录鼠标、键盘输入事件以供以后回放。该HOOK是全局HOOK,并且不能在指定线程中使用。 
    WH_JOURNALPLAYBACK Hook 
    ` WH_JOURNALPLAYBACK Hook使应用程序可以向系统消息队列中插入消息。该HOOK可以回放以前由WH_JOURNALRECORD HOOK录制的鼠标、键盘输入事件。在WH_JOURNALPLAYBACK Hook安装到系统时,鼠标、键盘输入事件将被屏蔽。该HOOK同样是一个全局HOOK,不能在指定线程中使用。 
    WH_JOURNALPLAYBACK Hook返回一个时间暂停值,它告诉系统,在处理当前回放的消息时,系统等待百分之几秒。这使得此HOOK可以控制在回放时的时间事件。 
    WH_KEYBOARD Hook 
    WH_KEYBOARD Hook使应用程序可以监视由GetMessage和PeekMessage返回的WM_KEYDOWN 及WM_KEYUP消息。应用程序使用该HOOK监视发送到消息队列中的键盘输入。 
    WH_MOUSE Hook 
    WH_MOUSE Hook 使应用程序可以监视由GetMessage和PeekMessage返回的消息。应用程序使用该HOOK监视发送到消息队列中的鼠标输入。 
    WH_MSGFILTER and WH_SYSMSGFILTER Hooks 
    WH_MSGFILTER 和WH_SYSMSGFILTER Hooks使应用程序可以监视菜单、滚动条、消息框、对话框,当用户使用ALT+TAB或ALT+ESC来切换窗体时,该HOOK也可以拦截到消息。WH_MSGFILTER仅在应用程序内部监视菜单、滚动条、消息框、对话框,而WH_SYSMSGFILTER则可以在系统内监视所有应用程序的这些事件。 
    WH_SHELL Hook 
    一个SHELL程序可以使用WH_SHELL Hook来接收重要的信息。当一个SHELL程序被激活前或当前窗体被创建、消毁时,系统会调用WH_SHELL Hook过程。 
    使用HOOK 
    安装、消毁HOOK过程 
    监视系统事件 安装、消毁HOOK过程 
    使用SetWindowsHookEx函数,指定一个HOOK类型,自己的HOOK过程是全局还是局部HOOK,同时给出HOOK过程的进入点,就可以轻松的安装你自己的HOOK过程。 
    为了安装一个全局HOOK过程,必须在应用程序外建立一个DLL,并将该HOOK函数封装到其中,应用程序在安装全局HOOK过程时必须先得到该DLL模块的句柄。将DLL名传递给LoadLibrary 函数,就会得到该DLL模块的句柄;得到该句柄 后,使用GetProcAddress函数可以得到HOOK过程的地址。最后,使用SetWindowsHookEx将HOOK过程的首址嵌入相应的HOOK链中,SetWindowsHookEx传递一个模块句柄,它为HOOK过程的进入点,线程标识符置为0,指出:该HOOK过程同系统中的所有线程关联。 
    以下是C写的例程,大家可以方便的转换为VB程序。 
    HOOKPROC hkprcSysMsg; 
    static HINSTANCE hinstDLL; 
    static HHOOK hhookSysMsg; 


    . hinstDLL = LoadLibrary((LPCTSTR) "c:\\windows\\sysmsg.dll"); 
    hkprcSysMsg = (HOOKPROC)GetProcAddress(hinstDLL, "SysMessageProc"); 
    hhookSysMsg = SetWindowsHookEx(WH_SYSMSGFILTER, 
    hkprcSysMsg, hinstDLL, 0); 
           以上代码来自: 源代码数据库(SourceDataBase)
               复制时间: 2002-04-13 19:18:26
               当前版本: 1.0.580
                   作者: Shawls
               个人主页: Http://Shawls.Yeah.Net
                 E-Mail: [email protected]
                     QQ: 9181729
      

  5.   

    ******************************************************
    这是我写的一个ActiveX Control的源码.
    为了屏蔽text控件的右键弹出菜单,重写了控件的窗口过程,拦截消息做相应处理.
    特点是把所有的控件实例的窗口过程都指向这一个过程.
    实现方法--在重写窗品过程时把窗品的ObjPtr(Me)写在了窗品的GWL_USERDATA中,
    在窗口过程中读取并判断,再调用相应的过程就可以了.
    ******************************************************
    *********************************
    模块代码
    *********************************Option ExplicitPublic Declare Sub CopyMemory _
       Lib "kernel32" Alias "RtlMoveMemory" _
          (pDest As Any, _
          pSrc As Any, _
          ByVal ByteLen As Long)Public Declare Function SetWindowLong _
       Lib "user32" Alias "SetWindowLongA" _
          (ByVal hWnd As Long, _
          ByVal nIndex As Long, _
          ByVal dwNewLong As Long) As LongPublic Declare Function GetWindowLong _
       Lib "user32" Alias "GetWindowLongA" _
          (ByVal hWnd As Long, _
          ByVal nIndex As Long) As LongPublic 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
    Public Const GWL_WNDPROC = (-4)
    Public Const GWL_USERDATA = (-21)Dim ctlShadowControl As TextEx
    Dim ptrObject As LongPublic Function SubWndProc( _
       ByVal hWnd As Long, _
       ByVal Msg As Long, _
       ByVal wParam As Long, _
       ByVal lParam As Long) As Long   On Error Resume Next   ptrObject = GetWindowLong(hWnd, GWL_USERDATA)
       CopyMemory ctlShadowControl, ptrObject, 4
       SubWndProc = ctlShadowControl.WindowProc(hWnd, Msg, wParam, lParam)
       CopyMemory ctlShadowControl, 0&, 4
       Set ctlShadowControl = Nothing
    End Function************************************
    usercontrol代码
    ************************************
    Option ExplicitPrivate mWndProcOrg As LongPrivate mHWndSubClassed As LongPrivate Const WM_MOUSEACTIVATE = &H21Const m_def_CanPopup = 0
    Dim m_CanPopup As BooleanPrivate Sub SubClass()
        If mWndProcOrg Then Exit Sub
       
        mWndProcOrg = SetWindowLong(txtEx.hWnd, GWL_WNDPROC, AddressOf SubWndProc)
        mHWndSubClassed = txtEx.hWnd
        Call SetWindowLong(mHWndSubClassed, GWL_USERDATA, ObjPtr(Me))
    End SubPrivate Sub UnSubClass()
        If mWndProcOrg = 0 Then Exit Sub
        
        SetWindowLong mHWndSubClassed, GWL_WNDPROC, mWndProcOrg
        mWndProcOrg = 0
    End SubFriend Function WindowProc(ByVal hWnd As Long, _
                               ByVal uMsg As Long, _
                               ByVal wParam As Long, _
                               ByVal lParam As Long) As Long
        If (Not (uMsg = 516)) Or (m_CanPopup) Then
            WindowProc = CallWindowProc(mWndProcOrg, hWnd, uMsg, wParam, ByVal lParam)
        End If
    End FunctionPrivate Sub UserControl_Initialize()
        txtEx.Top = 0
        txtEx.Left = 0
        SubClass
    End SubPrivate Sub UserControl_Resize()
        txtEx.Width = UserControl.Width
        txtEx.Height = UserControl.Height
    End SubPrivate Sub UserControl_Terminate()
        UnSubClass
    End SubPublic Property Get CanPopup() As Boolean
        CanPopup = m_CanPopup
    End PropertyPublic Property Let CanPopup(ByVal New_CanPopup As Boolean)
        m_CanPopup = New_CanPopup
        PropertyChanged "CanPopup"
    End PropertyPrivate Sub UserControl_InitProperties()
        m_CanPopup = m_def_CanPopup
    End SubPrivate Sub UserControl_ReadProperties(PropBag As PropertyBag)    m_CanPopup = PropBag.ReadProperty("CanPopup", m_def_CanPopup)
        txtEx.Locked = PropBag.ReadProperty("Locked", False)
    End SubPrivate Sub UserControl_WriteProperties(PropBag As PropertyBag)    Call PropBag.WriteProperty("CanPopup", m_CanPopup, m_def_CanPopup)
        Call PropBag.WriteProperty("Locked", txtEx.Locked, False)
    End SubPublic Property Get Locked() As Boolean
        Locked = txtEx.Locked
    End PropertyPublic Property Let Locked(ByVal New_Locked As Boolean)
        txtEx.Locked() = New_Locked
        PropertyChanged "Locked"
    End Property