在Dos的年代
,我们常会以拦截中断向量的方式
,做到按下某个hotkey而自动执行某个程式,在Window呢,也可以,不过它是用RegisterHotkeyAPI来完成
。 使用RegisterHotkey的概念是,它会定义一组按键的组合,当使用者不管在哪个程式之中,按下Window有注册的HotKey时,OS会传送WM_HOTKEY的讯息给待接收该讯息的Window,而该Window收到WM_HOTKEY时,便可知道有本身Thread所定义的HotKey被按下,於是可以从wParam,lParam来得知是哪一组HotKey被按下
。 RegisterHotKey(
ByValhwndAsLong,//接收Hotkey的Window
ByValidHotKeyasLong,//identifierofhotkey,range0x0000through0xBFFF
ByValModifiersAsLong,//定义altshiftcontrol等的组合
ByValuVirtKeyAsLong//virtual-keycode
)
WM_HOTKEY叁数的定义
idHotKey=wParam;//identifierofhotkey
Modifiers=(UINT)LOWORD(lParam);//key-modifierflags
uVirtKey=(UINT)HIWORD(lParam);//virtual-keycode
所以了,除了设定RegisterHotkey外,另要使用SubClassing的技巧才会得知HotKey被按下;最後,程式结束前要使用UnRegisterHotkey将HotKey的定义取消掉。
以下程式功能是:不管在哪个程式中,只要按下ALT-SHIFT-G便执行NotePad。
'以下在.BasOptionExplicit
DeclareFunctionSetWindowLongLib"user32"Alias"SetWindowLongA"_
(ByValhwndAsLong,ByValnIndexAsLong,ByValdwNewLongAsLong)AsLong
DeclareFunctionGetWindowLongLib"user32"Alias"GetWindowLongA"_
(ByValhwndAsLong,ByValnIndexAsLong)AsLong
DeclareFunctionCallWindowProcLib"user32"Alias"CallWindowProcA"_
(ByVallpPrevWndFuncAsLong,ByValhwndAsLong,ByValMsgAsLong,_
ByValwParamAsLong,ByVallParamAsLong)AsLong
DeclareFunctionRegisterHotKeyLib"user32"(ByValhwndAsLong,ByValidAsLong,ByValfsModifiersAsLong,ByValvkAsLong)AsLong
DeclareFunctionUnregisterHotKeyLib"user32"(ByValhwndAsLong,ByValidAsLong)AsLong
PublicConstWM_HOTKEY=&H312
PublicConstMOD_ALT=&H1
PublicConstMOD_CONTROL=&H2
PublicConstMOD_SHIFT=&H4
PublicConstGWL_WNDPROC=(-4)
PublicpreWinProcAsLong
PublicModifiersAsLong,uVirtKeyAsLong,idHotKeyAsLong
PrivateTypetaLong
llAsLong
EndType
PrivateTypet2Int
lWordAsInteger
hwordAsInteger
EndType
PublicFunctionwndproc(ByValhwndAsLong,ByValMsgAsLong,_
ByValwParamAsLong,ByVallParamAsLong)AsLong
IfMsg=WM_HOTKEYThen
IfwParam=idHotKeyThen
DimlpAstaLong,i2Ast2Int
lp.ll=lParam
LSeti2=lp
If(i2.lWord=Modifiers)Andi2.hword=uVirtKeyThen
Debug.Print"HotKeyShift-Alt-GPressed"
Shell"notepad",vbNormalFocus
EndIf
EndIf
EndIf
'将之送往原来的WindowProcedure
wndproc=CallWindowProc(preWinProc,hwnd,Msg,wParam,lParam)
EndFunction
'以下在Form
SubForm_Load()
DimretAsLong
preWinProc=GetWindowLong(Me.hwnd,GWL_WNDPROC)
ret=SetWindowLong(Me.hwnd,GWL_WNDPROC,AddressOfwndproc)
idHotKey=1'intherange&h0000through&hBFFF
Modifiers=MOD_ALT MOD_SHIFT
uVirtKey=vbKeyG
ret=RegisterHotKey(Me.hwnd,idHotKey,Modifiers,uVirtKey)
EndSub
PrivateSubForm_Unload(CancelAsInteger)
DimretAsLong
'取消Message的截取,而使之又只送往原来的WindowProcedure
ret=SetWindowLong(Me.hwnd,GWL_WNDPROC,preWinProc)
CallUnregisterHotKey(Me.hwnd,uVirtKey)
EndSub->