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

.NET/C# 使窗口永不获得焦点

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

有 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
    }
}

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

No Activate


参考资料

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

相关文章:

  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • WPF 应用完全模拟 UWP 的标题栏按钮
  • 让控制台支持 ANSI 转义序列,输出下划线、修改颜色或其他控制
  • 在 GitHub 公开仓库中隐藏自己的私人邮箱地址
  • Win32 程序在启动时激活前一个启动程序的窗口
  • C#/.NET 读取或修改文件的创建时间和修改时间
  • 通过解读 WPF 触摸源码,分析 WPF 插拔设备触摸失效的问题(问题篇)
  • .NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)
  • .NET 中 GetProcess 相关方法的性能
  • 常用输入法快速输入自定义格式的时间和日期(搜狗/QQ/手心/微软拼音)
  • 好的框架需要好的 API 设计 —— API 设计的六个原则
  • .NET/C# 使用反射注册事件
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
  • .NET/C# 使用反射调用含 ref 或 out 参数的方法
  • WPF 多线程 UI:设计一个异步加载 UI 的容器
  • AHK 中 = 和 == 等比较运算符的用法
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • JavaScript-Array类型
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • quasar-framework cnodejs社区
  • V4L2视频输入框架概述
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • #include到底该写在哪
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (十三)Flask之特殊装饰器详解
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (原創) 物件導向與老子思想 (OO)
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • .net php 通信,flash与asp/php/asp.net通信的方法
  • .net 发送邮件
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • .NET中GET与SET的用法
  • .Net中的集合
  • [BJDCTF 2020]easy_md5
  • [BZOJ] 2044: 三维导弹拦截
  • [C++] cout、wcout无法正常输出中文字符问题的深入调查(1):各种编译器测试
  • [C++]STL之map
  • [IE编程] 如何获得IE版本号
  • [Jquery] 实现温度计动画效果
  • [LeetCode]—Add Binary 两个字符串二进制相加
  • [leetcode]Clone Graph
  • [LeetCode]剑指 Offer 42. 连续子数组的最大和
  • [Linux]进程信号(信号入门 | 信号产生的方式 | 信号捕捉初识)
  • [pyqt5]pyqt5设置窗口背景图片后上面所有图片都会变成和背景图片一样
  • [Pytorch] pytorch笔记 三
  • [RK-Linux] Linux A/B System详解
  • [蓝桥杯 2022 省 A] 选数异或 题解 含源码
  • [陇剑杯 2021]日志分析
  • [嵌入式系统-4]:龙芯1B 开发学习套件-1-开发版硬件介绍
  • [数据集][目标检测]道路交通事故检测数据集VOC+YOLO格式11819张2类别
  • [数据库基础]——图解JOIN