zoukankan      html  css  js  c++  java
  • .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


    参考资料

  • 相关阅读:
    从人群中看出真正优秀的人!
    新东方在厦门大学演讲--笔摘
    vuepress+gitee 构建在线项目文档
    二维码科普
    Linux访问Window共享文件夹的配置步骤
    SQL Server使用笔记
    Progress笔记
    Linux使用笔记
    Linux下配置mail使用外部SMTP发送邮件
    SaaS、PaaS、IaaS的含义与区别
  • 原文地址:https://www.cnblogs.com/walterlv/p/10236434.html
Copyright © 2011-2022 走看看