当前位置: 首页 > 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 订阅(概念篇)
  • 【Amaple教程】5. 插件
  • 【个人向】《HTTP图解》阅后小结
  • docker python 配置
  • ES6 学习笔记(一)let,const和解构赋值
  • extract-text-webpack-plugin用法
  • Java多线程(4):使用线程池执行定时任务
  • Odoo domain写法及运用
  • Promise面试题2实现异步串行执行
  • Transformer-XL: Unleashing the Potential of Attention Models
  • Vue2.0 实现互斥
  • Webpack 4 学习01(基础配置)
  • 高程读书笔记 第六章 面向对象程序设计
  • 关于extract.autodesk.io的一些说明
  • 力扣(LeetCode)56
  • 前嗅ForeSpider中数据浏览界面介绍
  • 深度学习入门:10门免费线上课程推荐
  • 推荐一个React的管理后台框架
  • 用jquery写贪吃蛇
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​Python 3 新特性:类型注解
  • ​TypeScript都不会用,也敢说会前端?
  • #define用法
  • (175)FPGA门控时钟技术
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (理论篇)httpmoudle和httphandler一览
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (十一)图像的罗伯特梯度锐化
  • (转)shell调试方法
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置
  • .NET Core跨平台微服务学习资源
  • .net Signalr 使用笔记
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • .net和php怎么连接,php和apache之间如何连接
  • .Net接口调试与案例
  • /proc/vmstat 详解
  • [ vulhub漏洞复现篇 ] Django SQL注入漏洞复现 CVE-2021-35042