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

    xiaoxiao2021-03-26  43

    (注意:本章没有用到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 ); 注意 上面的 KeyboardProcLowLevelKeyboardProc 函数,前者是普通的钩子函数,而后者是一个低级的钩子函数,这两个函数的参数不同,所以要获取的值也不同!!   摘自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() 参数idHOOKWH_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

    );

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

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

    所以,当idHookWH_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:X",pKbs->vkCode,pKbs->scanCode);

     

    //ESC扫描码

                                if (pKbs->scanCode==0x01)

                                {                         

                                         returnTRUE;

                                }

                       }

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

    }

     

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

    转载请注明原文地址: https://ju.6miu.com/read-658341.html

    最新回复(0)