RegisterHotKey 全局快捷键的又一个选择 可以避免使用全局HOOK

使用RegisterHotkey的概念是,它会定义一组或单个按键的组合,不管在哪个程序之中,按下程序窗体有注册的HotKey时,系统会传送WM_HOTKEY 的讯息给待接收该讯息的程序窗体,而该程序窗体接收到WM_HOTKEY时,便可知道有本身Thread所定义的HotKey被按下,於是可以从wParam,lParam来得知是哪一组HotKey被按下,从而执行相应的操作.

函数声明的定义如下:

RegisterHotKey(ByVal hwnd As Long ,ByVal idHotKey as Long,ByVal Modifiers As Long,ByVal uVirtKey As Long)

hwnd //接收自定义热键的窗口的HWND
idHotKey //id为你自己定义的一个ID值对一个线程来讲其值必需在0x0000 - 0xBFFF范围之内,十进制为0~49151, 对DLL来讲其值必需在0xC000 - 0xFFFF 范围之内,十进制为49152~65535,在同一进程内该值必须唯一参数 fsModifiers指明与热键联合使用按键
Modifiers // 指明与热键联合使用按键(ALT,SHIFT,CTR的组合)如不需可置空
可取值为:MOD_ALT, MOD_CONTROL, MOD_WIN, MOD_SHIFT参数
或数字0为无组合键,1为Alt,2为Control,4为Shift,8为Windows
uVirtKey //自定义的虚拟按键码

WM_HOTKEY 叁数传递为
idHotKey => wParam;
Modifiers => (UINT) LOWORD(lParam);
uVirtKey = >(UINT) HIWORD(lParam);

所以,除设定RegisterHotkey外,另要使用SubClassing的技巧才会得知HotKey被按
下;最後,程序结束前要使用UnRegisterHotkey将HotKey的定义取消掉。切记,一定要有用有还!!!


以下demo 检测按键 F1 每次按下则打开系统计算器

窗体设计如下
模块 .bas
Option Explicit

Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
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
Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long, ByVal fsModifiers As Long, ByVal vk As Long) As Long
Declare Function UnregisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long) As Long

Public Const WM_HOTKEY = &H312
Public Const MOD_ALT = &H1
Public Const MOD_CONTROL = &H2
Public Const MOD_SHIFT = &H4
Public Const GWL_WNDPROC = (-4)

Public preWinProc As Long
Public Modifiers As Long, uVirtKey As Long, idHotKey As Long

Private Type taLong
   ll As Long
End Type
Private Type t2Int
   lWord As Integer
   hword As Integer
End Type
Public Function wndproc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If Msg = WM_HOTKEY Then
   If wParam = idHotKey Then
     Dim lp As taLong, i2 As t2Int
     lp.ll = lParam
     LSet i2 = lp
     If i2.hword = uVirtKey Then
        Shell "calc" '此处为接收到热键后需执行的操作
     End If
   End If
End If
'将之送往原来的Window Procedure
wndproc = CallWindowProc(preWinProc, hwnd, Msg, wParam, lParam)
End Function

窗体代码 .frm
Option Explicit
Private Sub reg_Click()'注册按钮
    Dim ret As Long
    preWinProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)
    ret = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf wndproc)
    idHotKey = 1 'in the range &h0000 through &hBFFF
    uVirtKey = vbKeyF1
    ret = RegisterHotKey(Me.hwnd, idHotKey, Modifiers, uVirtKey)
End Sub

Private Sub unReg_Click()'销毁按钮
    Dim ret As Long
    '取消Message的截取,而使之又只送往原来的Window Procedure
    ret = SetWindowLong(Me.hwnd, GWL_WNDPROC, preWinProc)
    Call UnregisterHotKey(Me.hwnd, uVirtKey)
End Sub

参考文章 RegisterHotKey的具体使用方法

你可能感兴趣的:(RegisterHotKey 全局快捷键的又一个选择 可以避免使用全局HOOK)