在實際應用中,有時程序需要在特定的鼠標、按鍵事件后,執行一些操作,比如:
1、點擊觸摸屏時觸發蜂鳴器。
2、在休眠狀態點擊觸摸屏后,讓程序結束休眠狀態。
3、設定全局的按鍵功能,如一鍵截圖或一鍵關機。
4、過濾一些鼠標或鍵盤操作等等。
這時,可以使用鍵盤鼠標鉤子來實現這些功能。
鉤子是WINDOWS/WINCE系統獨有的消息處理機制。通過系統調用,將消息處理程序段掛入系統,獲得消息處理優先控制權,在消息達到目的窗口前進行處理。鉤子函數可以通過判斷決定是否加工處理(改變)消息,或不做處理繼續傳遞各消息,或強制結束消息傳遞。
鉤子有很多種,WINCE系統已精簡到只有4種鉤子。同時鉤子又可做局部鉤子或全局鉤子,局部鉤子僅在指定進程內生效,而全局鉤子在系統范圍內都生效。一般的全局鉤子需要掛載到dll中使用,本文介紹的鼠標鉤子和鍵盤鉤子較特殊,不需要掛載到dll中即可全局生效。
鉤子的運行邏輯如下圖,每種鉤子可以掛入任意多個鉤子函數,以鏈表方式存儲。系統優先訪問鏈表首位的鉤子,然后依次傳遞消息給后面的鉤子處理。后掛入的鉤子位于鏈表的前端。
使用方法
添加鉤子分3步。
1、編寫鉤子函數處理代碼
2、調用API函數將鉤子函數掛入系統
3、創建消息循環,使鉤子運作起來
添加引用
使用鉤子需要用到函數,SetWindowsHookEx,UnhookWindowsHookEx,CallNextHookEx。及鍵盤鉤子鼠標鉤子的定義,及鍵盤消息,鼠標消息的結構體定義,均定義在pwinuser.h中。
#include "pwinuser.h"
創建需要掛入系統的消息處理函數
即鉤子函數,鉤子函數定義必須為制定的格式。
鉤子函數根據實際應用需求,決定是否調用CallNextHookEx,將消息傳遞給后面的鉤子處理。
首位的鉤子函數返回值決定該消息是丟棄,還是傳給系統消息處理函數,再分發給各窗口。
以下為鍵盤及鼠標鉤子函數的示例。
鍵盤鉤子函數
該鍵盤鉤子示例函數中,當檢測到按鍵‘1’按下時,調用Beep函數觸發蜂鳴器。
LRESULT CALLBACK KeyboardProc(intnCode,WPARAM wParam,LPARAM lParam)
{
KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;
if(wParam == WM_KEYDOWN) //按鈕按下
{
switch(pkbhs->vkCode)
{
case0x31: //按鈕‘’
Beep();
break;
defaut:
break;
}
}
returnCallNextHookEx(NULL,nCode,wParam,lParam);
}
注:
1、WINCE鍵盤鉤子函數得到的WPARAM記錄的消息類別,如按鍵是按下消息WM_KEYDOWN還是彈起消息WM_KEYUP。
LPARAM指向鍵盤消息結構體KBDLLHOOKSTRUCT,里面記錄有詳細信息,如觸發的按鍵是什么,有沒有輔助按下ALT鍵或者CTRL鍵,等等。
2、鉤子隊列第一個鉤子的返回值決定系統是否能接受到該消息。
返回0表示,將消息傳遞給系統消息處理函數繼續處理。
返回1表示,丟棄消息,系統將收不到該消息。
調用CallNextHookEx表示調用下一個鉤子消息處理函數,如果不調用,那么后面的鉤子函數將不產生作用。
鼠標(觸摸屏)鉤子函數
該鼠標鉤子示例函數中,當檢測到鼠標或觸摸屏點擊時,調用Beep函數觸發蜂鳴器。
LRESULT CALLBACK MouseHookProc(intnCode, WPARAM wParam, LPARAM lParam)
{
MSLLHOOKSTRUCT *pmshs = (MSLLHOOKSTRUCT *) lParam;
if(wParam == WM_LBUTTONDOWN) //鼠標點擊處理代碼
{
Beep();
}
returnCallNextHookEx(NULL,nCode,wParam,lParam);
}
注:
1、WINCE鼠標鉤子函數得到的WPARAM記錄的消息類別,如是鼠標按下還是彈起,還是雙擊,移動,等等。
LPARAM記錄的詳細信息,如點擊坐標,滾輪參數等等。
2、觸摸屏消息和鼠標消息是一樣的。
3、鉤子隊列第一個鉤子的返回值決定系統是否能接受到該消息。
返回0表示,將消息傳遞給系統消息處理函數繼續處理。
返回1表示,丟棄消息,系統將收不到該消息。
調用CallNextHookEx表示調用下一個鉤子消息處理函數,如果不調用,那么后面的鉤子函數將不產生作用。
Beep函數
在本文示例中,將嵌入式板子GPIO15連接上一個蜂鳴器,通過設置GPIO電平觸發蜂鳴器。
在程序初始段打開GPIO,獲得GPIO句柄。
#include"isa_dio.h"
HANDLE hGpio;
hGpio = OpenGPIO( _T("PIO1:"));
添加Beep函數,通過GPIO句柄操作GPIO15。
voidBeep()
{
GPIO_OutClear(hGpio, GPIO15);
Sleep(10);
GPIO_OutSet(hGpio, GPIO15);
}
添加鉤子
在主線程中調用SetWindowsHookEx函數向系統添加鉤子。
第一個參數為添加的鉤子類型,WH_KEYBOARD_LL為鍵盤鉤子,WH_MOUSE_LL為鼠標鉤子。
第二個參數為注入的消息處理函數指針,即前面定義的鉤子函數。
第三個參數為鉤子程序的instance指針,本文介紹的鉤子并不需要掛載到dll中使用,所以簡單設置為NULL即可。
最后個參數為鉤子關聯的線程句柄,這里為0表示關聯所有線程,即全局鉤子。
函數返回NULL表示添加鉤子失敗,成功返回鉤子句柄。
示例代碼如下:
HINSTANCE hInstance = NULL;
HHOOK g_hKBDhook = NULL;
HHOOK g_hMouseHook = NULL;
g_hKBDhook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, hInstance, 0);
if(g_hKBDhook == NULL)
{
returnfalse;
}
g_hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, hInstance, 0);
if(g_hMouseHook == NULL)
{
returnfalse;
}
添加消息循環
鉤子機制是基于消息循環的,所以添加消息循環是必須的,如果沒有添加消息循環,會導致系統消息進入鉤子后卡死。
MFC框架的程序已經自帶消息循環。
而命令行的程序則需要在主函數里添加以下代碼。
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
刪除鉤子
當不需要鉤子時,應當主動釋放鉤子。
UnhookWindowsHookEx(g_ hKBDhook);
UnhookWindowsHookEx(g_hMouseHook);
英創提供了例程及源代碼,有需要的客戶可以聯系英創工程師獲得。
-
WINDOWS
+關注
關注
4文章
3555瀏覽量
89049 -
嵌入式主板
+關注
關注
7文章
6086瀏覽量
35505
發布評論請先 登錄
相關推薦
評論