阻止键盘和鼠标事件到达特定应用程序

问题描述 投票:0回答:1

假设我们无法控制的应用程序安装了某种全局键盘或鼠标挂钩。是否可以阻止这些事件到达此应用程序?

c++ windows hook
1个回答
0
投票

如果您只是想阻止使用 LowLevelKeyboard(或鼠标)的应用程序的输入,那么钩子相当简单。

但是,如果您想阻止输入进入游戏或许多应用程序,则必须编写一个过滤驱动程序。大多数游戏不使用钩子,而是使用 API,例如 DirectInput 或 XInput,我相信它们直接与 HID 驱动程序对话。 我知道有 2 个项目已经做到了这一点,HidHideHidGuardian

至于阻止钩子,我编写了一个快速程序来做到这一点。 它的工作原理是安装自己的键盘钩子,检查要阻止输入的应用程序是否是前台窗口,然后如果是前台窗口,则钩子返回而不是调用下一个钩子。 修改它也很容易包括鼠标输入。 我认为只有在您希望阻止的应用程序之前运行该程序才有效,但这似乎并不重要。

这种方法存在一些问题。如果它不适用于大多数应用程序,或者仅部分适用于某些应用程序,请不要感到惊讶。 我还使用 WinForms 编写了一个测试应用程序来测试阻塞,它将控件文本设置为当前按下的键。它成功阻止了这一点,但它并没有阻止文本框接收其输入。

  • 它也会阻止其他应用程序接收挂钩,而不仅仅是您的目标。
  • 仅当应用程序是前台窗口时才会阻塞,这在大多数情况下可能不是问题,但也可能是问题。
  • 仅阻止应用程序调用其挂钩。如果它从钩子之外的任何地方获取输入,输入将到达应用程序(例如 WinForms 文本框)。

阻塞发生在

LowLevelKeyboardProc_cb,
,剩下的只是设置代码来获取句柄并设置挂钩。

LRESULT CALLBACK LowLevelKeyboardProc_cb(
_In_ int    nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam)
{
    HWND fWnd = GetForegroundWindow();
    
    //hBlock is the handle to the process's main window
    if (fWnd != hBlock || nCode < 0)
        return CallNextHookEx(hookId, nCode, wParam, lParam);
    else
        return 0; //Block
}
#include <iostream>
#include <stdlib.h>
#include <Windows.h>
#include <tlhelp32.h>

void SetHook();
void UninstallHook();
DWORD GetProcessIdFromName(const char* name);
HWND FindTopWindow(DWORD pid);

HWND hBlock;
HHOOK hookId;
DWORD pidBlock;

int main(int argc, char* argv[])
{
    char* processName = argv[1];

    printf("Searching for process \"%s\"...\n", processName);

    while (pidBlock == 0)
    {
        pidBlock = GetProcessIdFromName(processName);
    }

    std::cout << "Found\n";

    //Allow window to initialize.
    Sleep(1000);

    std::cout << "Searching for main window handle...\n";
    
    hBlock = FindTopWindow(pidBlock);
    
    if (hBlock == 0)
    {
        std::cout << "Could not find Window Handle\n";
        return 0;
    }

    std::cout << "Found\n";
    std::cout << "Installing Hook...\n";

    SetHook();

    std::cout << "Blocking...";  

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

LRESULT CALLBACK LowLevelKeyboardProc_cb(
    _In_ int    nCode,
    _In_ WPARAM wParam,
    _In_ LPARAM lParam
)
{
    HWND fWnd = GetForegroundWindow();

    if (fWnd != hBlock || nCode < 0)
        return CallNextHookEx(hookId, nCode, wParam, lParam);
    else
        return 0; //Block
}

void SetHook()
{
    HANDLE hProcess = GetCurrentProcess();
    HMODULE hModule = GetModuleHandle(NULL);

    hookId = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc_cb, hModule, 0);

    CloseHandle(hProcess);
}

void UninstallHook()
{
    if (hookId == 0)
        return;
    std::cout << "Uninstalling Hook.\n";
    UnhookWindowsHookEx(hookId);
    hookId = 0;
}

DWORD GetProcessIdFromName(const char* name)
{
    PROCESSENTRY32 entry;
    entry.dwSize = sizeof(PROCESSENTRY32);

    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (Process32First(snapshot, &entry) == TRUE)
    {
        while (Process32Next(snapshot, &entry) == TRUE)
        {
            size_t nChars;
            char szExeFile[64];
            wcstombs_s(&nChars, szExeFile, entry.szExeFile, sizeof(szExeFile));

            if (_stricmp(szExeFile, name) == 0)
            {
                DWORD pid = entry.th32ProcessID;
                CloseHandle(snapshot);
                return pid;
            }
        }
    }

    CloseHandle(snapshot);

    return 0;
}

HWND FindTopWindow(DWORD pid)
{
    std::pair<HWND, DWORD> params = { 0, pid };

    // Enumerate the windows using a lambda to process each window
    BOOL bResult = EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL
        {
            auto pParams = (std::pair<HWND, DWORD>*)(lParam);

            DWORD processId;
            if (GetWindowThreadProcessId(hwnd, &processId) && processId == pParams->second)
            {
                // Stop enumerating
                SetLastError(-1);
                pParams->first = hwnd;
                return FALSE;
            }

            // Continue enumerating
            return TRUE;
        }, (LPARAM)&params);

    if (!bResult && GetLastError() == -1 && params.first)
    {
        return params.first;
    }

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.