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


    昨天刚刚了解到系统热键的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
    ", 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("按下了加速键...
    ");
            }
        }

    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
    ", bControlKeyDown);
            //printf("ks->vkCode:%c
    ", ks->vkCode);
    
            if(ks->vkCode == VK_ESCAPE)
            {
                //printf("esc
    ");
    
                if(currentMouseLocationTarget == TARGET_NULL)
                {
    
                }
                else
                {
                    ...               
    
                   
    
                    if(hook_keyboard)
                    {
                        UnhookWindowsHookEx(hook_keyboard); //解锁
                        hook_keyboard = NULL;
                    }
    
                    return 1; //屏蔽掉, 不再向下传递
                }
            }
        }
    
        return CallNextHookEx(hook_keyboard, nCode, wParam, lParam); //返回给下一个钩子子程处理 (==不屏蔽)
    }
  • 相关阅读:
    Keras安装
    sql根据查询顺序返回结果
    @Configuration @Bean
    SQL高级优化系列
    数据结构与算法系列(二)-- 算法
    数据结构与算法系列(一)-- 数据结构
    Golang中Label的用法
    日志收集系统系列(五)之LogTransfer
    日志收集系统系列(四)之LogAgent优化
    日志收集系统系列(三)之LogAgent
  • 原文地址:https://www.cnblogs.com/personnel/p/12360097.html
Copyright © 2020-2023  润新知