在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->
|