经常在论坛中看到HOOK一说,知道它是比较高深的东西,兄弟不才,想窥其一二,百度几次,没有得到好的答案。所以发帖请教各位高手!HOOK到底是怎么一回事?!

解决方案 »

  1.   

    兄弟,这里写的挺清楚啊
    http://baike.baidu.com/view/107096.htm写一段代码测一下你就明白了
      

  2.   

    这个说得挺详细的,希望有帮助
    虽然我自己也不怎么懂
    http://www.vbaccelerator.com/home/Vb/Code/Libraries/Hooks/vbAccelerator_Hook_Library/article.asp
      

  3.   

    vb写不了系统级hook只能写写键盘钩子apihook完成不了
      

  4.   

    VB要做其它类型HOOK,总需要辅助手段,比如用别的语言写DLL,或者内嵌汇编之类....
      

  5.   

    今天学习了下,有俩问题:
    1、我用鼠标左键点中窗体的标题栏,拖动窗体,会产生什么系统消息?
    2、请大家帮我解释一下这些消息的意思:
       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_KEYBOARD_LL = 13
    Public Const WH_MAX = 11
    Public Const WH_MAXHOOK = WH_MAX
    Public Const WH_MIN = (-1)
    Public Const WH_MINHOOK = WH_MIN
    Public Const WH_MOUSE = 7
    Public Const WH_MOUSE_LL = 14
    Public Const WH_MSGFILTER = (-1)
    Public Const WH_SHELL = 10
    Public Const WH_SYSMSGFILTER = 6
      

  6.   

    //钩子类型 idHook 选项:
    WH_MSGFILTER       = -1; {线程级; 截获用户与控件交互的消息}
    WH_JOURNALRECORD   = 0; {系统级; 记录所有消息队列从消息队列送出的输入消息, 在消息从队列中清除时发生; 可用于宏记录}
    WH_JOURNALPLAYBACK = 1; {系统级; 回放由 WH_JOURNALRECORD 记录的消息, 也就是将这些消息重新送入消息队列}
    WH_KEYBOARD        = 2; {系统级或线程级; 截获键盘消息}
    WH_GETMESSAGE      = 3; {系统级或线程级; 截获从消息队列送出的消息}
    WH_CALLWNDPROC     = 4; {系统级或线程级; 截获发送到目标窗口的消息, 在 SendMessage 调用时发生}
    WH_CBT             = 5; {系统级或线程级; 截获系统基本消息, 譬如: 窗口的创建、激活、关闭、最大最小化、移动等等}
    WH_SYSMSGFILTER    = 6; {系统级; 截获系统范围内用户与控件交互的消息}
    WH_MOUSE           = 7; {系统级或线程级; 截获鼠标消息}
    WH_HARDWARE        = 8; {系统级或线程级; 截获非标准硬件(非鼠标、键盘)的消息}
    WH_DEBUG           = 9; {系统级或线程级; 在其他钩子调用前调用, 用于调试钩子}
    WH_SHELL           = 10; {系统级或线程级; 截获发向外壳应用程序的消息}
    WH_FOREGROUNDIDLE = 11; {系统级或线程级; 在程序前台线程空闲时调用}
    WH_CALLWNDPROCRET = 12; {系统级或线程级; 截获目标窗口处理完毕的消息, 在 SendMessage 调用后发生}
      

  7.   

    常用的Hook类型: 1、WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks 
          WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks使你可以监视发送到窗口过程的消息。系统在消息发送到接收窗口过程之前调用WH_CALLWNDPROC Hook子程,并且在窗口过程处理完消息之后调用WH_CALLWNDPROCRET Hook子程。
          WH_CALLWNDPROCRET Hook传递指针到CWPRETSTRUCT结构,再传递到Hook子程。CWPRETSTRUCT结构包含了来自处理消息的窗口过程的返回值,同样也包括了与这个消息关联的消息参数。 2、WH_CBT Hook 
          在以下事件之前,系统都会调用WH_CBT Hook子程,这些事件包括: 
        1. 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件; 
        2. 完成系统指令; 
        3. 来自系统消息队列中的移动鼠标,键盘事件; 
        4. 设置输入焦点事件; 
        5. 同步系统消息队列事件。 
    Hook子程的返回值确定系统是否允许或者防止这些操作中的一个。 3、WH_DEBUG Hook 
          在系统调用系统中与其他Hook关联的Hook子程之前,系统会调用WH_DEBUG Hook子程。你可以使用这个Hook来决定是否允许系统调用与其他Hook关联的Hook子程。 4、WH_FOREGROUNDIDLE Hook 
          当应用程序的前台线程处于空闲状态时,可以使用WH_FOREGROUNDIDLE Hook执行低优先级的任务。当应用程序的前台线程大概要变成空闲状态时,系统就会调用WH_FOREGROUNDIDLE Hook子程。 5、WH_GETMESSAGE Hook 
          应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函数返回的消息。你可以使用WH_GETMESSAGE Hook去监视鼠标和键盘输入,以及其他发送到消息队列中的消息。 6、WH_JOURNALPLAYBACK Hook 
          WH_JOURNALPLAYBACK Hook使应用程序可以插入消息到系统消息队列。可以使用这个Hook回放通过使用WH_JOURNALRECORD Hook记录下来的连续的鼠标和键盘事件。只要WH_JOURNALPLAYBACK Hook已经安装,正常的鼠标和键盘事件就是无效的。
          WH_JOURNALPLAYBACK Hook是全局Hook,它不能象线程特定Hook一样使用。       WH_JOURNALPLAYBACK Hook返回超时值,这个值告诉系统在处理来自回放Hook当前消息之前需要等待多长时间(毫秒)。这就使Hook可以控制实时事件的回放。
          WH_JOURNALPLAYBACK是system-wide local hooks,它們不會被注射到任何行程位址空間。(估计按键精灵是用这个hook做的) 7、WH_JOURNALRECORD Hook 
          WH_JOURNALRECORD Hook用来监视和记录输入事件。典型的,可以使用这个Hook记录连续的鼠标和键盘事件,然后通过使用WH_JOURNALPLAYBACK Hook来回放。
          WH_JOURNALRECORD Hook是全局Hook,它不能象线程特定Hook一样使用。
          WH_JOURNALRECORD是system-wide local hooks,它們不會被注射到任何行程位址空間。 8、WH_KEYBOARD Hook 
          在应用程序中,WH_KEYBOARD Hook用来监视WM_KEYDOWN and WM_KEYUP消息,这些消息通过GetMessage or PeekMessage function返回。可以使用这个Hook来监视输入到消息队列中的键盘消息。 9、WH_KEYBOARD_LL Hook 
          WH_KEYBOARD_LL Hook监视输入到线程消息队列中的键盘消息。 10、WH_MOUSE Hook 
            WH_MOUSE Hook监视从GetMessage 或者 PeekMessage 函数返回的鼠标消息。使用这个Hook监视输入到消息队列中的鼠标消息。 11、WH_MOUSE_LL Hook 
            WH_MOUSE_LL Hook监视输入到线程消息队列中的鼠标消息。 12、WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks 
            WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。
            WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通过安装了Hook子程的应用程序建立的对话框的消息。
            WH_SYSMSGFILTER Hook监视所有应用程序消息。
            WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式循环期间过滤消息,这等价于在主消息循环中过滤消息。通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。通过使用这个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循环里一样。 13、WH_SHELL Hook 
            外壳应用程序可以使用WH_SHELL Hook去接收重要的通知。当外壳应用程序是激活的并且当顶层窗口建立或者销毁时,系统调用WH_SHELL Hook子程。 
            WH_SHELL 共有5钟情況: 
            1. 只要有个top-level、unowned 窗口被产生、起作用、或是被摧毁; 
            2. 当Taskbar需要重画某个按钮; 
            3. 当系统需要显示关于Taskbar的一个程序的最小化形式; 
            4. 当目前的键盘布局状态改变; 
            5. 当使用者按Ctrl+Esc去执行Task Manager(或相同级别的程序)。 
            按照惯例,外壳应用程序都不接收WH_SHELL消息。所以,在应用程序能够接收WH_SHELL消息之前,应用程序必须调用SystemParametersInfo function注册它自己。 
      

  8.   

    ......
    simon_sun这一刻你不是一个人!你是一个神!我太崇拜你了!!!
      

  9.   

    如果这样:有进程A和进程B,A中有一个文本框,当鼠标点击它时,它获得焦点,我想在B中通过HOOK函数来取得它的句柄,该用什么消息来监视?API函数GetFocus可以取得拥有光标的控件的句柄,我用WH_MOUSE消息、WH_CBT消息试验了一下都没有成功。希望高手指点我一下。
      

  10.   

    如果是鼠标点击哪个文本框获得焦点,可以HOOK这个:WH_MOUSE_LL 
      

  11.   

    不同进程间,怎么设置SetWindowsHookEx的参数?也就是该函数的最后两个参数怎么设置?我现在只能完成同一进程中的。
      

  12.   

     如果要设置系统级钩子, 钩子函数必须在 DLL 中. 
    --------------------------------------------------------------------------------SetWindowsHookEx(
      idHook: Integer;   {钩子类型}
      lpfn: TFNHookProc; {函数指针}
      hmod: HINST;       {包含钩子函数的模块(EXE、DLL)句柄; 一般是 HInstance; 如果是当前线程这里可以是 0}
      dwThreadId: DWORD  {关联的线程; 可用 GetCurrentThreadId 获取当前线程; 0 表示是系统级钩子}
    ): HHOOK;            {返回钩子的句柄; 0 表示失败}//钩子类型 idHook 选项:
    WH_MSGFILTER       = -1; {线程级; 截获用户与控件交互的消息}
    WH_JOURNALRECORD   = 0;  {系统级; 记录所有消息队列从消息队列送出的输入消息, 在消息从队列中清除时发生; 可用于宏记录}
    WH_JOURNALPLAYBACK = 1;  {系统级; 回放由 WH_JOURNALRECORD 记录的消息, 也就是将这些消息重新送入消息队列}
    WH_KEYBOARD        = 2;  {系统级或线程级; 截获键盘消息}
    WH_GETMESSAGE      = 3;  {系统级或线程级; 截获从消息队列送出的消息}
    WH_CALLWNDPROC     = 4;  {系统级或线程级; 截获发送到目标窗口的消息, 在 SendMessage 调用时发生}
    WH_CBT             = 5;  {系统级或线程级; 截获系统基本消息, 譬如: 窗口的创建、激活、关闭、最大最小化、移动等等}
    WH_SYSMSGFILTER    = 6;  {系统级; 截获系统范围内用户与控件交互的消息}
    WH_MOUSE           = 7;  {系统级或线程级; 截获鼠标消息}
    WH_HARDWARE        = 8;  {系统级或线程级; 截获非标准硬件(非鼠标、键盘)的消息}
    WH_DEBUG           = 9;  {系统级或线程级; 在其他钩子调用前调用, 用于调试钩子}
    WH_SHELL           = 10; {系统级或线程级; 截获发向外壳应用程序的消息}
    WH_FOREGROUNDIDLE  = 11; {系统级或线程级; 在程序前台线程空闲时调用}
    WH_CALLWNDPROCRET  = 12; {系统级或线程级; 截获目标窗口处理完毕的消息, 在 SendMessage 调用后发生}事实上除非你使用一些特殊手段vb能完成的hook只有键盘鼠标钩子,而跨进程的其他类型钩子,则无法完成因为通常情况下vb生成的不是动态dll
      

  13.   

    我的就是捕获鼠标消息,只是跨进程的而已,没有办法吗?
    我认为问题的关键在于:
    hmod: HINST;      {包含钩子函数的模块(EXE、DLL)句柄; 一般是 HInstance; 如果是当前线程这里可以是 0} 
      dwThreadId: DWORD  {关联的线程; 可用 GetCurrentThreadId 获取当前线程; 0 表示是系统级钩子} 这两个参数的设置。我就是这个问题没有解决。
      

  14.   

    这个是网上流传的鼠标键盘钩子Private sub AddHook()
      '键盘钩子
      lHook(0) = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf CallKeyHookProc, App.hInstance, 0)
      '鼠标钩子
      lHook(1) = SetWindowsHookEx(WH_MOUSE_LL, AddressOf CallMouseHookProc, App.hInstance, 0)
    End Sub
    '卸钩子
    Private sub DelHook()
      UnhookWindowsHookEx lHook(0)
      UnhookWindowsHookEx lHook(1)
    End Sub
    '---------------------------------
    '模块
    Public 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
    Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
    Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
    Public Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
    Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, ByVal lpvSource As Long, ByVal cbCopy As Long)
    Public Type KEYMSGS
           vKey As Long          '虚拟码  (and &HFF)
           sKey As Long          '扫描码
           flag As Long          '键按下:128 抬起:0
           time As Long          'Window运行时间
    End Type
    Public Type MOUSEMSGS
           X As Long            'x座标
           Y As Long            'y座标
           a As Long
           b As Long
           time As Long         'Window运行时间
    End Type
    Public Type POINTAPI
        X As Long
        Y As Long
    End Type
    Public Const WH_KEYBOARD_LL = 13
    Public Const WH_MOUSE_LL = 14
    Public Const Alt_Down = &H20
    '-----------------------------------------
    '消息
    Public Const HC_ACTION = 0
    Public Const HC_SYSMODALOFF = 5
    Public Const HC_SYSMODALON = 4
    '键盘消息
    Public Const WM_KEYDOWN = &H100
    Public Const WM_KEYUP = &H101
    Public Const WM_SYSKEYDOWN = &H104
    Public Const WM_SYSKEYUP = &H105
    '鼠标消息
    Public Const WM_MOUSEMOVE = &H200
    Public Const WM_LBUTTONDOWN = &H201
    Public Const WM_LBUTTONUP = &H202
    Public Const WM_LBUTTONDBLCLK = &H203
    Public Const WM_RBUTTONDOWN = &H204
    Public Const WM_RBUTTONUP = &H205
    Public Const WM_RBUTTONDBLCLK = &H206
    Public Const WM_MBUTTONDOWN = &H207
    Public Const WM_MBUTTONUP = &H208
    Public Const WM_MBUTTONDBLCLK = &H209
    Public Const WM_MOUSEACTIVATE = &H21
    Public Const WM_MOUSEFIRST = &H200
    Public Const WM_MOUSELAST = &H209
    Public Const WM_MOUSEWHEEL = &H20A
    Public Declare Function GetKeyNameText Lib "user32" Alias "GetKeyNameTextA" (ByVal lParam As Long, ByVal lpBuffer As String, ByVal nSize As Long) As Long
    Public strKeyName As String * 255
    Public Declare Function GetActiveWindow Lib "user32" () As Long
    Public keyMsg As KEYMSGS
    Public MouseMsg As MOUSEMSGS
    Public lHook(1) As Long
    '----------------------------------------
    '模拟鼠标
    Private Const MOUSEEVENTF_LEFTDOWN = &H2
    Private Const MOUSEEVENTF_LEFTUP = &H4
    Private Const MOUSEEVENTF_ABSOLUTE = &H8000 '  absolute move
    Private Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)
    Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
    '--------------------------------------
    '模拟按键
    Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
    '鼠标钩子    
    Public Function CallMouseHookProc(ByVal code As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        Dim pt As POINTAPI    If code = HC_ACTION Then
          CopyMemory MouseMsg, lParam, LenB(MouseMsg)
          
          Form1.txtMsg(1).Text = "X=" + Str(MouseMsg.X) + " Y=" + Str(MouseMsg.Y)
          Form1.txtHwnd(1) = Format(wParam, "0")
          
          If wParam = WM_MBUTTONDOWN Then                      '把中键改为左键
               mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
               CallMouseHookProc = 1
          End If
          
          If wParam = WM_MBUTTONUP Then
              mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
              CallMouseHookProc = 1
          End If
            
        End If
        
        If code <> 0 Then
          CallMouseHookProc = CallNextHookEx(0, code, wParam, lParam)
        End If
      
    End Function
    '键盘钩子
    Public Function CallKeyHookProc(ByVal code As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        Dim lKey As Long
        Dim strKeyName As String * 255
        Dim strLen As Long
       
        If code = HC_ACTION Then
          CopyMemory keyMsg, lParam, LenB(keyMsg)
          Select Case wParam
            Case WM_SYSKEYDOWN, WM_KEYDOWN, WM_SYSKEYUP, WM_KEYUP:
            
                 
                lKey = keyMsg.sKey And &HFF           '扫描码
                lKey = lKey * 65536
                strLen = GetKeyNameText(lKey, strKeyName, 250)
                Form1.txtMsg(0).Text = "键名:" + Left(strKeyName, strLen) + " 虚拟码:" + Format(keyMsg.vKey And &HFF, "0") + " 扫描码:" + Format(lKey / 65536, "0")
                
                Form1.txtHwnd(0) = ""
                If (GetKeyState(vbKeyControl) And &H8000) Then
                   Form1.txtHwnd(0) = Form1.txtHwnd(0) + "Ctrl "
                End If
                
                If (keyMsg.flag And Alt_Down) <> 0 Then
                   Form1.txtHwnd(0) = Form1.txtHwnd(0) + "Alt "
                End If
                
                If (GetKeyState(vbKeyShift) And &H8000) Then
                  Form1.txtHwnd(0) = Form1.txtHwnd(0) + "Shift"
                End If
                  
                'keyMsg.vKey And &HFF   虚拟码
                'lKey / 65536           扫描码
                
                If (keyMsg.vKey And &HFF) = vbKeyY Then       '把Y键替换为N
                   If wParam = WM_SYSKEYDOWN Or wParam = WM_KEYDOWN Then
                      keybd_event vbKeyN, 0, 0, 0
                   End If
                   CallKeyHookProc = 1        '屏蔽按键
                End If
                
           End Select
        End If
       
        If code <> 0 Then
          CallKeyHookProc = CallNextHookEx(0, code, wParam, lParam)
        End If
      End Function
    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/c945124/archive/2005/05/23/379248.aspx
      

  15.   

    LZ的需求准确地说是子类化,跨进程子类人需要使用线程注入或标准DLL进行处理。
    如果仅仅是获得光标所在位置的控件或窗体句柄,则可以使用以下函数:
    Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
      

  16.   

    http://www.symental.com/sfw?f=GetHwndAndClass    On Error Resume Next
        Dim tPoint As POINTAPI
        Dim hWin As Long
        Dim Rtn As Long
        Dim strControl As String * 255
        Dim Txt(64000) As Byte
        Static lngLastHwnd&
        GetCursorPos tPoint '获得当前鼠标位置
        hWin = WindowFromPoint(tPoint.x, tPoint.y) '获得窗口名柄
        If lngLastHwnd = hWin Then Exit Sub Else lngLastHwnd = hWin
        
        GetClassName hWin, strControl, 255 '获得窗口类
        SendMessage hWin, &HD, 64000, Txt(0) '获得窗口标题(也可使用 API 函数:GetWindowText,但效果不佳)
        Text1.Text = StrConv(Txt, vbUnicode)
        Text2.Text = hWin
        Text3.Text = strControl
        
        If Not isShowAll Then Exit Sub
        Text4.Text = "句柄" & Space(6) & "ID" & Space(4) & "类名" & Space(21) & "文本内容" & vbCrLf
        Rtn = EnumChildWindows(hWin, AddressOf EnumChildProc, 0&)