快捷键(加速键),系统热键,键盘钩子的不同

昨天刚刚了解到系统热键的API: RegisterHotKey(),当时很感慨,因为这些年来,经常用到的是【快捷键】或用【键盘钩子】实现的全局快键键,因为我不知道有现成的系统热键的API可用,有点丢人了。

现在想想,系统的快捷键,系统热键,键盘钩子他们各有各的特点,简单做个总结:

1. 快捷键(Accelerator:加速键),特点是:窗口必须在获得焦点(激活的状态)下,才能响应快捷键。

我一般都是在 res.rc 中添加:

//
// Accelerator resources  加速键
// 详细介绍: https://docs.microsoft.com/en-us/windows/win32/menurc/accelerators-resource
//
LANGUAGE 0, SUBLANG_NEUTRAL
IDR_ACCELERATOR1 ACCELERATORS
{
    /*
    //快捷键的映射关系
    "^C",  ID_ACCELERATOR_DELETE                          // control C
    "K",   ID_ACCELERATOR_DELETE                          // shift K
    "k",   ID_ACCELERATOR_DELETE, ALT                     // alt k
    98,    ID_ACCELERATOR_DELETE, ASCII                   // b
    66,    ID_ACCELERATOR_DELETE, ASCII                   // B (shift b)
    "g",   ID_ACCELERATOR_DELETE                          // g
    "G",   ID_ACCELERATOR_DELETE                          // G (shift G)
    VK_F1, ID_ACCELERATOR_DELETE, VIRTKEY                 // F1
    VK_F1, ID_ACCELERATOR_DELETE, CONTROL, VIRTKEY        // control F1
    VK_F1, ID_ACCELERATOR_DELETE, SHIFT, VIRTKEY          // shift F1
    VK_F1, ID_ACCELERATOR_DELETE, ALT, VIRTKEY            // alt F1
    VK_F2, ID_ACCELERATOR_DELETE, ALT, SHIFT, VIRTKEY     // alt shift F2
    VK_F2, ID_ACCELERATOR_DELETE, CONTROL, SHIFT, VIRTKEY // ctrl shift F2
    VK_F2, ID_ACCELERATOR_DELETE, ALT, CONTROL, VIRTKEY   // alt control F2
    */

    //"H",        ID_ACCELERATOR_SCREENSHOT_STATIC, ALT, CONTROL, VIRTKEY  // ctrl + alt + h, 注意, 前面必须使用大写的 "H"
    VK_DELETE, ID_ACCELERATOR_DELETE, VIRTKEY
}

然后在主程序中 main() 中添加:

HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1)); // 加载加速键表
    //printf("hAccelTable:%ld\n", hAccelTable);


    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        //参考 - http://dec3.jlu.edu.cn/webcourse/T000024/files/bjjx/bjjx3.htmhttp://itzone.hk/article/article.php?aid=200406211205229426
        //TranslateAccelerator()函数确定存放在msg消息结构中的消息是不是键盘消息。
        //如果是,该函数将查找句柄为hAccel的加速键表。如果找到了一个匹配,则调用句桶为hwnd的窗口的窗口过程。
        //如果加速键ID与系统菜单的菜单项一致,则消息就是WM_SYSCOMMAND;否则,消息为WM_COMMAND。

        if(!TranslateAccelerator(hwnd, hAccelTable, &messages)) //启用加速键
        {
            /* Translate virtual-key messages into character messages */
            TranslateMessage(&messages);

            /* Send message to WindowProcedure */
            DispatchMessage(&messages);

        }
        else
        {
            //printf("按下了加速键...\n");
        }
    }

2. 系统热键,特点:窗口不激活也能接收到键盘消息。使用 RegisterHotKey() 注册,操作上很简单,但由于是全局性的,容易和别的软件发生热键冲突,导致热键注册失败。

3. 键盘钩子,特点:窗口不激活也能接收到键盘消息。使用上有点麻烦,但是这玩意一般情况下不会因与别软件冲突,而无法接收键盘消息。当然如果别的软件也有键盘钩子,同时禁止了键盘消息向下传递,会不会也无法接收键盘消息,我没测试)

//全局键盘钩子
//参考 - http://blog.csdn.net/one_six_mix/article/details/52044406
hook_keyboard = SetWindowsHookExA(WH_KEYBOARD_LL, keyboardHook, GetModuleHandleA(0), 0); //GetModuleHandleA(0)或 NULL, 都行
//钩子回调 - 全局键盘钩子
LRESULT CALLBACK keyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
{
    if(nCode == HC_ACTION) //当 nCode等于HC_ACTION时,要求得到处理
    {
        //参考 - http://bbs.csdn.net/topics/320236776
        //参考 - http://www.51hei.com/bbs/dpj-30393-1.html

        //BOOL bControlKeyDown = GetAsyncKeyState(VK_CONTROL) >> ((sizeof(SHORT) * 8 ) - 1);// 检查是否Ctrl键被按下

        KBDLLHOOKSTRUCT *ks = (KBDLLHOOKSTRUCT*)lParam;

        //printf("是否Ctrl键被按下:%d\n", bControlKeyDown);
        //printf("ks->vkCode:%c\n", ks->vkCode);

        if(ks->vkCode == VK_ESCAPE)
        {
            //printf("esc\n");

            if(currentMouseLocationTarget == TARGET_NULL)
            {

            }
            else
            {
                ...               

               

                if(hook_keyboard)
                {
                    UnhookWindowsHookEx(hook_keyboard); //解锁
                    hook_keyboard = NULL;
                }

                return 1; //屏蔽掉, 不再向下传递
            }
        }
    }

    return CallNextHookEx(hook_keyboard, nCode, wParam, lParam); //返回给下一个钩子子程处理 (==不屏蔽)
}

猜你喜欢

转载自www.cnblogs.com/personnel/p/12360097.html