From 7151fec7b82c536f6f52ef852e48f130d4669769 Mon Sep 17 00:00:00 2001 From: lindexi Date: Thu, 13 Aug 2020 22:49:32 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=8A=A0=E4=B8=8A=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E7=AA=97=E5=8F=A3=E5=88=B0=E6=9C=80=E5=89=8D=E7=9A=84=E8=BE=85?= =?UTF-8?q?=E5=8A=A9=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); From 652bdf918e732106797f84aefa0e7e5ed11b18f5 Mon Sep 17 00:00:00 2001 From: NaBian <836904362@qq.com> Date: Fri, 28 Aug 2020 00:00:50 +0800 Subject: [PATCH 2/2] update PushMainWindow2TopCommand --- .../Interactivity/Commands/PushMainWindow2TopCommand.cs | 9 ++------- .../HandyControl_Shared/Tools/Helper/WindowHelper.cs | 6 ++---- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/Shared/HandyControl_Shared/Interactivity/Commands/PushMainWindow2TopCommand.cs b/src/Shared/HandyControl_Shared/Interactivity/Commands/PushMainWindow2TopCommand.cs index 07a2427c..386d6a78 100644 --- a/src/Shared/HandyControl_Shared/Interactivity/Commands/PushMainWindow2TopCommand.cs +++ b/src/Shared/HandyControl_Shared/Interactivity/Commands/PushMainWindow2TopCommand.cs @@ -1,8 +1,7 @@ using System; using System.Windows; using System.Windows.Input; -using System.Windows.Interop; -using HandyControl.Tools.Interop; +using HandyControl.Tools; namespace HandyControl.Interactivity { @@ -15,11 +14,7 @@ namespace HandyControl.Interactivity if (Application.Current.MainWindow != null && Application.Current.MainWindow.Visibility != Visibility.Visible) { Application.Current.MainWindow.Show(); - var hwndSource = (HwndSource)PresentationSource.FromDependencyObject(Application.Current.MainWindow); - if (hwndSource != null) - { - InteropMethods.SetForegroundWindow(hwndSource.Handle); - } + WindowHelper.SetWindowToForeground(Application.Current.MainWindow); } } diff --git a/src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs b/src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs index 41436aac..fcbb36b6 100644 --- a/src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs +++ b/src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs @@ -157,15 +157,13 @@ namespace HandyControl.Tools /// 让窗口激活作为前台最上层窗口 /// /// - public static void SetWindowToForegroundWithAttachThreadInput(Window window) + public static void SetWindowToForeground(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 _); + 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 )