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.lWord = Modifiers) And i2.hword = uVirtKey Then Debug.Print “HotKey Shift-Alt-G Pressed ” Shell “notepad”, vbNormalFocus End If End If End If '如果不是热键信息则调用原来的程序 wndproc = CallWindowProc(preWinProc, hwnd, Msg, wParam, lParam) End Function
'以下程序放在窗体中 Sub Form_Load() Dim ret As Long '记录原来的window程序地址 preWinProc = GetWindowLong(Me.hwnd, GWL_WNDPROC) '用自定义程序代替原来的window程序 ret = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf wndproc) idHotKey = 1 'in the range &h0000 through &hBFFF Modifiers = MOD_ALT + MOD_SHIFT uVirtKey = vbKeyG '注册热键 ret =RegisterHotKey(Me.hwnd, idHotKey, Modifiers, uVirtKey) End Sub
Private Sub Form_Unload(Cancel As Integer) Dim ret As Long '取消Message的截取,使之送往原来的window程序 ret = SetWindowLong(Me.hwnd, GWL_WNDPROC, preWinProc) Call UnregisterHotKey(Me.hwnd, uVirtKey) End Sub
其它我想,用一个API函数就足够了,而且简单:Private Declare Function Getasynckeystate Lib "user32" (Byval vKey As Long) as Integer '该api函数是根据返回值来判断是否按下指定键(无论在前台或后台皆可)的,返回值小于0时则为按下了该键,不然……你说呢?Private Sub Timer1_Timer() Dim back_ctrl , back_alt , back_S as Long '定义back_ctrl等变量来接收返回值
back_ctrl = Getasynckeystate(17) '“17”为“ctrl”键的keycode值 back_alt = Getasynckeystate(18) '“18”为“alt”键的keycode值 back_S = Getasynckeystate(83) '“83”为“S”键的keycode值 If back_ctrl < 0 and back_alt < 0 and back_S < 0 then '判断ctrl和alt和S键是否同时被按下 shell "C:\WINNT\NOTEPAD.exe",vbNormalFocus '用shell函数来运行指定的“记事本”程序 End if End Sub 这样的话,就可以用Timer控件来检测键盘操作了。 (我也就是个学了一个多月编程的菜鸟,请多多指教!) E-mail: [email protected]
GetAsynckeyState就可以.......例如(按下ESC键就结束程序)Option Explicit Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As IntegerPrivate Sub Form_Load() Me.Caption = "点击窗体开始测试" End SubPrivate Sub Form_Click() Do DoEvents 'ESC If GetAsyncKeyState(27) <> 0 Then End End If DoEvents Loop End Sub
//Getasynckeystate是可以在整个系统下工作的!但需要有timer控件的支持,才能时时起作用。Return Value... Windows NT/2000/XP: The return value is zero for the following cases: The current desktop is not the active desktop The foreground thread belongs to another process and the desktop does not allow the hook or the journal record....MSDN上已经说明,对于NT系统,GetAsyncKeyState也会被隔离内存所作用,无法获取其它线程的输入(可能用AttachThreadInput附加线程输入就能解决)。所以还是用RegisterHotkey最正规,最安全。
'以下程序放在模块中
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.lWord = Modifiers) And i2.hword = uVirtKey Then
Debug.Print “HotKey Shift-Alt-G Pressed ”
Shell “notepad”, vbNormalFocus
End If
End If
End If
'如果不是热键信息则调用原来的程序
wndproc = CallWindowProc(preWinProc, hwnd, Msg, wParam, lParam)
End Function
'以下程序放在窗体中
Sub Form_Load()
Dim ret As Long
'记录原来的window程序地址
preWinProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)
'用自定义程序代替原来的window程序
ret = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf wndproc)
idHotKey = 1 'in the range &h0000 through &hBFFF
Modifiers = MOD_ALT + MOD_SHIFT
uVirtKey = vbKeyG
'注册热键
ret =RegisterHotKey(Me.hwnd, idHotKey, Modifiers, uVirtKey)
End Sub
Private Sub Form_Unload(Cancel As Integer)
Dim ret As Long
'取消Message的截取,使之送往原来的window程序
ret = SetWindowLong(Me.hwnd, GWL_WNDPROC, preWinProc)
Call UnregisterHotKey(Me.hwnd, uVirtKey)
End Sub
'该api函数是根据返回值来判断是否按下指定键(无论在前台或后台皆可)的,返回值小于0时则为按下了该键,不然……你说呢?Private Sub Timer1_Timer()
Dim back_ctrl , back_alt , back_S as Long
'定义back_ctrl等变量来接收返回值
back_ctrl = Getasynckeystate(17) '“17”为“ctrl”键的keycode值
back_alt = Getasynckeystate(18) '“18”为“alt”键的keycode值
back_S = Getasynckeystate(83) '“83”为“S”键的keycode值 If back_ctrl < 0 and back_alt < 0 and back_S < 0 then
'判断ctrl和alt和S键是否同时被按下
shell "C:\WINNT\NOTEPAD.exe",vbNormalFocus
'用shell函数来运行指定的“记事本”程序
End if
End Sub 这样的话,就可以用Timer控件来检测键盘操作了。
(我也就是个学了一个多月编程的菜鸟,请多多指教!)
E-mail: [email protected]
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As IntegerPrivate Sub Form_Load()
Me.Caption = "点击窗体开始测试"
End SubPrivate Sub Form_Click()
Do
DoEvents
'ESC
If GetAsyncKeyState(27) <> 0 Then
End
End If
DoEvents
Loop
End Sub
Windows NT/2000/XP: The return value is zero for the following cases: The current desktop is not the active desktop
The foreground thread belongs to another process and the desktop does not allow the hook or the journal record....MSDN上已经说明,对于NT系统,GetAsyncKeyState也会被隔离内存所作用,无法获取其它线程的输入(可能用AttachThreadInput附加线程输入就能解决)。所以还是用RegisterHotkey最正规,最安全。
如果像识别多种组合,建议使用系统键盘钩子。
不建议使用timer控件:Interval的值过大,则容易漏掉按键
Interval过小,太占用系统资源
同样容易出现漏掉按键的情况