拦截并阻止特定 window 的 ALT 按键

Intercept and prevent ALT keypress for specific window

我构建了一个 C# 应用程序,它采用另一个 window 处理程序及其过程,就像这个 post,我可以通过 PostMessage 从我的应用程序向 window 发送一些命令这个 window 即使在不活动时也会做出相应的反应。

当我按下 ALT 时出现问题,这个 window 像热键一样对 ALT + my_key_command 做出反应。 请解释如何阻止我的应用程序在特定 window 中处理 ALT 按键事件?这可能吗?

我只想关闭这个 window 的 ALT 键。示例如下:

    [DllImport("user32.dll")]
    static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);

    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll", SetLastError = true)]
    private static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

    [STAThread]
    static async Task Main()
    {
        await Task.Delay(TimeSpan.FromSeconds(5));
        IntPtr window = GetForegroundWindow();

        while (true)
        {
            int processId;
            GetWindowThreadProcessId(window, out processId);
            Process[] processes = Process.GetProcessesByName("iexplorer");
            var process = findProcessById(processes, processId);
            if (process != null)
            {
                PostMessage(process.MainWindowHandle, WM_KEYDOWN, 0x74, 0);
            }
            Thread.Sleep(5000);
        }
    }

    static private Process findProcessById(Process[] processes, int id)
    {
        Process result = null;
        foreach (Process proc in processes)
        {
            if (proc.Id == id)
                result = proc;
        }
        return result;
    }

这段代码很适合这些用途,但应用程序处理 ALT+F5 和 F5 命令的方式不同,所以我根本不需要 ALT+F5。这就是为什么我首先想到阻止ALT键。

请使用SetWindowsHookEx and WH_KEYBOARD.

您需要在目标程序中注入一个包含键盘钩子的dll。通过安装键盘钩子,防止ALT键的return。

示例代码:(C++)

.dll:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <windows.h>
#include <iostream>
#include <stdio.h>

HINSTANCE hinst;
#pragma data_seg(".shared")
HHOOK hhk;
#pragma data_seg()

LRESULT CALLBACK wireKeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
    if (code >= 0)
    {       
        switch (wParam)
        {
             case VK_MENU:
             {
                 return 1;
             }
        }
    }
    return CallNextHookEx(hhk, code, wParam, lParam);
}

extern "C" __declspec(dllexport) void install(unsigned long threadID) {
    hhk = SetWindowsHookEx(WH_KEYBOARD, wireKeyboardProc, hinst, threadID);
}
extern "C" __declspec(dllexport) void uninstall() {
    UnhookWindowsHookEx(hhk);
}

BOOL WINAPI DllMain(__in HINSTANCE hinstDLL, __in  DWORD fdwReason, __in  LPVOID lpvReserved) {
    hinst = hinstDLL;
    return TRUE;
}

.cpp

#include <Windows.h>
#include <stdio.h>
#include <tchar.h>

unsigned long GetTargetThreadIdFromWindow(const char* className, const char* windowName)
{
    HWND targetWnd;
    HANDLE hProcess;
    unsigned long processID = 0;

    targetWnd = FindWindow(className, windowName);
    return GetWindowThreadProcessId(targetWnd, &processID);
}

int main() {
    unsigned long threadID = GetTargetThreadIdFromWindow("Notepad", "1.txt - Notepad"); // Use Notepad for test
    printf("TID: %i", threadID);

    HINSTANCE hinst = LoadLibrary(_T("Mydll.dll"));

    if (hinst) {
        typedef void (*Install)(unsigned long);
        typedef void (*Uninstall)();

        Install install = (Install)GetProcAddress(hinst, "install");
        Uninstall uninstall = (Uninstall)GetProcAddress(hinst, "uninstall");

        install(threadID);

        MSG msg = {};

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

        uninstall();
    }

    return 0;
}

我用记事本作为测试对象,效果很好。这是c++代码,你可以根据需要转成C#代码。