吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 11651|回复: 17
收起左侧

[C&C++ 原创] 【C++】【超级模块】之【监视热键】

[复制链接]
海盗小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童鞋的指正。

再会。以上。


免费评分

参与人数 9吾爱币 +2 热心值 +9 收起 理由
hejialong + 2 + 1 谢谢@Thanks!
yyhf + 1 热心回复!
Cizel + 1 我很赞同!
熊猫京京 + 1 会MFC的大神不多了
我的爱是你 + 1 支持原创,况且这个对新手比较实用
xouou + 1 我很赞同!
repobor + 1 谢谢@Thanks!
寒枫雨雪 + 1 谢谢@Thanks!
zbnysjwsnd8 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

1257210463 发表于 2016-12-11 18:28
请问楼主数组赋值能这样写吗,你这是什么语言或者是什么编译器
SHORT KeyStatusCache[256];
        INT byTemp = 0;

        for (int i = 1; i <= 255; i++)
        {
                KeyStatusCache = 251;
                KeyStatusCache = GetAsyncKeyState(i);
        }

点评

这个语法显然是错误的,不知道怎么当时复制过来成这样了,回头看了下工程源码,发现少了下标i,真是醉了。  发表于 2016-12-12 13:51

免费评分

参与人数 1热心值 +1 收起 理由
海盗小K + 1 热心回复!

查看全部评分

 楼主| 海盗小K 发表于 2016-9-19 22:53
wxj364094000 发表于 2016-9-19 22:51
楼主是用c++& MFC写DNF辅助吗

最开始玩CE,CT。后来转易语言。之前又搞过一段时间MFC EXE,没图标的问题很烦,现在准备用Win32 DLL或者MFC DLL玩劫持。
绘梨衣 发表于 2016-9-19 22:28
xouou 发表于 2016-9-19 22:29
沙发 出租,  2CB/天
wxj364094000 发表于 2016-9-19 22:51
楼主是用c++& MFC写DNF辅助吗
熊猫京京 发表于 2016-9-19 23:39
海盗小K 发表于 2016-9-19 22:53
最开始玩CE,CT。后来转易语言。之前又搞过一段时间MFC EXE,没图标的问题很烦,现在准备用Win32 DLL或者 ...

如今会MFC的大神真是凤毛麟角
夜羽天隐 发表于 2016-9-20 07:21 来自手机
先学的c然后看不懂转的易语言然后又去学的java现在为了考级又学回来了
wxj364094000 发表于 2016-9-20 17:21
夜羽天隐 发表于 2016-9-20 07:21
先学的c然后看不懂转的易语言然后又去学的java现在为了考级又学回来了

c你看不懂?你去看谭浩强写的那本大学教材,就算你是个小学生都能看懂
头像被屏蔽
YY妖爱YY妖 发表于 2016-9-21 09:12
提示: 作者被禁止或删除 内容自动屏蔽
wxj364094000 发表于 2016-9-21 15:46
YY妖爱YY妖 发表于 2016-9-21 09:12
是吗 我不觉得  哦

请问你大学学的什么专业?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-21 19:45

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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