一个用WH_KEYBOARD_LL实现全局热键的例子

QUOTE:

Option Explicit
Private Declare Function SetWindowsHookEx _
               
Lib "user32" _
               
Alias "SetWindowsHookExW" (ByVal idHook As Long, _
                                          
ByVal lpfn As Long, _
                                          
ByVal hmod As Long, _
                                          
ByVal dwThreadId As Long) As Long
Private Declare Function
UnhookWindowsHookEx _
               
Lib "user32" (ByVal hHook As Long) As Long
Private Declare Function
CallNextHookEx _
               
Lib "user32" (ByVal hHook As Long, _
                              
ByVal nCode As Long, _
                              
ByVal wParam As Long, _
                              lParam
As Any) As Long
Private Declare Sub
CopyMemory _
               
Lib "kernel32" _
               
Alias "RtlMoveMemory" (ByVal Destination As Long, _
                                       
ByVal Source As Long, _
                                       
ByVal Length As Long)
                                       
Private Type KBDLLHOOKSTRUCT
        VKCode
As Long
        
scanCode As Long
        
flags As Long
        
time As Long
        
dwExtraInfo As Long
End
Type

Private Const VK_LSHIFT = &HA0
Private Const VK_RSHIFT = &HA1
Private Const VK_LCONTROL = &HA2
Private Const VK_RCONTROL = &HA3
Private Const VK_LMENU = &HA4 'MENU=ALT
Private Const VK_RMENU = &HA5
Private Const HC_ACTION = &H0
Private Const WM_KEYDOWN = &H100
Private Const WM_KEYUP = &H101

Dim hHook As Long

Dim
CtrlIsPressed As Boolean
Dim
ShiftIsPressed As Boolean
Dim
AltIsPressed As Boolean

Public
Type HotKeyInfo
        IncludeCtrl
As Boolean
        
IncludeShift As Boolean
        
IncludeAlt As Boolean
        
UserKey As String * 1
End Type

Private Type UsrHotKeyInfo
        UserInfo
As HotKeyInfo
        IsInUse
As Boolean
End
Type

Dim savedHotKeys() As UsrHotKeyInfo

Public Sub HotKey_Process(ByVal KeyVKCode As Long, ByVal nAction As Long)
        
If ((KeyVKCode = VK_LCONTROL) Or (KeyVKCode = VK_RCONTROL)) Then
               
CtrlIsPressed = (nAction = WM_KEYDOWN)
               
GoTo SubProc_Exit
        
End If
        If
((KeyVKCode = VK_LSHIFT) Or (KeyVKCode = VK_RSHIFT)) Then
               
ShiftIsPressed = (nAction = WM_KEYDOWN)
               
GoTo SubProc_Exit
        
End If
        If
((KeyVKCode = VK_LMENU) Or (KeyVKCode = VK_RMENU)) Then
               
AltIsPressed = (nAction = WM_KEYDOWN)
               
GoTo SubProc_Exit
        
End If
        If
(nAction = WM_KEYUP) Then Call HotKeyProc(PressedHotKeyIndex(KeyVKCode))
        
'CtrlIsPressed = False: ShiftIsPressed = False: AltIsPressed = False
SubProc_Exit:
        
End Sub

'ret val=index of hotkey
Public Function AddHotKey(ByRef addKeyInfo As HotKeyInfo) As Integer
        Dim
newInd As Integer
        Dim
I As Integer
        Dim
bFound As Boolean: bFound = False
        For
I = LBound(savedHotKeys) To UBound(savedHotKeys)
               
If (savedHotKeys(I).IsInUse = False) Then
                        
newInd = I: bFound = True
                        Exit For
                End If
        Next
        If
(Not bFound) Then
               
newInd = UBound(savedHotKeys) + 1
               
ReDim Preserve savedHotKeys(newInd)
        
End If
        With
savedHotKeys(newInd)
                .UserInfo = addKeyInfo
                .UserInfo.UserKey = UCase(.UserInfo.UserKey)
                .IsInUse =
True
        End With
End Function

Public Sub
ClearHotKeyList()
        
Erase savedHotKeys
        
ReDim savedHotKeys(0)
End Sub

Public Sub
DelHotKey(ByVal nIndex As Integer)
        savedHotKeys(nIndex).IsInUse =
False
End Sub

Private Function
PressedHotKeyIndex(ByVal VKCode As Long) As Integer
        
PressedHotKeyIndex = -1
        
Dim newInd As Integer
        Dim
I As Integer
        Dim
bFound As Boolean: bFound = False
        Dim
strPressedKey As String: strPressedKey = UCase(Chr(VKCode))
        
For I = LBound(savedHotKeys) To UBound(savedHotKeys)
               
With savedHotKeys(I)
               
                        
If (.IsInUse = True) Then
                                If
((.UserInfo.IncludeAlt = AltIsPressed) And _
                                    (.UserInfo.IncludeCtrl = CtrlIsPressed)
And _
                                    (.UserInfo.IncludeShift = ShiftIsPressed)
And _
                                    (.UserInfo.UserKey = strPressedKey)) _
                                
Then
                                       
PressedHotKeyIndex = I: GoTo Func_Exit
                                
End If
                        End If
               
                End With
        Next
        
Func_Exit:

End Function

Private Sub
HotKeyProc(ByVal nIndex As Integer)

        
If (nIndex > -1) Then

                With
frmFunctionSelect

                        
Select Case nIndex

                                
Case 0 'HotKey 0 Pressed
                                'what can i do for u?
                        
End Select

                End With

        End If

End Sub

Public Function
DisableKbdHook() As Boolean
        
'Debug.Print "hHook: "; hHook
        
hHook = UnhookWindowsHookEx(hHook) - 1
        
DisableKbdHook = (hHook = 0)
End Function

Public Function
EnableKbdHook() As Boolean
        
'Debug.Print "hHook: "; hHook
        
If (hHook <= 0) Then hHook = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf LowLevelKeyboardProc, App.hInstance, 0)
        EnableKbdHook = (hHook <>
0)
End Function

Private Function
LowLevelKeyboardProc(ByVal nCode As Long, _
                                      
ByVal wParam As Long, _
                                      
ByVal lParam As Long) As Long

        If
(nCode <> HC_ACTION) Then
               
LowLevelKeyboardProc = CallNextHookEx(hHook, nCode, wParam, lParam)
               
Exit Function
        End If
        
        Call
HotKey_Process(GetKeyVKCode(lParam), wParam)

        LowLevelKeyboardProc = CallNextHookEx(hHook, nCode, wParam, lParam):
GoTo Exit_Func
Exit_Func:
End Function

Private Function
GetKeyVKCode(ByVal memAddr As Long) As Long
        Dim
curHs As KBDLLHOOKSTRUCT
        
Call CopyMemory(VarPtr(curHs), ByVal memAddr, Len(curHs))
        GetKeyVKCode = curHs.VKCode
End Function

Private Function
GetKeyScanCode(ByVal memAddr As Long) As Long
        Dim
curHs As KBDLLHOOKSTRUCT
        
Call CopyMemory(VarPtr(curHs), ByVal memAddr, Len(curHs))
        GetKeyScanCode = curHs.scanCode
End Function



[本日志由 JiaJia 于 2007-08-07 11:29 AM 编辑]
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: VB
评论: 0 | 引用: 0 | 查看次数: -
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.