C++捕获键盘特定键,即使在游戏中也是如此

C++ Capturing Keyboard Specific Keys even when in a game

本文关键字:游戏 键盘 C++      更新时间:2023-10-16

我编写了一个程序来更新流媒体时的k/d比率,我希望它易于使用,基本上可以按"shift+1"来增加我的击杀等。。现在,当我在谷歌chrome和其他一些应用程序中时,它可以工作,但当我在游戏中,在这种情况下是Arma,当我按下这些键时,它根本无法工作,我必须alt+tab,然后按下键,它就会工作。有没有办法让程序的关键捕获优先级是绝对的,也就是说比阿玛更重要,即使我在游戏中也会被捕获?

感谢

代码:

#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. 您编写一个钩子,并在运行时将其注入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后,您需要将其注入游戏进程,我建议使用Winject或Extreme Injector。如果你是个冒险家,你可以自己去写一本。我必须注意的是,如果你的游戏是基于多人游戏的,并且它使用了Antiheat,那么如果Antiheat使用白名单系统而不是黑名单系统来扫描游戏模块,你可能会引发某种攻击。

第二种方法是制作普通的可执行文件和SetWindowsHookEx来监视低级键盘事件。我自己很久以前就写过这篇文章,但由于我找不到它,我将简单地为您提供一个使用这种方法的键盘记录程序的例子,进行一些轻微的修改,它应该可以完美地工作,我已经自由地为您布局了一个基本的东西:

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

第二种方法可能会被一些反病毒检测为恶意软件,但它将能够在不进行任何调整的情况下将内容打印到控制台中,并且对初学者来说不那么复杂和简单。

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

对于特定于Windows的应用程序,应该很容易使用:

GetAsyncKeyState()

阅读文档,因为它给出了键的状态,当键向下/向上时,特定的位是开/关的。