有些窗口天生就是爲了輔助其它程序而使用的,典型的如“輸入法窗口”。這些窗口不希望搶奪其它窗口的焦點。
有 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
}
}
運行這段代碼,可以發現,即時我們的窗口中文本框獲得了焦點,焦點其實依然在外面的程序中。(我們的文本框依然不會響應鍵盤輸入的。)
參考資料
- 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/),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請與我聯繫。