1. 程式人生 > >.NET/C# 使視窗永不啟用(No Activate 永不獲得焦點)

.NET/C# 使視窗永不啟用(No Activate 永不獲得焦點)

原文 .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 位系統中需呼叫 GetWindowLongPtr 和 SetWindowLongPtr,而 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


參考資料

本文會經常更新,請閱讀原文: https://walterlv.com/post/no-activate-window.html

 ,以避免陳舊錯誤知識的誤導,同時有更好的閱讀體驗。