1

I am working on an ImGui project, and am trying to find a way to create custom key binds. I thought of just listing every single VK key code in a massive, if statement, but not only would that be bulky, but I would also not take certain keys such as some unique mouse buttons or any other key I may end up missing. I want a function that will store the next mouse or keyboard input into an integer, without the use of a predefined set of available inputs. I want to dynamically recognize any input key.

Minimal example:

const char* cbind0 = "none";
static bool bbind0 = false;
static int ibind0;
if (ImGui::Button(cbind0))
     bbind0 = true
if (bbind0 == true)
{
cbind0 = "press any key...";
CopyNextInputTo(ibind0); // Function to copy pressed key to our integer
}

This code would show up as a box in the GUI, and then the integer ibind0 which is containing our now determined keybind, will be used like so:

static bool option = false;
if (GetAsyncKeyState(ibind0) & 1)
{
option =! option; 
}

And now we can toggle our option on and off either using a GUI checkbox or by pressing the user-determined key. The only problem now being I have no clue how to dynamically record all possible inputs! Does anyone know any possible functions or methods? Thanks!

1 Answers1

0

Assuming you are the one creating the window you're using ImGui on, you can handle WM_KEYDOWN events in your WNDPROC callback. Here's a basic example of this in action that will create a pop-up message box whenever you press a key:

#ifndef UNICODE
#define UNICODE
#endif 

#include <Windows.h>

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
    const wchar_t WINDOW_CLASS_NAME[] = L"Keyboard Listener Class";
    const wchar_t WINDOW_TITLE[] = L"Keyboard Listener";

    WNDCLASS windowClass{};
    windowClass.lpfnWndProc = WindowProc;
    windowClass.hInstance = hInstance;
    windowClass.lpszClassName = WINDOW_CLASS_NAME;
    RegisterClass(&windowClass);

    HWND hWnd = CreateWindowEx(
        0,
        WINDOW_CLASS_NAME,
        WINDOW_TITLE,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 
        CW_USEDEFAULT, 
        CW_USEDEFAULT, 
        CW_USEDEFAULT,
        NULL,   
        NULL,
        hInstance,
        NULL
    );

    if (hWnd == NULL) {
        return EXIT_FAILURE;
    }

    ShowWindow(hWnd, nCmdShow);

    MSG msg{};
    while (GetMessage(&msg, NULL, 0, 0) > 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return EXIT_SUCCESS;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_DESTROY:
            PostQuitMessage(0);
            return EXIT_SUCCESS;
        case WM_KEYDOWN:
            wchar_t keyName[64];
            GetKeyNameText(lParam, keyName, sizeof(keyName));
            MessageBox(hWnd, keyName, L"Key Pressed!", MB_OK);
            return EXIT_SUCCESS;
        default:
            return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }

    return EXIT_SUCCESS;
}

Or, if you aren't the one actually creating the Window, you can hook into another Window's keyboard events using SetWindowsHookEx with the idHook parameter set to WH_KEYBOARD and passing in a KeyboardProc callback to the lpfn parameter.