Win32提供了SetForegroundWindow方法可以将应用设置到前台并激活,但是在某些场景下,只调用该接口会返回0,即设置失败。比如如下场景:
当前前台应用为一个全屏的应用,非前台应用的进程使用Process.Start()
方法启动截图工具,尝试使用SetForegroundWindow()
将窗口设置到前台,此时会概率性设置失败。
尝试了多种方法后,最终使用如下方法解决了该问题:
public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); public static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2); public const int SWP_NOSIZE = 0x1; public const int SWP_NOMOVE = 0x2; [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hwnd); [DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hwnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); public void StartSnippingTool() { if (!Envronment.Is64BitProcess) { Process.Start(@"C:\Windows\sysnative\SnippingTool.exe"); } else { Process.Start(@"C:\Windows\system32\SnippingTool.exe"); } Thread.Sleep(500); IntPtr snippingToolHandle = FindWindow("Microsoft-Windows-SnipperToolbar", "截图工具"); if (snippingToolHandle != IntPtr.Zero) { SetForegroundWindowCustom(snippingToolHandle); } } private void SetForegroundWindowCustom(IntPtr hwnd) { IntPtr currentWindow = GetForegroundWindow(); if (currentWindow == hwnd) { Console.WriteLine("应用已在顶层"); return; } SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); bool result = SetForegroundWindow(hwnd); if (result) { Console.WriteLine("置顶应用成功"); } else { Console.WriteLine("置顶应用失败"); } }