diff --git a/src/UI/Helpers/MainFormWinHelper.cs b/src/UI/Helpers/MainFormWinHelper.cs index 72b17a3..905af4e 100644 --- a/src/UI/Helpers/MainFormWinHelper.cs +++ b/src/UI/Helpers/MainFormWinHelper.cs @@ -136,6 +136,25 @@ public void ApplyRoundedCorners() catch { } } + // ================================================================= + // 置顶守护 + // ================================================================= + + /// + /// 通过 Win32 API 无条件强制置顶窗口。 + /// 不检查 WS_EX_TOPMOST 标志,因为在全屏应用(如 VMware、无边框全屏游戏)中 + /// 该标志可能仍然存在但窗口实际被覆盖,必须重新调用 SetWindowPos 才能恢复显示。 + /// + public void ReapplyTopMost() + { + try + { + SetWindowPos(_form.Handle, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + } + catch { } + } + // ================================================================= // Win32 API // ================================================================= @@ -152,11 +171,16 @@ public static int RegisterTaskbarCreatedMessage() [DllImport("dwmapi.dll")] private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize); [DllImport("user32.dll", SetLastError = true)] private static extern int GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("user32.dll", SetLastError = true)] private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); + [DllImport("user32.dll", SetLastError = true)] private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern int RegisterWindowMessage(string lpString); [DllImport("user32.dll", SetLastError = true)] public static extern bool ChangeWindowMessageFilter(uint message, uint dwFlag); public const uint MSGFLT_ADD = 1; + private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); + private const uint SWP_NOMOVE = 0x0002; + private const uint SWP_NOSIZE = 0x0001; + private const uint SWP_NOACTIVATE = 0x0010; private const int DWMWA_WINDOW_CORNER_PREFERENCE = 33; private const int DWMWCP_ROUND = 2; private const int DWMWA_BORDER_COLOR = 34; @@ -164,6 +188,7 @@ public static int RegisterTaskbarCreatedMessage() private const int GWL_EXSTYLE = -20; private const int WS_EX_TRANSPARENT = 0x20; private const int WS_EX_LAYERED = 0x80000; + private const int WS_EX_TOPMOST = 0x00000008; public static void ActivateWindow(IntPtr handle) => SetForegroundWindow(handle); } diff --git a/src/UI/MainForm_Transparent.cs b/src/UI/MainForm_Transparent.cs index 1aa385e..d66fb39 100644 --- a/src/UI/MainForm_Transparent.cs +++ b/src/UI/MainForm_Transparent.cs @@ -25,6 +25,7 @@ public class MainForm : Form private Point _dragOffset; private bool _uiDragging = false; + private System.Windows.Forms.Timer? _topMostGuardTimer; // 防止 Win11 自动隐藏无边框 + 无任务栏窗口 protected override CreateParams CreateParams @@ -324,31 +325,41 @@ protected override void OnShown(EventArgs e) { _ = _bizHelper.RunStartupChecksAsync(); } - // [Fix] 强制置顶刷新,增加重试机制确保在某些系统环境下依然生效 - if (_cfg.TopMost) - { - this.BeginInvoke(new Action(async () => - { - await Task.Delay(3000); - // 1. 立即执行第一次置顶 - this.TopMost = false; - await Task.Delay(1000); - this.TopMost = true; - this.BringToFront(); - })); - } + // [Fix] 置顶守护:周期性检测并恢复被虚拟桌面切换、全屏游戏等夺走的置顶状态 + StartTopMostGuard(); } protected override void OnFormClosed(FormClosedEventArgs e) { - _cfg.Save(); - TrafficLogger.Save(); + _topMostGuardTimer?.Stop(); + _topMostGuardTimer?.Dispose(); + _cfg.Save(); + TrafficLogger.Save(); src.WebServer.LiteWebServer.Instance?.Stop(); - + base.OnFormClosed(e); - + _ui?.Dispose(); _bizHelper.Dispose(); } + + private void StartTopMostGuard() + { + if (_topMostGuardTimer != null) return; + _topMostGuardTimer = new System.Windows.Forms.Timer { Interval = 3000 }; + _topMostGuardTimer.Tick += (_, __) => + { + if (_cfg.TopMost && Visible) + { + // 如果本应用有其他活动窗口(如设置面板),跳过强制置顶以免遮挡 + var activeForm = Form.ActiveForm; + if (activeForm != null && activeForm != this) + return; + + _winHelper.ReapplyTopMost(); + } + }; + _topMostGuardTimer.Start(); + } } }