You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#如何实现点击置顶窗体按钮向其他应用焦点控件发送文本

实现方案

点击置顶窗体按钮时文本无法发送到外部输入框的核心原因是:窗体默认会在点击时抢占输入焦点,导致外部目标文本框丢失光标,SendKeys 无法定位到正确的发送目标。Win+V系统剪贴板面板的核心逻辑就是点击时不抢夺前台焦点,下面提供两种可直接落地的实现,优先推荐第一种:

方法1:配置窗体为点击不抢焦点(交互完全对齐Win+V)

通过重写窗体创建参数添加扩展样式,让窗体点击时永远不抢占其他应用的输入焦点,外部文本框会持续持有闪烁光标,不需要额外做句柄缓存,直接在按钮Click事件写发送逻辑即可。
在窗体类中添加如下代码:

// Win32窗口样式常量
private const int WS_EX_NOACTIVATE = 0x08000000;
private const int WS_EX_TOOLWINDOW = 0x00000080;

protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        // 核心:添加不激活样式,点击窗体/控件时不抢前台焦点
        cp.ExStyle |= WS_EX_NOACTIVATE;
        // 可选:添加工具窗口样式,让窗体不显示在Alt+Tab切换列表中,和Win+V面板行为一致
        cp.ExStyle |= WS_EX_TOOLWINDOW;
        return cp;
    }
}

按钮点击事件直接写发送逻辑即可生效:

private void button1_Click(object sender, EventArgs e)
{
    SendKeys.Send("example");
}

注意:该样式下窗体内的输入类控件(比如文本框、下拉框)无法获得焦点,仅适合纯按钮、纯展示类的悬浮工具窗使用,如果你的窗体本身需要输入交互,请使用方法2。

方法2:缓存焦点切换前的外部窗口句柄(兼容带输入控件的窗体)

如果你的置顶窗体内有需要用户输入的控件,不能配置为不抢焦点,可以在窗体获得焦点的瞬间,把之前持有焦点的外部窗口句柄缓存下来,点击按钮时先把焦点切回目标窗口,再发送文本。
首先引入需要的Win32 API和缓存变量:

using System.Runtime.InteropServices;
using System.Threading;

public partial class MainForm : Form
{
    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();
    
    [DllImport("user32.dll")]
    private static extern bool SetForegroundWindow(IntPtr hWnd);

    // 缓存上一个持有焦点的外部窗口句柄
    private IntPtr _lastTargetHwnd = IntPtr.Zero;

重写窗体激活事件,在焦点从外部应用切到本窗体时记录目标句柄:

protected override void OnActivated(EventArgs e)
    {
        base.OnActivated(e);
        IntPtr prevHwnd = GetForegroundWindow();
        // 过滤掉本窗体自身的句柄,避免缓存错误
        if (prevHwnd != this.Handle)
        {
            _lastTargetHwnd = prevHwnd;
        }
    }

最后在按钮点击事件中实现焦点切回+文本发送逻辑:

private void button1_Click(object sender, EventArgs e)
    {
        if (_lastTargetHwnd == IntPtr.Zero) return;
        
        // 将焦点还给之前操作的外部窗口
        SetForegroundWindow(_lastTargetHwnd);
        // 等待50毫秒确保焦点切换完成,避免文本发送失败
        Thread.Sleep(50);
        SendKeys.Send("example");
    }
}

权限说明:如果目标程序是以管理员身份运行的,受Windows UIPI权限机制限制,普通权限下的SetForegroundWindow会调用失败,此时将你的程序也以管理员身份运行即可正常发送文本。

内容的提问来源于stack exchange,提问作者Caio Souza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 08:33:12