好友
阅读权限35
听众
最后登录1970-1-1
|
海盗小K
发表于 2016-9-19 21:59
本帖最后由 wushaominkk 于 2018-5-7 16:51 编辑
最近真的没啥时间了,无聊折腾了些小玩意儿,预计年后才能回归。
前段时间搞DNF辅助,必须要用到热键,C++的那个API RigisterHotkey各种不好使,然后自己对着超级模块封装了一个C++版本的,用着还不错,但是有些小bug。今晚没事回头调了几遍代码,把小bug修复了。现在分享出来,以后大家用C++监视热键的时候也能图个方便。
这个用法也非常简单,你会用超级模块,肯定会用这个,没什么差别。源码中附赠了一个超级模块中的【超级延时】功能函数,还有两个简单的弹窗测试函数。
先贴一下源码吧。
HotKey.h
[C++] 纯文本查看 复制代码 #ifndef _HOTKEY_H_
#define _HOTKEY_H_
#include<iostream>
#include<cstdlib>
#include<vector>
#include<Windows.h>
#define MOD_NONE 0x0000
typedef unsigned int HOTKEY_ID;
typedef DWORD PFUNC;
typedef struct tagHOTKEY_INFO
{
HOTKEY_ID HotkeyID;
PFUNC pfnCallbackFunc;
BYTE KeyCode;
BYTE FuncKey;
BYTE AnotherKeyCode;
BYTE byKeyStatus;
BOOL bStatus;
BOOL bDirectTrigger;
}HOTKEY_INFO, *PHOTKEY_INFO;
void HandleTheEvents();
void SuperDelay(int nElapse, int nUnit = 0);
VOID HotKeyTest();
VOID HotKeyTest2();
HOTKEY_ID HotkeyMonitor(PFUNC pfnCallbackFunc, BYTE KeyCode, BYTE FuncKeyStatus = MOD_NONE, BYTE AnotherKeyCode = 0, UINT uElapse = USER_TIMER_MINIMUM, BOOL bDirectTrigger = FALSE);
VOID CALLBACK HotKeyMonThread(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
BOOL HotKeyUnMonitor(HOTKEY_ID HotkeyID = 0);
#endif
HotKey.cpp
[C++] 纯文本查看 复制代码 #include"stdafx.h"
#include"HotKey.h"
std::vector<HOTKEY_INFO> HotKeyList;
void HandleTheEvents()
{
MSG msg;
while (PeekMessage(&msg, 0, 0, 0, 1))
{
DispatchMessage(&msg);
TranslateMessage(&msg);
}
}
void SuperDelay(int nElapse, int nUnit)
{
LARGE_INTEGER int64;
HANDLE hTimer;
if (1 == nUnit)
{
int64.QuadPart = -10 * nElapse;
hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
SetWaitableTimer(hTimer, &int64, 0, NULL, NULL, FALSE);
while (WAIT_OBJECT_0 != MsgWaitForMultipleObjects(1, &hTimer, FALSE, INFINITE, QS_ALLINPUT))
{
HandleTheEvents();
}
CloseHandle(hTimer);
return;
}
switch (nUnit)
{
case 0:
nUnit = 1;
break;
case 2:
nUnit = 1000;
break;
case 3:
nUnit = 1000 * 60;
break;
case 4:
nUnit = 1000 * 60 * 60;
break;
case 5:
nUnit = 1000 * 60 * 60 * 24;
break;
default:
break;
}
for (int i = 0; i < nUnit; i++)
{
int64.QuadPart = -10 * nElapse * 1000;
hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
SetWaitableTimer(hTimer, &int64, 0, NULL, NULL, FALSE);
while (WAIT_OBJECT_0 != MsgWaitForMultipleObjects(1, &hTimer, FALSE, INFINITE, QS_ALLINPUT))
{
HandleTheEvents();
}
CloseHandle(hTimer);
return;
}
}
VOID HotKeyTest()
{
MessageBox(NULL, _T("Test"), _T("Test"), MB_OK);
}
VOID HotKeyTest2()
{
MessageBox(NULL, _T("Test2"), _T("Test2"), MB_OK);
}
/*
.Function Name: HotkeyMonitor,监视一个热键, 当热键被触发时激活响应事件.(成功返回热键标识, 失败返回0).注:必须真实的按键才会触发热键
.Parameter pfnCallbackFunc, 子程序指针, , 响应事件(热键标识, 其它...), 事件参数数目不限!如果再次监视热键将响应事件!
.Parameter KeyCode, 字节型, , 触发事件的基本键
.Parameter FuncKeyStatus, 字节型, 可空, 1 Alt 2 Ctrl 4 Shift 8 Win 若要两个或以上的状态键, 则把它们的值相加,可以使用相应的宏MOD_ALT,MOD_CONTROL,MOD_SHIFT,MOD_WIN来位或运算
.Parameter AnotherKeyCode, 字节型, 可空, 如果你需要注册由两个普通键组合的热键, 可设置一个其它键代码.
.Parameter uElapse, 无符号整数型, 可空, 默认为10, 监视热键的周期时间(建议5 - 200之间)
.Parameter bDirectTrigger, 逻辑型, 可空, 默认为假:创建新的线程事件 真 : 直接调用事件等待返回
*/
HOTKEY_ID HotkeyMonitor(PFUNC pfnCallbackFunc, BYTE KeyCode, BYTE FuncKeyStatus, BYTE AnotherKeyCode, UINT uElapse, BOOL bDirectTrigger)
{
HOTKEY_INFO TempHotkeyInfo;
if (KeyCode <= 0)
return 0;
for (std::vector<HOTKEY_INFO>::iterator it = HotKeyList.begin(); it != HotKeyList.end(); it++)
{
if (it->KeyCode == KeyCode && it->FuncKey == FuncKeyStatus && it->AnotherKeyCode == AnotherKeyCode)
{
it->pfnCallbackFunc = pfnCallbackFunc;
it->bDirectTrigger = bDirectTrigger;
if (it->HotkeyID)
return it->HotkeyID;
it->HotkeyID = 1000001 + (it - HotKeyList.begin());
return it->HotkeyID;
}
}
TempHotkeyInfo.pfnCallbackFunc = pfnCallbackFunc;
TempHotkeyInfo.KeyCode = KeyCode;
TempHotkeyInfo.FuncKey = FuncKeyStatus;
TempHotkeyInfo.AnotherKeyCode = AnotherKeyCode;
TempHotkeyInfo.bDirectTrigger = bDirectTrigger;
TempHotkeyInfo.HotkeyID = 1000001 + HotKeyList.size();
HotKeyList.push_back(TempHotkeyInfo);
if (1000001 == TempHotkeyInfo.HotkeyID)
SetTimer(NULL, 666, uElapse, (TIMERPROC)&HotKeyMonThread);
return TempHotkeyInfo.HotkeyID;
}
//监视热键线程
VOID CALLBACK HotKeyMonThread(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
PFUNC pfnTempEvent;
UINT uTempID;
SHORT KeyStatusCache[256];
INT byTemp = 0;
for (int i = 1; i <= 255; i++)
{
KeyStatusCache[i] = 251;
KeyStatusCache[i] = GetAsyncKeyState(i);
}
for (std::vector<HOTKEY_INFO>::iterator it = HotKeyList.begin(); it != HotKeyList.end(); it++)
{
if (it->HotkeyID)
{
byTemp = (BYTE)(it->KeyCode);
byTemp = KeyStatusCache[byTemp];
if (0 == byTemp || 1 == byTemp)
{
if (1 == it->byKeyStatus)
it->byKeyStatus = 2;
else
{
it->byKeyStatus = 0;
continue;
}
}
else if (byTemp < 0)
{
if (0 == it->byKeyStatus)
it->byKeyStatus = 1;
else if (it->byKeyStatus < 0)
continue;
}
if (it->byKeyStatus > 0 && it->byKeyStatus != 88)
{
it->byKeyStatus = 88;
if (it->FuncKey == ((KeyStatusCache[18] < 0 ? MOD_ALT : 0)
| (KeyStatusCache[17] < 0 ? MOD_CONTROL : 0)
| (KeyStatusCache[16] < 0 ? MOD_SHIFT : 0)
| (KeyStatusCache[91] < 0 ? MOD_WIN : 0)))
{
if (it->AnotherKeyCode)
{
byTemp = it->AnotherKeyCode;
if (KeyStatusCache[byTemp] >= 0)
continue;
}
pfnTempEvent = it->pfnCallbackFunc;
uTempID = it->HotkeyID;
if (it->bDirectTrigger)
CallWindowProcA((WNDPROC)pfnTempEvent, (HWND)uTempID, 0, 0, 0);
else
CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pfnTempEvent, (LPVOID)uTempID, 0, NULL));
}
}
}
}
}
/*
.Function Name: HotKeyUnMonitor, 逻辑型 撤消由监视热键注册的一个或全部热键(成功返回真,失败返回假)
.Parameter HotkeyID, HOTKEY_ID型, 可空, 欲撤消的热键标识,如果留空则撤消全部热键
*/
BOOL HotKeyUnMonitor(HOTKEY_ID HotkeyID)
{
for (std::vector<HOTKEY_INFO>::iterator it = HotKeyList.begin(); it != HotKeyList.end(); it++)
{
if (0 == HotkeyID)
it->HotkeyID = 0;
else if (HotkeyID == it->HotkeyID)
{
it->HotkeyID = 0;
return TRUE;
}
}
return (0 == HotkeyID);
}
用法:先将这两个文件添加到你的VS工程,要用到监视热键的文件中头部加入#include "HotKey.h"然后调用即可。
例子:
[C++] 纯文本查看 复制代码
HOTKEY_ID vkid_F2 = 0, vkid_F3 = 0;
//HotKeyTest可以换成你的函数名
vkid_F2 = HotkeyMonitor((PFUNC)&HotKeyTest, VK_F2);
vkid_F3 = HotkeyMonitor((PFUNC)&HotKeyTest2, VK_LEFT, MOD_ALT);
HotKeyUnMonitor(vkid_F3);
文件简单,也懒得搞什么排版了。。。
注意:这是我从MFC工程中扒下来的,所以有#include "stdafx.h",如果你要用于非MFC工程的话,去掉该行,并添加#include <tchat.h>
感谢1257210463童鞋的指正。
再会。以上。
|
免费评分
-
查看全部评分
|