VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

有编程疑问吗?还请到提问专区发帖提问!
搜索
查看: 404|回复: 1

VC++基础班-[12]注册全局系统热键

[复制链接]
51_avatar_middle
online_admins Syc 发表于 2018-1-22 20:16:32 | 显示全部楼层 |阅读模式
------------------------------------------ Begin ----------------------------------------
①、注册全局系统热键的优点:
即使程序的窗口不是当前活动窗口、或者窗口最小化、隐藏后,也都可以响应热键;
比如QQ软件的默认呼出热键:Ctrl+Alt+Z 就是注册了全局系统热键;

②、注册窗口全局系统热键的步骤:

1> 调用 RegisterHotKey 函数注册全局系统热键;
BOOL RegisterHotKey(
    HWND hWnd,
    int id,
    UINT fsModifiers,
    UINT vk
);
hWnd : 指定响应该热键的窗口句柄;
id : 热键的标识,有点类似于 SetTimer 中的标识,作用域为线程内;
fsModifiers : 指定组合键,这个值可以由 MOD_ALT、MOD_CONTROL、MOD_SHIFT、MOD_WIN 中的一个或几个组成;
vk : 指定热键的虚拟键盘码,如:'A'
备注:这里的 Ctrl+Alt+A 这个组合键的作用域是全局的;

示例:RegisterHotKey(m_hWnd, 1000, MOD_CONTROL|MOD_ALT, 'Q');

2> 响应目标窗口的 WM_HOTKEY 消息;
3> 调用 UnregisterHotKey 卸载热键:
BOOL UnregisterHotKey(
    HWND hWnd,
    int id
);
hWnd : 热键关联的窗口句柄;
id : 热键的标识;
可以放到对话框类的 OnDestroy() 函数中进行调用,这样模态与非模态对话框都可以成功的进行卸载;

==============================================
③、热键提高篇:注册线程全局热键,没有窗口;

④、线程全局热键的步骤:
1> 声明线程函数:static UINT __cdecl ThreadProc(LPVOID pParam);
成员函数作为线程函数:http://www.cctry.com/thread-19591-1-1.html

2> 调用MFC中的 AfxBeginThread 函数进行新工作线程的创建: AfxBeginThread(ThreadProc, this);
3> 线程函数的实现://跟大家说明一下id和key作用域的问题
UINT CMFCTestDlg::ThreadProc(LPVOID pParam)
{
        CMFCTestDlg *pThis = (CMFCTestDlg *)pParam;
        BOOL bRet = RegisterHotKey(NULL, pThis->hotkey_n, MOD_CONTROL|MOD_ALT, 'E');
        int err = GetLastError();
        LPARAM lpa = MAKELPARAM(MOD_CONTROL|MOD_ALT, 'E');

        MSG stMsg = {0};
        while(GetMessage(&stMsg, NULL, 0, 0))
        {
                switch(stMsg.message)
                {
                case WM_HOTKEY:
                        ::MessageBox(NULL, _T("您按下了:Ctrl+Alt+E 热键!"), _T("友情提示"), MB_OK);
                        break;
                default:break;
                }
        }
        UnregisterHotKey(NULL, pThis->hotkey_n);

        return 0;
}

3> 线程函数的退出:
因为 GetMessage 是阻塞的,没有消息的话,那么就会一直等待,直到返回为止,所以我们要加一个“后门”,让其可以退出;
使用的方法就是把 GetMessage 换成 PeekMessage,这个函数是异步的,所以没有消息也可以返回:
UINT CMFCTestDlg::ThreadProc(LPVOID pParam)
{
        CMFCTestDlg *pThis = (CMFCTestDlg *)pParam;
        BOOL bRet = RegisterHotKey(NULL, pThis->hotkey_n, MOD_CONTROL|MOD_ALT, 'E');
        int err = GetLastError();
        LPARAM lpa = MAKELPARAM(MOD_CONTROL|MOD_ALT, 'E');

        MSG stMsg = {0};
        while(TRUE)
        {
                if (PeekMessage(&stMsg, NULL, 0, 0, PM_REMOVE)){
                        switch(stMsg.message)
                        {
                        case WM_HOTKEY:
                                ::MessageBox(NULL, _T("您按下了:Ctrl+Alt+E 热键!"), _T("友情提示"), MB_OK);
                                break;
                        default:break;
                        }
                }
                Sleep(100); //防止CPU过高
        }
        UnregisterHotKey(NULL, pThis->hotkey_n);

        return 0;
}
------------------------------------- End -------------------------------------------

相关课程演示细节还请观看视频教程!
本套教程由VC驿站原创,提供视频教程+售后答疑服务!
教程介绍及详情请见:http://www.cctry.com/thread-17282-1-1.html
VC驿站Vip会员详情请见:http://www.cctry.com/static/vip/index.html




上一篇:VC++基础班-[11]对话框程序响应组合按键
下一篇:VC++基础班-[13]控件自定义消息的响应

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

71_avatar_middle
在线会员 zzw843 发表于 2018-1-23 11:11:43 | 显示全部楼层
每天学习一点点,谢谢syc

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /1 下一条

QQ
QQ在线咨询
联系电话
13591366679
手机扫一扫 关注本站精彩内容
wxqrcode

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2018-10-16 10:40

Powered by Discuz! X3.4

© 2009-2018 cctry.com

快速回复 返回顶部 返回列表