提醒:本页面将不再更新、维护或者支持,文章、评论所叙述内容存在时效性,涉及技术细节或者软件使用方面不保证能够完全有效可操作,请谨慎参考!

好久不用VB写程序了,但是不得不承认VB的简单和高开发效率,这点比C/C++要好很多,尤其是一些开发周期短,实用性较强的软件。近期应单位要求,开发个××系统(名称保密),然后有个功能就是截获按键,实现特殊的按键热键的功能,首先想到的就是SetWindowsHookEx、CallNextHookEx 和UnhookWindowsHookEx,是的,想法很好,但是在实际运用时发现这几个C/C++下好用的函数老是容易导致VB崩溃,有时连IDE一起挂了,纠结了,因为这个系统最大的要求就是稳定,不能中途崩溃,为此我还特地建立了崩溃恢复机制,好了废话不说,这个问题总是要解决的,网上找到的一类代码比较混杂,大多是有问题的,最终我在vbaccelerator找到了个稳定可行的版本,那就是 《Win32 Hooks in VB - The vbAccelerator Hook Library》 这篇文章所介绍的Hook Library [下载地址] [源代码]

使用方法很简单,下载那个ActiveX DLL,然后VB引用,然后在窗体级代码中输入:

Implements IWindowsHook

Private Sub Form_Load()
   InstallHook Me, WH_JOURNALRECORD
End Sub

Private Sub Form_QueryUnload( _
      Cancel As Integer, UnloadMode As Integer)
   RemoveHook Me, WH_JOURNALRECORD
End Sub

Private Function IWindowsHook_HookProc( _
      ByVal eType As vbalWinHook.EHTHookTypeConstants, _
      ByVal nCode As Long, _
      ByVal wParam As Long, _
      ByVal lParam As Long, _
      bConsume As Boolean) As Long

   If (eType = WH_JOURNALRECORD) Then

      Dim cEvent As cJournallParam
      Set cEvent = JournalRecordlParam(lParam)

      ' cEvent now contains information about
      ' the Journal record message.

   End If

End Function

当然 《Using a Journal Record Hook to Capture Mouse and Key Events from any System Window》 给出了一个完整的示例,大家不妨参考一下。

后来发现一个问题,那就是Visual Basic的ListView控件老是接收到我们要处理的按键,原本是想要处理的按键被按键勾子截获后就被“吃掉”不再继续传递,但是即使将IWindowsHook_HookProc的bConsume设为True也无济于事,后来我想起了以前看到的一个简单的办法,那就是KeyPress,看下面的代码:

Private Sub ListView1_KeyPress(KeyAscii As Integer)
  ' 如果按下字母B,则“吃掉”这个按键
  If KeyAscii = vbKeyB Then KeyAscii = 0
End Sub

上述代码中,如果接收到字母则将KeyAscii置0,这样控件本身就不再处理这个按键了。