首页 > 学院 > 开发设计 > 正文

浅谈C++KeyboardProc|LowLevelKeyboardProc函数使用

2019-11-14 10:12:30
字体:
来源:转载
供稿:网友

(注意:本章没有用到DLL,而是直接钩住当前程序!!)

首先列举 一下WindowsHOOK基本的函数(主要关于键盘…):

HHOOK WINAPI SetWindowsHookEx(

  _In_ int       idHook,

 _In_ HOOKPROC  lpfn,

 _In_ HINSTANCE hMod,

  _In_ DWord    dwThreadId

);

LRESULT WINAPI CallNextHookEx(
  _In_opt_ HHOOK  hhk,
  _In_     int    nCode,
  _In_     WPARAM wParam,
  _In_     LPARAM lParam
);

BOOL WINAPI UnhookWindowsHookEx(

  _In_ HHOOKhhk

);

LRESULT CALLBACK KeyboardProc(

  _In_ int    code,

  _In_ WPARAMwParam,

  _In_ LPARAMlParam

);

LRESULT CALLBACK LowLevelKeyboardProc(
  _In_ int    nCode,
  _In_ WPARAM wParam,
  _In_ LPARAM lParam
);
注意 上面的 KeyboardProc 和 LowLevelKeyboardProc 函数,前者是普通的钩子函数,而后者是一个低级的钩子函数,这两个函数的参数不同,所以要获取的值也不同!!
 
摘自MSDN:
KeyboardProc的函数参数(wparam和lparam)使用

wParam [in]

Type: WPARAM

The virtual-key code of the key thatgenerated the keystroke message.

lParam [in]

Type: LPARAM

The repeat count, scan code, extended-key flag, contextcode, previous key-state flag, and transition-state flag. For more informationabout thelParam parameter, seeKeystroke Message Flags. The following table describes the bits of this value.

由此可看出 ,wparam主要是键盘的虚拟键代码lparam主要是:

The lParam parameter of a keystroke message containsadditional information about the keystroke that generated the message. Thisinformation includes therepeat count, the scan code, the extended-key flag, thecontext code, the previous key-state flag, and the transition-state flag.The following illustration shows the locations of these flags and values in thelParam parameter.

怎么说呢,这个参数其实主要看16-23位,刚好达到8位,也就是一个扫描码

那么像这样的参数给我们有什么用啊?其实如果你 用过函数 GetKeyNameText

就知道了,他的第一个参数就是lparam,也就是KeyboardProc 第三个参数!!是不是很巧?就是用他来获取到按下的键盘名,所以这个函数 可以和KeyboardProc 一起使用!

 

下面就介绍 LowLevelboardProc 函数,参数和KeyboardProc 一样,但是参数所起的作用差距很大,可谓 失之毫厘,差之千里~~

当 SetWindowsHookEx() 参数idHOOK 为WH_KEYBORAD_LL时,这个函数的参数中的wparam 为 键盘消息,如WM_KEYDOMN… 那么lparam 就是一个 LPKBDLLHOOKSTRUCT结构体了!看这个结构体的名字就知道这是一个用于 低级键盘钩子的,“LL”->”LowLevel“,呵呵~这个结构体中 包括了 虚拟键代码 和 扫描码!

如上所述,我们大概就知道LowLevelboardProc 和 KeyboardProc的差别了,

但别忘了还有那个 SetWindowsHookEx()函数,现在在回忆一下那个函数原型:

 HHOOK WINAPI SetWindowsHookEx(

  _In_ int       idHook,

  _In_ HOOKPROC  lpfn,

  _In_ HINSTANCE hMod,

  _In_ DWORD    dwThreadId

);

当IdHook为WH_KEYBOARD 时,lpfn为KeyboardProc(名字自定义),hMod为当前程序实例句柄,MFC 有多种方法获取,如:AfxGetInstanceHandle()  

最后一个 dwThreadId为0!!至于为什么,我现在还不是很清楚,希望有大神解答…

所以,当idHook为WH_KEYBOARD_LL时,dwThreadid 必须为当前模块的线程ID!

看下图来对比下:

 

据此,我把主要代码给出来

HHOOK hHook2;

LRESULT CALLBACK KeyBoradProc(intcode,WPARAMwp,LPARAMlp)

{

         if (code<0)

         {

                   return CallNextHookEx(hHook2,code,wp,lp);

         }

         WCHAR szkeyValue[20]={ 0 };

         //wsprintf(szkeyValue, L"%c", wp);  //虚拟键代码

            //获取按键的名称          

         GetKeyNameText(lp,szkeyValue, 50);

         AfxGetMainWnd()->SetDlgItemText(IDC_EDIT1,szkeyValue);

         return CallNextHookEx(hHook2,code,wp,lp);

}

       //安装键盘钩子

         hHook2 = SetWindowsHookEx(WH_KEYBOARD,KeyBoradProc,AfxGetInstanceHandle(),GetCurrentThreadId());      //注意这里的线程ID为当前程序的线程ID!

      

         //卸载钩子

UnhookWindowsHookEx(hHook2);

下面是关于低级键盘钩子的代码;

         //低级的键盘钩子

         hHook= ::SetWindowsHookEx(WH_KEYBOARD_LL,myLowLevelKeyboardProc,AfxGetInstanceHandle(),0);//注意这里TID为 0

 

         //卸载低级钩子

UnhookWindowsHookEx(hHook)

 

//低级钩子函数处理过程

LRESULT CALLBACK LowLevelKeyboardProc(_In_int   code,_In_WPARAMwParam,_In_LPARAMlParam)

{

                   if (code < 0)

                   {

                            returnCallNextHookEx(hHook,code,wParam,lParam);

                   }

 

                  // 低级键盘钩子时,wparam参数为 WM键盘消息!!!

 

                   //按下的

                   if (code ==HC_ACTION&&wParam==WM_KEYDOWN)

                   {

                            LPKBDLLHOOKSTRUCTpKbs = (LPKBDLLHOOKSTRUCT)lParam;

                            WCHARszlMsg[100] = { 0 };

                            wsprintf(szMsg,L"vkCode:%c-scanCode:%02X",pKbs->vkCode,pKbs->scanCode);

 

//ESC键扫描码

                            if (pKbs->scanCode==0x01)

                            {                         

                                     returnTRUE;

                            }

                   }

                   return CallNextHookEx(hHook,code,wParam,lParam);

}

 

基本上注释已经说明了,那么本文也就到此结束了…


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表