From 042b153684644adcf339d8b70e378513ebf13e8b Mon Sep 17 00:00:00 2001
From: CJKmkp <2564608840@qq.com>
Date: Wed, 13 Aug 2025 12:52:56 +0800
Subject: [PATCH] =?UTF-8?q?improve:=E7=AA=97=E5=8F=A3=E7=BD=AE=E9=A1=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Ink Canvas/MainWindow.xaml.cs | 190 +++++++++++++++++++++++++++++++++-
1 file changed, 185 insertions(+), 5 deletions(-)
diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs
index 6be9f1ef..8aa1e679 100644
--- a/Ink Canvas/MainWindow.xaml.cs
+++ b/Ink Canvas/MainWindow.xaml.cs
@@ -225,6 +225,10 @@ namespace Ink_Canvas
// 初始化窗口置顶开关
ToggleSwitchAlwaysOnTop.IsOn = Settings.Advanced.IsAlwaysOnTop;
ApplyAlwaysOnTop();
+
+ // 添加窗口激活事件处理,确保置顶状态在窗口重新激活时得到保持
+ this.Activated += Window_Activated;
+ this.Deactivated += Window_Deactivated;
}
@@ -620,6 +624,9 @@ namespace Ink_Canvas
CleanupClipboardMonitoring();
ClipboardNotification.Stop();
+ // 停止置顶维护定时器
+ StopTopmostMaintenance();
+
LogHelper.WriteLogToFile("Ink Canvas closed", LogHelper.LogType.Event);
// 检查是否有待安装的更新
@@ -1630,13 +1637,26 @@ namespace Ink_Canvas
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
+ [DllImport("user32.dll")]
+ private static extern bool BringWindowToTop(IntPtr hWnd);
+ [DllImport("user32.dll")]
+ private static extern bool SetForegroundWindow(IntPtr hWnd);
+
+
private const int GWL_EXSTYLE = -20;
private const int WS_EX_NOACTIVATE = 0x08000000;
+ private const int WS_EX_TOPMOST = 0x00000008;
private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
private static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
private const uint SWP_NOMOVE = 0x0002;
private const uint SWP_NOSIZE = 0x0001;
private const uint SWP_NOACTIVATE = 0x0010;
+ private const uint SWP_SHOWWINDOW = 0x0040;
+ private const uint SWP_NOOWNERZORDER = 0x0200;
+
+ // 添加定时器来维护置顶状态
+ private DispatcherTimer topmostMaintenanceTimer;
+ private bool isTopmostMaintenanceEnabled = false;
private void ApplyNoFocusMode()
{
@@ -1654,14 +1674,139 @@ namespace Ink_Canvas
private void ApplyAlwaysOnTop()
{
- var hwnd = new WindowInteropHelper(this).Handle;
- if (Settings.Advanced.IsAlwaysOnTop)
+ try
{
- SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ var hwnd = new WindowInteropHelper(this).Handle;
+ if (Settings.Advanced.IsAlwaysOnTop)
+ {
+ // 先设置WPF的Topmost属性
+ Topmost = true;
+
+ // 使用更强的Win32 API调用来确保置顶
+ // 1. 设置窗口样式为置顶
+ int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+ SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_TOPMOST);
+
+ // 2. 使用SetWindowPos确保窗口在最顶层
+ SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
+
+ // 3. 如果启用了无焦点模式,需要特殊处理
+ if (Settings.Advanced.IsNoFocusMode)
+ {
+ // 启动置顶维护定时器
+ StartTopmostMaintenance();
+ }
+ else
+ {
+ // 停止置顶维护定时器
+ StopTopmostMaintenance();
+ }
+
+ // 添加调试日志
+ LogHelper.WriteLogToFile($"应用窗口置顶: 启用置顶 (无焦点模式: {Settings.Advanced.IsNoFocusMode})", LogHelper.LogType.Trace);
+ }
+ else
+ {
+ // 取消置顶时
+ // 1. 先使用Win32 API取消置顶
+ SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
+
+ // 2. 移除置顶窗口样式
+ int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+ SetWindowLong(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_TOPMOST);
+
+ // 3. 停止置顶维护定时器
+ StopTopmostMaintenance();
+
+ // 注意:这里不直接设置Topmost,让其他代码根据模式决定
+
+ // 添加调试日志
+ LogHelper.WriteLogToFile($"应用窗口置顶: 取消置顶", LogHelper.LogType.Trace);
+ }
}
- else
+ catch (Exception ex)
{
- SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ LogHelper.WriteLogToFile($"应用窗口置顶失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 启动置顶维护定时器
+ ///
+ private void StartTopmostMaintenance()
+ {
+ if (isTopmostMaintenanceEnabled) return;
+
+ if (topmostMaintenanceTimer == null)
+ {
+ topmostMaintenanceTimer = new DispatcherTimer();
+ topmostMaintenanceTimer.Interval = TimeSpan.FromMilliseconds(500); // 每500ms检查一次
+ topmostMaintenanceTimer.Tick += TopmostMaintenanceTimer_Tick;
+ }
+
+ topmostMaintenanceTimer.Start();
+ isTopmostMaintenanceEnabled = true;
+ LogHelper.WriteLogToFile("启动置顶维护定时器", LogHelper.LogType.Trace);
+ }
+
+ ///
+ /// 停止置顶维护定时器
+ ///
+ private void StopTopmostMaintenance()
+ {
+ if (topmostMaintenanceTimer != null && isTopmostMaintenanceEnabled)
+ {
+ topmostMaintenanceTimer.Stop();
+ isTopmostMaintenanceEnabled = false;
+ LogHelper.WriteLogToFile("停止置顶维护定时器", LogHelper.LogType.Trace);
+ }
+ }
+
+ ///
+ /// 置顶维护定时器事件
+ ///
+ private void TopmostMaintenanceTimer_Tick(object sender, EventArgs e)
+ {
+ try
+ {
+ if (!Settings.Advanced.IsAlwaysOnTop || !Settings.Advanced.IsNoFocusMode)
+ {
+ StopTopmostMaintenance();
+ return;
+ }
+
+ var hwnd = new WindowInteropHelper(this).Handle;
+ if (hwnd == IntPtr.Zero) return;
+
+ // 检查窗口是否仍然可见且不是最小化状态
+ if (!IsWindow(hwnd) || !IsWindowVisible(hwnd) || IsIconic(hwnd))
+ {
+ return;
+ }
+
+ // 检查当前窗口是否在最顶层
+ var foregroundWindow = GetForegroundWindow();
+ if (foregroundWindow != hwnd)
+ {
+ // 如果窗口不在最顶层,重新设置置顶
+ SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
+
+ // 确保窗口样式正确
+ int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+ if ((exStyle & WS_EX_TOPMOST) == 0)
+ {
+ SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_TOPMOST);
+ }
+
+ LogHelper.WriteLogToFile("置顶维护: 重新设置窗口置顶", LogHelper.LogType.Trace);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"置顶维护定时器出错: {ex.Message}", LogHelper.LogType.Error);
}
}
@@ -1695,6 +1840,12 @@ namespace Ink_Canvas
Settings.Advanced.IsNoFocusMode = toggle != null && toggle.IsOn;
SaveSettingsToFile();
ApplyNoFocusMode();
+
+ // 如果启用了窗口置顶,需要重新应用置顶设置以处理无焦点模式的变化
+ if (Settings.Advanced.IsAlwaysOnTop)
+ {
+ ApplyAlwaysOnTop();
+ }
}
private void ToggleSwitchAlwaysOnTop_Toggled(object sender, RoutedEventArgs e)
@@ -1705,6 +1856,35 @@ namespace Ink_Canvas
SaveSettingsToFile();
ApplyAlwaysOnTop();
}
+
+ private void Window_Activated(object sender, EventArgs e)
+ {
+ // 窗口激活时,如果启用了置顶功能,重新应用置顶设置
+ if (Settings.Advanced.IsAlwaysOnTop)
+ {
+ // 使用Dispatcher.BeginInvoke确保在UI线程上执行
+ Dispatcher.BeginInvoke(new Action(() =>
+ {
+ ApplyAlwaysOnTop();
+ }), System.Windows.Threading.DispatcherPriority.Loaded);
+ }
+ }
+
+ ///
+ /// 窗口失去焦点时的处理
+ ///
+ private void Window_Deactivated(object sender, EventArgs e)
+ {
+ // 窗口失去焦点时,如果启用了置顶功能且处于无焦点模式,重新应用置顶设置
+ if (Settings.Advanced.IsAlwaysOnTop && Settings.Advanced.IsNoFocusMode)
+ {
+ // 使用Dispatcher.BeginInvoke确保在UI线程上执行
+ Dispatcher.BeginInvoke(new Action(() =>
+ {
+ ApplyAlwaysOnTop();
+ }), System.Windows.Threading.DispatcherPriority.Loaded);
+ }
+ }
#region Image Toolbar Event Handlers