From dce5722e9630d20d5e492fde6bec8bf8ddabe667 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Wed, 13 Aug 2025 21:59:35 +0800 Subject: [PATCH 01/45] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow.xaml.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index 8aa1e679..2a3a5623 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -1801,7 +1801,6 @@ namespace Ink_Canvas SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_TOPMOST); } - LogHelper.WriteLogToFile("置顶维护: 重新设置窗口置顶", LogHelper.LogType.Trace); } } catch (Exception ex) @@ -1960,4 +1959,4 @@ namespace Ink_Canvas #endregion } -} \ No newline at end of file +} From 69023f98d9cea86284d1ae45ff756da3a5b59b5e Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Wed, 13 Aug 2025 22:00:53 +0800 Subject: [PATCH 02/45] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow.xaml.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index 2a3a5623..31bc55a5 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -1702,9 +1702,6 @@ namespace Ink_Canvas // 停止置顶维护定时器 StopTopmostMaintenance(); } - - // 添加调试日志 - LogHelper.WriteLogToFile($"应用窗口置顶: 启用置顶 (无焦点模式: {Settings.Advanced.IsNoFocusMode})", LogHelper.LogType.Trace); } else { From 5b4c966354d4ff7ecd56bff6e04f7a9708295612 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Wed, 13 Aug 2025 22:03:18 +0800 Subject: [PATCH 03/45] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index 167b5556..bc433b70 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -2906,15 +2906,6 @@ namespace Ink_Canvas // 设置高光位置 FloatingbarSelectionBG.Visibility = Visibility.Visible; System.Windows.Controls.Canvas.SetLeft(FloatingbarSelectionBG, position); - - // 详细的调试信息 - string debugInfo = $"设置高光位置: {mode} -> {position:F2}, " + - $"高光宽度: {actualHighlightWidth:F2}, " + - $"快捷调色盘: {quickColorPaletteMode}, 宽度: {quickColorPaletteWidth:F2}, 总宽度: {quickColorPaletteTotalWidth:F2}, " + - $"按钮宽度: cursor={cursorWidth:F2}, pen={penWidth:F2}, delete={deleteWidth:F2}, " + - $"eraser={eraserWidth:F2}, eraserByStrokes={eraserByStrokesWidth:F2}, select={selectWidth:F2}"; - - LogHelper.WriteLogToFile(debugInfo, LogHelper.LogType.Trace); } catch (Exception ex) { From 723c825df2136a764f61f64e2b8f293b3a546e73 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Mon, 18 Aug 2025 17:42:36 +0800 Subject: [PATCH 04/45] =?UTF-8?q?fix:=E5=85=B3=E6=9C=BA=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E4=BD=BF=E7=94=A8=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/App.xaml.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Ink Canvas/App.xaml.cs b/Ink Canvas/App.xaml.cs index e3ac9b51..aed955f9 100644 --- a/Ink Canvas/App.xaml.cs +++ b/Ink Canvas/App.xaml.cs @@ -338,6 +338,13 @@ namespace Ink_Canvas WriteCrashLog($"最后错误信息: {lastErrorMessage}"); } } + + // 新增:关机保存使用时间数据 + private void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e) + { + string reason = e.Reason == SessionEndReasons.Logoff ? "用户注销" : "系统关机"; + DeviceIdentifier.SaveUsageStatsOnShutdown(); + } // 新增:记录崩溃日志 private static void WriteCrashLog(string message) From cce0b930ecbfe62a9a5dd55f3cffdf1bf6a380be Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Mon, 18 Aug 2025 17:49:33 +0800 Subject: [PATCH 05/45] =?UTF-8?q?fix:=E5=85=B3=E6=9C=BA=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E4=BD=BF=E7=94=A8=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/DeviceIdentifier.cs | 147 ++++++++++++++++++++++++- 1 file changed, 146 insertions(+), 1 deletion(-) diff --git a/Ink Canvas/Helpers/DeviceIdentifier.cs b/Ink Canvas/Helpers/DeviceIdentifier.cs index a82fe3a8..274d46e7 100644 --- a/Ink Canvas/Helpers/DeviceIdentifier.cs +++ b/Ink Canvas/Helpers/DeviceIdentifier.cs @@ -2745,5 +2745,150 @@ namespace Ink_Canvas.Helpers return errorMsg; } } + /// + /// 关机时保存使用时间数据 + /// + public static void SaveUsageStatsOnShutdown() + { + lock (fileLock) // 确保线程安全 + { + try + { + // 1. 加载现有使用统计数据 + UsageStats stats = LoadUsageStats(); + if (stats == null) + { + stats = new UsageStats { DeviceId = DeviceId }; + } + + // 2. 计算本次会话时长 + TimeSpan sessionDuration = DateTime.Now - App.appStartTime; + long sessionSeconds = (long)sessionDuration.TotalSeconds; + + // 3. 更新统计数据 + stats.TotalUsageSeconds += sessionSeconds; + stats.LaunchCount++; + stats.AverageSessionSeconds = stats.TotalUsageSeconds / (double)stats.LaunchCount; + stats.LastLaunchTime = DateTime.Now; + + // 4. 保存到所有备份位置 + SaveUsageStatsToAllLocations(stats); + + LogHelper.WriteLogToFile($"使用时间数据已保存: 总时长 {stats.TotalUsageSeconds} 秒"); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"关机时保存使用时间数据失败: {ex.Message}", LogHelper.LogType.Error); + } + } + } + + /// + /// 加载现有使用统计数据(从主文件或备份) + /// + private static UsageStats LoadUsageStats() + { + // 尝试从主文件加载 + if (File.Exists(UsageStatsFilePath)) + { + try + { + string json = File.ReadAllText(UsageStatsFilePath); + return JsonConvert.DeserializeObject(json); + } + catch + { + // 主文件损坏,尝试从备份加载 + if (File.Exists(BackupUsageStatsPath)) + { + try + { + string backupJson = File.ReadAllText(BackupUsageStatsPath); + return JsonConvert.DeserializeObject(backupJson); + } + catch + { + // 可继续尝试其他备份路径 + return LoadFromOtherBackups(); + } + } + } + } + return null; + } + + /// + /// 从其他备份路径加载数据 + /// + private static UsageStats LoadFromOtherBackups() + { + // 尝试二级备份 + if (File.Exists(SecondaryUsageBackupPath)) + { + try + { + return JsonConvert.DeserializeObject(File.ReadAllText(SecondaryUsageBackupPath)); + } + catch { } + } + + // 尝试三级备份 + if (File.Exists(TertiaryUsageBackupPath)) + { + try + { + return JsonConvert.DeserializeObject(File.ReadAllText(TertiaryUsageBackupPath)); + } + catch { } + } + + // 尝试四级备份 + if (File.Exists(QuaternaryUsageBackupPath)) + { + try + { + return JsonConvert.DeserializeObject(File.ReadAllText(QuaternaryUsageBackupPath)); + } + catch { } + } + + return null; + } + + /// + /// 保存使用统计数据到所有备份位置 + /// + private static void SaveUsageStatsToAllLocations(UsageStats stats) + { + string json = JsonConvert.SerializeObject(stats, Formatting.Indented); + + // 保存到主文件 + SaveToFile(UsageStatsFilePath, json); + // 保存到多重备份路径 + SaveToFile(BackupUsageStatsPath, json); + SaveToFile(SecondaryUsageBackupPath, json); + SaveToFile(TertiaryUsageBackupPath, json); + SaveToFile(QuaternaryUsageBackupPath, json); + } + + /// + /// 辅助方法:保存内容到文件(确保目录存在) + /// + private static void SaveToFile(string path, string content) + { + try + { + string dir = Path.GetDirectoryName(path); + if (!Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + File.WriteAllText(path, content); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"保存文件 {path} 失败: {ex.Message}", LogHelper.LogType.Warning); + } + } } -} \ No newline at end of file +} From cc8863085952433231b683be430180e2c18d5541 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Mon, 18 Aug 2025 17:54:41 +0800 Subject: [PATCH 06/45] =?UTF-8?q?fix:=E5=85=B3=E6=9C=BA=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E4=BD=BF=E7=94=A8=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/DeviceIdentifier.cs | 108 ------------------------- 1 file changed, 108 deletions(-) diff --git a/Ink Canvas/Helpers/DeviceIdentifier.cs b/Ink Canvas/Helpers/DeviceIdentifier.cs index 274d46e7..0ee14e12 100644 --- a/Ink Canvas/Helpers/DeviceIdentifier.cs +++ b/Ink Canvas/Helpers/DeviceIdentifier.cs @@ -2782,113 +2782,5 @@ namespace Ink_Canvas.Helpers } } } - - /// - /// 加载现有使用统计数据(从主文件或备份) - /// - private static UsageStats LoadUsageStats() - { - // 尝试从主文件加载 - if (File.Exists(UsageStatsFilePath)) - { - try - { - string json = File.ReadAllText(UsageStatsFilePath); - return JsonConvert.DeserializeObject(json); - } - catch - { - // 主文件损坏,尝试从备份加载 - if (File.Exists(BackupUsageStatsPath)) - { - try - { - string backupJson = File.ReadAllText(BackupUsageStatsPath); - return JsonConvert.DeserializeObject(backupJson); - } - catch - { - // 可继续尝试其他备份路径 - return LoadFromOtherBackups(); - } - } - } - } - return null; - } - - /// - /// 从其他备份路径加载数据 - /// - private static UsageStats LoadFromOtherBackups() - { - // 尝试二级备份 - if (File.Exists(SecondaryUsageBackupPath)) - { - try - { - return JsonConvert.DeserializeObject(File.ReadAllText(SecondaryUsageBackupPath)); - } - catch { } - } - - // 尝试三级备份 - if (File.Exists(TertiaryUsageBackupPath)) - { - try - { - return JsonConvert.DeserializeObject(File.ReadAllText(TertiaryUsageBackupPath)); - } - catch { } - } - - // 尝试四级备份 - if (File.Exists(QuaternaryUsageBackupPath)) - { - try - { - return JsonConvert.DeserializeObject(File.ReadAllText(QuaternaryUsageBackupPath)); - } - catch { } - } - - return null; - } - - /// - /// 保存使用统计数据到所有备份位置 - /// - private static void SaveUsageStatsToAllLocations(UsageStats stats) - { - string json = JsonConvert.SerializeObject(stats, Formatting.Indented); - - // 保存到主文件 - SaveToFile(UsageStatsFilePath, json); - // 保存到多重备份路径 - SaveToFile(BackupUsageStatsPath, json); - SaveToFile(SecondaryUsageBackupPath, json); - SaveToFile(TertiaryUsageBackupPath, json); - SaveToFile(QuaternaryUsageBackupPath, json); - } - - /// - /// 辅助方法:保存内容到文件(确保目录存在) - /// - private static void SaveToFile(string path, string content) - { - try - { - string dir = Path.GetDirectoryName(path); - if (!Directory.Exists(dir)) - { - Directory.CreateDirectory(dir); - } - File.WriteAllText(path, content); - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"保存文件 {path} 失败: {ex.Message}", LogHelper.LogType.Warning); - } - } } } From 975b563b8d77f7e336fbc56da0c7e40348f6d1fe Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Mon, 18 Aug 2025 17:57:56 +0800 Subject: [PATCH 07/45] =?UTF-8?q?fix:=E5=85=B3=E6=9C=BA=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E4=BD=BF=E7=94=A8=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/App.xaml.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Ink Canvas/App.xaml.cs b/Ink Canvas/App.xaml.cs index aed955f9..04a78827 100644 --- a/Ink Canvas/App.xaml.cs +++ b/Ink Canvas/App.xaml.cs @@ -287,6 +287,7 @@ namespace Ink_Canvas { string reason = e.Reason == SessionEndReasons.Logoff ? "用户注销" : "系统关机"; WriteCrashLog($"系统会话即将结束: {reason}"); + DeviceIdentifier.SaveUsageStatsOnShutdown(); } // 新增:控制台取消事件处理 @@ -338,13 +339,6 @@ namespace Ink_Canvas WriteCrashLog($"最后错误信息: {lastErrorMessage}"); } } - - // 新增:关机保存使用时间数据 - private void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e) - { - string reason = e.Reason == SessionEndReasons.Logoff ? "用户注销" : "系统关机"; - DeviceIdentifier.SaveUsageStatsOnShutdown(); - } // 新增:记录崩溃日志 private static void WriteCrashLog(string message) From 502e2050711451cd885f1bedb2ab0e484abd2d3c Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Mon, 18 Aug 2025 18:01:23 +0800 Subject: [PATCH 08/45] =?UTF-8?q?fix:=E5=85=B3=E6=9C=BA=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E4=BD=BF=E7=94=A8=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/App.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ink Canvas/App.xaml.cs b/Ink Canvas/App.xaml.cs index 04a78827..0f50976a 100644 --- a/Ink Canvas/App.xaml.cs +++ b/Ink Canvas/App.xaml.cs @@ -45,7 +45,7 @@ namespace Ink_Canvas // 新增:进程ID private static int currentProcessId = Process.GetCurrentProcess().Id; // 新增:应用启动时间 - private static DateTime appStartTime = DateTime.Now; + internal static DateTime appStartTime { get; private set; } // 新增:最后一次错误信息 private static string lastErrorMessage = string.Empty; // 新增:是否已初始化崩溃监听器 From f331cb1b4d52b76d416d83e29a892d468623404d Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Tue, 19 Aug 2025 17:41:42 +0800 Subject: [PATCH 09/45] fix:issue #110 --- Ink Canvas/MainWindow_cs/MW_TrayIcon.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ink Canvas/MainWindow_cs/MW_TrayIcon.cs b/Ink Canvas/MainWindow_cs/MW_TrayIcon.cs index ec79414c..96796023 100644 --- a/Ink Canvas/MainWindow_cs/MW_TrayIcon.cs +++ b/Ink Canvas/MainWindow_cs/MW_TrayIcon.cs @@ -84,7 +84,7 @@ namespace Ink_Canvas startInfo.UseShellExecute = true; // 启动进程但不等待 - Process.Start(startInfo); + Process.Start(new ProcessStartInfo(exePath, "-delay 2000") { UseShellExecute = true }); } catch (Exception ex) { From 35cfd26ecea1e1118bab6645f4a169c893f7910b Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Tue, 19 Aug 2025 17:52:02 +0800 Subject: [PATCH 10/45] =?UTF-8?q?fix:=E9=80=80=E5=87=BA=E4=B8=8D=E5=AE=8C?= =?UTF-8?q?=E5=85=A8=E6=97=B6=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/AutoUpdateHelper.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Ink Canvas/Helpers/AutoUpdateHelper.cs b/Ink Canvas/Helpers/AutoUpdateHelper.cs index 138c0090..d0910eb9 100644 --- a/Ink Canvas/Helpers/AutoUpdateHelper.cs +++ b/Ink Canvas/Helpers/AutoUpdateHelper.cs @@ -45,9 +45,9 @@ namespace Ink_Canvas.Helpers new UpdateLineGroup { GroupName = "GitHub主线", - VersionUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt", - DownloadUrlFormat = "https://github.com/InkCanvasForClass/community/releases/download/{0}/InkCanvasForClass.CE.{0}.zip", - LogUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/main/UpdateLog.md" + VersionUrl = "https://bgithub.xyz/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt", + DownloadUrlFormat = "https://bgithub.xyz/InkCanvasForClass/community/releases/download/{0}/InkCanvasForClass.CE.{0}.zip", + LogUrl = "https://bgithub.xyz/InkCanvasForClass/community/raw/refs/heads/main/UpdateLog.md" }, new UpdateLineGroup { @@ -80,9 +80,9 @@ namespace Ink_Canvas.Helpers new UpdateLineGroup { GroupName = "GitHub主线", - VersionUrl = "https://github.com/InkCanvasForClass/community-beta/raw/refs/heads/main/AutomaticUpdateVersionControl.txt", - DownloadUrlFormat = "https://github.com/InkCanvasForClass/community-beta/releases/download/{0}/InkCanvasForClass.CE.{0}.zip", - LogUrl = "https://github.com/InkCanvasForClass/community-beta/raw/refs/heads/main/UpdateLog.md" + VersionUrl = "https://bgithub.xyz/InkCanvasForClass/community-beta/raw/refs/heads/main/AutomaticUpdateVersionControl.txt", + DownloadUrlFormat = "https://bgithub.xyz/InkCanvasForClass/community-beta/releases/download/{0}/InkCanvasForClass.CE.{0}.zip", + LogUrl = "https://bgithub.xyz/InkCanvasForClass/community-beta/raw/refs/heads/main/UpdateLog.md" }, new UpdateLineGroup { @@ -1195,7 +1195,7 @@ namespace Ink_Canvas.Helpers StringBuilder batchContent = new StringBuilder(); batchContent.AppendLine("@echo off"); - + batchContent.AppendLine("echo Set objShell = CreateObject(\"WScript.Shell\") > \"%temp%\\hideme.vbs\""); batchContent.AppendLine("echo objShell.Run \"cmd /c \"\"\" ^& WScript.Arguments(0) ^& \"\"\"\", 0, True >> \"%temp%\\hideme.vbs\""); batchContent.AppendLine("echo Wscript.Sleep 100 >> \"%temp%\\hideme.vbs\""); @@ -1210,6 +1210,7 @@ namespace Ink_Canvas.Helpers batchContent.AppendLine($"echo goto CHECK_PROCESS >> \"{updateBatPath}\""); batchContent.AppendLine($"echo ) >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo timeout /t 1 /nobreak > nul >> \"{updateBatPath}\""); batchContent.AppendLine($"echo echo Application closed, starting update process... >> \"{updateBatPath}\""); batchContent.AppendLine($"echo timeout /t 2 /nobreak ^> nul >> \"{updateBatPath}\""); @@ -1514,7 +1515,7 @@ namespace Ink_Canvas.Helpers LogHelper.WriteLogToFile("AutoUpdate | 开始测试Windows 7 TLS连接..."); // 测试GitHub连接 - var testUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt"; + var testUrl = "https://bgithub.xyz/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt"; using (var handler = new HttpClientHandler()) { From 063f8b175162c85fefe0556732bc07230c448d22 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Tue, 19 Aug 2025 18:04:45 +0800 Subject: [PATCH 11/45] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/DeviceIdentifier.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Ink Canvas/Helpers/DeviceIdentifier.cs b/Ink Canvas/Helpers/DeviceIdentifier.cs index 0ee14e12..5d1d9d67 100644 --- a/Ink Canvas/Helpers/DeviceIdentifier.cs +++ b/Ink Canvas/Helpers/DeviceIdentifier.cs @@ -2773,8 +2773,6 @@ namespace Ink_Canvas.Helpers // 4. 保存到所有备份位置 SaveUsageStatsToAllLocations(stats); - - LogHelper.WriteLogToFile($"使用时间数据已保存: 总时长 {stats.TotalUsageSeconds} 秒"); } catch (Exception ex) { From f94d81ad20a6bd23a097f45326efff1e0f6c8a91 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 23 Aug 2025 02:44:14 +0000 Subject: [PATCH 12/45] docs: update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5887da59..3e09af86 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ CJK_mkp
CJK_mkp

🚧 📖 💻 + Hydrogen
Hydrogen

💻 CreeperAWA
CreeperAWA

💻 2,2,3-三甲基戊烷
2,2,3-三甲基戊烷

📝 📖 🎨 Alan-CRL
Alan-CRL

💻 🚇 📖 💵 @@ -92,7 +93,7 @@ Awesome Iwb
Awesome Iwb

📖 - PrefacedCorg
PrefacedCorg

💻 + PrefacedCorg
PrefacedCorg

💻 🎨 From 68ea32385536468b0d94c0ef2c5cf71fc8ac023f Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 23 Aug 2025 02:44:15 +0000 Subject: [PATCH 13/45] docs: update .all-contributorsrc --- .all-contributorsrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 41dcfa6e..3ac1bb16 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -86,7 +86,8 @@ "avatar_url": "https://avatars.githubusercontent.com/u/129855423?v=4", "profile": "https://github.com/PrefacedCorg", "contributions": [ - "code" + "code", + "design" ] } ] From aba6c18a2515411d081d5b8e229aa51e490304e6 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 18:24:24 +0800 Subject: [PATCH 14/45] fix:issue #133 --- Ink Canvas/MainWindow_cs/MW_TouchEvents.cs | 186 +++++++++++++++++++-- 1 file changed, 172 insertions(+), 14 deletions(-) diff --git a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs index 49b8aeb8..44a9671d 100644 --- a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs +++ b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs @@ -1,6 +1,7 @@ using Ink_Canvas.Helpers; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using System.Windows; @@ -343,6 +344,10 @@ namespace Ink_Canvas private InkCanvasEditingMode palmEraserLastEditingMode = InkCanvasEditingMode.Ink; private bool palmEraserLastIsHighlighter; private bool palmEraserWasEnabledBeforeMultiTouch; + private bool palmEraserTouchDownHandled = false; // 新增:标记手掌擦触摸按下是否已处理 + private DateTime palmEraserActivationTime; // 新增:记录手掌擦激活时间 + private const int PALM_ERASER_TIMEOUT_MS = 5000; // 新增:手掌擦超时时间(5秒) + private System.Windows.Threading.DispatcherTimer palmEraserRecoveryTimer; // 新增:手掌擦恢复定时器 private void inkCanvas_PreviewTouchDown(object sender, TouchEventArgs e) { @@ -395,8 +400,8 @@ namespace Ink_Canvas BlackboardUIGridForInkReplay.IsHitTestVisible = false; dec.Add(e.TouchDevice.Id); - // Palm Eraser 逻辑 - if (Settings.Canvas.EnablePalmEraser && dec.Count >= 2 && !isPalmEraserActive) + // Palm Eraser 逻辑 - 修复:只在触摸按下时处理一次,避免重复触发 + if (Settings.Canvas.EnablePalmEraser && dec.Count >= 2 && !isPalmEraserActive && !palmEraserTouchDownHandled) { var bounds = e.GetTouchPoint(inkCanvas).Bounds; double palmThreshold = 40; // 触摸面积阈值,可根据实际调整 @@ -408,6 +413,11 @@ namespace Ink_Canvas // 切换为橡皮擦 EraserIcon_Click(null, null); isPalmEraserActive = true; + palmEraserActivationTime = DateTime.Now; // 记录激活时间 + palmEraserTouchDownHandled = true; // 标记已处理 + + // 启动恢复定时器,防止卡死 + StartPalmEraserRecoveryTimer(); } } @@ -474,23 +484,86 @@ namespace Ink_Canvas { // 恢复高光状态 drawingAttributes.IsHighlighter = palmEraserLastIsHighlighter; - // 恢复编辑模式 - if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) + // 恢复编辑模式 - 修复:确保正确恢复状态 + try { - if (palmEraserLastEditingMode == InkCanvasEditingMode.Ink) + if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) { - PenIcon_Click(null, null); - } - else if (palmEraserLastEditingMode == InkCanvasEditingMode.Select) - { - SymbolIconSelect_MouseUp(null, null); - } - else - { - inkCanvas.EditingMode = palmEraserLastEditingMode; + if (palmEraserLastEditingMode == InkCanvasEditingMode.Ink) + { + PenIcon_Click(null, null); + } + else if (palmEraserLastEditingMode == InkCanvasEditingMode.Select) + { + SymbolIconSelect_MouseUp(null, null); + } + else + { + inkCanvas.EditingMode = palmEraserLastEditingMode; + } } } + catch (Exception ex) + { + // 如果恢复失败,强制切换到批注模式 + Trace.WriteLine($"Palm eraser recovery failed: {ex.Message}, forcing to Ink mode"); + inkCanvas.EditingMode = InkCanvasEditingMode.Ink; + } + + // 重置手掌擦状态 isPalmEraserActive = false; + palmEraserTouchDownHandled = false; + + // 停止恢复定时器 + StopPalmEraserRecoveryTimer(); + + // 确保触摸事件能正常响应 + inkCanvas.IsHitTestVisible = true; + inkCanvas.IsManipulationEnabled = true; + } + + // 新增:超时检测 - 如果手掌擦激活时间过长,强制重置状态 + if (isPalmEraserActive && dec.Count == 0) + { + var timeSinceActivation = DateTime.Now - palmEraserActivationTime; + if (timeSinceActivation.TotalMilliseconds > PALM_ERASER_TIMEOUT_MS) + { + Trace.WriteLine($"Palm eraser timeout detected ({timeSinceActivation.TotalMilliseconds}ms), forcing recovery"); + + // 强制恢复状态 + try + { + if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) + { + if (palmEraserLastEditingMode == InkCanvasEditingMode.Ink) + { + PenIcon_Click(null, null); + } + else if (palmEraserLastEditingMode == InkCanvasEditingMode.Select) + { + SymbolIconSelect_MouseUp(null, null); + } + else + { + inkCanvas.EditingMode = palmEraserLastEditingMode; + } + } + } + catch (Exception ex) + { + Trace.WriteLine($"Palm eraser timeout recovery failed: {ex.Message}, forcing to Ink mode"); + inkCanvas.EditingMode = InkCanvasEditingMode.Ink; + } + + // 重置所有手掌擦状态 + isPalmEraserActive = false; + palmEraserTouchDownHandled = false; + inkCanvas.IsHitTestVisible = true; + inkCanvas.IsManipulationEnabled = true; + + // 停止恢复定时器 + StopPalmEraserRecoveryTimer(); + } } // 修复:几何绘制模式下,触摸抬手时应该正确处理,而不是简单模拟鼠标事件 if (drawingShapeMode != 0) @@ -551,6 +624,16 @@ namespace Ink_Canvas { inkCanvas.EditingMode = lastInkCanvasEditingMode; } + + // 修复:确保手掌擦除后触摸事件能正常响应 + if (isPalmEraserActive) + { + // 如果手掌擦还在激活状态但触摸点已清空,强制重置状态 + isPalmEraserActive = false; + palmEraserTouchDownHandled = false; + inkCanvas.IsHitTestVisible = true; + inkCanvas.IsManipulationEnabled = true; + } } } inkCanvas.Opacity = 1; @@ -753,5 +836,80 @@ namespace Ink_Canvas ToggleSwitchEnablePalmEraser.IsOn = false; } } + + /// + /// 启动手掌擦恢复定时器,防止卡死状态 + /// + private void StartPalmEraserRecoveryTimer() + { + if (palmEraserRecoveryTimer == null) + { + palmEraserRecoveryTimer = new System.Windows.Threading.DispatcherTimer(); + palmEraserRecoveryTimer.Interval = TimeSpan.FromMilliseconds(1000); // 每秒检查一次 + palmEraserRecoveryTimer.Tick += PalmEraserRecoveryTimer_Tick; + } + + palmEraserRecoveryTimer.Start(); + } + + /// + /// 停止手掌擦恢复定时器 + /// + private void StopPalmEraserRecoveryTimer() + { + if (palmEraserRecoveryTimer != null) + { + palmEraserRecoveryTimer.Stop(); + } + } + + /// + /// 手掌擦恢复定时器事件处理 + /// + private void PalmEraserRecoveryTimer_Tick(object sender, EventArgs e) + { + if (!isPalmEraserActive) return; + + // 检查是否超时 + var timeSinceActivation = DateTime.Now - palmEraserActivationTime; + if (timeSinceActivation.TotalMilliseconds > PALM_ERASER_TIMEOUT_MS) + { + Trace.WriteLine($"Palm eraser recovery timer triggered, forcing recovery after {timeSinceActivation.TotalMilliseconds}ms"); + + // 强制恢复状态 + try + { + if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) + { + if (palmEraserLastEditingMode == InkCanvasEditingMode.Ink) + { + PenIcon_Click(null, null); + } + else if (palmEraserLastEditingMode == InkCanvasEditingMode.Select) + { + SymbolIconSelect_MouseUp(null, null); + } + else + { + inkCanvas.EditingMode = palmEraserLastEditingMode; + } + } + } + catch (Exception ex) + { + Trace.WriteLine($"Palm eraser recovery timer failed: {ex.Message}, forcing to Ink mode"); + inkCanvas.EditingMode = InkCanvasEditingMode.Ink; + } + + // 重置所有手掌擦状态 + isPalmEraserActive = false; + palmEraserTouchDownHandled = false; + inkCanvas.IsHitTestVisible = true; + inkCanvas.IsManipulationEnabled = true; + + // 停止定时器 + StopPalmEraserRecoveryTimer(); + } + } } } From c86ce00a1744d821670c8c0c2199f83b78bdab4c Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 18:29:24 +0800 Subject: [PATCH 15/45] =?UTF-8?q?fix:=E5=BF=AB=E6=8D=B7=E8=B0=83=E8=89=B2?= =?UTF-8?q?=E6=9D=BF=E4=B8=8D=E6=94=AF=E6=8C=81=E8=8D=A7=E5=85=89=E7=AC=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MainWindow_cs/MW_FloatingBarIcons.cs | 88 +++++++++++++++---- 1 file changed, 72 insertions(+), 16 deletions(-) diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index bc433b70..a6799df9 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -1993,6 +1993,59 @@ namespace Ink_Canvas drawingAttributes.Color = color; inkCanvas.DefaultDrawingAttributes.Color = color; + // 如果当前是荧光笔模式,同时更新荧光笔颜色和属性 + if (penType == 1) + { + // 根据颜色设置对应的荧光笔颜色索引 + if (color == Colors.White || IsColorSimilar(color, Color.FromRgb(250, 250, 250), 10)) + { + highlighterColor = 101; // 白色荧光笔 + } + else if (color == Colors.Black) + { + highlighterColor = 100; // 黑色荧光笔 + } + else if (color == Colors.Yellow || IsColorSimilar(color, Color.FromRgb(234, 179, 8), 15) || + IsColorSimilar(color, Color.FromRgb(250, 204, 21), 15) || + IsColorSimilar(color, Color.FromRgb(253, 224, 71), 15)) + { + highlighterColor = 103; // 黄色荧光笔 + } + else if (color == Color.FromRgb(255, 165, 0) || IsColorSimilar(color, Color.FromRgb(249, 115, 22), 15) || + IsColorSimilar(color, Color.FromRgb(234, 88, 12), 15)) + { + highlighterColor = 109; // 橙色荧光笔 + } + else if (color == Color.FromRgb(37, 99, 235)) + { + highlighterColor = 106; // 蓝色荧光笔 + } + else if (color == Colors.Red || IsColorSimilar(color, Color.FromRgb(220, 38, 38), 15) || + IsColorSimilar(color, Color.FromRgb(239, 68, 68), 15)) + { + highlighterColor = 102; // 红色荧光笔 + } + else if (color == Colors.Green || IsColorSimilar(color, Color.FromRgb(22, 163, 74), 15)) + { + highlighterColor = 104; // 绿色荧光笔 + } + else if (color == Color.FromRgb(147, 51, 234)) + { + highlighterColor = 107; // 紫色荧光笔 + } + + // 确保荧光笔属性正确设置 + drawingAttributes.Width = Settings.Canvas.HighlighterWidth / 2; + drawingAttributes.Height = Settings.Canvas.HighlighterWidth; + drawingAttributes.StylusTip = StylusTip.Rectangle; + drawingAttributes.IsHighlighter = true; + + inkCanvas.DefaultDrawingAttributes.Width = Settings.Canvas.HighlighterWidth / 2; + inkCanvas.DefaultDrawingAttributes.Height = Settings.Canvas.HighlighterWidth; + inkCanvas.DefaultDrawingAttributes.StylusTip = StylusTip.Rectangle; + inkCanvas.DefaultDrawingAttributes.IsHighlighter = true; + } + // 更新颜色状态 if (currentMode == 0) { @@ -2047,50 +2100,53 @@ namespace Ink_Canvas QuickColorGreenCheckSingle.Visibility = Visibility.Collapsed; // 显示当前选中颜色的check图标 - if (IsColorSimilar(selectedColor, Colors.White, 10) || IsColorSimilar(selectedColor, Color.FromRgb(250, 250, 250), 10)) + // 在荧光笔模式下,使用更宽松的颜色匹配 + int tolerance = (penType == 1) ? 25 : 15; // 荧光笔模式使用更大的容差 + + if (IsColorSimilar(selectedColor, Colors.White, tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(250, 250, 250), tolerance)) { QuickColorWhiteCheck.Visibility = Visibility.Visible; QuickColorWhiteCheckSingle.Visibility = Visibility.Visible; } - else if (IsColorSimilar(selectedColor, Colors.Black, 10)) + else if (IsColorSimilar(selectedColor, Colors.Black, tolerance)) { QuickColorBlackCheck.Visibility = Visibility.Visible; QuickColorBlackCheckSingle.Visibility = Visibility.Visible; } - else if (IsColorSimilar(selectedColor, Colors.Yellow, 15) || - IsColorSimilar(selectedColor, Color.FromRgb(234, 179, 8), 15) || - IsColorSimilar(selectedColor, Color.FromRgb(250, 204, 21), 15) || - IsColorSimilar(selectedColor, Color.FromRgb(253, 224, 71), 15)) + else if (IsColorSimilar(selectedColor, Colors.Yellow, tolerance) || + IsColorSimilar(selectedColor, Color.FromRgb(234, 179, 8), tolerance) || + IsColorSimilar(selectedColor, Color.FromRgb(250, 204, 21), tolerance) || + IsColorSimilar(selectedColor, Color.FromRgb(253, 224, 71), tolerance)) { QuickColorYellowCheck.Visibility = Visibility.Visible; QuickColorYellowCheckSingle.Visibility = Visibility.Visible; } - else if (IsColorSimilar(selectedColor, Color.FromRgb(255, 165, 0), 15) || - IsColorSimilar(selectedColor, Color.FromRgb(249, 115, 22), 15) || - IsColorSimilar(selectedColor, Color.FromRgb(234, 88, 12), 15)) + else if (IsColorSimilar(selectedColor, Color.FromRgb(255, 165, 0), tolerance) || + IsColorSimilar(selectedColor, Color.FromRgb(249, 115, 22), tolerance) || + IsColorSimilar(selectedColor, Color.FromRgb(234, 88, 12), tolerance)) { QuickColorOrangeCheck.Visibility = Visibility.Visible; QuickColorOrangeCheckSingle.Visibility = Visibility.Visible; } - else if (IsColorSimilar(selectedColor, Color.FromRgb(37, 99, 235), 15)) + else if (IsColorSimilar(selectedColor, Color.FromRgb(37, 99, 235), tolerance)) { QuickColorBlueCheck.Visibility = Visibility.Visible; // 单行显示模式没有蓝色,所以不设置单行的check } - else if (IsColorSimilar(selectedColor, Colors.Red, 15) || - IsColorSimilar(selectedColor, Color.FromRgb(220, 38, 38), 15) || - IsColorSimilar(selectedColor, Color.FromRgb(239, 68, 68), 15)) + else if (IsColorSimilar(selectedColor, Colors.Red, tolerance) || + IsColorSimilar(selectedColor, Color.FromRgb(220, 38, 38), tolerance) || + IsColorSimilar(selectedColor, Color.FromRgb(239, 68, 68), tolerance)) { QuickColorRedCheck.Visibility = Visibility.Visible; QuickColorRedCheckSingle.Visibility = Visibility.Visible; } - else if (IsColorSimilar(selectedColor, Colors.Green, 15) || - IsColorSimilar(selectedColor, Color.FromRgb(22, 163, 74), 15)) + else if (IsColorSimilar(selectedColor, Colors.Green, tolerance) || + IsColorSimilar(selectedColor, Color.FromRgb(22, 163, 74), tolerance)) { QuickColorGreenCheck.Visibility = Visibility.Visible; QuickColorGreenCheckSingle.Visibility = Visibility.Visible; } - else if (IsColorSimilar(selectedColor, Color.FromRgb(147, 51, 234), 15)) + else if (IsColorSimilar(selectedColor, Color.FromRgb(147, 51, 234), tolerance)) { QuickColorPurpleCheck.Visibility = Visibility.Visible; // 单行显示模式没有紫色,所以不设置单行的check From 84edb7bbe687c5c19c103581883b8500ca99b884 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 18:39:12 +0800 Subject: [PATCH 16/45] =?UTF-8?q?fix:=E5=BF=AB=E6=8D=B7=E8=B0=83=E8=89=B2?= =?UTF-8?q?=E6=9D=BF=E4=B8=8D=E6=94=AF=E6=8C=81=E8=8D=A7=E5=85=89=E7=AC=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow_cs/MW_Colors.cs | 3 +++ .../MainWindow_cs/MW_FloatingBarIcons.cs | 22 ++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Ink Canvas/MainWindow_cs/MW_Colors.cs b/Ink Canvas/MainWindow_cs/MW_Colors.cs index 07b4570a..4c003865 100644 --- a/Ink Canvas/MainWindow_cs/MW_Colors.cs +++ b/Ink Canvas/MainWindow_cs/MW_Colors.cs @@ -595,6 +595,9 @@ namespace Ink_Canvas drawingAttributes.Height = Settings.Canvas.HighlighterWidth; drawingAttributes.StylusTip = StylusTip.Rectangle; drawingAttributes.IsHighlighter = true; + + // 确保荧光笔模式切换后正确更新颜色和快捷调色板指示器 + ColorSwitchCheck(); } private void BtnColorBlack_Click(object sender, RoutedEventArgs e) diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index a6799df9..9d32dd4e 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -2011,8 +2011,10 @@ namespace Ink_Canvas { highlighterColor = 103; // 黄色荧光笔 } - else if (color == Color.FromRgb(255, 165, 0) || IsColorSimilar(color, Color.FromRgb(249, 115, 22), 15) || - IsColorSimilar(color, Color.FromRgb(234, 88, 12), 15)) + else if (color == Color.FromRgb(255, 165, 0) || IsColorSimilar(color, Color.FromRgb(249, 115, 22), 20) || + IsColorSimilar(color, Color.FromRgb(234, 88, 12), 20) || + IsColorSimilar(color, Color.FromRgb(251, 146, 60), 20) || + IsColorSimilar(color, Color.FromRgb(253, 126, 20), 20)) { highlighterColor = 109; // 橙色荧光笔 } @@ -2044,6 +2046,9 @@ namespace Ink_Canvas inkCanvas.DefaultDrawingAttributes.Height = Settings.Canvas.HighlighterWidth; inkCanvas.DefaultDrawingAttributes.StylusTip = StylusTip.Rectangle; inkCanvas.DefaultDrawingAttributes.IsHighlighter = true; + + // 确保荧光笔颜色索引正确更新 + inkCanvas.DefaultDrawingAttributes.Color = drawingAttributes.Color; } // 更新颜色状态 @@ -2077,6 +2082,12 @@ namespace Ink_Canvas // 更新颜色显示 ColorSwitchCheck(); + + // 如果当前是荧光笔模式,调用ColorSwitchCheck确保颜色索引正确更新 + if (penType == 1) + { + ColorSwitchCheck(); + } } private void UpdateQuickColorPaletteIndicator(Color selectedColor) @@ -2123,7 +2134,9 @@ namespace Ink_Canvas } else if (IsColorSimilar(selectedColor, Color.FromRgb(255, 165, 0), tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(249, 115, 22), tolerance) || - IsColorSimilar(selectedColor, Color.FromRgb(234, 88, 12), tolerance)) + IsColorSimilar(selectedColor, Color.FromRgb(234, 88, 12), tolerance) || + IsColorSimilar(selectedColor, Color.FromRgb(251, 146, 60), tolerance) || + IsColorSimilar(selectedColor, Color.FromRgb(253, 126, 20), tolerance)) { QuickColorOrangeCheck.Visibility = Visibility.Visible; QuickColorOrangeCheckSingle.Visibility = Visibility.Visible; @@ -2140,8 +2153,7 @@ namespace Ink_Canvas QuickColorRedCheck.Visibility = Visibility.Visible; QuickColorRedCheckSingle.Visibility = Visibility.Visible; } - else if (IsColorSimilar(selectedColor, Colors.Green, tolerance) || - IsColorSimilar(selectedColor, Color.FromRgb(22, 163, 74), tolerance)) + else if (IsColorSimilar(selectedColor, Color.FromRgb(22, 163, 74), tolerance)) { QuickColorGreenCheck.Visibility = Visibility.Visible; QuickColorGreenCheckSingle.Visibility = Visibility.Visible; From 9e63a3f49bb7987441087d9722e166b0ea5d7946 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 18:43:47 +0800 Subject: [PATCH 17/45] =?UTF-8?q?fix:=E5=BF=AB=E6=8D=B7=E8=B0=83=E8=89=B2?= =?UTF-8?q?=E6=9D=BF=E4=B8=8D=E6=94=AF=E6=8C=81=E8=8D=A7=E5=85=89=E7=AC=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index 9d32dd4e..dd3b4191 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -836,7 +836,7 @@ namespace Ink_Canvas break; case "QuickColorOrange": case "QuickColorOrangeSingle": - border.Background = new SolidColorBrush(Color.FromRgb(255, 165, 0)); + border.Background = new SolidColorBrush(Color.FromRgb(251, 150, 80)); break; case "QuickColorYellow": case "QuickColorYellowSingle": @@ -1948,7 +1948,7 @@ namespace Ink_Canvas private void QuickColorOrange_Click(object sender, RoutedEventArgs e) { - SetQuickColor(Color.FromRgb(255, 165, 0)); // 橙色 + SetQuickColor(Color.FromRgb(251, 150, 80)); // 橙色 } private void QuickColorYellow_Click(object sender, RoutedEventArgs e) @@ -2011,7 +2011,7 @@ namespace Ink_Canvas { highlighterColor = 103; // 黄色荧光笔 } - else if (color == Color.FromRgb(255, 165, 0) || IsColorSimilar(color, Color.FromRgb(249, 115, 22), 20) || + else if (color == Color.FromRgb(255, 165, 0) || color == Color.FromRgb(251, 150, 80) || IsColorSimilar(color, Color.FromRgb(249, 115, 22), 20) || IsColorSimilar(color, Color.FromRgb(234, 88, 12), 20) || IsColorSimilar(color, Color.FromRgb(251, 146, 60), 20) || IsColorSimilar(color, Color.FromRgb(253, 126, 20), 20)) @@ -2056,7 +2056,7 @@ namespace Ink_Canvas { // 桌面模式 if (color == Colors.White) lastDesktopInkColor = 5; - else if (color == Color.FromRgb(255, 165, 0)) lastDesktopInkColor = 8; // 橙色 + else if (color == Color.FromRgb(251, 150, 80)) lastDesktopInkColor = 8; // 橙色 else if (color == Colors.Yellow) lastDesktopInkColor = 4; else if (color == Colors.Black) lastDesktopInkColor = 0; else if (color == Color.FromRgb(37, 99, 235)) lastDesktopInkColor = 3; // 蓝色 @@ -2068,7 +2068,7 @@ namespace Ink_Canvas { // 白板模式 if (color == Colors.White) lastBoardInkColor = 5; - else if (color == Color.FromRgb(255, 165, 0)) lastBoardInkColor = 8; // 橙色 + else if (color == Color.FromRgb(251, 150, 80)) lastBoardInkColor = 8; // 橙色 else if (color == Colors.Yellow) lastBoardInkColor = 4; else if (color == Colors.Black) lastBoardInkColor = 0; else if (color == Color.FromRgb(37, 99, 235)) lastBoardInkColor = 3; // 蓝色 @@ -2133,6 +2133,7 @@ namespace Ink_Canvas QuickColorYellowCheckSingle.Visibility = Visibility.Visible; } else if (IsColorSimilar(selectedColor, Color.FromRgb(255, 165, 0), tolerance) || + IsColorSimilar(selectedColor, Color.FromRgb(251, 150, 80), tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(249, 115, 22), tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(234, 88, 12), tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(251, 146, 60), tolerance) || From 8f01b6c5fe1c82993782708fc95b874cc69043c1 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 18:51:16 +0800 Subject: [PATCH 18/45] =?UTF-8?q?fix:=E5=88=87=E6=8D=A2=E6=97=B6=E8=8D=A7?= =?UTF-8?q?=E5=85=89=E7=AC=94=E7=8A=B6=E6=80=81=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MainWindow_cs/MW_FloatingBarIcons.cs | 71 ++++++++++++++----- 1 file changed, 55 insertions(+), 16 deletions(-) diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index dd3b4191..eae5db73 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -1724,13 +1724,27 @@ namespace Ink_Canvas } } - // 修复:从线擦切换到批注时,重置为默认笔模式(非高光显示) + // 修复:从线擦切换到批注时,保持之前的笔类型状态 + // 如果之前是荧光笔模式,则保持荧光笔状态;否则重置为默认笔模式 forceEraser = false; forcePointEraser = false; drawingShapeMode = 0; - penType = 0; - drawingAttributes.IsHighlighter = false; - drawingAttributes.StylusTip = StylusTip.Ellipse; + + // 保持之前的笔类型状态,而不是强制重置 + if (!wasHighlighter) + { + penType = 0; + drawingAttributes.IsHighlighter = false; + drawingAttributes.StylusTip = StylusTip.Ellipse; + } + // 如果之前是荧光笔模式,则保持荧光笔属性 + else if (penType == 1) + { + drawingAttributes.IsHighlighter = true; + drawingAttributes.StylusTip = StylusTip.Rectangle; + drawingAttributes.Width = Settings.Canvas.HighlighterWidth / 2; + drawingAttributes.Height = Settings.Canvas.HighlighterWidth; + } ColorSwitchCheck(); HideSubPanels("pen", true); @@ -1742,13 +1756,26 @@ namespace Ink_Canvas // 修复:从线擦切换到批注时,确保正确重置状态 if (forceEraser) { - // 从橡皮擦模式切换过来,重置为默认笔模式 + // 从橡皮擦模式切换过来,保持之前的笔类型状态 forceEraser = false; forcePointEraser = false; drawingShapeMode = 0; - penType = 0; - drawingAttributes.IsHighlighter = false; - drawingAttributes.StylusTip = StylusTip.Ellipse; + + // 保持之前的笔类型状态,而不是强制重置 + if (!wasHighlighter) + { + penType = 0; + drawingAttributes.IsHighlighter = false; + drawingAttributes.StylusTip = StylusTip.Ellipse; + } + // 如果之前是荧光笔模式,则保持荧光笔属性 + else if (penType == 1) + { + drawingAttributes.IsHighlighter = true; + drawingAttributes.StylusTip = StylusTip.Rectangle; + drawingAttributes.Width = Settings.Canvas.HighlighterWidth / 2; + drawingAttributes.Height = Settings.Canvas.HighlighterWidth; + } // 在非白板模式下,从线擦切换到批注时不直接弹出子面板 if (currentMode != 1) @@ -1800,13 +1827,26 @@ namespace Ink_Canvas } inkCanvas.EditingMode = InkCanvasEditingMode.Ink; - // 修复:从线擦切换到批注时,重置为默认笔模式(非高光显示) + // 修复:从线擦切换到批注时,保持之前的笔类型状态 forceEraser = false; forcePointEraser = false; drawingShapeMode = 0; - penType = 0; - drawingAttributes.IsHighlighter = false; - drawingAttributes.StylusTip = StylusTip.Ellipse; + + // 保持之前的笔类型状态,而不是强制重置 + if (!wasHighlighter) + { + penType = 0; + drawingAttributes.IsHighlighter = false; + drawingAttributes.StylusTip = StylusTip.Ellipse; + } + // 如果之前是荧光笔模式,则保持荧光笔属性 + else if (penType == 1) + { + drawingAttributes.IsHighlighter = true; + drawingAttributes.StylusTip = StylusTip.Rectangle; + drawingAttributes.Width = Settings.Canvas.HighlighterWidth / 2; + drawingAttributes.Height = Settings.Canvas.HighlighterWidth; + } ColorSwitchCheck(); HideSubPanels("pen", true); @@ -1918,10 +1958,9 @@ namespace Ink_Canvas inkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke; drawingShapeMode = 0; - // 修复:切换到线擦时,确保重置笔的状态 - penType = 0; - drawingAttributes.IsHighlighter = false; - drawingAttributes.StylusTip = StylusTip.Ellipse; + // 修复:切换到线擦时,保存当前的笔类型状态,而不是强制重置 + // 这样从线擦切换回批注时,可以恢复之前的荧光笔状态 + // penType 和 drawingAttributes 的状态将在 PenIcon_Click 中根据 wasHighlighter 来恢复 inkCanvas_EditingModeChanged(inkCanvas, null); CancelSingleFingerDragMode(); From 8719677f11f76915a04501b1a1703b60db6c23cf Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 18:55:36 +0800 Subject: [PATCH 19/45] =?UTF-8?q?fix:=E5=BC=80=E5=90=AF=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=90=8E=E6=89=8B=E5=8A=BF=E9=9D=A2=E6=9D=BF?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow_cs/MW_Colors.cs | 4 ++++ Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs | 8 ++++++++ Ink Canvas/MainWindow_cs/MW_PPT.cs | 11 +++++++++++ 3 files changed, 23 insertions(+) diff --git a/Ink Canvas/MainWindow_cs/MW_Colors.cs b/Ink Canvas/MainWindow_cs/MW_Colors.cs index 4c003865..fdd0b1ea 100644 --- a/Ink Canvas/MainWindow_cs/MW_Colors.cs +++ b/Ink Canvas/MainWindow_cs/MW_Colors.cs @@ -28,6 +28,10 @@ namespace Ink_Canvas AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide); AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide); AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide); + + // 在PPT模式下隐藏手势面板 + AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder); + AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder); } BtnHideInkCanvas_Click(BtnHideInkCanvas, null); diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index eae5db73..0a17d259 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -2472,6 +2472,10 @@ namespace Ink_Canvas DeselectUIElement(); + // 在PPT模式下隐藏手势面板 + AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder); + AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder); + SaveStrokes(true); ClearStrokes(true); RestoreStrokes(true); @@ -2517,6 +2521,10 @@ namespace Ink_Canvas // 取消任何UI元素的选择 DeselectUIElement(); + // 在PPT模式下隐藏手势面板 + AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder); + AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder); + SaveStrokes(); ClearStrokes(true); RestoreStrokes(true); diff --git a/Ink Canvas/MainWindow_cs/MW_PPT.cs b/Ink Canvas/MainWindow_cs/MW_PPT.cs index 452f3f8b..50cf5edf 100644 --- a/Ink Canvas/MainWindow_cs/MW_PPT.cs +++ b/Ink Canvas/MainWindow_cs/MW_PPT.cs @@ -292,6 +292,10 @@ namespace Ink_Canvas BorderFloatingBarMainControls.Visibility = Visibility.Visible; + // 在PPT模式下隐藏手势面板 + AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder); + AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder); + if (Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow && !Settings.Automation.IsAutoFoldInPPTSlideShow) BtnColorRed_Click(null, null); @@ -394,6 +398,13 @@ namespace Ink_Canvas // 注意:这里只清空索引0的备份,不影响白板页面的墨迹(索引1及以上) TimeMachineHistories[0] = null; + // 退出PPT模式时恢复手势面板的显示状态 + if (Settings.Gesture.IsEnableTwoFingerGesture && ToggleSwitchEnableMultiTouchMode.IsOn) + { + // 根据手势设置决定是否显示手势面板 + CheckEnableTwoFingerGestureBtnVisibility(true); + } + if (GridTransparencyFakeBackground.Background != Brushes.Transparent) BtnHideInkCanvas_Click(BtnHideInkCanvas, null); } From a5eb1dfca7331010927c3d7108b437bd48eab612 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 18:58:57 +0800 Subject: [PATCH 20/45] =?UTF-8?q?fix:=E5=BC=80=E5=90=AF=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=90=8E=E6=89=8B=E5=8A=BF=E9=9D=A2=E6=9D=BF?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow_cs/MW_Colors.cs | 3 ++- Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs | 17 ++++++++++++----- Ink Canvas/MainWindow_cs/MW_PPT.cs | 12 +++++++++--- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/Ink Canvas/MainWindow_cs/MW_Colors.cs b/Ink Canvas/MainWindow_cs/MW_Colors.cs index fdd0b1ea..baa50911 100644 --- a/Ink Canvas/MainWindow_cs/MW_Colors.cs +++ b/Ink Canvas/MainWindow_cs/MW_Colors.cs @@ -29,9 +29,10 @@ namespace Ink_Canvas AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide); AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide); - // 在PPT模式下隐藏手势面板 + // 在PPT模式下隐藏手势面板和手势按钮 AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder); AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder); + EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed; } BtnHideInkCanvas_Click(BtnHideInkCanvas, null); diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index 0a17d259..edd67c3d 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -124,6 +124,13 @@ namespace Ink_Canvas /// private void CheckEnableTwoFingerGestureBtnVisibility(bool isVisible) { + // 在PPT模式下始终隐藏手势按钮 + if (currentMode == 0 || BtnPPTSlideShowEnd.Visibility == Visibility.Visible) + { + EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed; + return; + } + if (StackPanelCanvasControls.Visibility != Visibility.Visible || BorderFloatingBarMainControls.Visibility != Visibility.Visible) { @@ -131,9 +138,7 @@ namespace Ink_Canvas } else if (isVisible) { - if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) - EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed; - else EnableTwoFingerGestureBorder.Visibility = Visibility.Visible; + EnableTwoFingerGestureBorder.Visibility = Visibility.Visible; } else { @@ -2472,9 +2477,10 @@ namespace Ink_Canvas DeselectUIElement(); - // 在PPT模式下隐藏手势面板 + // 在PPT模式下隐藏手势面板和手势按钮 AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder); AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder); + EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed; SaveStrokes(true); ClearStrokes(true); @@ -2521,9 +2527,10 @@ namespace Ink_Canvas // 取消任何UI元素的选择 DeselectUIElement(); - // 在PPT模式下隐藏手势面板 + // 在PPT模式下隐藏手势面板和手势按钮 AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder); AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder); + EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed; SaveStrokes(); ClearStrokes(true); diff --git a/Ink Canvas/MainWindow_cs/MW_PPT.cs b/Ink Canvas/MainWindow_cs/MW_PPT.cs index 50cf5edf..384f86c3 100644 --- a/Ink Canvas/MainWindow_cs/MW_PPT.cs +++ b/Ink Canvas/MainWindow_cs/MW_PPT.cs @@ -292,9 +292,10 @@ namespace Ink_Canvas BorderFloatingBarMainControls.Visibility = Visibility.Visible; - // 在PPT模式下隐藏手势面板 + // 在PPT模式下隐藏手势面板和手势按钮 AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder); AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder); + EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed; if (Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow && !Settings.Automation.IsAutoFoldInPPTSlideShow) @@ -398,12 +399,17 @@ namespace Ink_Canvas // 注意:这里只清空索引0的备份,不影响白板页面的墨迹(索引1及以上) TimeMachineHistories[0] = null; - // 退出PPT模式时恢复手势面板的显示状态 + // 退出PPT模式时恢复手势面板和手势按钮的显示状态 if (Settings.Gesture.IsEnableTwoFingerGesture && ToggleSwitchEnableMultiTouchMode.IsOn) { - // 根据手势设置决定是否显示手势面板 + // 根据手势设置决定是否显示手势面板和手势按钮 CheckEnableTwoFingerGestureBtnVisibility(true); } + else + { + // 如果手势功能未启用,确保手势按钮保持隐藏 + EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed; + } if (GridTransparencyFakeBackground.Background != Brushes.Transparent) BtnHideInkCanvas_Click(BtnHideInkCanvas, null); From 40eeb9db66f4dd29a60c3f49f25007e9baef7187 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 19:04:46 +0800 Subject: [PATCH 21/45] =?UTF-8?q?fix:=E9=80=80=E5=87=BA=E6=94=BE=E6=98=A0?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E5=90=8E=E6=B5=AE=E5=8A=A8=E6=A0=8F=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow_cs/MW_PPT.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Ink Canvas/MainWindow_cs/MW_PPT.cs b/Ink Canvas/MainWindow_cs/MW_PPT.cs index 384f86c3..07b2abcc 100644 --- a/Ink Canvas/MainWindow_cs/MW_PPT.cs +++ b/Ink Canvas/MainWindow_cs/MW_PPT.cs @@ -411,6 +411,16 @@ namespace Ink_Canvas EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed; } + // 退出PPT模式时隐藏快捷调色盘 + if (QuickColorPalettePanel != null) + { + QuickColorPalettePanel.Visibility = Visibility.Collapsed; + } + if (QuickColorPaletteSingleRowPanel != null) + { + QuickColorPaletteSingleRowPanel.Visibility = Visibility.Collapsed; + } + if (GridTransparencyFakeBackground.Background != Brushes.Transparent) BtnHideInkCanvas_Click(BtnHideInkCanvas, null); } @@ -423,6 +433,9 @@ namespace Ink_Canvas await Task.Delay(150); await Application.Current.Dispatcher.InvokeAsync(() => { + // 强制重新计算浮动栏位置,确保在退出PPT模式后正确复位 + // 先调用桌面模式的复位方法,然后调用通用的位置计算方法 + PureViewboxFloatingBarMarginAnimationInDesktopMode(); ViewboxFloatingBarMarginAnimation(100, true); }); } From 44278d68b4e791abcc84cc1eec055aff4b363779 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 19:10:53 +0800 Subject: [PATCH 22/45] =?UTF-8?q?fix:=E7=BF=BB=E9=A1=B5=E6=8E=A7=E4=BB=B6?= =?UTF-8?q?=E4=B8=8D=E5=90=88=E7=90=86=E7=9A=84=E6=98=BE=E7=A4=BA=E6=97=B6?= =?UTF-8?q?=E6=9C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/PPTManager.cs | 46 ++++++++++++++++++++++++++++++ Ink Canvas/Helpers/PPTUIManager.cs | 29 ++++++++++++++++++- Ink Canvas/MainWindow_cs/MW_PPT.cs | 27 ++++++++++++++++++ 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/Ink Canvas/Helpers/PPTManager.cs b/Ink Canvas/Helpers/PPTManager.cs index 1a2d5a90..c51fa589 100644 --- a/Ink Canvas/Helpers/PPTManager.cs +++ b/Ink Canvas/Helpers/PPTManager.cs @@ -25,6 +25,7 @@ namespace Ink_Canvas.Helpers public event Action PresentationOpen; public event Action PresentationClose; public event Action PPTConnectionChanged; + public event Action SlideShowStateChanged; #endregion #region Properties @@ -92,6 +93,7 @@ namespace Ink_Canvas.Helpers #region Private Fields private Timer _connectionCheckTimer; + private Timer _slideShowStateCheckTimer; private Timer _wpsProcessCheckTimer; private Process _wpsProcess; private bool _hasWpsProcessId; @@ -99,6 +101,7 @@ namespace Ink_Canvas.Helpers private int _wpsProcessCheckCount; private WpsWindowInfo _lastForegroundWpsWindow; private DateTime _lastWindowCheckTime = DateTime.MinValue; + private bool _lastSlideShowState = false; private readonly object _lockObject = new object(); private bool _disposed = false; #endregion @@ -114,6 +117,10 @@ namespace Ink_Canvas.Helpers _connectionCheckTimer = new Timer(500); _connectionCheckTimer.Elapsed += OnConnectionCheckTimerElapsed; _connectionCheckTimer.AutoReset = true; + + _slideShowStateCheckTimer = new Timer(1000); + _slideShowStateCheckTimer.Elapsed += OnSlideShowStateCheckTimerElapsed; + _slideShowStateCheckTimer.AutoReset = true; } public void StartMonitoring() @@ -121,6 +128,7 @@ namespace Ink_Canvas.Helpers if (!_disposed) { _connectionCheckTimer?.Start(); + _slideShowStateCheckTimer?.Start(); LogHelper.WriteLogToFile("PPT监控已启动", LogHelper.LogType.Trace); } } @@ -128,6 +136,7 @@ namespace Ink_Canvas.Helpers public void StopMonitoring() { _connectionCheckTimer?.Stop(); + _slideShowStateCheckTimer?.Stop(); DisconnectFromPPT(); LogHelper.WriteLogToFile("PPT监控已停止", LogHelper.LogType.Trace); } @@ -146,6 +155,18 @@ namespace Ink_Canvas.Helpers } } + private void OnSlideShowStateCheckTimerElapsed(object sender, ElapsedEventArgs e) + { + try + { + CheckSlideShowState(); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"PPT放映状态检查失败: {ex}", LogHelper.LogType.Error); + } + } + private void CheckAndConnectToPPT() { lock (_lockObject) @@ -187,6 +208,30 @@ namespace Ink_Canvas.Helpers } } + private void CheckSlideShowState() + { + try + { + if (!IsConnected) return; + + var currentSlideShowState = IsInSlideShow; + if (currentSlideShowState != _lastSlideShowState) + { + _lastSlideShowState = currentSlideShowState; + SlideShowStateChanged?.Invoke(currentSlideShowState); + + if (!currentSlideShowState) + { + LogHelper.WriteLogToFile("检测到PPT放映已结束", LogHelper.LogType.Trace); + } + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"检查PPT放映状态异常: {ex}", LogHelper.LogType.Error); + } + } + private Microsoft.Office.Interop.PowerPoint.Application TryConnectToPowerPoint() { try @@ -1627,6 +1672,7 @@ namespace Ink_Canvas.Helpers StopWpsProcessCheckTimer(); _connectionCheckTimer?.Dispose(); + _slideShowStateCheckTimer?.Dispose(); _wpsProcessCheckTimer?.Dispose(); _disposed = true; diff --git a/Ink Canvas/Helpers/PPTUIManager.cs b/Ink Canvas/Helpers/PPTUIManager.cs index ca235958..fd2f5add 100644 --- a/Ink Canvas/Helpers/PPTUIManager.cs +++ b/Ink Canvas/Helpers/PPTUIManager.cs @@ -3,6 +3,7 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Threading; +using Ink_Canvas.Helpers; namespace Ink_Canvas.Helpers { @@ -120,6 +121,29 @@ namespace Ink_Canvas.Helpers }); } + /// + /// 处理PPT放映状态变化 + /// + public void OnSlideShowStateChanged(bool isInSlideShow) + { + _dispatcher.InvokeAsync(() => + { + try + { + if (!isInSlideShow) + { + // 如果不在放映模式,隐藏所有导航面板 + HideAllNavigationPanels(); + LogHelper.WriteLogToFile("PPT放映状态变化:隐藏导航面板", LogHelper.LogType.Trace); + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"处理PPT放映状态变化失败: {ex}", LogHelper.LogType.Error); + } + }); + } + /// /// 更新导航面板显示状态 /// @@ -130,7 +154,10 @@ namespace Ink_Canvas.Helpers try { // 检查是否应该显示PPT按钮 - bool shouldShowButtons = ShowPPTButton && _mainWindow.BtnPPTSlideShowEnd.Visibility == Visibility.Visible; + // 不仅要检查按钮设置,还要确保确实在PPT放映模式下 + bool shouldShowButtons = ShowPPTButton && + _mainWindow.BtnPPTSlideShowEnd.Visibility == Visibility.Visible && + _mainWindow.PPTManager?.IsInSlideShow == true; if (!shouldShowButtons) { diff --git a/Ink Canvas/MainWindow_cs/MW_PPT.cs b/Ink Canvas/MainWindow_cs/MW_PPT.cs index 07b2abcc..8753f03b 100644 --- a/Ink Canvas/MainWindow_cs/MW_PPT.cs +++ b/Ink Canvas/MainWindow_cs/MW_PPT.cs @@ -86,6 +86,11 @@ namespace Ink_Canvas private PPTManager _pptManager; private PPTInkManager _pptInkManager; private PPTUIManager _pptUIManager; + + /// + /// 获取PPT管理器实例(供UI管理器使用) + /// + public PPTManager PPTManager => _pptManager; #endregion #region PPT Manager Initialization @@ -104,6 +109,7 @@ namespace Ink_Canvas _pptManager.SlideShowEnd += OnPPTSlideShowEnd; _pptManager.PresentationOpen += OnPPTPresentationOpen; _pptManager.PresentationClose += OnPPTPresentationClose; + _pptManager.SlideShowStateChanged += OnPPTSlideShowStateChanged; // 初始化墨迹管理器 _pptInkManager = new PPTInkManager(); @@ -242,6 +248,27 @@ namespace Ink_Canvas } } + private void OnPPTSlideShowStateChanged(bool isInSlideShow) + { + try + { + Application.Current.Dispatcher.InvokeAsync(() => + { + // 通知UI管理器放映状态变化 + _pptUIManager?.OnSlideShowStateChanged(isInSlideShow); + + if (!isInSlideShow) + { + LogHelper.WriteLogToFile("PPT放映状态变化:退出放映模式", LogHelper.LogType.Trace); + } + }); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"处理PPT放映状态变化失败: {ex}", LogHelper.LogType.Error); + } + } + private async void OnPPTSlideShowBegin(SlideShowWindow wn) { try From 15082c2c52eab3ba779aa1d85e1d81341528ec81 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 19:16:19 +0800 Subject: [PATCH 23/45] =?UTF-8?q?fix:=E5=A2=A8=E8=BF=B9=E5=87=BA=E7=8E=B0?= =?UTF-8?q?=E5=9C=A8=E4=B8=8D=E5=AF=B9=E5=BA=94=E7=9A=84PPT=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/PPTInkManager.cs | 24 +++++++++++++++++++++--- Ink Canvas/MainWindow_cs/MW_PPT.cs | 11 +++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/Ink Canvas/Helpers/PPTInkManager.cs b/Ink Canvas/Helpers/PPTInkManager.cs index 0c548829..f8c62ccb 100644 --- a/Ink Canvas/Helpers/PPTInkManager.cs +++ b/Ink Canvas/Helpers/PPTInkManager.cs @@ -55,6 +55,13 @@ namespace Ink_Canvas.Helpers { try { + // 完全清理之前的墨迹状态 + ClearAllStrokes(); + + // 重置墨迹锁定状态 + _inkLockUntil = DateTime.MinValue; + _lockedSlideIndex = -1; + // 生成演示文稿唯一标识符 _currentPresentationId = GeneratePresentationId(presentation); @@ -152,17 +159,28 @@ namespace Ink_Canvas.Helpers { try { - // 如果有当前墨迹,先保存 + // 如果有当前墨迹,先保存到正确的页面 if (currentStrokes != null && currentStrokes.Count > 0) { - SaveCurrentSlideStrokes(_lockedSlideIndex > 0 ? _lockedSlideIndex : slideIndex, currentStrokes); + // 确定要保存的页面索引 + int saveToSlideIndex = _lockedSlideIndex > 0 ? _lockedSlideIndex : slideIndex; + + // 确保页面索引有效 + if (saveToSlideIndex > 0 && saveToSlideIndex < _memoryStreams.Length) + { + SaveCurrentSlideStrokes(saveToSlideIndex, currentStrokes); + LogHelper.WriteLogToFile($"已保存第{saveToSlideIndex}页墨迹,墨迹数量: {currentStrokes.Count}", LogHelper.LogType.Trace); + } } // 设置墨迹锁定 LockInkForSlide(slideIndex); // 加载新页面的墨迹 - return LoadSlideStrokes(slideIndex); + var newStrokes = LoadSlideStrokes(slideIndex); + LogHelper.WriteLogToFile($"已切换到第{slideIndex}页,加载墨迹数量: {newStrokes.Count}", LogHelper.LogType.Trace); + + return newStrokes; } catch (Exception ex) { diff --git a/Ink Canvas/MainWindow_cs/MW_PPT.cs b/Ink Canvas/MainWindow_cs/MW_PPT.cs index 8753f03b..9ccf8b6b 100644 --- a/Ink Canvas/MainWindow_cs/MW_PPT.cs +++ b/Ink Canvas/MainWindow_cs/MW_PPT.cs @@ -200,6 +200,15 @@ namespace Ink_Canvas { Application.Current.Dispatcher.InvokeAsync(() => { + // 在初始化墨迹管理器之前,先清理画布上的所有墨迹 + ClearStrokes(true); + + // 清理备份历史记录,防止旧演示文稿的墨迹影响新演示文稿 + if (TimeMachineHistories != null && TimeMachineHistories.Length > 0) + { + TimeMachineHistories[0] = null; + } + // 初始化墨迹管理器 _pptInkManager?.InitializePresentation(pres); @@ -219,6 +228,8 @@ namespace Ink_Canvas } _pptUIManager?.UpdateConnectionStatus(true); + + LogHelper.WriteLogToFile($"已打开新演示文稿: {pres.Name},墨迹状态已清理", LogHelper.LogType.Event); }); } catch (Exception ex) From ec2d5043ffa4cb361060c5a70af83a9bdccb0ff5 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 19:27:30 +0800 Subject: [PATCH 24/45] =?UTF-8?q?add:=E5=BA=95=E9=83=A8PPT=E7=BF=BB?= =?UTF-8?q?=E9=A1=B5=E6=8C=89=E9=92=AE=E8=B0=83=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/PPTUIManager.cs | 6 + Ink Canvas/MainWindow.xaml | 155 ++++++++++++++++++ Ink Canvas/MainWindow_cs/MW_PPT.cs | 2 + Ink Canvas/MainWindow_cs/MW_Settings.cs | 152 +++++++++++++++++ Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs | 4 + Ink Canvas/Resources/Settings.cs | 8 + 6 files changed, 327 insertions(+) diff --git a/Ink Canvas/Helpers/PPTUIManager.cs b/Ink Canvas/Helpers/PPTUIManager.cs index fd2f5add..dfb4d353 100644 --- a/Ink Canvas/Helpers/PPTUIManager.cs +++ b/Ink Canvas/Helpers/PPTUIManager.cs @@ -19,6 +19,8 @@ namespace Ink_Canvas.Helpers public int PPTBButtonsOption { get; set; } = 121; public int PPTLSButtonPosition { get; set; } = 0; public int PPTRSButtonPosition { get; set; } = 0; + public int PPTLBButtonPosition { get; set; } = 0; + public int PPTRBButtonPosition { get; set; } = 0; public bool EnablePPTButtonPageClickable { get; set; } = true; #endregion @@ -169,6 +171,10 @@ namespace Ink_Canvas.Helpers _mainWindow.LeftSidePanelForPPTNavigation.Margin = new Thickness(0, 0, 0, PPTLSButtonPosition * 2); _mainWindow.RightSidePanelForPPTNavigation.Margin = new Thickness(0, 0, 0, PPTRSButtonPosition * 2); + // 设置底部按钮水平位置 + _mainWindow.LeftBottomPanelForPPTNavigation.Margin = new Thickness(6 + PPTLBButtonPosition, 0, 0, 6); + _mainWindow.RightBottomPanelForPPTNavigation.Margin = new Thickness(0, 0, 6 + PPTRBButtonPosition, 6); + // 根据显示选项设置面板可见性 var displayOption = PPTButtonsDisplayOption.ToString(); if (displayOption.Length >= 4) diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml index ae433f8f..96397e85 100644 --- a/Ink Canvas/MainWindow.xaml +++ b/Ink Canvas/MainWindow.xaml @@ -1618,6 +1618,161 @@ + + + + + + + + + + + + + + + + + + + = 500) + { + if (PPTButtonLBPositionValueSlider.Value >= 500) + { + PPTBtnLBPlusBtn.IsEnabled = false; + PPTBtnLBPlusBtn.Opacity = 0.5; + PPTButtonLBPositionValueSlider.Value = 500; + } + else if (PPTButtonLBPositionValueSlider.Value <= -500) + { + PPTBtnLBMinusBtn.IsEnabled = false; + PPTBtnLBMinusBtn.Opacity = 0.5; + PPTButtonLBPositionValueSlider.Value = -500; + } + } + else + { + PPTBtnLBPlusBtn.IsEnabled = true; + PPTBtnLBPlusBtn.Opacity = 1; + PPTBtnLBMinusBtn.IsEnabled = true; + PPTBtnLBMinusBtn.Opacity = 1; + } + + if (PPTButtonRBPositionValueSlider.Value <= -500 || PPTButtonRBPositionValueSlider.Value >= 500) + { + if (PPTButtonRBPositionValueSlider.Value >= 500) + { + PPTBtnRBPlusBtn.IsEnabled = false; + PPTBtnRBPlusBtn.Opacity = 0.5; + PPTButtonRBPositionValueSlider.Value = 500; + } + else if (PPTButtonRBPositionValueSlider.Value <= -500) + { + PPTBtnRBMinusBtn.IsEnabled = false; + PPTBtnRBMinusBtn.Opacity = 0.5; + PPTButtonRBPositionValueSlider.Value = -500; + } + } + else + { + PPTBtnRBPlusBtn.IsEnabled = true; + PPTBtnRBPlusBtn.Opacity = 1; + PPTBtnRBMinusBtn.IsEnabled = true; + PPTBtnRBMinusBtn.Opacity = 1; + } } private void PPTBtnLSPlusBtn_Clicked(object sender, RoutedEventArgs e) @@ -834,6 +881,8 @@ namespace Ink_Canvas _pptUIManager.PPTBButtonsOption = Settings.PowerPointSettings.PPTBButtonsOption; _pptUIManager.PPTLSButtonPosition = Settings.PowerPointSettings.PPTLSButtonPosition; _pptUIManager.PPTRSButtonPosition = Settings.PowerPointSettings.PPTRSButtonPosition; + _pptUIManager.PPTLBButtonPosition = Settings.PowerPointSettings.PPTLBButtonPosition; + _pptUIManager.PPTRBButtonPosition = Settings.PowerPointSettings.PPTRBButtonPosition; _pptUIManager.UpdateNavigationPanelsVisibility(); _pptUIManager.UpdateNavigationButtonStyles(); } @@ -2798,6 +2847,109 @@ namespace Ink_Canvas SaveSettingsToFile(); } + #region 底部按钮水平位置控制 + + private void PPTButtonLBPositionValueSlider_ValueChanged(object sender, RoutedEventArgs e) + { + if (!isLoaded) return; + Settings.PowerPointSettings.PPTLBButtonPosition = (int)PPTButtonLBPositionValueSlider.Value; + UpdatePPTBtnSlidersStatus(); + UpdatePPTUIManagerSettings(); + SliderDelayAction.DebounceAction(2000, null, SaveSettingsToFile); + UpdatePPTBtnPreview(); + } + + private void PPTButtonRBPositionValueSlider_ValueChanged(object sender, RoutedEventArgs e) + { + if (!isLoaded) return; + Settings.PowerPointSettings.PPTRBButtonPosition = (int)PPTButtonRBPositionValueSlider.Value; + UpdatePPTBtnSlidersStatus(); + UpdatePPTUIManagerSettings(); + SliderDelayAction.DebounceAction(2000, null, SaveSettingsToFile); + UpdatePPTBtnPreview(); + } + + private void PPTBtnLBPlusBtn_Clicked(object sender, RoutedEventArgs e) + { + if (!isLoaded) return; + PPTButtonLBPositionValueSlider.Value++; + UpdatePPTBtnSlidersStatus(); + Settings.PowerPointSettings.PPTLBButtonPosition = (int)PPTButtonLBPositionValueSlider.Value; + SaveSettingsToFile(); + UpdatePPTBtnPreview(); + } + + private void PPTBtnLBMinusBtn_Clicked(object sender, RoutedEventArgs e) + { + if (!isLoaded) return; + PPTButtonLBPositionValueSlider.Value--; + UpdatePPTBtnSlidersStatus(); + Settings.PowerPointSettings.PPTLBButtonPosition = (int)PPTButtonLBPositionValueSlider.Value; + SaveSettingsToFile(); + UpdatePPTBtnPreview(); + } + + private void PPTBtnLBSyncBtn_Clicked(object sender, RoutedEventArgs e) + { + if (!isLoaded) return; + PPTButtonRBPositionValueSlider.Value = PPTButtonLBPositionValueSlider.Value; + UpdatePPTBtnSlidersStatus(); + Settings.PowerPointSettings.PPTRBButtonPosition = (int)PPTButtonLBPositionValueSlider.Value; + SaveSettingsToFile(); + UpdatePPTBtnPreview(); + } + + private void PPTBtnLBResetBtn_Clicked(object sender, RoutedEventArgs e) + { + if (!isLoaded) return; + PPTButtonLBPositionValueSlider.Value = 0; + UpdatePPTBtnSlidersStatus(); + Settings.PowerPointSettings.PPTLBButtonPosition = 0; + SaveSettingsToFile(); + UpdatePPTBtnPreview(); + } + + private void PPTBtnRBPlusBtn_Clicked(object sender, RoutedEventArgs e) + { + if (!isLoaded) return; + PPTButtonRBPositionValueSlider.Value++; + UpdatePPTBtnSlidersStatus(); + Settings.PowerPointSettings.PPTRBButtonPosition = (int)PPTButtonRBPositionValueSlider.Value; + SaveSettingsToFile(); + UpdatePPTBtnPreview(); + } + + private void PPTBtnRBMinusBtn_Clicked(object sender, RoutedEventArgs e) + { + if (!isLoaded) return; + PPTButtonRBPositionValueSlider.Value--; + UpdatePPTBtnSlidersStatus(); + Settings.PowerPointSettings.PPTRBButtonPosition = (int)PPTButtonRBPositionValueSlider.Value; + SaveSettingsToFile(); + UpdatePPTBtnPreview(); + } + + private void PPTBtnRBSyncBtn_Clicked(object sender, RoutedEventArgs e) + { + if (!isLoaded) return; + PPTButtonLBPositionValueSlider.Value = PPTButtonRBPositionValueSlider.Value; + UpdatePPTBtnSlidersStatus(); + Settings.PowerPointSettings.PPTLBButtonPosition = (int)PPTButtonRBPositionValueSlider.Value; + SaveSettingsToFile(); + UpdatePPTBtnPreview(); + } + + private void PPTBtnRBResetBtn_Clicked(object sender, RoutedEventArgs e) + { + if (!isLoaded) return; + PPTButtonRBPositionValueSlider.Value = 0; + Settings.PowerPointSettings.PPTRBButtonPosition = 0; + SaveSettingsToFile(); + UpdatePPTBtnPreview(); + } + + #endregion + } } diff --git a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs index 77e50239..b350d73c 100644 --- a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs +++ b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs @@ -427,6 +427,10 @@ namespace Ink_Canvas PPTButtonRightPositionValueSlider.Value = Settings.PowerPointSettings.PPTRSButtonPosition; + PPTButtonLBPositionValueSlider.Value = Settings.PowerPointSettings.PPTLBButtonPosition; + + PPTButtonRBPositionValueSlider.Value = Settings.PowerPointSettings.PPTRBButtonPosition; + UpdatePPTBtnSlidersStatus(); UpdatePPTBtnPreview(); diff --git a/Ink Canvas/Resources/Settings.cs b/Ink Canvas/Resources/Settings.cs index 3f7546bb..d5c7b5a0 100644 --- a/Ink Canvas/Resources/Settings.cs +++ b/Ink Canvas/Resources/Settings.cs @@ -245,6 +245,14 @@ namespace Ink_Canvas [JsonProperty("pptRSButtonPosition")] public int PPTRSButtonPosition { get; set; } + // 0居中,+就是往右,-就是往左 + [JsonProperty("pptLBButtonPosition")] + public int PPTLBButtonPosition { get; set; } + + // 0居中,+就是往右,-就是往左 + [JsonProperty("pptRBButtonPosition")] + public int PPTRBButtonPosition { get; set; } + [JsonProperty("pptSButtonsOption")] public int PPTSButtonsOption { get; set; } = 221; From d01a24f87994a43a414875df9ab6f18eb88be469 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 19:32:13 +0800 Subject: [PATCH 25/45] =?UTF-8?q?add:=E5=BA=95=E9=83=A8=E7=BF=BB=E9=A1=B5?= =?UTF-8?q?=E6=8E=A7=E4=BB=B6=E9=A2=84=E8=A7=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow.xaml | 16 ++++++++++++++-- Ink Canvas/MainWindow_cs/MW_Settings.cs | 3 +++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml index 96397e85..d6893bd0 100644 --- a/Ink Canvas/MainWindow.xaml +++ b/Ink Canvas/MainWindow.xaml @@ -1430,9 +1430,21 @@ + VerticalAlignment="Bottom" HorizontalAlignment="Left" RenderTransformOrigin="0.5,0.5"> + + + + + + + VerticalAlignment="Bottom" HorizontalAlignment="Right" RenderTransformOrigin="0.5,0.5"> + + + + + + diff --git a/Ink Canvas/MainWindow_cs/MW_Settings.cs b/Ink Canvas/MainWindow_cs/MW_Settings.cs index 3b0061fb..d3a695fc 100644 --- a/Ink Canvas/MainWindow_cs/MW_Settings.cs +++ b/Ink Canvas/MainWindow_cs/MW_Settings.cs @@ -971,6 +971,9 @@ namespace Ink_Canvas PPTBtnPreviewRSTransform.Y = -(Settings.PowerPointSettings.PPTRSButtonPosition * 0.5); PPTBtnPreviewLSTransform.Y = -(Settings.PowerPointSettings.PPTLSButtonPosition * 0.5); + + PPTBtnPreviewLBTransform.X = -(Settings.PowerPointSettings.PPTLBButtonPosition * 0.5); + PPTBtnPreviewRBTransform.X = -(Settings.PowerPointSettings.PPTRBButtonPosition * 0.5); } private void ToggleSwitchShowCursor_Toggled(object sender, RoutedEventArgs e) From 70735943c304ae424435d4c2fa7d641b2d56a447 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 19:43:09 +0800 Subject: [PATCH 26/45] =?UTF-8?q?add:=E9=95=BF=E6=8C=89=E7=BF=BB=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/PPTUIManager.cs | 1 + Ink Canvas/MainWindow.xaml | 13 +++ Ink Canvas/MainWindow_cs/MW_PPT.cs | 94 +++++++++++++++++++ Ink Canvas/MainWindow_cs/MW_Settings.cs | 9 ++ Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs | 3 + Ink Canvas/Resources/Settings.cs | 3 + 6 files changed, 123 insertions(+) diff --git a/Ink Canvas/Helpers/PPTUIManager.cs b/Ink Canvas/Helpers/PPTUIManager.cs index dfb4d353..6fe95e2c 100644 --- a/Ink Canvas/Helpers/PPTUIManager.cs +++ b/Ink Canvas/Helpers/PPTUIManager.cs @@ -22,6 +22,7 @@ namespace Ink_Canvas.Helpers public int PPTLBButtonPosition { get; set; } = 0; public int PPTRBButtonPosition { get; set; } = 0; public bool EnablePPTButtonPageClickable { get; set; } = true; + public bool EnablePPTButtonLongPressPageTurn { get; set; } = true; #endregion #region Private Fields diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml index d6893bd0..9597d615 100644 --- a/Ink Canvas/MainWindow.xaml +++ b/Ink Canvas/MainWindow.xaml @@ -1843,6 +1843,19 @@ + + + + + diff --git a/Ink Canvas/MainWindow_cs/MW_PPT.cs b/Ink Canvas/MainWindow_cs/MW_PPT.cs index 3a5cd22d..4834a155 100644 --- a/Ink Canvas/MainWindow_cs/MW_PPT.cs +++ b/Ink Canvas/MainWindow_cs/MW_PPT.cs @@ -11,6 +11,7 @@ using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Media; +using System.Windows.Threading; using Application = System.Windows.Application; using File = System.IO.File; using MessageBox = System.Windows.MessageBox; @@ -80,6 +81,13 @@ namespace Ink_Canvas private bool isPresentationHaveBlackSpace; private string pptName; private bool _isPptClickingBtnTurned; + + // 长按翻页相关字段 + private DispatcherTimer _longPressTimer; + private bool _isLongPressActive = false; + private bool _isLongPressNext = true; // true为下一页,false为上一页 + private const int LongPressDelay = 500; // 长按延迟时间(毫秒) + private const int LongPressInterval = 200; // 长按翻页间隔(毫秒) #endregion #region PPT Managers @@ -98,6 +106,9 @@ namespace Ink_Canvas { try { + // 初始化长按定时器 + InitializeLongPressTimer(); + // 初始化PPT管理器 _pptManager = new PPTManager(); _pptManager.IsSupportWPS = Settings.PowerPointSettings.IsSupportWPS; @@ -127,6 +138,7 @@ namespace Ink_Canvas _pptUIManager.PPTLBButtonPosition = Settings.PowerPointSettings.PPTLBButtonPosition; _pptUIManager.PPTRBButtonPosition = Settings.PowerPointSettings.PPTRBButtonPosition; _pptUIManager.EnablePPTButtonPageClickable = Settings.PowerPointSettings.EnablePPTButtonPageClickable; + _pptUIManager.EnablePPTButtonLongPressPageTurn = Settings.PowerPointSettings.EnablePPTButtonLongPressPageTurn; LogHelper.WriteLogToFile("PPT管理器初始化完成", LogHelper.LogType.Event); } @@ -157,6 +169,8 @@ namespace Ink_Canvas { _pptManager?.Dispose(); _pptInkManager?.Dispose(); + _longPressTimer?.Stop(); + _longPressTimer = null; _pptManager = null; _pptInkManager = null; _pptUIManager = null; @@ -167,6 +181,60 @@ namespace Ink_Canvas LogHelper.WriteLogToFile($"释放PPT管理器失败: {ex}", LogHelper.LogType.Error); } } + + /// + /// 初始化长按定时器 + /// + private void InitializeLongPressTimer() + { + _longPressTimer = new DispatcherTimer(); + _longPressTimer.Interval = TimeSpan.FromMilliseconds(LongPressDelay); + _longPressTimer.Tick += OnLongPressTimerTick; + } + + /// + /// 启动长按检测 + /// + /// 触发事件的控件 + /// 是否为下一页按钮 + private void StartLongPressDetection(object sender, bool isNext) + { + if (!Settings.PowerPointSettings.EnablePPTButtonLongPressPageTurn) return; + + _isLongPressNext = isNext; + _isLongPressActive = false; + _longPressTimer?.Start(); + } + + /// + /// 停止长按检测 + /// + private void StopLongPressDetection() + { + _longPressTimer?.Stop(); + _isLongPressActive = false; + } + + /// + /// 长按定时器事件处理 + /// + private void OnLongPressTimerTick(object sender, EventArgs e) + { + if (!Settings.PowerPointSettings.EnablePPTButtonLongPressPageTurn) return; + + _isLongPressActive = true; + _longPressTimer.Interval = TimeSpan.FromMilliseconds(LongPressInterval); + + // 执行翻页 + if (_isLongPressNext) + { + BtnPPTSlidesDown_Click(BtnPPTSlidesDown, null); + } + else + { + BtnPPTSlidesUp_Click(BtnPPTSlidesUp, null); + } + } #endregion #region New PPT Event Handlers @@ -1047,6 +1115,12 @@ namespace Ink_Canvas { PPTRBPreviousButtonFeedbackBorder.Opacity = 0.15; } + + // 启动长按检测 + if (Settings.PowerPointSettings.EnablePPTButtonLongPressPageTurn) + { + StartLongPressDetection(sender, false); + } } private void GridPPTControlPrevious_MouseLeave(object sender, MouseEventArgs e) { @@ -1067,6 +1141,9 @@ namespace Ink_Canvas { PPTRBPreviousButtonFeedbackBorder.Opacity = 0; } + + // 停止长按检测 + StopLongPressDetection(); } private void GridPPTControlPrevious_MouseUp(object sender, MouseButtonEventArgs e) { @@ -1087,6 +1164,10 @@ namespace Ink_Canvas { PPTRBPreviousButtonFeedbackBorder.Opacity = 0; } + + // 停止长按检测 + StopLongPressDetection(); + BtnPPTSlidesUp_Click(BtnPPTSlidesUp, null); } @@ -1110,6 +1191,12 @@ namespace Ink_Canvas { PPTRBNextButtonFeedbackBorder.Opacity = 0.15; } + + // 启动长按检测 + if (Settings.PowerPointSettings.EnablePPTButtonLongPressPageTurn) + { + StartLongPressDetection(sender, true); + } } private void GridPPTControlNext_MouseLeave(object sender, MouseEventArgs e) { @@ -1130,6 +1217,9 @@ namespace Ink_Canvas { PPTRBNextButtonFeedbackBorder.Opacity = 0; } + + // 停止长按检测 + StopLongPressDetection(); } private void GridPPTControlNext_MouseUp(object sender, MouseButtonEventArgs e) { @@ -1150,6 +1240,10 @@ namespace Ink_Canvas { PPTRBNextButtonFeedbackBorder.Opacity = 0; } + + // 停止长按检测 + StopLongPressDetection(); + BtnPPTSlidesDown_Click(BtnPPTSlidesDown, null); } diff --git a/Ink Canvas/MainWindow_cs/MW_Settings.cs b/Ink Canvas/MainWindow_cs/MW_Settings.cs index d3a695fc..011c9842 100644 --- a/Ink Canvas/MainWindow_cs/MW_Settings.cs +++ b/Ink Canvas/MainWindow_cs/MW_Settings.cs @@ -511,6 +511,13 @@ namespace Ink_Canvas SaveSettingsToFile(); } + private void ToggleSwitchEnablePPTButtonLongPressPageTurn_OnToggled(object sender, RoutedEventArgs e) + { + if (!isLoaded) return; + Settings.PowerPointSettings.EnablePPTButtonLongPressPageTurn = ToggleSwitchEnablePPTButtonLongPressPageTurn.IsOn; + SaveSettingsToFile(); + } + private void CheckboxEnableLBPPTButton_IsCheckChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; @@ -883,6 +890,8 @@ namespace Ink_Canvas _pptUIManager.PPTRSButtonPosition = Settings.PowerPointSettings.PPTRSButtonPosition; _pptUIManager.PPTLBButtonPosition = Settings.PowerPointSettings.PPTLBButtonPosition; _pptUIManager.PPTRBButtonPosition = Settings.PowerPointSettings.PPTRBButtonPosition; + _pptUIManager.EnablePPTButtonPageClickable = Settings.PowerPointSettings.EnablePPTButtonPageClickable; + _pptUIManager.EnablePPTButtonLongPressPageTurn = Settings.PowerPointSettings.EnablePPTButtonLongPressPageTurn; _pptUIManager.UpdateNavigationPanelsVisibility(); _pptUIManager.UpdateNavigationButtonStyles(); } diff --git a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs index b350d73c..454f45a1 100644 --- a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs +++ b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs @@ -367,6 +367,9 @@ namespace Ink_Canvas ToggleSwitchEnablePPTButtonPageClickable.IsOn = Settings.PowerPointSettings.EnablePPTButtonPageClickable; + ToggleSwitchEnablePPTButtonLongPressPageTurn.IsOn = + Settings.PowerPointSettings.EnablePPTButtonLongPressPageTurn; + var dops = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString(); var dopsc = dops.ToCharArray(); if ((dopsc[0] == '1' || dopsc[0] == '2') && (dopsc[1] == '1' || dopsc[1] == '2') && diff --git a/Ink Canvas/Resources/Settings.cs b/Ink Canvas/Resources/Settings.cs index d5c7b5a0..a80971c5 100644 --- a/Ink Canvas/Resources/Settings.cs +++ b/Ink Canvas/Resources/Settings.cs @@ -262,6 +262,9 @@ namespace Ink_Canvas [JsonProperty("enablePPTButtonPageClickable")] public bool EnablePPTButtonPageClickable { get; set; } = true; + [JsonProperty("enablePPTButtonLongPressPageTurn")] + public bool EnablePPTButtonLongPressPageTurn { get; set; } = true; + // -- new -- [JsonProperty("powerPointSupport")] From 108c6b2b17ac731e90ae0f74ae26df53359b6afb Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 20:24:48 +0800 Subject: [PATCH 27/45] =?UTF-8?q?improve:=E4=BD=BF=E7=94=A8=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/DeviceIdentifier.cs | 306 +++++++++++++++++++++++-- 1 file changed, 285 insertions(+), 21 deletions(-) diff --git a/Ink Canvas/Helpers/DeviceIdentifier.cs b/Ink Canvas/Helpers/DeviceIdentifier.cs index 5d1d9d67..79140029 100644 --- a/Ink Canvas/Helpers/DeviceIdentifier.cs +++ b/Ink Canvas/Helpers/DeviceIdentifier.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Reflection; using System.Security.Cryptography; using System.Text; +using System.Threading; namespace Ink_Canvas.Helpers { @@ -2750,35 +2751,298 @@ namespace Ink_Canvas.Helpers /// public static void SaveUsageStatsOnShutdown() { - lock (fileLock) // 确保线程安全 + // 使用超时锁防止死锁 + if (!Monitor.TryEnter(fileLock, TimeSpan.FromSeconds(30))) + { + LogHelper.WriteLogToFile("DeviceIdentifier | 关机保存超时,使用备用保存策略", LogHelper.LogType.Warning); + SaveUsageStatsOnShutdownFallback(); + return; + } + + try + { + LogHelper.WriteLogToFile("DeviceIdentifier | 开始关机时保存使用时间数据", LogHelper.LogType.Info); + + // 1. 加载现有使用统计数据(多重恢复策略) + UsageStats stats = LoadUsageStatsWithFallback(); + if (stats == null) + { + stats = new UsageStats { DeviceId = DeviceId }; + LogHelper.WriteLogToFile("DeviceIdentifier | 创建新的使用统计数据", LogHelper.LogType.Info); + } + + // 2. 计算本次会话时长(防止异常值) + TimeSpan sessionDuration = DateTime.Now - App.appStartTime; + long sessionSeconds = Math.Max(0, (long)sessionDuration.TotalSeconds); + + // 防止异常大的会话时长(超过24小时) + if (sessionSeconds > 86400) + { + sessionSeconds = 86400; + LogHelper.WriteLogToFile($"DeviceIdentifier | 会话时长异常,已限制为24小时: {sessionSeconds}秒", LogHelper.LogType.Warning); + } + + // 3. 更新统计数据 + stats.TotalUsageSeconds += sessionSeconds; + stats.LaunchCount++; + stats.AverageSessionSeconds = stats.TotalUsageSeconds / (double)Math.Max(1, stats.LaunchCount); + stats.LastLaunchTime = DateTime.Now; + + // 更新数据哈希值 + stats.UpdateDataHash(); + + // 4. 多重保存策略 - 确保数据不丢失 + var saveResults = new List(); + + // 4.1 保存到所有文件位置 + saveResults.Add(SaveUsageStatsToAllFileLocations(stats)); + + // 4.2 保存到所有注册表位置 + saveResults.Add(SaveUsageStatsToAllRegistryLocations(stats)); + + // 4.3 保存到内存缓存(作为最后防线) + SaveUsageStatsToMemoryCache(stats); + + // 4.4 强制刷新文件系统缓存 + ForceFlushFileSystem(); + + // 4.5 验证保存结果 + var verificationResult = VerifyDataSaveResults(stats, saveResults); + + LogHelper.WriteLogToFile($"DeviceIdentifier | 关机保存完成,验证结果: {verificationResult}", LogHelper.LogType.Info); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"DeviceIdentifier | 关机时保存使用时间数据失败: {ex.Message}", LogHelper.LogType.Error); + + // 即使主保存失败,也要尝试备用保存 + try + { + SaveUsageStatsOnShutdownFallback(); + } + catch (Exception fallbackEx) + { + LogHelper.WriteLogToFile($"DeviceIdentifier | 备用保存也失败: {fallbackEx.Message}", LogHelper.LogType.Error); + } + } + finally + { + Monitor.Exit(fileLock); + } + } + + /// + /// 关机保存的备用策略 + /// + private static void SaveUsageStatsOnShutdownFallback() + { + try + { + LogHelper.WriteLogToFile("DeviceIdentifier | 执行关机保存备用策略", LogHelper.LogType.Warning); + + // 使用最基本的保存方式 + var stats = new UsageStats { DeviceId = DeviceId }; + stats.TotalUsageSeconds = 1; // 最小记录 + stats.LaunchCount = 1; + stats.LastLaunchTime = DateTime.Now; + + // 只保存到最可靠的位置 + SaveUsageStatsToFile(BackupUsageStatsPath, stats); + SaveUsageStatsToRegistry(stats); + + LogHelper.WriteLogToFile("DeviceIdentifier | 备用策略执行完成", LogHelper.LogType.Info); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"DeviceIdentifier | 备用策略执行失败: {ex.Message}", LogHelper.LogType.Error); + } + } + + /// + /// 加载使用统计数据(带多重恢复策略) + /// + private static UsageStats LoadUsageStatsWithFallback() + { + try + { + // 1. 尝试从主文件加载 + var stats = LoadUsageStats(); + if (stats != null) return stats; + + // 2. 尝试从备份文件加载 + stats = LoadUsageStatsFromFile(BackupUsageStatsPath); + if (stats != null) return stats; + + // 3. 尝试从其他备份位置加载 + var backupPaths = new[] { SecondaryUsageBackupPath, TertiaryUsageBackupPath, QuaternaryUsageBackupPath }; + foreach (var path in backupPaths) + { + stats = LoadUsageStatsFromFile(path); + if (stats != null) return stats; + } + + // 4. 尝试从注册表恢复 + stats = LoadUsageStatsFromRegistry(); + if (stats != null) return stats; + + return null; + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"DeviceIdentifier | 多重恢复加载失败: {ex.Message}", LogHelper.LogType.Error); + return null; + } + } + + /// + /// 保存使用统计到所有文件位置 + /// + private static string SaveUsageStatsToAllFileLocations(UsageStats stats) + { + var results = new List(); + var filePaths = new[] + { + UsageStatsFilePath, + BackupUsageStatsPath, + SecondaryUsageBackupPath, + TertiaryUsageBackupPath, + QuaternaryUsageBackupPath + }; + + foreach (var filePath in filePaths) { try { - // 1. 加载现有使用统计数据 - UsageStats stats = LoadUsageStats(); - if (stats == null) - { - stats = new UsageStats { DeviceId = DeviceId }; - } - - // 2. 计算本次会话时长 - TimeSpan sessionDuration = DateTime.Now - App.appStartTime; - long sessionSeconds = (long)sessionDuration.TotalSeconds; - - // 3. 更新统计数据 - stats.TotalUsageSeconds += sessionSeconds; - stats.LaunchCount++; - stats.AverageSessionSeconds = stats.TotalUsageSeconds / (double)stats.LaunchCount; - stats.LastLaunchTime = DateTime.Now; - - // 4. 保存到所有备份位置 - SaveUsageStatsToAllLocations(stats); + SaveUsageStatsToFile(filePath, stats); + results.Add($"✓ {Path.GetFileName(filePath)}"); } catch (Exception ex) { - LogHelper.WriteLogToFile($"关机时保存使用时间数据失败: {ex.Message}", LogHelper.LogType.Error); + results.Add($"✗ {Path.GetFileName(filePath)}: {ex.Message}"); } } + + return string.Join("\n", results); } + + /// + /// 保存使用统计到所有注册表位置 + /// + private static string SaveUsageStatsToAllRegistryLocations(UsageStats stats) + { + var results = new List(); + + try + { + // 主注册表位置 + SaveUsageStatsToRegistry(stats); + results.Add("✓ 主注册表位置"); + } + catch (Exception ex) + { + results.Add($"✗ 主注册表位置: {ex.Message}"); + } + + try + { + // 备用注册表位置 + SaveUsageStatsToMultipleRegistryLocations(stats); + results.Add("✓ 备用注册表位置"); + } + catch (Exception ex) + { + results.Add($"✗ 备用注册表位置: {ex.Message}"); + } + + return string.Join("\n", results); + } + + /// + /// 保存使用统计到内存缓存 + /// + private static void SaveUsageStatsToMemoryCache(UsageStats stats) + { + try + { + // 将数据保存到静态变量作为内存备份 + _cachedUsageStats = stats; + LogHelper.WriteLogToFile("DeviceIdentifier | 数据已保存到内存缓存", LogHelper.LogType.Info); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"DeviceIdentifier | 保存到内存缓存失败: {ex.Message}", LogHelper.LogType.Error); + } + } + + /// + /// 强制刷新文件系统缓存 + /// + private static void ForceFlushFileSystem() + { + try + { + // 强制刷新所有相关目录 + var directories = new[] + { + Path.GetDirectoryName(UsageStatsFilePath), + Path.GetDirectoryName(BackupUsageStatsPath), + Path.GetDirectoryName(SecondaryUsageBackupPath), + Path.GetDirectoryName(TertiaryUsageBackupPath), + Path.GetDirectoryName(QuaternaryUsageBackupPath) + }; + + foreach (var dir in directories.Where(d => !string.IsNullOrEmpty(d) && Directory.Exists(d))) + { + try + { + // 创建临时文件来强制刷新 + var tempFile = Path.Combine(dir, ".flush.tmp"); + File.WriteAllText(tempFile, DateTime.Now.ToString()); + File.Delete(tempFile); + } + catch { /* 忽略刷新错误 */ } + } + + LogHelper.WriteLogToFile("DeviceIdentifier | 文件系统缓存刷新完成", LogHelper.LogType.Info); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"DeviceIdentifier | 文件系统缓存刷新失败: {ex.Message}", LogHelper.LogType.Error); + } + } + + /// + /// 验证数据保存结果 + /// + private static string VerifyDataSaveResults(UsageStats stats, List saveResults) + { + var verification = new StringBuilder(); + verification.AppendLine("数据保存验证结果:"); + verification.AppendLine(string.Join("\n", saveResults)); + + // 验证关键数据是否保存成功 + try + { + var savedStats = LoadUsageStats(); + if (savedStats != null && savedStats.DeviceId == stats.DeviceId) + { + verification.AppendLine("✓ 主数据文件验证成功"); + } + else + { + verification.AppendLine("✗ 主数据文件验证失败"); + } + } + catch (Exception ex) + { + verification.AppendLine($"✗ 主数据文件验证异常: {ex.Message}"); + } + + return verification.ToString(); + } + + // 内存缓存变量 + private static UsageStats _cachedUsageStats; } } + From 710a9014dd618840da790d40b2e5425a8cdf9b3a Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 23 Aug 2025 21:39:00 +0800 Subject: [PATCH 28/45] improve:issue #112 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 301 +++++++++++++++ Ink Canvas/Helpers/InkFadeManager.cs | 264 +++++++++++++ Ink Canvas/Helpers/PPTUIManager.cs | 1 - Ink Canvas/MainWindow.xaml.cs | 59 ++- .../MainWindow_cs/MW_ClipboardHandler.cs | 2 +- .../MainWindow_cs/MW_FloatingBarIcons.cs | 19 +- Ink Canvas/MainWindow_cs/MW_Hotkeys.cs | 2 +- Ink Canvas/MainWindow_cs/MW_Screenshot.cs | 2 +- Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs | 4 +- Ink Canvas/Windows/HotkeyItem.xaml | 65 ++++ Ink Canvas/Windows/HotkeyItem.xaml.cs | 166 ++++++++ Ink Canvas/Windows/HotkeySettingsWindow.xaml | 191 ++++++++++ .../Windows/HotkeySettingsWindow.xaml.cs | 357 ++++++++++++++++++ 13 files changed, 1414 insertions(+), 19 deletions(-) create mode 100644 Ink Canvas/Helpers/GlobalHotkeyManager.cs create mode 100644 Ink Canvas/Helpers/InkFadeManager.cs create mode 100644 Ink Canvas/Windows/HotkeyItem.xaml create mode 100644 Ink Canvas/Windows/HotkeyItem.xaml.cs create mode 100644 Ink Canvas/Windows/HotkeySettingsWindow.xaml create mode 100644 Ink Canvas/Windows/HotkeySettingsWindow.xaml.cs diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs new file mode 100644 index 00000000..4ab1a459 --- /dev/null +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -0,0 +1,301 @@ +using System; +using System.Collections.Generic; +using System.Windows.Input; +using NHotkey.Wpf; + +namespace Ink_Canvas.Helpers +{ + /// + /// 全局快捷键管理器 - 使用NHotkey库实现全局快捷键功能 + /// + public class GlobalHotkeyManager : IDisposable + { + #region Private Fields + private readonly Dictionary _registeredHotkeys; + private readonly MainWindow _mainWindow; + private bool _isDisposed = false; + #endregion + + #region Constructor + public GlobalHotkeyManager(MainWindow mainWindow) + { + _mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); + _registeredHotkeys = new Dictionary(); + } + #endregion + + #region Public Methods + /// + /// 注册全局快捷键 + /// + /// 快捷键名称 + /// 按键 + /// 修饰键 + /// 执行动作 + /// 是否注册成功 + public bool RegisterHotkey(string hotkeyName, Key key, ModifierKeys modifiers, Action action) + { + try + { + if (_isDisposed) + return false; + + // 如果快捷键已存在,先注销 + if (_registeredHotkeys.ContainsKey(hotkeyName)) + { + UnregisterHotkey(hotkeyName); + } + + // 创建快捷键信息 + var hotkeyInfo = new HotkeyInfo + { + Name = hotkeyName, + Key = key, + Modifiers = modifiers, + Action = action + }; + + // 注册快捷键 + HotkeyManager.Current.AddOrReplace(hotkeyName, key, modifiers, (sender, e) => + { + try + { + // 确保在主线程中执行 + _mainWindow.Dispatcher.Invoke(() => + { + action?.Invoke(); + }); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"执行快捷键 {hotkeyName} 时出错: {ex.Message}", LogHelper.LogType.Error); + } + }); + + _registeredHotkeys[hotkeyName] = hotkeyInfo; + LogHelper.WriteLogToFile($"成功注册全局快捷键: {hotkeyName} ({modifiers}+{key})", LogHelper.LogType.Event); + return true; + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"注册全局快捷键 {hotkeyName} 失败: {ex.Message}", LogHelper.LogType.Error); + return false; + } + } + + /// + /// 注销指定快捷键 + /// + /// 快捷键名称 + /// 是否注销成功 + public bool UnregisterHotkey(string hotkeyName) + { + try + { + if (_isDisposed || !_registeredHotkeys.ContainsKey(hotkeyName)) + return false; + + HotkeyManager.Current.Remove(hotkeyName); + _registeredHotkeys.Remove(hotkeyName); + LogHelper.WriteLogToFile($"成功注销全局快捷键: {hotkeyName}", LogHelper.LogType.Event); + return true; + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"注销全局快捷键 {hotkeyName} 失败: {ex.Message}", LogHelper.LogType.Error); + return false; + } + } + + /// + /// 注销所有快捷键 + /// + public void UnregisterAllHotkeys() + { + try + { + if (_isDisposed) + return; + + foreach (var hotkeyName in _registeredHotkeys.Keys) + { + try + { + HotkeyManager.Current.Remove(hotkeyName); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"注销快捷键 {hotkeyName} 时出错: {ex.Message}", LogHelper.LogType.Warning); + } + } + + _registeredHotkeys.Clear(); + LogHelper.WriteLogToFile("已注销所有全局快捷键", LogHelper.LogType.Event); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"注销所有快捷键时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + + /// + /// 检查快捷键是否已注册 + /// + /// 快捷键名称 + /// 是否已注册 + public bool IsHotkeyRegistered(string hotkeyName) + { + return _registeredHotkeys.ContainsKey(hotkeyName); + } + + /// + /// 获取已注册的快捷键列表 + /// + /// 快捷键信息列表 + public List GetRegisteredHotkeys() + { + return new List(_registeredHotkeys.Values); + } + + /// + /// 注册默认快捷键集合 + /// + public void RegisterDefaultHotkeys() + { + try + { + // 基本操作快捷键 + RegisterHotkey("Undo", Key.Z, ModifierKeys.Control, () => _mainWindow.SymbolIconUndo_MouseUp(null, null)); + RegisterHotkey("Redo", Key.Y, ModifierKeys.Control, () => _mainWindow.SymbolIconRedo_MouseUp(null, null)); + RegisterHotkey("Clear", Key.E, ModifierKeys.Control, () => _mainWindow.SymbolIconDelete_MouseUp(null, null)); + RegisterHotkey("Paste", Key.V, ModifierKeys.Control, () => _mainWindow.HandleGlobalPaste(null, null)); + + // 工具切换快捷键 + RegisterHotkey("SelectTool", Key.S, ModifierKeys.Alt, () => _mainWindow.SymbolIconSelect_MouseUp(null, null)); + RegisterHotkey("DrawTool", Key.D, ModifierKeys.Alt, () => _mainWindow.PenIcon_Click(null, null)); + RegisterHotkey("EraserTool", Key.E, ModifierKeys.Alt, () => _mainWindow.EraserIcon_Click(null, null)); + RegisterHotkey("BlackboardTool", Key.B, ModifierKeys.Alt, () => _mainWindow.ImageBlackboard_MouseUp(null, null)); + RegisterHotkey("QuitDrawTool", Key.Q, ModifierKeys.Alt, () => _mainWindow.CursorIcon_Click(null, null)); + + // 画笔快捷键 - 使用反射访问penType字段 + RegisterHotkey("Pen1", Key.D1, ModifierKeys.Alt, () => SwitchToPenType(0)); + RegisterHotkey("Pen2", Key.D2, ModifierKeys.Alt, () => SwitchToPenType(1)); + RegisterHotkey("Pen3", Key.D3, ModifierKeys.Alt, () => SwitchToPenType(2)); + RegisterHotkey("Pen4", Key.D4, ModifierKeys.Alt, () => SwitchToPenType(3)); + RegisterHotkey("Pen5", Key.D5, ModifierKeys.Alt, () => SwitchToPenType(4)); + + // 功能快捷键 + RegisterHotkey("DrawLine", Key.L, ModifierKeys.Alt, () => _mainWindow.BtnDrawLine_Click(null, null)); + RegisterHotkey("Screenshot", Key.C, ModifierKeys.Alt, () => _mainWindow.SaveScreenShotToDesktop()); + RegisterHotkey("Hide", Key.V, ModifierKeys.Alt, () => _mainWindow.SymbolIconEmoji_MouseUp(null, null)); + + // 退出快捷键 + RegisterHotkey("Exit", Key.Escape, ModifierKeys.None, () => _mainWindow.KeyExit(null, null)); + + LogHelper.WriteLogToFile("已注册默认全局快捷键集合", LogHelper.LogType.Event); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"注册默认快捷键时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + + /// + /// 从设置加载快捷键配置 + /// + public void LoadHotkeysFromSettings() + { + try + { + // 这里可以从配置文件或设置中加载自定义快捷键 + // 暂时使用默认快捷键 + RegisterDefaultHotkeys(); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"从设置加载快捷键时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + + /// + /// 保存快捷键配置到设置 + /// + public void SaveHotkeysToSettings() + { + try + { + // 这里可以将快捷键配置保存到配置文件或设置中 + LogHelper.WriteLogToFile("快捷键配置已保存", LogHelper.LogType.Event); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"保存快捷键配置时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + #endregion + + #region Private Helper Methods + /// + /// 切换到指定笔类型 + /// + /// 笔类型索引 + private void SwitchToPenType(int penTypeIndex) + { + try + { + // 通过反射访问主窗口的penType字段 + var penTypeField = _mainWindow.GetType().GetField("penType", + System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + + if (penTypeField != null) + { + penTypeField.SetValue(_mainWindow, penTypeIndex); + + // 调用CheckPenTypeUIState方法更新UI状态 + var checkPenTypeMethod = _mainWindow.GetType().GetMethod("CheckPenTypeUIState", + System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + + if (checkPenTypeMethod != null) + { + checkPenTypeMethod.Invoke(_mainWindow, null); + } + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"切换到笔类型{penTypeIndex}时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + #endregion + + #region IDisposable Implementation + public void Dispose() + { + if (!_isDisposed) + { + UnregisterAllHotkeys(); + _isDisposed = true; + } + } + #endregion + + #region Nested Classes + /// + /// 快捷键信息类 + /// + public class HotkeyInfo + { + public string Name { get; set; } + public Key Key { get; set; } + public ModifierKeys Modifiers { get; set; } + public Action Action { get; set; } + + public override string ToString() + { + var modifiersText = Modifiers == ModifierKeys.None ? "" : $"{Modifiers}+"; + return $"{modifiersText}{Key}"; + } + } + #endregion + } +} \ No newline at end of file diff --git a/Ink Canvas/Helpers/InkFadeManager.cs b/Ink Canvas/Helpers/InkFadeManager.cs new file mode 100644 index 00000000..6ddbc874 --- /dev/null +++ b/Ink Canvas/Helpers/InkFadeManager.cs @@ -0,0 +1,264 @@ +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Media.Animation; +using System.Windows.Threading; +using System.Windows.Ink; + +namespace Ink_Canvas.Helpers +{ + /// + /// 墨迹渐隐管理器 - 管理墨迹的渐隐动画和状态 + /// + public class InkFadeManager + { + #region Properties + /// + /// 是否启用墨迹渐隐功能 + /// + public bool IsEnabled { get; set; } = false; + + /// + /// 墨迹渐隐时间(毫秒) + /// + public int FadeTime { get; set; } = 3000; + + /// + /// 渐隐动画持续时间(毫秒) + /// + public int AnimationDuration { get; set; } = 1000; + #endregion + + #region Private Fields + private readonly MainWindow _mainWindow; + private readonly Dispatcher _dispatcher; + private readonly Dictionary _fadeTimers; + private readonly Dictionary _strokeVisuals; + #endregion + + #region Constructor + public InkFadeManager(MainWindow mainWindow) + { + _mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); + _dispatcher = _mainWindow.Dispatcher; + _fadeTimers = new Dictionary(); + _strokeVisuals = new Dictionary(); + } + #endregion + + #region Public Methods + /// + /// 添加需要渐隐的墨迹 + /// + /// 墨迹对象 + /// 墨迹的视觉元素 + public void AddFadingStroke(Stroke stroke, UIElement visual) + { + if (!IsEnabled || stroke == null || visual == null) return; + + try + { + // 记录墨迹和视觉元素的对应关系 + _strokeVisuals[stroke] = visual; + + // 创建定时器,在指定时间后开始渐隐动画 + var timer = new DispatcherTimer + { + Interval = TimeSpan.FromMilliseconds(FadeTime) + }; + + timer.Tick += (sender, e) => + { + StartFadeAnimation(stroke); + timer.Stop(); + _fadeTimers.Remove(stroke); + }; + + _fadeTimers[stroke] = timer; + timer.Start(); + + // 将视觉元素添加到画布上 + _dispatcher.InvokeAsync(() => + { + try + { + if (_mainWindow.inkCanvas != null) + { + _mainWindow.inkCanvas.Children.Add(visual); + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"添加墨迹视觉元素到画布失败: {ex}", LogHelper.LogType.Error); + } + }); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"添加渐隐墨迹失败: {ex}", LogHelper.LogType.Error); + } + } + + /// + /// 移除墨迹 + /// + /// 要移除的墨迹 + public void RemoveStroke(Stroke stroke) + { + if (stroke == null) return; + + try + { + if (_fadeTimers.TryGetValue(stroke, out var timer)) + { + timer.Stop(); + _fadeTimers.Remove(stroke); + } + + if (_strokeVisuals.TryGetValue(stroke, out var visual)) + { + _dispatcher.InvokeAsync(() => + { + try + { + if (_mainWindow.inkCanvas != null && _mainWindow.inkCanvas.Children.Contains(visual)) + { + _mainWindow.inkCanvas.Children.Remove(visual); + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"从画布移除墨迹视觉元素失败: {ex}", LogHelper.LogType.Error); + } + }); + + _strokeVisuals.Remove(stroke); + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"移除渐隐墨迹失败: {ex}", LogHelper.LogType.Error); + } + } + + /// + /// 清除所有渐隐墨迹 + /// + public void ClearAllFadingStrokes() + { + try + { + foreach (var timer in _fadeTimers.Values) + { + timer.Stop(); + } + + _fadeTimers.Clear(); + + _dispatcher.InvokeAsync(() => + { + try + { + if (_mainWindow.inkCanvas != null) + { + foreach (var visual in _strokeVisuals.Values) + { + if (_mainWindow.inkCanvas.Children.Contains(visual)) + { + _mainWindow.inkCanvas.Children.Remove(visual); + } + } + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"清除所有墨迹视觉元素失败: {ex}", LogHelper.LogType.Error); + } + }); + + _strokeVisuals.Clear(); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"清除所有渐隐墨迹失败: {ex}", LogHelper.LogType.Error); + } + } + + /// + /// 更新渐隐时间设置 + /// + /// 新的渐隐时间(毫秒) + public void UpdateFadeTime(int fadeTime) + { + FadeTime = fadeTime; + + foreach (var kvp in _fadeTimers) + { + var stroke = kvp.Key; + var timer = kvp.Value; + + timer.Stop(); + timer.Interval = TimeSpan.FromMilliseconds(FadeTime); + timer.Start(); + } + } + + /// + /// 更新动画持续时间设置 + /// + /// 新的动画持续时间(毫秒) + public void UpdateAnimationDuration(int animationDuration) + { + AnimationDuration = animationDuration; + } + #endregion + + #region Private Methods + /// + /// 开始渐隐动画 + /// + /// 要渐隐的墨迹 + private void StartFadeAnimation(Stroke stroke) + { + if (!_strokeVisuals.TryGetValue(stroke, out var visual)) return; + + try + { + _dispatcher.InvokeAsync(() => + { + var fadeAnimation = new DoubleAnimation + { + From = 1.0, + To = 0.0, + Duration = TimeSpan.FromMilliseconds(AnimationDuration), + EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut } + }; + + fadeAnimation.Completed += (sender, e) => + { + try + { + if (_mainWindow.inkCanvas != null && _mainWindow.inkCanvas.Children.Contains(visual)) + { + _mainWindow.inkCanvas.Children.Remove(visual); + } + + RemoveStroke(stroke); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"渐隐动画完成后清理墨迹失败: {ex}", LogHelper.LogType.Error); + } + }; + + visual.BeginAnimation(UIElement.OpacityProperty, fadeAnimation); + }); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"开始渐隐动画失败: {ex}", LogHelper.LogType.Error); + } + } + #endregion + } +} \ No newline at end of file diff --git a/Ink Canvas/Helpers/PPTUIManager.cs b/Ink Canvas/Helpers/PPTUIManager.cs index 6fe95e2c..5bf4b636 100644 --- a/Ink Canvas/Helpers/PPTUIManager.cs +++ b/Ink Canvas/Helpers/PPTUIManager.cs @@ -3,7 +3,6 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Threading; -using Ink_Canvas.Helpers; namespace Ink_Canvas.Helpers { diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index 31bc55a5..14a0ff8d 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -41,6 +41,9 @@ namespace Ink_Canvas private int currentPageIndex; private System.Windows.Controls.Canvas currentCanvas; private AutoUpdateHelper.UpdateLineGroup AvailableLatestLineGroup; + + // 全局快捷键管理器 + private GlobalHotkeyManager _globalHotkeyManager; @@ -495,6 +498,9 @@ namespace Ink_Canvas // 初始化剪贴板监控 InitializeClipboardMonitoring(); + + // 初始化全局快捷键管理器 + InitializeGlobalHotkeyManager(); } private void SystemEventsOnDisplaySettingsChanged(object sender, EventArgs e) @@ -623,6 +629,13 @@ namespace Ink_Canvas // 清理剪贴板监控 CleanupClipboardMonitoring(); ClipboardNotification.Stop(); + + // 清理全局快捷键管理器 + if (_globalHotkeyManager != null) + { + _globalHotkeyManager.Dispose(); + _globalHotkeyManager = null; + } // 停止置顶维护定时器 StopTopmostMaintenance(); @@ -1067,10 +1080,7 @@ namespace Ink_Canvas // 新增:快捷键设置 private void NavShortcuts_Click(object sender, RoutedEventArgs e) { - // 切换到快捷键设置页面 - ShowSettingsSection("shortcuts"); - // 如果设置部分尚未快捷键 - MessageBox.Show("设置功能正在开发中", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + OpenHotkeySettingsWindow(); } private void BtnCloseSettings_Click(object sender, RoutedEventArgs e) @@ -1955,5 +1965,46 @@ namespace Ink_Canvas } #endregion + + #region 全局快捷键管理 + /// + /// 初始化全局快捷键管理器 + /// + private void InitializeGlobalHotkeyManager() + { + try + { + _globalHotkeyManager = new GlobalHotkeyManager(this); + _globalHotkeyManager.LoadHotkeysFromSettings(); + LogHelper.WriteLogToFile("全局快捷键管理器已初始化", LogHelper.LogType.Event); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"初始化全局快捷键管理器时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + + /// + /// 打开快捷键设置窗口 + /// + private void OpenHotkeySettingsWindow() + { + try + { + if (_globalHotkeyManager == null) + { + MessageBox.Show("快捷键管理器尚未初始化,请稍后重试。", "错误", MessageBoxButton.OK, MessageBoxImage.Error); + return; + } + var hotkeySettingsWindow = new HotkeySettingsWindow(this, _globalHotkeyManager); + hotkeySettingsWindow.ShowDialog(); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"打开快捷键设置窗口时出错: {ex.Message}", LogHelper.LogType.Error); + MessageBox.Show($"打开快捷键设置窗口时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); + } + } + #endregion } } diff --git a/Ink Canvas/MainWindow_cs/MW_ClipboardHandler.cs b/Ink Canvas/MainWindow_cs/MW_ClipboardHandler.cs index de6b9ba3..ee4a6152 100644 --- a/Ink Canvas/MainWindow_cs/MW_ClipboardHandler.cs +++ b/Ink Canvas/MainWindow_cs/MW_ClipboardHandler.cs @@ -185,7 +185,7 @@ namespace Ink_Canvas } // 处理全局粘贴快捷键 - private async void HandleGlobalPaste(object sender, ExecutedRoutedEventArgs e) + internal async void HandleGlobalPaste(object sender, ExecutedRoutedEventArgs e) { try { diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index edd67c3d..67f0ec06 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -186,7 +186,7 @@ namespace Ink_Canvas GridForFloatingBarDraging.Visibility = Visibility.Visible; } - private void SymbolIconEmoji_MouseUp(object sender, MouseButtonEventArgs e) + internal void SymbolIconEmoji_MouseUp(object sender, MouseButtonEventArgs e) { isDragDropInEffect = false; @@ -495,7 +495,8 @@ namespace Ink_Canvas #endregion #region 撤銷重做按鈕 - private void SymbolIconUndo_MouseUp(object sender, MouseButtonEventArgs e) + + internal void SymbolIconUndo_MouseUp(object sender, MouseButtonEventArgs e) { //if (lastBorderMouseDownObject != sender) return; @@ -508,7 +509,7 @@ namespace Ink_Canvas HideSubPanels(); } - private void SymbolIconRedo_MouseUp(object sender, MouseButtonEventArgs e) + internal void SymbolIconRedo_MouseUp(object sender, MouseButtonEventArgs e) { //if (lastBorderMouseDownObject != sender) return; @@ -528,7 +529,7 @@ namespace Ink_Canvas //private bool Not_Enter_Blackboard_fir_Mouse_Click = true; private bool isDisplayingOrHidingBlackboard; - private void ImageBlackboard_MouseUp(object sender, MouseButtonEventArgs e) + internal void ImageBlackboard_MouseUp(object sender, MouseButtonEventArgs e) { if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel) @@ -728,7 +729,7 @@ namespace Ink_Canvas #region 清空畫布按鈕 - private void SymbolIconDelete_MouseUp(object sender, MouseButtonEventArgs e) + internal void SymbolIconDelete_MouseUp(object sender, MouseButtonEventArgs e) { if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel) @@ -778,7 +779,7 @@ namespace Ink_Canvas /// /// sender /// MouseButtonEventArgs - private void SymbolIconSelect_MouseUp(object sender, MouseButtonEventArgs e) + internal void SymbolIconSelect_MouseUp(object sender, MouseButtonEventArgs e) { if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel) @@ -1542,7 +1543,7 @@ namespace Ink_Canvas }); } - private async void CursorIcon_Click(object sender, RoutedEventArgs e) + internal async void CursorIcon_Click(object sender, RoutedEventArgs e) { if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel) ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent); @@ -1648,7 +1649,7 @@ namespace Ink_Canvas } } - private void PenIcon_Click(object sender, RoutedEventArgs e) + internal void PenIcon_Click(object sender, RoutedEventArgs e) { if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel) @@ -1866,7 +1867,7 @@ namespace Ink_Canvas CheckColorTheme(); } - private void EraserIcon_Click(object sender, RoutedEventArgs e) + internal void EraserIcon_Click(object sender, RoutedEventArgs e) { EnterMultiTouchModeIfNeeded(); bool isAlreadyEraser = inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint; diff --git a/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs b/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs index 594d3a21..79ef9e5f 100644 --- a/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs +++ b/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs @@ -57,7 +57,7 @@ namespace Ink_Canvas } - private void KeyExit(object sender, ExecutedRoutedEventArgs e) + internal void KeyExit(object sender, ExecutedRoutedEventArgs e) { if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) BtnPPTSlideShowEnd_Click(BtnPPTSlideShowEnd, null); } diff --git a/Ink Canvas/MainWindow_cs/MW_Screenshot.cs b/Ink Canvas/MainWindow_cs/MW_Screenshot.cs index 38b40348..00e537fd 100644 --- a/Ink Canvas/MainWindow_cs/MW_Screenshot.cs +++ b/Ink Canvas/MainWindow_cs/MW_Screenshot.cs @@ -42,7 +42,7 @@ namespace Ink_Canvas SaveInkCanvasStrokes(false); } - private void SaveScreenShotToDesktop() + internal void SaveScreenShotToDesktop() { var desktopPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), diff --git a/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs b/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs index 9e520900..fdaf44ba 100644 --- a/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs +++ b/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs @@ -172,8 +172,8 @@ namespace Ink_Canvas return Task.FromResult(true); } - - private async void BtnDrawLine_Click(object sender, MouseButtonEventArgs e) + + internal async void BtnDrawLine_Click(object sender, MouseButtonEventArgs e) { await CheckIsDrawingShapesInMultiTouchMode(); EnterShapeDrawingMode(1); diff --git a/Ink Canvas/Windows/HotkeyItem.xaml b/Ink Canvas/Windows/HotkeyItem.xaml new file mode 100644 index 00000000..a7ebf536 --- /dev/null +++ b/Ink Canvas/Windows/HotkeyItem.xaml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + +