【问题标题】:C# SendKeys to foreground window in Windows 7 not workingC#SendKeys到Windows 7中的前台窗口不起作用
【发布时间】:2014-03-14 02:22:21
【问题描述】:

我正在尝试在 Visual Studio 2012 中使用 C# 构建一个全局热键应用程序,以便在 Windows 7 上运行。除了 SendKeys 从未在应用程序中显示之外,我一切正常。

这是我用来发送击键的代码:

更新以使用GetFocusedWindow 示例进行调试。

StringBuilder className = new StringBuilder(256);
IntPtr hWnd = GetForegroundWindow();
GetClassName(hWnd, className, className.Capacity);
Debug.WriteLine("Foreground window: {0}={1}", hWnd.ToInt32().ToString("X"), className);
hWnd = GetFocusedWindow();
GetClassName(hWnd, className, className.Capacity);
Debug.WriteLine("Focused window: {0}={1}", hWnd.ToInt32().ToString("X"), className);

SendKeys.Send("Hello World");

当我调试程序时,聚焦记事本,然后点击热键,我收到以下调试消息,并且按键从未插入到记事本中:

Foreground Window: 4F02B6=Notepad
Focused Window: 1B6026A=WindowsForms10.Window.8.app.0.bf7d44_r11_ad1

如何将击键发送到当前前台窗口?

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    前景窗口并不一定意味着聚焦窗口。顶层前台窗口的子窗口可能具有焦点,而您正在向其父窗口发送键。

    从另一个进程中检索获得焦点的子窗口有点棘手。尝试以下GetFocusedWindow 的实现,使用它代替GetForegroundWindow(未经测试):

    static IntPtr GetFocusedWindow()
    {
        uint currentThread = GetCurrentThreadId();
    
        IntPtr activeWindow = GetForegroundWindow();
        uint activeProcess;
        uint activeThread = GetWindowThreadProcessId(activeWindow, out activeProcess);
    
        if (currentThread != activeThread)
            AttachThreadInput(currentThread, activeThread, true);
        try
        {
            return GetFocus();
        }
        finally
        {
            if (currentThread != activeThread)
                AttachThreadInput(currentThread, activeThread, false);
        }
    }
    
    [DllImport("kernel32.dll")]
    static extern uint GetCurrentThreadId();
    
    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();
    
    [DllImport("user32.dll")]
    static extern IntPtr GetFocus();
    
    [DllImport("user32.dll", SetLastError = true)]
    static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
    
    [DllImport("user32.dll")]
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
    

    更新以解决评论:

    当我使用此功能时,它会将焦点设置到我的应用程序窗口。

    很难说出你那边出了什么问题,当焦点在记事本内时,以下内容对我有用:

    private async void Form1_Load(object sender, EventArgs e)
    {
        var className = new StringBuilder(200);
        while (true)
        {
            await Task.Delay(500);
            IntPtr focused = GetFocusedWindow();
            GetClassName(focused, className, className.Capacity);
            var classNameStr = className.ToString();
            this.Text = classNameStr;
            if (classNameStr == "Edit")
                SendKeys.Send("Hello!");
        }
    }
    

    【讨论】:

    • 当我使用此功能时,它会将焦点设置到我的应用程序窗口。
    • 更新问题以使用 GetFocusedWindow 显示调试。
    • @JamesA,我无法复制这个。您能否发布一个可以帮助重新制作的小型 WinForms 应用程序源?
    • 这似乎是不允许服务与桌面交互的问题。我已经通过将应用程序分解为通过 WCF 连接的服务和客户端来解决它。谢谢大家的帮助。
    猜你喜欢
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2011-12-16
    • 1970-01-01
    • 2020-10-13
    • 1970-01-01
    • 1970-01-01
    • 2021-06-01
    相关资源
    最近更新 更多