From 7151fec7b82c536f6f52ef852e48f130d4669769 Mon Sep 17 00:00:00 2001 From: lindexi Date: Thu, 13 Aug 2020 22:49:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E4=B8=8A=E8=AE=BE=E7=BD=AE=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E5=88=B0=E6=9C=80=E5=89=8D=E7=9A=84=E8=BE=85=E5=8A=A9?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Tools/Helper/WindowHelper.cs | 39 +++++++++++++++++++ .../Tools/Interop/InteropMethods.cs | 7 ++++ 2 files changed, 46 insertions(+) diff --git a/src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs b/src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs index b951640a..41436aac 100644 --- a/src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs +++ b/src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs @@ -152,5 +152,44 @@ namespace HandyControl.Tools public static IntPtr GetHandle(this Window window) => new WindowInteropHelper(window).EnsureHandle(); public static HwndSource GetHwndSource(this Window window) => HwndSource.FromHwnd(window.GetHandle()); + + /// + /// 让窗口激活作为前台最上层窗口 + /// + /// + public static void SetWindowToForegroundWithAttachThreadInput(Window window) + { + // [WPF 让窗口激活作为前台最上层窗口的方法 - lindexi - 博客园](https://www.cnblogs.com/lindexi/p/12749671.html) + var interopHelper = new WindowInteropHelper(window); + // 以下 Win32 方法可以在 https://github.com/kkwpsv/lsjutil/tree/master/Src/Lsj.Util.Win32 找到 + var thisWindowThreadId = InteropMethods.GetWindowThreadProcessId(interopHelper.Handle, out _); + var currentForegroundWindow = InteropMethods.GetForegroundWindow(); + var currentForegroundWindowThreadId = + InteropMethods.GetWindowThreadProcessId(currentForegroundWindow, out _); + + // [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.更改窗口的Z Order,SetWindowPos使之最上,为了不影响后续窗口的Z Order,改完之后,再还原 +     5.最后SetForegroundWindow + */ + + InteropMethods.AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, true); + + window.Show(); + window.Activate(); + // 去掉和其他线程的输入链接 + InteropMethods.AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, false); + + // 用于踢掉其他的在上层的窗口 + if (window.Topmost != true) + { + window.Topmost = true; + window.Topmost = false; + } + } } } diff --git a/src/Shared/HandyControl_Shared/Tools/Interop/InteropMethods.cs b/src/Shared/HandyControl_Shared/Tools/Interop/InteropMethods.cs index 72a22351..ea9cbd44 100644 --- a/src/Shared/HandyControl_Shared/Tools/Interop/InteropMethods.cs +++ b/src/Shared/HandyControl_Shared/Tools/Interop/InteropMethods.cs @@ -43,6 +43,13 @@ namespace HandyControl.Tools.Interop [DllImport(InteropValues.ExternDll.User32, SetLastError = true, CharSet = CharSet.Auto)] internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); + [DllImport(InteropValues.ExternDll.User32, SetLastError = true, CharSet = CharSet.Auto)] + internal static extern bool AttachThreadInput(in uint currentForegroundWindowThreadId, + in uint thisWindowThreadId, bool isAttach); + + [DllImport(InteropValues.ExternDll.User32, SetLastError = true, CharSet = CharSet.Auto)] + internal static extern IntPtr GetForegroundWindow(); + [DllImport(InteropValues.ExternDll.Kernel32, SetLastError = true, CharSet = CharSet.Auto)] internal static extern IntPtr OpenProcess(InteropValues.ProcessAccess dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId);