Нажатие клавиши со стрелкой обнаружено в ЛЮБОЙ ТОЧКЕ - PullRequest
0 голосов
/ 25 октября 2019

Я провел некоторый поиск того, как обнаружение нажатий клавиш работает с c ++, и у меня есть программа обнаружения клавиш, которая проверяет Вниз и Клавиша со стрелкой вправо , которая работает нормально. Однако у меня есть другая очень простая программа ввода, и я хочу знать, возможно ли иметь возможность обнаружить нажатие клавиши со стрелкой, когда пользователь вводит где-то еще , то есть, например, в переменную something1,

Вот что я имею в виду:

#include <iostream>
#include <string>
#include <Windows.h>
#include <conio.h>

using namespace std;

#define KEY_RIGHT 77
#define KEY_DOWN 80

string something1, something2, something3;

bool loggedIn = false;
int value = 0;

void type() {
cout << "Type something: ";
cin >> something1;

cout << "Type something again: ";
cin >> something2;

cout << "Type something one more time: ";
cin >> something3;
}

int main()
{
type();

while (loggedIn == false)
{
    value = 0;

    switch ((value = _getch())) {
        break;
    case KEY_DOWN:
        cout << "You pressed the Down Arrow Key" << endl;
        break;
    case KEY_RIGHT:
        cout << "You pressed the Right Arrow Key" << endl;
        break;
    }

}
}

Функция type() запрашивает у пользователя 3 строки, поэтому мы не запускаем цикл while до тех пор, пока не будут переданы все 3 строки. Но есть ли способ каким-то образом объединить эти 2 блока кода, чтобы, в то время как пользователь, например, вводил переменную something1 и нажимал Стрелка вниз , они бросали сообщение в KEY_DOWN case?

Я не уверен, что такое возможно, но я подумал, стоит ли спрашивать.

1 Ответ

0 голосов
/ 29 октября 2019

Как сказал @ Реми Лебо, вы можете использовать SetWindowsHookEx () для обнаружения клавиши со стрелкой.

Вот пример:

#define _WIN32_WINNT 0x0400
#pragma comment( lib, "user32.lib" )

#include <Windows.h>
#include <conio.h>
#include <stdio.h>
#include <iostream>
#include <string>

using namespace std;

HHOOK hKeyboardHook;
string something1;
string something2;
string something3;

__declspec(dllexport) LRESULT CALLBACK KeyboardEvent(int nCode, WPARAM wParam, LPARAM lParam)
{
    DWORD SHIFT_key = 0;
    DWORD CTRL_key = 0;
    DWORD ALT_key = 0;


    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;
        int key = hooked_key.vkCode;
        if (key == 40)
        {
            cout << "You pressed the Down Arrow Key" << endl;
        }   

    }
    return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}

void MessageLoop()
{
    MSG message;
    while (GetMessage(&message, NULL, 0, 0))
    {
        TranslateMessage(&message);
        DispatchMessage(&message);
    }
}

DWORD WINAPI my_HotKey(LPVOID lpParm)
{
    HINSTANCE hInstance = GetModuleHandle(NULL);
    if (!hInstance) hInstance = LoadLibrary((LPCSTR)lpParm);
    if (!hInstance) return 1;

    hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyboardEvent, hInstance, NULL);
    MessageLoop();
    UnhookWindowsHookEx(hKeyboardHook);
    return 0;
}

int main(int argc, char** argv)
{
    HANDLE hThread;
    DWORD dwThread; 
    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
    DWORD mode = 0;

    GetConsoleMode(out, &mode);
    SetConsoleMode(out, mode &~ENABLE_LINE_INPUT);

    hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)my_HotKey, (LPVOID)argv[0], NULL, &dwThread);

    std::cout << "Type something: " << endl;
    cin >> something1 ;
    std::cout << "Type something again: " << endl;
    cin >> something2;
    std::cout << "Type something one more time: " << endl;
    cin >> something3;

    /* uncomment to hide console window */
 //ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);
    //Used for test:
    std::cout<< "----" << something1;
    std::cout << "-------" << something2;
    std::cout << "----------" << something3;
    if (hThread) return WaitForSingleObject(hThread, INFINITE);
    else return 1;

}

Отладка:

enter image description here

Если вы не знаете, как пользоваться крючком, обратитесь к официальной документации.

Ссылка: Использование хуков

Вам нужно создать еще один поток для размещения MessageLoop, потому что оба входных потока MessageLoop и cin имеют механизмы блокировки.

Примечание: Из-за механизма кэширования самой консоли, для некоторых эффектов клавиш со стрелками, таких как ввод символов, нажатие стрелки вверх очистит символы. Пожалуйста, попробуйте сами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...