在 WPF 中,若是想要使用代碼控制,讓某個窗口做爲當前用戶的輸入的邏輯焦點的窗口,也就是在當前用戶活動的窗口的最上層窗口,默認使用 Activate 方法,經過這個方法在大部分設備均可以作到激活窗口html
可是在一些特殊的設備上,使用下面代碼調起窗口只是在任務欄閃爍圖標,而沒有讓窗口放在最上層git
window.Show(); window.Activate();
在大部分設備上,經過 Show 和 Activate 組合可讓窗口做爲當前用戶活動的,即便窗口以前是最小化或隱藏,均可以經過 Show 的方法顯示github
可是某些設備窗口被蓋在其餘的窗口的下面,此時的窗口的 window.IsActive 仍是 true 可是調用 Activate 不會讓窗口放在上層c#
我在網上看到好多小夥伴調用了 SetForegroundWindow 方法,其實如今 WPF 是開源的,能夠看到 Window 的 Activate 方法是這樣寫工具
public bool Activate() { // this call ends up throwing an exception if Activate // is not allowed VerifyApiSupported(); VerifyContextAndObjectState(); VerifyHwndCreateShowState(); // Adding check for IsCompositionTargetInvalid if (IsSourceWindowNull || IsCompositionTargetInvalid) { return false; } return UnsafeNativeMethods.SetForegroundWindow(new HandleRef(null, CriticalHandle)); }
源代碼請看 github測試
也就是調用 SetForegroundWindow 和調用 Activate 方法是差很少的,若是調用 Activate 應該調用 SetForegroundWindow 也差很少this
經過大佬的 SetForegroundWindow的正確用法 - 子塢 - 博客園 能夠了解到,須要按照如下步驟線程
1.獲得窗口句柄FindWindow 2.切換鍵盤輸入焦點AttachThreadInput 3.顯示窗口ShowWindow(有些窗口被最小化/隱藏了) 4.更改窗口的Zorder,SetWindowPos使之最上,爲了避免影響後續窗口的Zorder,改完以後,再還原 5.最後SetForegroundWindow
在 WPF 中對應的更改窗口的順序使用的是 Topmost 屬性,同時設置順序須要作必定小的更改code
在 WPF 中經過 c# - Bring a window to the front in WPF - Stack Overflow 能夠了解到如何用 AttachThreadInput 方法htm
整個代碼請看下面,具體的 win32 方法我就沒有寫出來了,請小夥伴本身添加
private static void SetWindowToForegroundWithAttachThreadInput(Window window) { var interopHelper = new WindowInteropHelper(window); var thisWindowThreadId = Win32.User32.GetWindowThreadProcessId(interopHelper.Handle, IntPtr.Zero); var currentForegroundWindow = Win32.User32.GetForegroundWindow(); var currentForegroundWindowThreadId = Win32.User32.GetWindowThreadProcessId(currentForegroundWindow, IntPtr.Zero); // [c# - Bring a window to the front in WPF - Stack Overflow](https://stackoverflow.com/questions/257587/bring-a-window-to-the-front-in-wpf ) // [SetForegroundWindow的正確用法 - 子塢 - 博客園](https://www.cnblogs.com/ziwuge/archive/2012/01/06/2315342.html ) /* 1.獲得窗口句柄FindWindow 2.切換鍵盤輸入焦點AttachThreadInput 3.顯示窗口ShowWindow(有些窗口被最小化/隱藏了) 4.更改窗口的Zorder,SetWindowPos使之最上,爲了避免影響後續窗口的Zorder,改完以後,再還原 5.最後SetForegroundWindow */ Win32.User32.AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, true); window.Show(); window.Activate(); // 去掉和其餘線程的輸入連接 Win32.User32.AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, false); // 用於踢掉其餘的在上層的窗口 window.Topmost = true; window.Topmost = false;
我測試了幾個本來沒有讓窗口放在上層的設備,使用上面的代碼能夠設置,可是我不瞭解設置上面代碼可能的坑是什麼
附帶 walterlv 的測試工具,能夠用來拿到當前的 GetForegroundWindow 是哪一個
另外少君小夥伴寫了一個有趣的庫,裏面封裝了不少 win32 的方法,請看 kkwpsv lsjutil