拦截并阻止特定窗口的 ALT 按键

Posted

技术标签:

【中文标题】拦截并阻止特定窗口的 ALT 按键【英文标题】:Intercept and prevent ALT keypress for specific window 【发布时间】:2020-08-24 16:41:19 【问题描述】:

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

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

我只想为 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;
    

【问题讨论】:

注入一个使用SetWindowsHookEx的dll和一个键盘钩子来钩键.. 使用 WindowsHooks 时要非常小心 - 了解可以搞砸事情的各种方式。 您要解决什么问题?这个问题询问您提出的解决方案。这种现象通常被描述为XY Problem。 我没有看到代码中建立了任何窗口层次结构。不过,我确实看到了带有 WM_KEYDOWN 消息的 PostMessage。众所周知,you can't simulate keyboard input with PostMessage。那么,您要解决的真正问题是什么? 我需要我的应用程序将 F1、F2、... F12 等命令发送到另一个应用程序(窗口),例如 Internet Explorer。此代码适用于这些目的,但应用程序处理 ALT+F5 和 F5 命令的方式不同,所以我根本不需要 ALT+F5。这就是为什么我首先想到要阻止 ALT 键。如果有其他方法可以解决这个问题,我会尝试所有方法 【参考方案1】:

这段代码可以很好地用于这些目的,但是应用程序处理 ALT+F5 和 F5 命令的方式不同,所以我根本不需要 ALT+F5。这就是为什么我首先想到要屏蔽 ALT 键。

请使用SetWindowsHookEx 和WH_KEYBOARD。

您需要将包含键盘挂钩的 dll 注入目标程序。通过安装一个键盘挂钩,并防止 ALT 键返回。

示例代码:(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#代码。

【讨论】:

谢谢!我会尽快尝试的!

以上是关于拦截并阻止特定窗口的 ALT 按键的主要内容,如果未能解决你的问题,请参考以下文章

怎么关闭广告拦截插件?

wpf阻止键盘快捷键alt+space,alt+F4

解决弹出的窗口window.open会被浏览器阻止的问题

IE8怎么把已经允许弹出的窗口重新阻止该窗口弹出呢?

阻止特定进程的 Windows 错误报告 (DW20.exe) 窗口

苹果手机怎么阻止弹出网页