查看: 715|回复: 0

[C++资源] C++版 【超级模块】之【监视热键】

[复制链接]
发表于 2016-9-19 22:13 | 显示全部楼层 |阅读模式
官方团队 2016-9-19 22:13 715 0 显示全部楼层
最近真的没啥时间了,无聊折腾了些小玩意儿,预计年后才能回归。

前段时间搞DNF辅助,必须要用到热键,C++的那个API RigisterHotkey各种不好使,然后自己对着超级模块封装了一个C++版本的,用着还不错,但是有些小bug。今晚没事回头调了几遍代码,把小bug修复了。现在分享出来,以后大家用C++监视热键的时候也能图个方便。

这个用法也非常简单,你会用超级模块,肯定会用这个,没什么差别。源码中附赠了一个超级模块中的【超级延时】功能函数,还有两个简单的弹窗测试函数。

先贴一下源码吧。

HotKey.h
  1. #ifndef _HOTKEY_H_
  2. #define _HOTKEY_H_

  3. #include<iostream>
  4. #include<cstdlib>
  5. #include<vector>
  6. #include<Windows.h>


  7. #define MOD_NONE 0x0000

  8. typedef unsigned int HOTKEY_ID;
  9. typedef DWORD PFUNC;


  10. typedef struct tagHOTKEY_INFO
  11. {
  12.         HOTKEY_ID HotkeyID;
  13.         PFUNC pfnCallbackFunc;
  14.         BYTE KeyCode;
  15.         BYTE FuncKey;
  16.         BYTE AnotherKeyCode;
  17.         BYTE byKeyStatus;
  18.         BOOL bStatus;
  19.         BOOL bDirectTrigger;
  20. }HOTKEY_INFO, *PHOTKEY_INFO;

  21. void HandleTheEvents();
  22. void SuperDelay(int nElapse, int nUnit = 0);
  23. VOID HotKeyTest();
  24. VOID HotKeyTest2();

  25. HOTKEY_ID HotkeyMonitor(PFUNC pfnCallbackFunc, BYTE KeyCode, BYTE FuncKeyStatus = MOD_NONE, BYTE AnotherKeyCode = 0, UINT uElapse = USER_TIMER_MINIMUM, BOOL bDirectTrigger = FALSE);
  26. VOID CALLBACK HotKeyMonThread(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
  27. BOOL HotKeyUnMonitor(HOTKEY_ID HotkeyID = 0);


  28. #endif
复制代码

HotKey.cpp
  1. #include"stdafx.h"
  2. #include"HotKey.h"


  3. std::vector<HOTKEY_INFO> HotKeyList;

  4. void HandleTheEvents()
  5. {
  6.         MSG msg;
  7.         while (PeekMessage(&msg, 0, 0, 0, 1))
  8.         {
  9.                 DispatchMessage(&msg);
  10.                 TranslateMessage(&msg);
  11.         }
  12. }

  13. void SuperDelay(int nElapse, int nUnit)
  14. {
  15.         LARGE_INTEGER int64;
  16.         HANDLE hTimer;

  17.         if (1 == nUnit)
  18.         {
  19.                 int64.QuadPart = -10 * nElapse;
  20.                 hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
  21.                 SetWaitableTimer(hTimer, &int64, 0, NULL, NULL, FALSE);
  22.                 while (WAIT_OBJECT_0 != MsgWaitForMultipleObjects(1, &hTimer, FALSE, INFINITE, QS_ALLINPUT))
  23.                 {
  24.                         HandleTheEvents();
  25.                 }
  26.                 CloseHandle(hTimer);
  27.                 return;
  28.         }
  29.         switch (nUnit)
  30.         {
  31.         case 0:
  32.                 nUnit = 1;
  33.                 break;
  34.         case 2:
  35.                 nUnit = 1000;
  36.                 break;
  37.         case 3:
  38.                 nUnit = 1000 * 60;
  39.                 break;
  40.         case 4:
  41.                 nUnit = 1000 * 60 * 60;
  42.                 break;
  43.         case 5:
  44.                 nUnit = 1000 * 60 * 60 * 24;
  45.                 break;
  46.         default:
  47.                 break;
  48.         }

  49.         for (int i = 0; i < nUnit; i++)
  50.         {
  51.                 int64.QuadPart = -10 * nElapse * 1000;
  52.                 hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
  53.                 SetWaitableTimer(hTimer, &int64, 0, NULL, NULL, FALSE);
  54.                 while (WAIT_OBJECT_0 != MsgWaitForMultipleObjects(1, &hTimer, FALSE, INFINITE, QS_ALLINPUT))
  55.                 {
  56.                         HandleTheEvents();
  57.                 }
  58.                 CloseHandle(hTimer);
  59.                 return;
  60.         }

  61. }


  62. VOID HotKeyTest()
  63. {
  64.         MessageBox(NULL, _T("Test"), _T("Test"), MB_OK);
  65. }

  66. VOID HotKeyTest2()
  67. {
  68.         MessageBox(NULL, _T("Test2"), _T("Test2"), MB_OK);
  69. }

  70. /*

  71. .Function Name: HotkeyMonitor,监视一个热键, 当热键被触发时激活响应事件.(成功返回热键标识, 失败返回0).注:必须真实的按键才会触发热键
  72. .Parameter pfnCallbackFunc, 子程序指针, , 响应事件(热键标识, 其它...), 事件参数数目不限!如果再次监视热键将响应事件!
  73. .Parameter KeyCode, 字节型, , 触发事件的基本键
  74. .Parameter FuncKeyStatus, 字节型, 可空, 1 Alt  2 Ctrl  4 Shift  8 Win 若要两个或以上的状态键, 则把它们的值相加,可以使用相应的宏MOD_ALT,MOD_CONTROL,MOD_SHIFT,MOD_WIN来位或运算
  75. .Parameter AnotherKeyCode, 字节型, 可空, 如果你需要注册由两个普通键组合的热键, 可设置一个其它键代码.
  76. .Parameter uElapse, 无符号整数型, 可空, 默认为10, 监视热键的周期时间(建议5 - 200之间)
  77. .Parameter bDirectTrigger, 逻辑型, 可空, 默认为假:创建新的线程事件 真 : 直接调用事件等待返回

  78. */
  79. HOTKEY_ID HotkeyMonitor(PFUNC pfnCallbackFunc, BYTE KeyCode, BYTE FuncKeyStatus, BYTE AnotherKeyCode, UINT uElapse, BOOL bDirectTrigger)
  80. {
  81.         HOTKEY_INFO TempHotkeyInfo;

  82.         if (KeyCode <= 0)
  83.                 return 0;

  84.         for (std::vector<HOTKEY_INFO>::iterator it = HotKeyList.begin(); it != HotKeyList.end(); it++)
  85.         {
  86.                 if (it->KeyCode == KeyCode && it->FuncKey == FuncKeyStatus && it->AnotherKeyCode == AnotherKeyCode)
  87.                 {
  88.                         it->pfnCallbackFunc = pfnCallbackFunc;
  89.                         it->bDirectTrigger = bDirectTrigger;
  90.                         if (it->HotkeyID)
  91.                                 return it->HotkeyID;
  92.                         it->HotkeyID = 1000001 + (it - HotKeyList.begin());
  93.                         return it->HotkeyID;
  94.                 }
  95.         }

  96.         TempHotkeyInfo.pfnCallbackFunc = pfnCallbackFunc;
  97.         TempHotkeyInfo.KeyCode = KeyCode;
  98.         TempHotkeyInfo.FuncKey = FuncKeyStatus;
  99.         TempHotkeyInfo.AnotherKeyCode = AnotherKeyCode;
  100.         TempHotkeyInfo.bDirectTrigger = bDirectTrigger;
  101.         TempHotkeyInfo.HotkeyID = 1000001 + HotKeyList.size();

  102.         HotKeyList.push_back(TempHotkeyInfo);

  103.         if (1000001 == TempHotkeyInfo.HotkeyID)
  104.                 SetTimer(NULL, 666, uElapse, (TIMERPROC)&HotKeyMonThread);

  105.         return TempHotkeyInfo.HotkeyID;
  106. }


  107. //监视热键线程
  108. VOID CALLBACK HotKeyMonThread(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
  109. {
  110.         PFUNC pfnTempEvent;
  111.         UINT uTempID;
  112.         SHORT KeyStatusCache[256];
  113.         INT byTemp = 0;

  114.         for (int i = 1; i <= 255; i++)
  115.         {
  116.                 KeyStatusCache = 251;
  117.                 KeyStatusCache = GetAsyncKeyState(i);
  118.         }
  119.         for (std::vector<HOTKEY_INFO>::iterator it = HotKeyList.begin(); it != HotKeyList.end(); it++)
  120.         {
  121.                 if (it->HotkeyID)
  122.                 {
  123.                         byTemp = (BYTE)(it->KeyCode);
  124.                         byTemp = KeyStatusCache[byTemp];

  125.                         if (0 == byTemp || 1 == byTemp)
  126.                         {
  127.                                 if (1 == it->byKeyStatus)
  128.                                         it->byKeyStatus = 2;
  129.                                 else
  130.                                 {
  131.                                         it->byKeyStatus = 0;
  132.                                         continue;
  133.                                 }
  134.                         }
  135.                         else if (byTemp < 0)
  136.                         {
  137.                                 if (0 == it->byKeyStatus)
  138.                                         it->byKeyStatus = 1;
  139.                                 else if (it->byKeyStatus < 0)
  140.                                         continue;
  141.                         }

  142.                         if (it->byKeyStatus > 0 && it->byKeyStatus != 88)
  143.                         {
  144.                                 it->byKeyStatus = 88;
  145.                                 if (it->FuncKey == ((KeyStatusCache[18] < 0 ? MOD_ALT : 0)
  146.                                         | (KeyStatusCache[17] < 0 ? MOD_CONTROL : 0)
  147.                                         | (KeyStatusCache[16] < 0 ? MOD_SHIFT : 0)
  148.                                         | (KeyStatusCache[91] < 0 ? MOD_WIN : 0)))
  149.                                 {
  150.                                         if (it->AnotherKeyCode)
  151.                                         {
  152.                                                 byTemp = it->AnotherKeyCode;
  153.                                                 if (KeyStatusCache[byTemp] >= 0)
  154.                                                         continue;
  155.                                         }
  156.                                         pfnTempEvent = it->pfnCallbackFunc;
  157.                                         uTempID = it->HotkeyID;
  158.                                         if (it->bDirectTrigger)
  159.                                                 CallWindowProcA((WNDPROC)pfnTempEvent, (HWND)uTempID, 0, 0, 0);
  160.                                         else
  161.                                                 CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pfnTempEvent, (LPVOID)uTempID, 0, NULL));
  162.                                 }
  163.                         }
  164.                 }
  165.         }

  166. }

  167. /*

  168. .Function Name: HotKeyUnMonitor, 逻辑型  撤消由监视热键注册的一个或全部热键(成功返回真,失败返回假)
  169. .Parameter HotkeyID, HOTKEY_ID型, 可空, 欲撤消的热键标识,如果留空则撤消全部热键

  170. */

  171. BOOL HotKeyUnMonitor(HOTKEY_ID HotkeyID)
  172. {
  173.         for (std::vector<HOTKEY_INFO>::iterator it = HotKeyList.begin(); it != HotKeyList.end(); it++)
  174.         {
  175.                 if (0 == HotkeyID)
  176.                         it->HotkeyID = 0;
  177.                 else if (HotkeyID == it->HotkeyID)
  178.                 {
  179.                         it->HotkeyID = 0;
  180.                         return TRUE;
  181.                 }
  182.         }
  183.         return (0 == HotkeyID);
  184. }
复制代码

用法:先将这两个文件添加到你的VS工程,要用到监视热键的文件中头部加入#include "HotKey.h"然后调用即可。

例子:


  1. HOTKEY_ID vkid_F2 = 0, vkid_F3 = 0;


  2. //HotKeyTest可以换成你的函数名
  3. vkid_F2 = HotkeyMonitor((PFUNC)&HotKeyTest, VK_F2);
  4. vkid_F3 = HotkeyMonitor((PFUNC)&HotKeyTest2, VK_LEFT, MOD_ALT);

  5. HotKeyUnMonitor(vkid_F3);
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则 返回列表 发新帖

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