C++ 即使在游戏中也能捕获键盘特定键

标签 c++ keyboard record keystroke

我编写了一个程序来在流式传输时更新我的​​ k/d 比率,我希望它易于使用,基本上能够按“shift + 1”来增加我的杀戮等。 现在当我在谷歌浏览器和其他一些应用程序中时它可以工作,但是当我在游戏中时,在这种情况下是 Arma,当我按下这些键时它只是不这样做,我必须 alt+tab 然后按下按键,它就会工作。 有什么方法可以使程序的关键捕获优先级是绝对的,也就是比 Arma 更重要,即使我在游戏中也会被捕获?

谢谢

代码:

#include <iostream>
#include <windows.h>

using namespace std;

int main(int argc, const char * argv[]) {
RegisterHotKey(NULL, 1, MOD_SHIFT, 0x31); // shift + 1
RegisterHotKey(NULL, 2, MOD_SHIFT, 0x32);// shift + 2
RegisterHotKey(NULL, 3, MOD_SHIFT, 0x33);// shift + 3
RegisterHotKey(NULL, 4, MOD_SHIFT, 0x30);// shift + 0
//shift + 1 = kill
//shift + 2 = death
//shift + 3 = reset
//shift + 0 = close;
int exit = 0;
int kill = 0;
int death = 0;

cout << "K: " << kill << endl;
cout << "D: " << death;

do
{
    int showKill = kill;
    int showDeath = death;
    do
    {
        MSG msg = {0};
        if (GetMessageA(&msg, NULL, 0, 0) != 0)
            if(msg.message == WM_HOTKEY)
            {
                if(msg.wParam == 1)
                    kill++;
                else if(msg.wParam == 2)
                    death++;
                else if(msg.wParam == 3)
                {
                    kill = 0;
                    death = 0;
                }
                else
                {
                    exit++;
                    break;
                }
            }
    }
    while(kill == showKill && death == showDeath);

    system("CLS");//clear the console
    cout << "K: " << kill << endl;
    cout << "D: " << death;
}
while(exit == 0);


UnregisterHotKey(NULL, 1);
UnregisterHotKey(NULL, 2);
UnregisterHotKey(NULL, 3);
UnregisterHotKey(NULL, 4);
return 0;
}

最佳答案

根据我的想法,假设您在 Windows 上玩游戏,有两种非常简单的方法可以解决此问题:

  1. 您编写一个钩子(Hook)并在运行时将其注入(inject) game.exe。
  2. 您使用 SetWindowsHookEx 并捕获键盘低级输入事件。

第一种方法要求您编写一个 dll 模块,这样您就可以使用大部分已经编写的代码,它应该是这样的:

#include <windows.h>
#include <iostream>

using namespace std;

DWORD WINAPI KeyThread(LPVOID)
{
    RegisterHotKey(NULL, 1, MOD_SHIFT, 0x31); // shift + 1
    RegisterHotKey(NULL, 2, MOD_SHIFT, 0x32);// shift + 2
    RegisterHotKey(NULL, 3, MOD_SHIFT, 0x33);// shift + 3
    RegisterHotKey(NULL, 4, MOD_SHIFT, 0x30);// shift + 0
    //shift + 1 = kill
    //shift + 2 = death
    //shift + 3 = reset
    //shift + 0 = close;
    int exit = 0;
    int kill = 0;
    int death = 0;

    // There's no console here so cout won't work, you'll need to use MessageBox or make a file log somewhere
    cout << "K: " << kill << endl;
    cout << "D: " << death;

    do
    {
        int showKill = kill;
        int showDeath = death;
        do
        {
            MSG msg = {0};
            if (GetMessageA(&msg, NULL, 0, 0) != 0)
                if(msg.message == WM_HOTKEY)
                {
                    if(msg.wParam == 1)
                        kill++;
                    else if(msg.wParam == 2)
                        death++;
                    else if(msg.wParam == 3)
                    {
                        kill = 0;
                        death = 0;
                    }
                    else
                    {
                        exit++;
                        break;
                    }
                }
        }
        while(kill == showKill && death == showDeath);

        system("CLS");//clear the console
        cout << "K: " << kill << endl;
        cout << "D: " << death;
    }while(exit == 0);


    UnregisterHotKey(NULL, 1);
    UnregisterHotKey(NULL, 2);
    UnregisterHotKey(NULL, 3);
    UnregisterHotKey(NULL, 4);
}

BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID lpvReserved)
{
    if (fdwReason == DLL_PROCESS_ATTACH)
    {
        CreateThread(NULL, NULL, KeyThread, NULL, NULL, NULL);
    }
    return TRUE;
}

编译dll后你需要将它注入(inject)你的游戏进程,我推荐WinjectExtreme Injector .如果你胆子大,你可以自己写一个。我必须注意,如果您的游戏是基于多人游戏并且使用了反作弊,那么如果该反作弊使用白名单系统而不是黑名单系统来扫描游戏模块,您可能会触发某种攻击。

第二种方法是制作普通的可执行文件和SetWindowsHookEx监视低级键盘事件。这是我自己很久以前写的,但找不到了,我就简单地给你一个example of keylogger使用这种方法,稍微修改一下,它应该可以完美地工作,我冒昧地为你设计了一个基本的东西:

#include <windows.h>
#include <stdio.h>

HHOOK hKeyboardHook = NULL;
LRESULT WINAPI LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if ((nCode == HC_ACTION) && ((wParam == WM_SYSKEYDOWN) || (wParam == WM_KEYDOWN)))
    {
        KBDLLHOOKSTRUCT hooked_key = *((KBDLLHOOKSTRUCT*)lParam);
        DWORD dwMsg = 1;
        dwMsg += hooked_key.scanCode << 16;
        dwMsg += hooked_key.flags << 24;
        char lpszKeyName[1024] = { 0 };
        lpszKeyName[0] = '[';
        int i = GetKeyNameText(dwMsg, (lpszKeyName + 1), 0xFF) + 1;
        int key = hooked_key.vkCode;
        lpszKeyName[i] = ']';

        if (key >= 'A' && key <= 'Z')
        {
            if (GetAsyncKeyState(VK_SHIFT) >= 0)
            {
                key += 0x20;
            }
                printf("%c \n", key);
        }

        else
        {
            printf("%s \n", lpszKeyName);
        }
    }
    return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}


int main()
{
    MSG message;
    HINSTANCE hins;
    hins = GetModuleHandle(NULL);
    hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)LowLevelKeyboardProc, hins, 0);

    // Message pump
    while (GetMessage(&message, NULL, 0, 0))
    {
        TranslateMessage(&message);
        DispatchMessage(&message);
    }
    UnhookWindowsHookEx(hKeyboardHook);
    return 0;
}

第二种方法可能会被某些防病毒软件检测为恶意软件,但它无需任何调整即可将内容打印到控制台,并且对初学者来说不那么复杂和直接。

我必须提到代码示例未经测试,因此可能存在一些语法错误,但逻辑本身应该是正确的。

关于C++ 即使在游戏中也能捕获键盘特定键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33747930/

相关文章:

c++ - Xcode 错误编译 C++ 预期成员名称或声明说明符后的 ';'

iOS滚动到 View 文本字段之外

database - 行、记录和元组之间有什么区别?

javascript - 如何合并两个音频文件 - JavaScript?

c++ - operator= 和 C++ 中未继承的函数?

c++ - 成员因以下成员的初始化而损坏

ios - Facebook 和键盘动画管理

mysql - 如何获取每个类别具有不同限制的类别随机记录

C++ : Confused in dealing with multiple classes

javascript - 在 jQuery 中绑定(bind)箭头键(输入和文本区域除外)