流沙团
vc++基础班[12]---注册全局系统热键
2017-9-12 流沙团
vc++基础班[12]---注册全局系统热键

------------------------------------------ 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;

}
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容