鼠标键盘钩子,屏蔽/修改按键消息

QT中使用钩子需要
#include <Windows.h>

鼠标键盘钩子各有两个,一个是普通的,一个是底层钩子,代码的写法差不多,区别是底层钩子比普通钩子更早接收到消息,还有个debug钩子,在所有的普通钩子前接收到消息。

不同的钩子对应的回调函数的写法(形参、返回值的意义):https://blog.csdn.net/jiangxinyu/article/details/5284067,如果链接失效,自行搜索《HOOK钩子机制学习笔记(4) - 钩子函数说明》

安装钩子:

HHOOK keyHook=NULL;
HHOOK mouseHook=NULL;

void install_Hook()//安装钩子
{
    //这两个底层钩子,不要DLL就可以全局
    //底层鼠标钩子
    //mouseHook =SetWindowsHookEx( WH_MOUSE_LL,mouseProc,GetModuleHandle(NULL),0);
    
    //底层键盘钩子
    keyHook =SetWindowsHookEx( WH_KEYBOARD_LL,keyProc,GetModuleHandle(NULL),0);//GetModuleHandle(NULL)取得本程序的句柄
    if(NULL == keyHook)
        qDebug() << "warning: keyHook failed!";
    
}

卸载钩子:

//卸载钩子
void unHook()
{
    UnhookWindowsHookEx(keyHook);
  //  UnhookWindowsHookEx(mouseHook);
}

键盘钩子的回调函数:

/* 功能:键盘钩子回调,钩子类型不同,则形参的意义也不同,对于底层LL键盘钩子,形参为:
 * 形参:nCode
 *      wParam 按键的状态,可能的值为WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN、WM_SYSKEYUP
 *      lParam 按键的软件码、硬件码、标志位、扩展信息(需强转转为KBDLLHOOKSTRUCT *类型) * 
 * */
LRESULT CALLBACK keyProc(int nCode,WPARAM wParam,LPARAM lParam )
{
    KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;
    //如果nCode等于HC_ACTION则处理该消息,如果小于0,则钩子子程就必须将该消息传递给 CallNextHookEx
    if(nCode == HC_ACTION)
    {
        // qDebug() << "pkbhs->vkCode=" << pkbhs->vkCode;
        qDebug() << "vkCode = " << pkbhs->vkCode << ", flags = " << pkbhs->flags ;
        if(pkbhs->vkCode == VK_ESCAPE && GetAsyncKeyState(VK_CONTROL)& 0x8000 && GetAsyncKeyState(VK_SHIFT)&0x8000){
                    qDebug() << "Ctrl+Shift+Esc";
        }else if(pkbhs->vkCode == VK_ESCAPE && GetAsyncKeyState(VK_CONTROL) & 0x8000){
            qDebug() << "Ctrl+Esc";
        }else if(pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN){
            qDebug() << "Alt+Tab";
        }else if(pkbhs->vkCode == VK_ESCAPE && pkbhs->flags &LLKHF_ALTDOWN){
            qDebug() << "Alt+Esc";
        }else if(pkbhs->vkCode == VK_LWIN || pkbhs->vkCode == VK_RWIN){
            qDebug() << "LWIN/RWIN";
        }else if(pkbhs->vkCode == VK_F4 && pkbhs->flags & LLKHF_ALTDOWN){
            qDebug() << "Alt+F4";
        }
        if(pkbhs->vkCode == VK_F12)
        {
            void unHook();
            qApp->quit();
        }
        return 1;//返回1表示截取消息不再传递,返回0表示不作处理,消息继续传递
    }
    else
        return CallNextHookEx(keyHook, nCode, wParam, lParam);
}


上面的例子通过return 1截断了键盘的消息,如果想修改键盘的消息,可以在return 1之前加上以下代码:

    DWORD keyUpFlag =  (wParam == WM_KEYUP) ? KEYEVENTF_KEYUP : 0;//方法1
    //DWORD keyUpFlag =  (pkbhs->flags & 0x80) == 0? 0 : KEYEVENTF_KEYUP;//方法2
    static const int scanCode = MapVirtualKey('A', MAPVK_VK_TO_VSC);
    keybd_event('A', scanCode, keyUpFlag, pkbhs->dwExtraInfo);
    return 1;

keybd_event用来模拟产生一个键盘消息,4个参数分别为:按键值、按键的硬件码、按下还是弹起、额外信息。

注意第三个参数,按下或者弹起这个标志位,这个标志位只能填0或KEYEVENTF_KEYUP,分别代表压下和弹起,

截获的消息中有两个地方可以得知按下还是弹起,一个是wParam,另一个是lParam(pkbhs->flags) 


猜你喜欢

转载自blog.csdn.net/qq_31073871/article/details/80681855
今日推荐