如何正确使用键盘钩按键组合以阻止键并再次按C 将其解开

How to correctly use keyboard hooks to press a key combination to block a key and to press it again to unblock it in C++

本文关键字:何正确 键盘 组合      更新时间:2023-10-16

在以下代码中,我没有构建错误,但是"键a被阻止"。未在运行时打印:

#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <Windows.h>
#include <sstream>
#define _WIN32_WINNT 0x050
using namespace std;
string intToHexString(int intValue) {
    string hexStr;
    /// integer value to hex-string
    stringstream sstream;
    sstream << "0x" <<  hex << (int)intValue;
    hexStr = sstream.str();
    sstream.clear();    //clears out the stream-string
    return hexStr;
}
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    BOOL locked = FALSE;
    PKBDLLHOOKSTRUCT hookStruct;
    if (nCode == HC_ACTION) {
        switch (wParam)
        {
        case WM_KEYDOWN:
        case WM_SYSKEYDOWN:
        case WM_KEYUP:
        case WM_SYSKEYUP:
            hookStruct = (PKBDLLHOOKSTRUCT)lParam;
      /**
        * this is where the problem is
      */
            //ctrl+alt+n
            if (hookStruct->vkCode == 0x11 && hookStruct->vkCode == 0x12 && hookStruct->vkCode == 0x4E
                && !locked) {
                locked = TRUE;
                if (hookStruct->vkCode == 0x41) {
                    cout << "The key A is blocked" << endl;
                    return 1;
                }
            }
            else if (hookStruct->vkCode == 0x11 && hookStruct->vkCode == 0x12 && hookStruct->vkCode == 0x4E) {
                locked = FALSE;
                BlockInput(locked);
                cout << "The key is unblocked" << endl;
            }
            else {
                return CallNextHookEx(NULL, nCode, wParam, lParam);
            }
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}
int main()
{
    char key_pressed;
    int ascii_value;
    string key_press_special;
    HHOOK hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0);
    cout << "press any key to see it's Character, ASCII and Scan Code" << endl;
    cout << "Press ESC key to Exit" << endl;
    while(1) {
        key_pressed = _getch();
        if (key_pressed == 13) {
            key_press_special = "Enter";
            cout << "Character: " << key_press_special << endl;
        }
        else if (key_pressed == 9) {
            key_press_special = "Tab";
            cout << "Character: " << key_press_special << endl;
        }
        else if (key_pressed == 27) {
            key_press_special = "ESC";
            cout << "Character: " << key_press_special << endl;
        }
        else {
            cout << "Character: " << key_pressed << endl;
        }
         ascii_value = key_pressed;
        cout << "The ASCII Value is: " << ascii_value << endl;
        int scan = MapVirtualKey(ascii_value, 0);
        string scanCode = intToHexString(scan);
        cout << "Scan Code is: " << scanCode << endl;
        if (key_pressed == 27) {
            break;
        }
        else {
            continue;
        }
    }
    
    UnhookWindowsHookEx(hhkLowLevelKybd);
    return 0;
}

您的钩子正在尝试处理完整的 ctrl alt n 序列关键,这根本不是它的工作方式。您必须单独处理键。

尝试更多这样的东西:

bool ctrlDown = false;
bool altDown = false;
bool nDown = false;
bool locked = false;
void UpdateLock()
{
    if (ctrlDown && altDown && nDown) {
        locked = !locked;
        if (!locked) BlockInput(FALSE);
        cout << (locked ? "" : "not ") << "locked" << endl;
    }
}
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION) {
        PKBDLLHOOKSTRUCT hookStruct = (PKBDLLHOOKSTRUCT) lParam;
        switch (wParam)
        {
        case WM_KEYDOWN:
        case WM_SYSKEYDOWN:
            switch (hookStruct->vkCode)
            {
            case VK_CONTROL:
                if (!ctrlDown) {
                    ctrlDown = true;
                    UpdateLock();
                }
                break;
            case VK_MENU:
                if (!altDown) {
                    altDown = true;
                    UpdateLock();
                }
                break;
            case 'N':
                if (!nDown) {
                    nDown = true;
                    UpdateLock();
                }
                break;
            }
            break;
        case WM_KEYUP:
        case WM_SYSKEYUP:
            switch (hookStruct->vkCode)
            {
            case VK_CONTROL:
                ctrlDown = false;
                break;
            case VK_MENU:
                altDown = false;
                break;
            case 'N':
                nDown = false;
                break;
           }
           break;
        }
        if ((hookStruct->vkCode == 'A') && locked) {
            cout << "The key A is blocked" << endl;
            return 1;
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

uptevoted答案无法正常工作,因为LowlevelkeyboardProc永远不会收到vk_control,至少在WinxP和以后。它始终是vk_lcontrol或vk_rcontrol。否则,这是一个好主意,但是显然它从未经过编译和测试,因此可能还有其他错误。

对于可能过于杀伤但充满爱意的示例,请查看Autohotkey的来源:

https://github.com/autohotkey/autohotkey/blob/master/source/hook.cpp#l201