2012年4月11日 星期三

VBA Bind Keys (keybinding) in a Form

(1) 雖然有 Form_KeyDown 事件, 但若 Form 上面有其他按鈕或輸入框, 則 Form_KeyDown 事件不會被觸發到
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
    Select Case KeyCode
         Case vbKeyW
             BackColor = QBColor(15)
         Case vbKeyF
             ForeColor = QBColor(5)
         Case vbKeyM
             MsgBox "Added more keys...", vbInformation
    End Select
End Sub

(2) 另外一種則是在 UserForm_Activate 事件中持續使用 GetAsyncKeyState 捕獲 keybord state, 但 VBA 內建沒有延遲函式 (Sleep、Delay、Timer 等), 則持續迴圈會耗用 CPU, 或設法加入 Sleep 函式 Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer

Private Sub UserForm_Activate()
    Do
        If GetAsyncKeyState(vbKeyControl) And GetAsyncKeyState(vbKeyA) Then MsgBox "你按了Ctrl+A"
    DoEvents ' 避免持續占用 CPU
    If s = True Then Exit Do
    Loop
End Sub

(3) 最後的方法則是使用在表單載入時 UserForm_Initialize 執行系統函式 SetTimer


模組  moduleKeyBinding
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer

Public Function keyCapture()
    ' 偵測是否按下 Ctrl + d
    If GetAsyncKeyState(vbKeyControl) And GetAsyncKeyState(vbKeyD) Then
        MsgBox "進入 Develop 模式"
   
        Application.Visible = True
    End If
End Function
表單 TheMainMenuForm
Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long

Private Sub UserForm_Initialize()
    SetTimer 0, 1, 1000, AddressOf moduleKeyBinding.keyCapture
End Sub




Reference :
How do i bind a key?
[VB]&[VBA] 如果判別是否按了ctrl+a的鍵?
[VBA] 使用Timer
完整功能的VBA Timer类

沒有留言:

張貼留言