以下这段代码,经常导致我程序崩溃或死锁一样,请高手看看是哪里的问题.(把段码提出单独测试好像没什么问题)
   
Public Type KBDLLHOOKSTRUCT
  vkCode As Long       
  scanCode As Long      
  flags As Long         
  time As Long          
  dwExtraInfo As Long   
End TypePublic 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 Sub CopyMemory Lib "kernel32" _
   Alias "RtlMoveMemory" _
  (pDest As Any, _
   pSource As Any, _
   ByVal cb As Long)
   
   
Public Declare Function UnhookWindowsHookEx Lib "user32" _
  (ByVal hHook As Long) As LongPublic Declare Function CallNextHookEx Lib "user32" _
  (ByVal hHook As Long, _
   ByVal nCode As Long, _
   ByVal wParam As Long, _
   ByVal lParam As Long) As LongPublic Type KeyboardBytes
   kbByte(0 To 255) As Byte
End TypePublic Declare Function GetKeyboardState Lib "user32" _
   (ByVal kbArray As KeyboardBytes) As LongPublic Declare Function GetKeyState Lib "user32" _
  (ByVal nVirtKey As Long) As IntegerPublic Declare Function GetAsyncKeyState Lib "user32" _
   (ByVal vKey As Long) As IntegerPublic m_hDllKbdHook As Long  
                               
Public Declare Function SetWindowPos Lib "user32" _
    (ByVal hwnd As Long, _
     ByVal hWndInsertAfter As Long, _
     ByVal x As Long, _
     ByVal y As Long, _
     ByVal cx As Long, _
     ByVal cy As Long, _
     ByVal wFlags As Long) As Long
Public Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long'常量声明省略Public Function LowLevelKeyboardProc(ByVal nCode As Long, _
                                     ByVal wParam As Long, _
                                     ByVal lParam As Long) As Long    Static kbdllhs As KBDLLHOOKSTRUCT
    On Local Error Resume Next
    
    If nCode = HC_ACTION Then
    
       Call CopyMemory(kbdllhs, ByVal lParam, Len(kbdllhs))   'F10 --------------
       If (kbdllhs.vkCode = VK_F10) Then
            LowLevelKeyboardProc = 1
            FrmMain.CommandKaishi_Click
            Exit Function
       End If                                                'F11 --------------
       If (kbdllhs.vkCode = VK_F11) Then
            LowLevelKeyboardProc = 1
            FrmMain.CommandZanTing_Click
            Exit Function
       End If                                     
    End If                                        
    LowLevelKeyboardProc = CallNextHookEx(m_hDllKbdHook, _
                                         nCode, _
                                         wParam, _
                                         lParam)
End Function
'在Frmmain的load事件中加载HOOK
    'HOOK键盘
   m_hDllKbdHook = SetWindowsHookEx(WH_KEYBOARD_LL, _
                                   AddressOf LowLevelKeyboardProc, _
                                   App.hInstance, _
                                   0&)
'在Frmmain的queryunload事件中卸载HOOK    If m_hDllKbdHook <> 0 Then
        Call UnhookWindowsHookEx(m_hDllKbdHook)
    End If
但是程序运行时,使用热键出有时会崩溃,有时会像死锁样动不了.不知道是哪里错了请高手赐教!感谢

解决方案 »

  1.   

    VB6实现键盘鼠标全局Hook
      

  2.   

    现在查明程序死锁不是HOOK引起的,但程序崩溃并提示引用内存错误是和HOOK有关的,希望有高手来!!
      

  3.   

    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的应用程序产生冲突。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);