using System; namespace Notify.Interop; /// /// 把目标窗口拉回前台 /// /// Windows 限制后台进程抢焦点,这里用一套组合技绕过:ALT 键模拟 + /// AttachThreadInput 把当前线程与前台/目标线程的输入队列挂接 + /// SetWindowPos/BringWindowToTop/SwitchToThisWindow/SetForegroundWindow 多管齐下 /// public static class WindowActivator { public static bool Activate(IntPtr hwnd) { if (hwnd == IntPtr.Zero || !Win32.IsWindow(hwnd)) { return false; } try { // 最小化的先还原 if (Win32.IsIconic(hwnd)) { Win32.ShowWindow(hwnd, Win32.SW_RESTORE); } var foreground = Win32.GetForegroundWindow(); var curThread = Win32.GetCurrentThreadId(); var fgThread = Win32.GetWindowThreadProcessId(foreground, out _); var targetThread = Win32.GetWindowThreadProcessId(hwnd, out _); // 模拟一次 ALT 抬起,满足 Windows 的"防焦点抢占"前置条件 Win32.keybd_event(Win32.VK_MENU, 0, 0, IntPtr.Zero); Win32.keybd_event(Win32.VK_MENU, 0, Win32.KEYEVENTF_KEYUP, IntPtr.Zero); if (fgThread != curThread) { Win32.AttachThreadInput(curThread, fgThread, true); } if (targetThread != curThread && targetThread != fgThread) { Win32.AttachThreadInput(curThread, targetThread, true); } Win32.AllowSetForegroundWindow(Win32.ASFW_ANY); Win32.SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, Win32.SWP_NOMOVE | Win32.SWP_NOSIZE | Win32.SWP_SHOWWINDOW); Win32.BringWindowToTop(hwnd); Win32.SwitchToThisWindow(hwnd, true); Win32.SetForegroundWindow(hwnd); Win32.ShowWindow(hwnd, Win32.SW_SHOW); if (targetThread != curThread && targetThread != fgThread) { Win32.AttachThreadInput(curThread, targetThread, false); } if (fgThread != curThread) { Win32.AttachThreadInput(curThread, fgThread, false); } return Win32.GetForegroundWindow() == hwnd; } catch { return false; } } }