当前位置: 首页 > news >正文

.NET/C# 使窗口永不激活(No Activate 永不获得焦点)

有些窗口天生就是为了辅助其它程序而使用的,典型的如“输入法窗口”。这些窗口不希望抢夺其它窗口的焦点。

有 Win32 方法来解决这样的问题,WS_EX_NOACTIVATE 便是关键。


具体来说,是给窗口样式中额外添加一个 WS_EX_NOACTIVATE 位。

var handle = GetTheWindowHandle();
int exstyle = GetWindowLong(handle, GWL_EXSTYLE);
SetWindowLong(handle, GWL_EXSTYLE, exstyle | WS_EX_NOACTIVATE);

当然,这里需要用到 P/Invoke 平台调用,可以阅读 使用 PInvoke.net Visual Studio Extension 辅助编写 Win32 函数签名 了解快速生成平台调用方法签名的方法。

于是,我们将完整的窗口代码写完,是下面这样。

注意 64 位系统中需调用 GetWindowLongPtrSetWindowLongPtr,而 32 位系统中是没有这两个方法的;在任何版本的 Windows 中都是这样。当然,64 位系统会为其上运行的 32 位进程模拟 32 位系统的环境。

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;

namespace Walterlv.Demo
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            SourceInitialized += OnSourceInitialized;
        }
        
        private void OnSourceInitialized(object sender, EventArgs e)
        {
            var handle = new WindowInteropHelper(this).Handle;
            var exstyle = GetWindowLong(handle, GWL_EXSTYLE);
            SetWindowLong(handle, GWL_EXSTYLE, new IntPtr(exstyle.ToInt32() | WS_EX_NOACTIVATE));
        }

        #region Native Methods

        private const int WS_EX_NOACTIVATE = 0x08000000;
        private const int GWL_EXSTYLE = -20;

        public static IntPtr GetWindowLong(IntPtr hWnd, int nIndex)
        {
            return Environment.Is64BitProcess
                ? GetWindowLong64(hWnd, nIndex)
                : GetWindowLong32(hWnd, nIndex);
        }

        public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
        {
            return Environment.Is64BitProcess
                ? SetWindowLong64(hWnd, nIndex, dwNewLong)
                : SetWindowLong32(hWnd, nIndex, dwNewLong);
        }

        [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
        private static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
        private static extern IntPtr GetWindowLong64(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
        private static extern IntPtr SetWindowLong32(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
        private static extern IntPtr SetWindowLong64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        #endregion
    }
}

运行这段代码,可以发现,即时我们的窗口中文本框获得了焦点,焦点其实依然在外面的程序中。(我们的文本框依然不会响应键盘输入的。)

在这里插入图片描述


参考资料

  • c# - Not take focus, but allow interaction? - Stack Overflow
  • Extended Window Styles - Microsoft Docs
  • GetWindowLongPtr function (Windows)
  • SetWindowLongPtr function (Windows)

我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

相关文章:

  • 语法高亮不够漂亮?这里有你想要的 Rouge 主题
  • 理解 UWP 视图的概念,让 UWP 应用显示多个窗口(多视图)
  • UWP 扩展/自定义标题栏的方法,一些概念和一些注意事项
  • 图片点击放大,你的网页也能做到!
  • UWP 应用中 CoreApplication / Application, CoreWindow / Window 之间的区别
  • 使用 C# 代码创建快捷方式文件
  • 发布了一款库(或工具包),如何持续地编写更新日志(ChangeLog)?
  • Windows 无法删除文件夹 —— 访问被拒绝 / 因为目录不是空的
  • 如何精准地用打印机在贺卡或邀请函上打字
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • 使用 Postman 调试 ASP.NET Core 开发的 API
  • 只有你能 new 出来!.NET 隐藏构造函数的 n 种方法(Builder Pattern / 构造器模式)
  • UWP 中的各种文件路径(用户、缓存、漫游、安装……)
  • 使用并解析 OPML 格式的订阅列表来转移自己的 RSS 订阅(解析篇)
  • 使用并解析 OPML 格式的订阅列表来转移自己的 RSS 订阅(概念篇)
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • django开发-定时任务的使用
  • Elasticsearch 参考指南(升级前重新索引)
  • JS基础之数据类型、对象、原型、原型链、继承
  • Promise初体验
  • sessionStorage和localStorage
  • Terraform入门 - 1. 安装Terraform
  • windows下mongoDB的环境配置
  • zookeeper系列(七)实战分布式命名服务
  • 阿里云前端周刊 - 第 26 期
  • 半理解系列--Promise的进化史
  • 深入浅出webpack学习(1)--核心概念
  • 微信支付JSAPI,实测!终极方案
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 怎样选择前端框架
  • 400多位云计算专家和开发者,加入了同一个组织 ...
  • 扩展资源服务器解决oauth2 性能瓶颈
  • # centos7下FFmpeg环境部署记录
  • #13 yum、编译安装与sed命令的使用
  • #大学#套接字
  • $L^p$ 调和函数恒为零
  • (9)目标检测_SSD的原理
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (二开)Flink 修改源码拓展 SQL 语法
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (循环依赖问题)学习spring的第九天
  • .java 指数平滑_转载:二次指数平滑法求预测值的Java代码
  • .Net 8.0 新的变化
  • .Net mvc总结
  • .net Stream篇(六)
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • .NET 中的轻量级线程安全
  • .NET/ASP.NETMVC 深入剖析 Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(二)...
  • .NET设计模式(2):单件模式(Singleton Pattern)
  • .NET实现之(自动更新)
  • .pyc文件还原.py文件_Python什么情况下会生成pyc文件?
  • /ThinkPHP/Library/Think/Storage/Driver/File.class.php  LINE: 48
  • @Async注解的坑,小心
  • [ vulhub漏洞复现篇 ] ECShop 2.x / 3.x SQL注入/远程执行代码漏洞 xianzhi-2017-02-82239600