From d41ecd9d55b101ae61104c2b9591ec83c3696bdf Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Mon, 25 Aug 2025 09:00:45 +0800 Subject: [PATCH 01/39] =?UTF-8?q?fix:=E4=BF=AE=E6=AD=A3=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/AutoUpdateHelper.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Ink Canvas/Helpers/AutoUpdateHelper.cs b/Ink Canvas/Helpers/AutoUpdateHelper.cs index d0910eb9..b12e2260 100644 --- a/Ink Canvas/Helpers/AutoUpdateHelper.cs +++ b/Ink Canvas/Helpers/AutoUpdateHelper.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Concurrent; @@ -45,9 +45,9 @@ namespace Ink_Canvas.Helpers new UpdateLineGroup { GroupName = "GitHub主线", - 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" + 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" }, new UpdateLineGroup { @@ -80,9 +80,9 @@ namespace Ink_Canvas.Helpers new UpdateLineGroup { GroupName = "GitHub主线", - 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" + 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" }, 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\""); @@ -1515,7 +1515,7 @@ namespace Ink_Canvas.Helpers LogHelper.WriteLogToFile("AutoUpdate | 开始测试Windows 7 TLS连接..."); // 测试GitHub连接 - var testUrl = "https://bgithub.xyz/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt"; + var testUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt"; using (var handler = new HttpClientHandler()) { @@ -1631,4 +1631,3 @@ namespace Ink_Canvas.Helpers } } } - From 0ba00c08efb7427769a6dc888fff0a5ce5c071ff Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Mon, 25 Aug 2025 09:53:01 +0800 Subject: [PATCH 02/39] =?UTF-8?q?fix:=E6=9B=B4=E6=96=B0=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/AutoUpdateHelper.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Ink Canvas/Helpers/AutoUpdateHelper.cs b/Ink Canvas/Helpers/AutoUpdateHelper.cs index b12e2260..b9903a23 100644 --- a/Ink Canvas/Helpers/AutoUpdateHelper.cs +++ b/Ink Canvas/Helpers/AutoUpdateHelper.cs @@ -67,11 +67,13 @@ namespace Ink_Canvas.Helpers { GroupName = "智教联盟", DownloadUrlFormat = "https://get.smart-teach.cn/d/Ningbo-S3/shared/jiangling/community/InkCanvasForClass.CE.{0}.zip", + LogUrl = "https://bgithub.xyz/InkCanvasForClass/community/raw/refs/heads/main/UpdateLog.md" }, new UpdateLineGroup { GroupName = "inkeys", DownloadUrlFormat = "https://iccce.inkeys.top/Release/InkCanvasForClass.CE.{0}.zip", + LogUrl = "https://bgithub.xyz/InkCanvasForClass/community/raw/refs/heads/main/UpdateLog.md" } } }, @@ -102,11 +104,13 @@ namespace Ink_Canvas.Helpers { GroupName = "智教联盟", DownloadUrlFormat = "https://get.smart-teach.cn/d/Ningbo-S3/shared/jiangling/community-beta/InkCanvasForClass.CE.{0}.zip", + LogUrl = "https://bgithub.xyz/InkCanvasForClass/community-beta/raw/refs/heads/main/UpdateLog.md" }, new UpdateLineGroup { GroupName = "inkeys", DownloadUrlFormat = "https://iccce.inkeys.top/Beta/InkCanvasForClass.CE.{0}.zip", + LogUrl = "https://bgithub.xyz/InkCanvasForClass/community-beta/raw/refs/heads/main/UpdateLog.md" } } } From 876cc116ea1d0c8ec74335efd0a5039a04ac199e Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Wed, 27 Aug 2025 12:23:05 +0800 Subject: [PATCH 03/39] fix:issue #140 --- Ink Canvas/MainWindow.xaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml index dc54dd47..e3d92bfa 100644 --- a/Ink Canvas/MainWindow.xaml +++ b/Ink Canvas/MainWindow.xaml @@ -5684,6 +5684,7 @@ @@ -8676,6 +8677,7 @@ From b428b4ec5be9f319cc53d08d73f872860ae63a5e Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:57:06 +0800 Subject: [PATCH 04/39] =?UTF-8?q?=E5=9B=9E=E6=BB=9A=E7=AD=89=E5=BE=85?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=88=AA=E5=9B=BE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow_cs/MW_Screenshot.cs | 403 ++-------------------- 1 file changed, 28 insertions(+), 375 deletions(-) diff --git a/Ink Canvas/MainWindow_cs/MW_Screenshot.cs b/Ink Canvas/MainWindow_cs/MW_Screenshot.cs index 00e537fd..715118f7 100644 --- a/Ink Canvas/MainWindow_cs/MW_Screenshot.cs +++ b/Ink Canvas/MainWindow_cs/MW_Screenshot.cs @@ -1,431 +1,84 @@ -using Ink_Canvas.Helpers; using System; -using System.Collections.Generic; using System.Drawing; -using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; -using System.Threading.Tasks; using System.Windows; using System.Windows.Forms; -using System.Windows.Media.Imaging; -using Application = System.Windows.Application; -using Clipboard = System.Windows.Clipboard; -using Size = System.Drawing.Size; -namespace Ink_Canvas -{ - // 截图结果结构体 - public struct ScreenshotResult - { - public System.Drawing.Rectangle Area; - public List Path; - - public ScreenshotResult(System.Drawing.Rectangle area, List path = null) - { - Area = area; - Path = path; - } - } - - public partial class MainWindow : Window - { - private void SaveScreenShot(bool isHideNotification, string fileName = null) - { +namespace Ink_Canvas { + public partial class MainWindow : Window { + private void SaveScreenShot(bool isHideNotification, string fileName = null) { var savePath = Settings.Automation.IsSaveScreenshotsInDateFolders ? GetDateFolderPath(fileName) : GetDefaultFolderPath(); CaptureAndSaveScreenshot(savePath, isHideNotification); - - if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) + + if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) SaveInkCanvasStrokes(false); } - internal void SaveScreenShotToDesktop() - { + internal void SaveScreenShotToDesktop() { var desktopPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png"); CaptureAndSaveScreenshot(desktopPath, false); - - if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) + + if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) SaveInkCanvasStrokes(false); } // 提取公共的截图和保存逻辑 - private void CaptureAndSaveScreenshot(string savePath, bool isHideNotification) - { + private void CaptureAndSaveScreenshot(string savePath, bool isHideNotification) { var rc = SystemInformation.VirtualScreen; - + using (var bitmap = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb)) - using (var memoryGraphics = Graphics.FromImage(bitmap)) - { - // 设置高质量渲染 - memoryGraphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; - memoryGraphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; - memoryGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - memoryGraphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; - + using (var memoryGraphics = Graphics.FromImage(bitmap)) { memoryGraphics.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, CopyPixelOperation.SourceCopy); - + // 确保目录存在 var directory = Path.GetDirectoryName(savePath); - if (!Directory.Exists(directory)) - { + if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } - - // 使用PNG格式保存,确保透明度信息不丢失 + bitmap.Save(savePath, ImageFormat.Png); } - - if (!isHideNotification) - { + + if (!isHideNotification) { ShowNotification($"截图成功保存至 {savePath}"); } } // 获取日期文件夹路径 - private string GetDateFolderPath(string fileName) - { - if (string.IsNullOrWhiteSpace(fileName)) - { + private string GetDateFolderPath(string fileName) { + if (string.IsNullOrWhiteSpace(fileName)) { fileName = DateTime.Now.ToString("HH-mm-ss"); } - + var basePath = Settings.Automation.AutoSavedStrokesLocation; var dateFolder = DateTime.Now.ToString("yyyyMMdd"); - + return Path.Combine( - basePath, - "Auto Saved - Screenshots", - dateFolder, + basePath, + "Auto Saved - Screenshots", + dateFolder, $"{fileName}.png"); } // 获取默认文件夹路径 - private string GetDefaultFolderPath() - { + private string GetDefaultFolderPath() { var basePath = Settings.Automation.AutoSavedStrokesLocation; var screenshotsFolder = Path.Combine(basePath, "Auto Saved - Screenshots"); - - if (!Directory.Exists(screenshotsFolder)) - { + + if (!Directory.Exists(screenshotsFolder)) { Directory.CreateDirectory(screenshotsFolder); } - + return Path.Combine( - screenshotsFolder, + screenshotsFolder, $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png"); } - - // 截图并复制到剪贴板 - private async Task CaptureScreenshotToClipboard() - { - try - { - // 隐藏主窗口以避免截图包含窗口本身 - var originalVisibility = this.Visibility; - this.Visibility = Visibility.Hidden; - - // 等待窗口隐藏 - await Task.Delay(200); - - // 启动区域选择截图 - var screenshotResult = await ShowScreenshotSelector(); - - // 恢复窗口显示 - this.Visibility = originalVisibility; - - if (screenshotResult.HasValue && screenshotResult.Value.Area.Width > 0 && screenshotResult.Value.Area.Height > 0) - { - // 截取选定区域 - using (var originalBitmap = CaptureScreenArea(screenshotResult.Value.Area)) - { - if (originalBitmap != null) - { - Bitmap finalBitmap = originalBitmap; - bool needDisposeFinalBitmap = false; - - try - { - // 如果有路径信息,应用形状遮罩 - if (screenshotResult.Value.Path != null && screenshotResult.Value.Path.Count > 0) - { - finalBitmap = ApplyShapeMask(originalBitmap, screenshotResult.Value.Path, screenshotResult.Value.Area); - needDisposeFinalBitmap = true; // 标记需要释放新创建的位图 - } - - // 将截图复制到剪贴板 - CopyBitmapToClipboard(finalBitmap); - - // 等待窗口完全显示后自动粘贴 - await Task.Delay(100); - await AutoPasteScreenshot(); - } - finally - { - // 如果创建了新的位图,需要释放它 - if (needDisposeFinalBitmap && finalBitmap != originalBitmap) - { - finalBitmap.Dispose(); - } - } - } - } - } - else - { - ShowNotification("截图已取消"); - } - } - catch (Exception ex) - { - ShowNotification($"截图失败: {ex.Message}"); - this.Visibility = Visibility.Visible; - } - } - - // 显示截图区域选择器 - private async Task ShowScreenshotSelector() - { - ScreenshotResult? result = null; - - try - { - await Application.Current.Dispatcher.InvokeAsync(() => - { - var selectorWindow = new ScreenshotSelectorWindow(); - if (selectorWindow.ShowDialog() == true) - { - result = new ScreenshotResult( - selectorWindow.SelectedArea.Value, - selectorWindow.SelectedPath - ); - } - }); - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"显示截图选择器失败: {ex.Message}", LogHelper.LogType.Error); - } - - return result; - } - - // 截取指定屏幕区域 - private Bitmap CaptureScreenArea(System.Drawing.Rectangle area) - { - try - { - // 确保区域在有效范围内 - var virtualScreen = SystemInformation.VirtualScreen; - - // 调整区域边界,确保不超出屏幕范围 - int x = Math.Max(area.X, virtualScreen.X); - int y = Math.Max(area.Y, virtualScreen.Y); - int right = Math.Min(area.Right, virtualScreen.Right); - int bottom = Math.Min(area.Bottom, virtualScreen.Bottom); - - int width = Math.Max(1, right - x); - int height = Math.Max(1, bottom - y); - - // 创建支持透明度的位图 - var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); - using (var graphics = Graphics.FromImage(bitmap)) - { - // 设置高质量渲染 - graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; - graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; - graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; - - // 截取屏幕区域 - graphics.CopyFromScreen(x, y, 0, 0, new Size(width, height), CopyPixelOperation.SourceCopy); - } - - LogHelper.WriteLogToFile($"成功截取区域: X={x}, Y={y}, Width={width}, Height={height}", LogHelper.LogType.Info); - return bitmap; - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"截取屏幕区域失败: {ex.Message}", LogHelper.LogType.Error); - return null; - } - } - - // 自动粘贴截图到画布 - private async Task AutoPasteScreenshot() - { - try - { - // 只在白板模式下自动粘贴 - if (currentMode == 1) - { - await PasteImageFromClipboard(); - ShowNotification("截图已自动插入到画布"); - } - else - { - ShowNotification("截图已复制到剪贴板,可在白板模式下粘贴"); - } - } - catch (Exception ex) - { - ShowNotification($"自动粘贴截图失败: {ex.Message}"); - LogHelper.WriteLogToFile($"自动粘贴截图失败: {ex.Message}", LogHelper.LogType.Error); - } - } - - // 将Bitmap复制到剪贴板 - private void CopyBitmapToClipboard(Bitmap bitmap) - { - try - { - // 将System.Drawing.Bitmap转换为WPF BitmapSource - var bitmapSource = ConvertBitmapToBitmapSource(bitmap); - - // 复制到剪贴板 - Clipboard.SetImage(bitmapSource); - } - catch (Exception ex) - { - ShowNotification($"复制到剪贴板失败: {ex.Message}"); - } - } - - // 应用形状遮罩到截图 - private Bitmap ApplyShapeMask(Bitmap bitmap, List path, System.Drawing.Rectangle area) - { - try - { - // 验证路径参数 - if (path == null || path.Count < 3) - { - LogHelper.WriteLogToFile("路径点数不足,无法应用形状遮罩", LogHelper.LogType.Warning); - return bitmap; - } - - // 获取DPI缩放比例 - var dpiScale = GetDpiScale(); - var virtualScreen = SystemInformation.VirtualScreen; - - // 创建结果位图,确保支持透明度 - var resultBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb); - - // 首先将整个位图设置为透明 - using (var resultGraphics = Graphics.FromImage(resultBitmap)) - { - // 清除位图,设置为完全透明 - resultGraphics.Clear(System.Drawing.Color.Transparent); - - // 设置高质量渲染 - resultGraphics.SmoothingMode = SmoothingMode.AntiAlias; - resultGraphics.CompositingQuality = CompositingQuality.HighQuality; - resultGraphics.CompositingMode = CompositingMode.SourceOver; - - // 创建路径 - using (var pathGraphics = new GraphicsPath()) - { - // 转换WPF坐标到GDI+坐标,考虑DPI缩放和屏幕偏移 - var points = new PointF[path.Count]; - for (int i = 0; i < path.Count; i++) - { - // 将WPF坐标转换为实际屏幕坐标,然后相对于截图区域计算偏移 - double screenX = (path[i].X * dpiScale) + virtualScreen.Left; - double screenY = (path[i].Y * dpiScale) + virtualScreen.Top; - - // 计算相对于截图区域的坐标 - float relativeX = (float)(screenX - area.X); - float relativeY = (float)(screenY - area.Y); - - // 确保坐标在有效范围内 - relativeX = Math.Max(0, Math.Min(relativeX, bitmap.Width - 1)); - relativeY = Math.Max(0, Math.Min(relativeY, bitmap.Height - 1)); - - points[i] = new PointF(relativeX, relativeY); - } - - // 添加路径 - 使用FillMode.Winding确保路径正确填充 - pathGraphics.FillMode = FillMode.Winding; - pathGraphics.AddPolygon(points); - - // 验证路径是否有效 - if (!pathGraphics.IsVisible(0, 0) && pathGraphics.GetBounds().Width > 0 && pathGraphics.GetBounds().Height > 0) - { - // 设置裁剪区域为路径内部 - resultGraphics.SetClip(pathGraphics); - - // 在裁剪区域内绘制原始图像 - resultGraphics.DrawImage(bitmap, 0, 0); - - // 重置裁剪区域,确保后续操作不受影响 - resultGraphics.ResetClip(); - } - else - { - LogHelper.WriteLogToFile("生成的路径无效,返回原始图像", LogHelper.LogType.Warning); - // 如果路径无效,返回透明图像 - return resultBitmap; - } - } - } - - LogHelper.WriteLogToFile($"成功应用形状遮罩,路径点数: {path.Count}", LogHelper.LogType.Info); - return resultBitmap; - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"应用形状遮罩失败: {ex.Message}", LogHelper.LogType.Error); - // 返回完全透明的图像而不是原始图像 - var transparentBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb); - using (var g = Graphics.FromImage(transparentBitmap)) - { - g.Clear(System.Drawing.Color.Transparent); - } - return transparentBitmap; - } - } - - // 获取DPI缩放比例 - private double GetDpiScale() - { - var source = PresentationSource.FromVisual(this); - if (source?.CompositionTarget != null) - { - return source.CompositionTarget.TransformToDevice.M11; - } - return 1.0; // 默认DPI - } - - // 将System.Drawing.Bitmap转换为WPF BitmapSource - private BitmapSource ConvertBitmapToBitmapSource(Bitmap bitmap) - { - try - { - using (var memory = new MemoryStream()) - { - // 使用PNG格式保存,确保透明度信息不丢失 - bitmap.Save(memory, ImageFormat.Png); - memory.Position = 0; - - var bitmapImage = new BitmapImage(); - bitmapImage.BeginInit(); - bitmapImage.StreamSource = memory; - bitmapImage.CacheOption = BitmapCacheOption.OnLoad; - bitmapImage.EndInit(); - bitmapImage.Freeze(); - - return bitmapImage; - } - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"转换位图失败: {ex.Message}", LogHelper.LogType.Error); - throw; - } - } } } From c03bbd9e132f8d3a28043d17b3def070aea5910c Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:41:58 +0800 Subject: [PATCH 05/39] fix:issue #140 --- Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index bc6ce32c..c63faaf9 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -915,7 +915,11 @@ namespace Ink_Canvas HideSubPanels(); BtnSettings_Click(null, null); } - + private async void SymbolIconScreenshot_MouseUp(object sender, MouseButtonEventArgs e) { + HideSubPanelsImmediately(); + await Task.Delay(50); + SaveScreenShotToDesktop(); + } private void ImageCountdownTimer_MouseUp(object sender, MouseButtonEventArgs e) { From 620bcf6fab137f588968c8a746b40712cbdb62ea Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:43:04 +0800 Subject: [PATCH 06/39] fix:issue #140 --- Ink Canvas/MainWindow_cs/MW_Screenshot.cs | 403 ++++++++++++++++++++-- 1 file changed, 375 insertions(+), 28 deletions(-) diff --git a/Ink Canvas/MainWindow_cs/MW_Screenshot.cs b/Ink Canvas/MainWindow_cs/MW_Screenshot.cs index 715118f7..00e537fd 100644 --- a/Ink Canvas/MainWindow_cs/MW_Screenshot.cs +++ b/Ink Canvas/MainWindow_cs/MW_Screenshot.cs @@ -1,84 +1,431 @@ +using Ink_Canvas.Helpers; using System; +using System.Collections.Generic; using System.Drawing; +using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; +using System.Threading.Tasks; using System.Windows; using System.Windows.Forms; +using System.Windows.Media.Imaging; +using Application = System.Windows.Application; +using Clipboard = System.Windows.Clipboard; +using Size = System.Drawing.Size; -namespace Ink_Canvas { - public partial class MainWindow : Window { - private void SaveScreenShot(bool isHideNotification, string fileName = null) { +namespace Ink_Canvas +{ + // 截图结果结构体 + public struct ScreenshotResult + { + public System.Drawing.Rectangle Area; + public List Path; + + public ScreenshotResult(System.Drawing.Rectangle area, List path = null) + { + Area = area; + Path = path; + } + } + + public partial class MainWindow : Window + { + private void SaveScreenShot(bool isHideNotification, string fileName = null) + { var savePath = Settings.Automation.IsSaveScreenshotsInDateFolders ? GetDateFolderPath(fileName) : GetDefaultFolderPath(); CaptureAndSaveScreenshot(savePath, isHideNotification); - - if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) + + if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) SaveInkCanvasStrokes(false); } - internal void SaveScreenShotToDesktop() { + internal void SaveScreenShotToDesktop() + { var desktopPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png"); CaptureAndSaveScreenshot(desktopPath, false); - - if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) + + if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) SaveInkCanvasStrokes(false); } // 提取公共的截图和保存逻辑 - private void CaptureAndSaveScreenshot(string savePath, bool isHideNotification) { + private void CaptureAndSaveScreenshot(string savePath, bool isHideNotification) + { var rc = SystemInformation.VirtualScreen; - + using (var bitmap = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb)) - using (var memoryGraphics = Graphics.FromImage(bitmap)) { + using (var memoryGraphics = Graphics.FromImage(bitmap)) + { + // 设置高质量渲染 + memoryGraphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + memoryGraphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + memoryGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; + memoryGraphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; + memoryGraphics.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, CopyPixelOperation.SourceCopy); - + // 确保目录存在 var directory = Path.GetDirectoryName(savePath); - if (!Directory.Exists(directory)) { + if (!Directory.Exists(directory)) + { Directory.CreateDirectory(directory); } - + + // 使用PNG格式保存,确保透明度信息不丢失 bitmap.Save(savePath, ImageFormat.Png); } - - if (!isHideNotification) { + + if (!isHideNotification) + { ShowNotification($"截图成功保存至 {savePath}"); } } // 获取日期文件夹路径 - private string GetDateFolderPath(string fileName) { - if (string.IsNullOrWhiteSpace(fileName)) { + private string GetDateFolderPath(string fileName) + { + if (string.IsNullOrWhiteSpace(fileName)) + { fileName = DateTime.Now.ToString("HH-mm-ss"); } - + var basePath = Settings.Automation.AutoSavedStrokesLocation; var dateFolder = DateTime.Now.ToString("yyyyMMdd"); - + return Path.Combine( - basePath, - "Auto Saved - Screenshots", - dateFolder, + basePath, + "Auto Saved - Screenshots", + dateFolder, $"{fileName}.png"); } // 获取默认文件夹路径 - private string GetDefaultFolderPath() { + private string GetDefaultFolderPath() + { var basePath = Settings.Automation.AutoSavedStrokesLocation; var screenshotsFolder = Path.Combine(basePath, "Auto Saved - Screenshots"); - - if (!Directory.Exists(screenshotsFolder)) { + + if (!Directory.Exists(screenshotsFolder)) + { Directory.CreateDirectory(screenshotsFolder); } - + return Path.Combine( - screenshotsFolder, + screenshotsFolder, $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png"); } + + // 截图并复制到剪贴板 + private async Task CaptureScreenshotToClipboard() + { + try + { + // 隐藏主窗口以避免截图包含窗口本身 + var originalVisibility = this.Visibility; + this.Visibility = Visibility.Hidden; + + // 等待窗口隐藏 + await Task.Delay(200); + + // 启动区域选择截图 + var screenshotResult = await ShowScreenshotSelector(); + + // 恢复窗口显示 + this.Visibility = originalVisibility; + + if (screenshotResult.HasValue && screenshotResult.Value.Area.Width > 0 && screenshotResult.Value.Area.Height > 0) + { + // 截取选定区域 + using (var originalBitmap = CaptureScreenArea(screenshotResult.Value.Area)) + { + if (originalBitmap != null) + { + Bitmap finalBitmap = originalBitmap; + bool needDisposeFinalBitmap = false; + + try + { + // 如果有路径信息,应用形状遮罩 + if (screenshotResult.Value.Path != null && screenshotResult.Value.Path.Count > 0) + { + finalBitmap = ApplyShapeMask(originalBitmap, screenshotResult.Value.Path, screenshotResult.Value.Area); + needDisposeFinalBitmap = true; // 标记需要释放新创建的位图 + } + + // 将截图复制到剪贴板 + CopyBitmapToClipboard(finalBitmap); + + // 等待窗口完全显示后自动粘贴 + await Task.Delay(100); + await AutoPasteScreenshot(); + } + finally + { + // 如果创建了新的位图,需要释放它 + if (needDisposeFinalBitmap && finalBitmap != originalBitmap) + { + finalBitmap.Dispose(); + } + } + } + } + } + else + { + ShowNotification("截图已取消"); + } + } + catch (Exception ex) + { + ShowNotification($"截图失败: {ex.Message}"); + this.Visibility = Visibility.Visible; + } + } + + // 显示截图区域选择器 + private async Task ShowScreenshotSelector() + { + ScreenshotResult? result = null; + + try + { + await Application.Current.Dispatcher.InvokeAsync(() => + { + var selectorWindow = new ScreenshotSelectorWindow(); + if (selectorWindow.ShowDialog() == true) + { + result = new ScreenshotResult( + selectorWindow.SelectedArea.Value, + selectorWindow.SelectedPath + ); + } + }); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"显示截图选择器失败: {ex.Message}", LogHelper.LogType.Error); + } + + return result; + } + + // 截取指定屏幕区域 + private Bitmap CaptureScreenArea(System.Drawing.Rectangle area) + { + try + { + // 确保区域在有效范围内 + var virtualScreen = SystemInformation.VirtualScreen; + + // 调整区域边界,确保不超出屏幕范围 + int x = Math.Max(area.X, virtualScreen.X); + int y = Math.Max(area.Y, virtualScreen.Y); + int right = Math.Min(area.Right, virtualScreen.Right); + int bottom = Math.Min(area.Bottom, virtualScreen.Bottom); + + int width = Math.Max(1, right - x); + int height = Math.Max(1, bottom - y); + + // 创建支持透明度的位图 + var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); + using (var graphics = Graphics.FromImage(bitmap)) + { + // 设置高质量渲染 + graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; + graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; + + // 截取屏幕区域 + graphics.CopyFromScreen(x, y, 0, 0, new Size(width, height), CopyPixelOperation.SourceCopy); + } + + LogHelper.WriteLogToFile($"成功截取区域: X={x}, Y={y}, Width={width}, Height={height}", LogHelper.LogType.Info); + return bitmap; + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"截取屏幕区域失败: {ex.Message}", LogHelper.LogType.Error); + return null; + } + } + + // 自动粘贴截图到画布 + private async Task AutoPasteScreenshot() + { + try + { + // 只在白板模式下自动粘贴 + if (currentMode == 1) + { + await PasteImageFromClipboard(); + ShowNotification("截图已自动插入到画布"); + } + else + { + ShowNotification("截图已复制到剪贴板,可在白板模式下粘贴"); + } + } + catch (Exception ex) + { + ShowNotification($"自动粘贴截图失败: {ex.Message}"); + LogHelper.WriteLogToFile($"自动粘贴截图失败: {ex.Message}", LogHelper.LogType.Error); + } + } + + // 将Bitmap复制到剪贴板 + private void CopyBitmapToClipboard(Bitmap bitmap) + { + try + { + // 将System.Drawing.Bitmap转换为WPF BitmapSource + var bitmapSource = ConvertBitmapToBitmapSource(bitmap); + + // 复制到剪贴板 + Clipboard.SetImage(bitmapSource); + } + catch (Exception ex) + { + ShowNotification($"复制到剪贴板失败: {ex.Message}"); + } + } + + // 应用形状遮罩到截图 + private Bitmap ApplyShapeMask(Bitmap bitmap, List path, System.Drawing.Rectangle area) + { + try + { + // 验证路径参数 + if (path == null || path.Count < 3) + { + LogHelper.WriteLogToFile("路径点数不足,无法应用形状遮罩", LogHelper.LogType.Warning); + return bitmap; + } + + // 获取DPI缩放比例 + var dpiScale = GetDpiScale(); + var virtualScreen = SystemInformation.VirtualScreen; + + // 创建结果位图,确保支持透明度 + var resultBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb); + + // 首先将整个位图设置为透明 + using (var resultGraphics = Graphics.FromImage(resultBitmap)) + { + // 清除位图,设置为完全透明 + resultGraphics.Clear(System.Drawing.Color.Transparent); + + // 设置高质量渲染 + resultGraphics.SmoothingMode = SmoothingMode.AntiAlias; + resultGraphics.CompositingQuality = CompositingQuality.HighQuality; + resultGraphics.CompositingMode = CompositingMode.SourceOver; + + // 创建路径 + using (var pathGraphics = new GraphicsPath()) + { + // 转换WPF坐标到GDI+坐标,考虑DPI缩放和屏幕偏移 + var points = new PointF[path.Count]; + for (int i = 0; i < path.Count; i++) + { + // 将WPF坐标转换为实际屏幕坐标,然后相对于截图区域计算偏移 + double screenX = (path[i].X * dpiScale) + virtualScreen.Left; + double screenY = (path[i].Y * dpiScale) + virtualScreen.Top; + + // 计算相对于截图区域的坐标 + float relativeX = (float)(screenX - area.X); + float relativeY = (float)(screenY - area.Y); + + // 确保坐标在有效范围内 + relativeX = Math.Max(0, Math.Min(relativeX, bitmap.Width - 1)); + relativeY = Math.Max(0, Math.Min(relativeY, bitmap.Height - 1)); + + points[i] = new PointF(relativeX, relativeY); + } + + // 添加路径 - 使用FillMode.Winding确保路径正确填充 + pathGraphics.FillMode = FillMode.Winding; + pathGraphics.AddPolygon(points); + + // 验证路径是否有效 + if (!pathGraphics.IsVisible(0, 0) && pathGraphics.GetBounds().Width > 0 && pathGraphics.GetBounds().Height > 0) + { + // 设置裁剪区域为路径内部 + resultGraphics.SetClip(pathGraphics); + + // 在裁剪区域内绘制原始图像 + resultGraphics.DrawImage(bitmap, 0, 0); + + // 重置裁剪区域,确保后续操作不受影响 + resultGraphics.ResetClip(); + } + else + { + LogHelper.WriteLogToFile("生成的路径无效,返回原始图像", LogHelper.LogType.Warning); + // 如果路径无效,返回透明图像 + return resultBitmap; + } + } + } + + LogHelper.WriteLogToFile($"成功应用形状遮罩,路径点数: {path.Count}", LogHelper.LogType.Info); + return resultBitmap; + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"应用形状遮罩失败: {ex.Message}", LogHelper.LogType.Error); + // 返回完全透明的图像而不是原始图像 + var transparentBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb); + using (var g = Graphics.FromImage(transparentBitmap)) + { + g.Clear(System.Drawing.Color.Transparent); + } + return transparentBitmap; + } + } + + // 获取DPI缩放比例 + private double GetDpiScale() + { + var source = PresentationSource.FromVisual(this); + if (source?.CompositionTarget != null) + { + return source.CompositionTarget.TransformToDevice.M11; + } + return 1.0; // 默认DPI + } + + // 将System.Drawing.Bitmap转换为WPF BitmapSource + private BitmapSource ConvertBitmapToBitmapSource(Bitmap bitmap) + { + try + { + using (var memory = new MemoryStream()) + { + // 使用PNG格式保存,确保透明度信息不丢失 + bitmap.Save(memory, ImageFormat.Png); + memory.Position = 0; + + var bitmapImage = new BitmapImage(); + bitmapImage.BeginInit(); + bitmapImage.StreamSource = memory; + bitmapImage.CacheOption = BitmapCacheOption.OnLoad; + bitmapImage.EndInit(); + bitmapImage.Freeze(); + + return bitmapImage; + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"转换位图失败: {ex.Message}", LogHelper.LogType.Error); + throw; + } + } } } From e9014c6f5d0ce258741577e11e3753906acdae11 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 28 Aug 2025 01:01:07 +0000 Subject: [PATCH 07/39] docs: update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3e09af86..998d06cd 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,7 @@ PrefacedCorg
PrefacedCorg

💻 🎨 + Jursin
Jursin

🎨 From 54eb3307119cb2c5a8d84aa8f08f87cc362a3837 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 28 Aug 2025 01:01:08 +0000 Subject: [PATCH 08/39] docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 3ac1bb16..dd376fcb 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -89,6 +89,15 @@ "code", "design" ] + }, + { + "login": "Jursin", + "name": "Jursin", + "avatar_url": "https://avatars.githubusercontent.com/u/127487914?v=4", + "profile": "http://blog.jursin.top", + "contributions": [ + "design" + ] } ] } From e5a976abcf130c1a0d854ec00e77b42749549afb Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 17:37:08 +0800 Subject: [PATCH 09/39] fix:issue #141 --- Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index c63faaf9..18b36731 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -737,6 +737,8 @@ namespace Ink_Canvas SwitchToDefaultPen(null, null); CheckColorTheme(true); + // 延迟半秒后再刷新快捷键状态 + Task.Delay(500).ContinueWith(_ => Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => RefreshHotkeyState()))); } #endregion From 27493b857cfd83902cd54401c10e4208515ce382 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 17:41:29 +0800 Subject: [PATCH 10/39] =?UTF-8?q?=E6=92=A4=E9=94=80=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index 18b36731..c63faaf9 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -737,8 +737,6 @@ namespace Ink_Canvas SwitchToDefaultPen(null, null); CheckColorTheme(true); - // 延迟半秒后再刷新快捷键状态 - Task.Delay(500).ContinueWith(_ => Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => RefreshHotkeyState()))); } #endregion From 3ac88bb4006b623774db7f26f8f39b21a9e0bcab Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:02:44 +0800 Subject: [PATCH 11/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 33 +++++------------------ 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index 66d7cba2..e7939ef1 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -17,7 +17,7 @@ namespace Ink_Canvas.Helpers private readonly Dictionary _registeredHotkeys; private readonly MainWindow _mainWindow; private bool _isDisposed = false; - private bool _hotkeysShouldBeRegistered = false; // 启动时不注册热键,等待需要时再注册 + private bool _hotkeysShouldBeRegistered = ture // 启动时注册热键 // 配置文件路径 private static readonly string HotkeyConfigFile = Path.Combine(App.RootPath, "HotkeyConfig.json"); @@ -28,7 +28,7 @@ namespace Ink_Canvas.Helpers { _mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); _registeredHotkeys = new Dictionary(); - _hotkeysShouldBeRegistered = false; // 启动时不注册热键,等待需要时再注册 + _hotkeysShouldBeRegistered = true; // 启动时注册热键 } #endregion @@ -764,33 +764,14 @@ namespace Ink_Canvas.Helpers if (isMouseMode) { - // 在鼠标模式下,注销所有快捷键以释放系统快捷键 + // 在鼠标模式下 if (_hotkeysShouldBeRegistered) { - UnregisterAllHotkeys(); - _hotkeysShouldBeRegistered = false; + e.Handled = false; } else { - // 快捷键已经处于注销状态,无需重复注销 - } - } - else - { - // 在批注/选择/其他工具模式下,重新注册所有快捷键 - if (!_hotkeysShouldBeRegistered) - { - // 第一次切换到批注/选择/其他工具模式,启用快捷键注册 - EnableHotkeyRegistration(); - } - else if (_registeredHotkeys.Count == 0) - { - // 快捷键已启用但数量为0,重新注册 - LoadHotkeysFromSettings(); - } - else - { - // 当前已有快捷键注册,无需重新注册 + // 快捷键已经处于放行状态 } } } @@ -806,7 +787,7 @@ namespace Ink_Canvas.Helpers { if (!_isDisposed) { - UnregisterAllHotkeys(); + _isDisposed = true; } } @@ -851,4 +832,4 @@ namespace Ink_Canvas.Helpers } #endregion } -} \ No newline at end of file +} From 78b66c141ef7d3fc6431d8e4fbe11418aa0016d9 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:05:20 +0800 Subject: [PATCH 12/39] fix:issue #141 --- .../MainWindow_cs/MW_FloatingBarIcons.cs | 47 ------------------- 1 file changed, 47 deletions(-) diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index c63faaf9..08d98002 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -28,35 +28,6 @@ namespace Ink_Canvas { public partial class MainWindow : Window { - #region 快捷键状态管理 - - /// - /// 统一的快捷键状态刷新方法 - /// 在工具切换时调用,避免重复代码 - /// - private void RefreshHotkeyState() - { - try - { - var hotkeyManagerField = this.GetType().GetField("_globalHotkeyManager", - System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - if (hotkeyManagerField != null) - { - var hotkeyManager = hotkeyManagerField.GetValue(this); - if (hotkeyManager != null) - { - var updateMethod = hotkeyManager.GetType().GetMethod("UpdateHotkeyRegistrationState"); - updateMethod?.Invoke(hotkeyManager, null); - } - } - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"刷新快捷键状态时出错: {ex.Message}", LogHelper.LogType.Warning); - } - } - - #endregion #region "手勢"按鈕 @@ -820,8 +791,6 @@ namespace Ink_Canvas BtnSelect_Click(null, null); HideSubPanels("select"); - // 工具切换完成后,统一刷新快捷键状态 - RefreshHotkeyState(); } #endregion @@ -1685,14 +1654,6 @@ namespace Ink_Canvas else ViewboxFloatingBarMarginAnimation(100, true); } - - // 工具切换完成后,统一刷新快捷键状态 - RefreshHotkeyState(); - - if (BtnSwitchTheme.Content.ToString() == "浅色") - BtnSwitch.Content = "黑板"; - else - BtnSwitch.Content = "白板"; } internal void PenIcon_Click(object sender, RoutedEventArgs e) @@ -1965,9 +1926,6 @@ namespace Ink_Canvas AnimationsHelper.HideWithSlideAndFade(BoardEraserSizePanel); } } - - // 工具切换完成后,统一刷新快捷键状态 - RefreshHotkeyState(); } private void BoardEraserIcon_Click(object sender, RoutedEventArgs e) @@ -2002,9 +1960,6 @@ namespace Ink_Canvas AnimationsHelper.HideWithSlideAndFade(EraserSizePanel); } } - - // 工具切换完成后,统一刷新快捷键状态 - RefreshHotkeyState(); } private void EraserIconByStrokes_Click(object sender, RoutedEventArgs e) @@ -2034,8 +1989,6 @@ namespace Ink_Canvas HideSubPanels("eraserByStrokes"); - // 工具切换完成后,统一刷新快捷键状态 - RefreshHotkeyState(); } private void CursorWithDelIcon_Click(object sender, RoutedEventArgs e) From 357983179cf1f402f211bcbba38ca9dac63f2731 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:07:39 +0800 Subject: [PATCH 13/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index e7939ef1..fdd6b2ff 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -17,7 +17,7 @@ namespace Ink_Canvas.Helpers private readonly Dictionary _registeredHotkeys; private readonly MainWindow _mainWindow; private bool _isDisposed = false; - private bool _hotkeysShouldBeRegistered = ture // 启动时注册热键 + private bool _hotkeysShouldBeRegistered = true; // 启动时注册热键 // 配置文件路径 private static readonly string HotkeyConfigFile = Path.Combine(App.RootPath, "HotkeyConfig.json"); From ec0fb0c3cf5050cb2cae43afa685144a67483d87 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:10:52 +0800 Subject: [PATCH 14/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index fdd6b2ff..4747534d 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -767,7 +767,7 @@ namespace Ink_Canvas.Helpers // 在鼠标模式下 if (_hotkeysShouldBeRegistered) { - e.Handled = false; + Handled = false; } else { From 3427cbdc2eaabf5b278e85cd3bf6bd34d1d43339 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:11:26 +0800 Subject: [PATCH 15/39] fix:issue #141 --- Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index 08d98002..d86e5d7a 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -1866,9 +1866,6 @@ namespace Ink_Canvas } } - - // 延迟半秒后再刷新快捷键状态 - Task.Delay(500).ContinueWith(_ => Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => RefreshHotkeyState()))); // 修复:从线擦切换到批注时,保持之前的笔类型状态 forceEraser = false; From cb4ed77572ad08581684d3db9e87ca64698f352b Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:17:29 +0800 Subject: [PATCH 16/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 32 +++++++---------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index 4747534d..97d06130 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -753,31 +753,19 @@ namespace Ink_Canvas.Helpers } /// - /// 动态管理快捷键注册状态 - /// 根据当前工具选择状态自动注册或注销快捷键 + /// 鼠标事件处理方法 /// - public void UpdateHotkeyRegistrationState() + private void OnMouseModeEvent(object sender, MouseEventArgs e) { - try + bool isMouseMode = IsInSelectMode(); + + if (isMouseMode) { - bool isMouseMode = IsInSelectMode(); - - if (isMouseMode) - { - // 在鼠标模式下 - if (_hotkeysShouldBeRegistered) - { - Handled = false; - } - else - { - // 快捷键已经处于放行状态 - } - } - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"更新快捷键注册状态时出错: {ex.Message}", LogHelper.LogType.Error); + // 在鼠标模式下设置事件处理状态 + e.Handled = false; + + // 调用快捷键状态更新方法 + UpdateHotkeyRegistrationState(); } } #endregion From dac05fec84829f7dbc5c08d578681d955e304484 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:20:44 +0800 Subject: [PATCH 17/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index 97d06130..b7368d66 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -768,6 +768,34 @@ namespace Ink_Canvas.Helpers UpdateHotkeyRegistrationState(); } } + + /// + /// 动态管理快捷键 + /// + public void UpdateHotkeyRegistrationState() + { + try + { + bool isMouseMode = IsInSelectMode(); + + if (isMouseMode) + { + // 在鼠标模式下 + if (_hotkeysShouldBeRegistered) + { + e.Handled = false; + } + else + { + // 快捷键已经处于放行状态 + } + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"更新快捷键注册状态时出错: {ex.Message}", LogHelper.LogType.Error); + } + } #endregion #region IDisposable Implementation From 52f8e249545231cb9a20138def7878e5adefa7e8 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:24:12 +0800 Subject: [PATCH 18/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index b7368d66..31c671fa 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -783,7 +783,7 @@ namespace Ink_Canvas.Helpers // 在鼠标模式下 if (_hotkeysShouldBeRegistered) { - e.Handled = false; + EnableHotkeyRegistration(); } else { From 9d43056361aa47987b593f6fe09b9bd0a8585f2d Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:25:04 +0800 Subject: [PATCH 19/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 32 +---------------------- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index 31c671fa..c1fd8855 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -763,39 +763,9 @@ namespace Ink_Canvas.Helpers { // 在鼠标模式下设置事件处理状态 e.Handled = false; - - // 调用快捷键状态更新方法 - UpdateHotkeyRegistrationState(); - } - } - - /// - /// 动态管理快捷键 - /// - public void UpdateHotkeyRegistrationState() - { - try - { - bool isMouseMode = IsInSelectMode(); - - if (isMouseMode) - { - // 在鼠标模式下 - if (_hotkeysShouldBeRegistered) - { - EnableHotkeyRegistration(); - } - else - { - // 快捷键已经处于放行状态 - } - } - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"更新快捷键注册状态时出错: {ex.Message}", LogHelper.LogType.Error); } } + #endregion #region IDisposable Implementation From c6acafd3a61e62895a3fbc7e06c7ab419cc8ea68 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:28:17 +0800 Subject: [PATCH 20/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index c1fd8855..6057d828 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -17,7 +17,6 @@ namespace Ink_Canvas.Helpers private readonly Dictionary _registeredHotkeys; private readonly MainWindow _mainWindow; private bool _isDisposed = false; - private bool _hotkeysShouldBeRegistered = true; // 启动时注册热键 // 配置文件路径 private static readonly string HotkeyConfigFile = Path.Combine(App.RootPath, "HotkeyConfig.json"); @@ -28,7 +27,6 @@ namespace Ink_Canvas.Helpers { _mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); _registeredHotkeys = new Dictionary(); - _hotkeysShouldBeRegistered = true; // 启动时注册热键 } #endregion From 83824131377e35ad71a948f1476b1ec096168532 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:31:59 +0800 Subject: [PATCH 21/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index 6057d828..f3e53f9c 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -17,6 +17,7 @@ namespace Ink_Canvas.Helpers private readonly Dictionary _registeredHotkeys; private readonly MainWindow _mainWindow; private bool _isDisposed = false; + private bool _hotkeysShouldBeRegistered = true; // 启动时注册热键 // 配置文件路径 private static readonly string HotkeyConfigFile = Path.Combine(App.RootPath, "HotkeyConfig.json"); From c807f97c29272ae4a422a021a510a490ecfd927d Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:32:47 +0800 Subject: [PATCH 22/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index f3e53f9c..7392e161 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -28,6 +28,7 @@ namespace Ink_Canvas.Helpers { _mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); _registeredHotkeys = new Dictionary(); + InitializeHotkeysOnStartup(); } #endregion From f5a08b225c300eb492d538f4ba5ec9b9a2a180db Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:35:17 +0800 Subject: [PATCH 23/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index 7392e161..f3e53f9c 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -28,7 +28,6 @@ namespace Ink_Canvas.Helpers { _mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); _registeredHotkeys = new Dictionary(); - InitializeHotkeysOnStartup(); } #endregion From a67b7a2fd0471adceb12076cdb1122a50822fec3 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 20:13:43 +0800 Subject: [PATCH 24/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index f3e53f9c..b97cf885 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -28,6 +28,7 @@ namespace Ink_Canvas.Helpers { _mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); _registeredHotkeys = new Dictionary(); + _hotkeysShouldBeRegistered = true; // 启动时注册热键 } #endregion @@ -763,6 +764,10 @@ namespace Ink_Canvas.Helpers // 在鼠标模式下设置事件处理状态 e.Handled = false; } + else + { + e.Handled = true; + } } #endregion From 206ae3d9edb732549cb03dc8f6b38adbf5a43bca Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 21:02:47 +0800 Subject: [PATCH 25/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index b97cf885..7f1de40d 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -767,6 +767,8 @@ namespace Ink_Canvas.Helpers else { e.Handled = true; + EnableHotkeyRegistration(); + LoadHotkeysFromSettings(); } } From d2b3b38d9e47e35565bdfe1b0ac60e925ec67c24 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Thu, 28 Aug 2025 22:13:18 +0800 Subject: [PATCH 26/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index 7f1de40d..36e71425 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -770,6 +770,25 @@ namespace Ink_Canvas.Helpers EnableHotkeyRegistration(); LoadHotkeysFromSettings(); } + // 更新快捷键注册状态 + try + { + var hotkeyManagerField = this.GetType().GetField("_globalHotkeyManager", + System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + if (hotkeyManagerField != null) + { + var hotkeyManager = hotkeyManagerField.GetValue(this); + if (hotkeyManager != null) + { + var updateMethod = hotkeyManager.GetType().GetMethod("UpdateHotkeyRegistrationState"); + updateMethod?.Invoke(hotkeyManager, null); + } + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"更新快捷键状态时出错: {ex.Message}", LogHelper.LogType.Warning); + } } #endregion From 588d1822b182e79e9b444338d46835ad2b4b57d7 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 30 Aug 2025 11:20:53 +0800 Subject: [PATCH 27/39] fix:issue #141 --- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 103 +++++++++++------- Ink Canvas/MainWindow.xaml.cs | 41 ++++++- Ink Canvas/MainWindow_cs/MW_BoardIcons.cs | 6 +- Ink Canvas/MainWindow_cs/MW_Colors.cs | 3 +- .../MainWindow_cs/MW_FloatingBarIcons.cs | 25 +++-- .../MainWindow_cs/MW_SelectionGestures.cs | 18 ++- 6 files changed, 136 insertions(+), 60 deletions(-) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index 36e71425..467adec2 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -288,7 +288,7 @@ namespace Ink_Canvas.Helpers } else { - // 如果配置文件不存在,才使用默认快捷键 + // 如果配置文件不存在或加载失败,使用默认快捷键 if (!File.Exists(HotkeyConfigFile)) { LogHelper.WriteLogToFile("配置文件不存在,注册默认快捷键", LogHelper.LogType.Info); @@ -297,7 +297,9 @@ namespace Ink_Canvas.Helpers } else { - LogHelper.WriteLogToFile("配置文件存在但加载失败,保持当前状态", LogHelper.LogType.Warning); + LogHelper.WriteLogToFile("配置文件存在但加载失败,回退到默认快捷键", LogHelper.LogType.Warning); + RegisterDefaultHotkeys(); + _hotkeysShouldBeRegistered = true; } } } @@ -350,7 +352,9 @@ namespace Ink_Canvas.Helpers } else { - LogHelper.WriteLogToFile("快捷键注册功能已经启用", LogHelper.LogType.Info); + LogHelper.WriteLogToFile("快捷键注册功能已经启用,重新加载快捷键设置", LogHelper.LogType.Info); + // 即使已经启用,也要重新加载快捷键设置以确保快捷键正常工作 + LoadHotkeysFromSettings(); } } catch (Exception ex) @@ -359,6 +363,61 @@ namespace Ink_Canvas.Helpers } } + /// + /// 禁用快捷键注册功能 + /// 调用此方法后,快捷键将被注销 + /// + public void DisableHotkeyRegistration() + { + try + { + if (_hotkeysShouldBeRegistered) + { + _hotkeysShouldBeRegistered = false; + LogHelper.WriteLogToFile("禁用快捷键注册功能", LogHelper.LogType.Info); + + // 注销所有快捷键 + UnregisterAllHotkeys(); + } + else + { + LogHelper.WriteLogToFile("快捷键注册功能已经禁用", LogHelper.LogType.Info); + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"禁用快捷键注册功能时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + + /// + /// 根据当前工具模式更新快捷键状态 + /// 在工具切换时调用此方法 + /// + /// 是否为鼠标模式(选择模式) + public void UpdateHotkeyStateForToolMode(bool isMouseMode) + { + try + { + if (isMouseMode) + { + // 鼠标模式下禁用快捷键,让键盘操作放行 + DisableHotkeyRegistration(); + LogHelper.WriteLogToFile("切换到鼠标模式,禁用快捷键以放行键盘操作", LogHelper.LogType.Info); + } + else + { + // 非鼠标模式下启用快捷键 + EnableHotkeyRegistration(); + LogHelper.WriteLogToFile("切换到非鼠标模式,启用快捷键", LogHelper.LogType.Info); + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"更新快捷键状态时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + /// /// 更新快捷键配置 /// @@ -752,44 +811,6 @@ namespace Ink_Canvas.Helpers } } - /// - /// 鼠标事件处理方法 - /// - private void OnMouseModeEvent(object sender, MouseEventArgs e) - { - bool isMouseMode = IsInSelectMode(); - - if (isMouseMode) - { - // 在鼠标模式下设置事件处理状态 - e.Handled = false; - } - else - { - e.Handled = true; - EnableHotkeyRegistration(); - LoadHotkeysFromSettings(); - } - // 更新快捷键注册状态 - try - { - var hotkeyManagerField = this.GetType().GetField("_globalHotkeyManager", - System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - if (hotkeyManagerField != null) - { - var hotkeyManager = hotkeyManagerField.GetValue(this); - if (hotkeyManager != null) - { - var updateMethod = hotkeyManager.GetType().GetMethod("UpdateHotkeyRegistrationState"); - updateMethod?.Invoke(hotkeyManager, null); - } - } - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"更新快捷键状态时出错: {ex.Message}", LogHelper.LogType.Warning); - } - } #endregion diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index c4667900..27d2234e 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -274,7 +274,8 @@ namespace Ink_Canvas drawingAttributes.FitToCurve = Settings.Canvas.FitToCurve; } - inkCanvas.EditingMode = InkCanvasEditingMode.Ink; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.Ink); inkCanvas.Gesture += InkCanvas_Gesture; } catch { } @@ -2025,8 +2026,9 @@ namespace Ink_Canvas try { _globalHotkeyManager = new GlobalHotkeyManager(this); - // 不在这里加载快捷键,等待需要时再加载 - LogHelper.WriteLogToFile("全局快捷键管理器已初始化(未加载快捷键)", LogHelper.LogType.Event); + // 启动时加载快捷键,默认启用 + _globalHotkeyManager.EnableHotkeyRegistration(); + LogHelper.WriteLogToFile("全局快捷键管理器已初始化并加载快捷键", LogHelper.LogType.Event); } catch (Exception ex) { @@ -2179,5 +2181,38 @@ namespace Ink_Canvas } } #endregion + + /// + /// 集中管理工具模式切换和快捷键状态更新 + /// 避免在每个工具按钮点击时重复刷新快捷键状态 + /// + /// 新的编辑模式 + /// 可选的额外操作委托 + internal void SetCurrentToolMode(InkCanvasEditingMode newMode, Action additionalActions = null) + { + try + { + // 执行模式切换 + inkCanvas.EditingMode = newMode; + + // 根据模式确定是否为鼠标模式(无工具模式) + bool isMouseMode = newMode == InkCanvasEditingMode.None; + + // 更新快捷键状态 + if (_globalHotkeyManager != null) + { + _globalHotkeyManager.UpdateHotkeyStateForToolMode(isMouseMode); + } + + // 执行额外的操作(如果有) + additionalActions?.Invoke(); + + LogHelper.WriteLogToFile($"工具模式已切换到: {newMode}, 鼠标模式: {isMouseMode}", LogHelper.LogType.Trace); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"设置工具模式时出错: {ex.Message}", LogHelper.LogType.Error); + } + } } } diff --git a/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs b/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs index 03ee7c86..f94917af 100644 --- a/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs @@ -704,7 +704,8 @@ namespace Ink_Canvas forceEraser = false; forcePointEraser = false; drawingShapeMode = 0; - inkCanvas.EditingMode = InkCanvasEditingMode.Select; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.Select); SetCursorBasedOnEditingMode(inkCanvas); } @@ -721,7 +722,8 @@ namespace Ink_Canvas forcePointEraser = false; inkCanvas.EraserShape = new EllipseStylusShape(5, 5); - inkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.EraseByStroke); drawingShapeMode = 0; // 修复:切换到线擦时,确保重置笔的状态 diff --git a/Ink Canvas/MainWindow_cs/MW_Colors.cs b/Ink Canvas/MainWindow_cs/MW_Colors.cs index baa50911..57ce6f80 100644 --- a/Ink Canvas/MainWindow_cs/MW_Colors.cs +++ b/Ink Canvas/MainWindow_cs/MW_Colors.cs @@ -64,7 +64,8 @@ namespace Ink_Canvas { inkCanvas.IsManipulationEnabled = true; drawingShapeMode = 0; - inkCanvas.EditingMode = InkCanvasEditingMode.Ink; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.Ink); CancelSingleFingerDragMode(); CheckColorTheme(); } diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index d86e5d7a..f70732f8 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -1562,6 +1562,10 @@ namespace Ink_Canvas // 隱藏高亮 HideFloatingBarHighlight(); + // 使用集中化的工具模式切换方法,确保快捷键状态正确更新 + // 鼠标模式下应该禁用快捷键以放行键盘操作 + SetCurrentToolMode(InkCanvasEditingMode.None); + // 切换前自动截图保存墨迹 if (inkCanvas.Strokes.Count > 0 && inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) @@ -1684,7 +1688,8 @@ namespace Ink_Canvas if (Pen_Icon.Background == null || StackPanelCanvasControls.Visibility == Visibility.Collapsed) { - inkCanvas.EditingMode = InkCanvasEditingMode.Ink; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.Ink); GridTransparencyFakeBackground.Opacity = 1; GridTransparencyFakeBackground.Background = new SolidColorBrush(StringToColor("#01FFFFFF")); @@ -1717,7 +1722,8 @@ namespace Ink_Canvas StackPanelCanvasControls.Visibility = Visibility.Visible; //AnimationsHelper.ShowWithSlideFromLeftAndFade(StackPanelCanvasControls); CheckEnableTwoFingerGestureBtnVisibility(true); - inkCanvas.EditingMode = InkCanvasEditingMode.Ink; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.Ink); // 在批注模式下显示快捷调色盘(如果设置中启用了) if (Settings.Appearance.IsShowQuickColorPalette && QuickColorPalettePanel != null && QuickColorPaletteSingleRowPanel != null) @@ -1838,7 +1844,8 @@ namespace Ink_Canvas { SaveStrokes(); } - inkCanvas.EditingMode = InkCanvasEditingMode.Ink; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.Ink); // 修复:从线擦切换到批注时,保持之前的笔类型状态 forceEraser = false; @@ -1898,7 +1905,8 @@ namespace Ink_Canvas EnableAdvancedEraserSystem(); // 使用新的高级橡皮擦系统 - inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.EraseByPoint); ApplyAdvancedEraserShape(); // 使用新的橡皮擦形状应用方法 SetCursorBasedOnEditingMode(inkCanvas); HideSubPanels("eraser"); // 高亮橡皮按钮 @@ -1937,7 +1945,8 @@ namespace Ink_Canvas EnableAdvancedEraserSystem(); // 使用新的高级橡皮擦系统 - inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.EraseByPoint); ApplyAdvancedEraserShape(); // 使用新的橡皮擦形状应用方法 SetCursorBasedOnEditingMode(inkCanvas); HideSubPanels("eraser"); // 高亮橡皮按钮 @@ -1974,7 +1983,8 @@ namespace Ink_Canvas forcePointEraser = false; inkCanvas.EraserShape = new EllipseStylusShape(5, 5); - inkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.EraseByStroke); drawingShapeMode = 0; // 修复:切换到线擦时,保存当前的笔类型状态,而不是强制重置 @@ -2255,7 +2265,8 @@ namespace Ink_Canvas } else { - inkCanvas.EditingMode = InkCanvasEditingMode.Select; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.Select); } } diff --git a/Ink Canvas/MainWindow_cs/MW_SelectionGestures.cs b/Ink Canvas/MainWindow_cs/MW_SelectionGestures.cs index c302795f..a87dec7b 100644 --- a/Ink Canvas/MainWindow_cs/MW_SelectionGestures.cs +++ b/Ink Canvas/MainWindow_cs/MW_SelectionGestures.cs @@ -276,8 +276,10 @@ namespace Ink_Canvas { if (inkCanvas.GetSelectedStrokes().Count == inkCanvas.Strokes.Count) { - inkCanvas.EditingMode = InkCanvasEditingMode.Ink; - inkCanvas.EditingMode = InkCanvasEditingMode.Select; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.Ink, () => { + SetCurrentToolMode(InkCanvasEditingMode.Select); + }); } else { @@ -290,7 +292,8 @@ namespace Ink_Canvas } else { - inkCanvas.EditingMode = InkCanvasEditingMode.Select; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.Select); } } @@ -454,7 +457,8 @@ namespace Ink_Canvas else { // 新增:启动套索选择模式 - inkCanvas.EditingMode = InkCanvasEditingMode.Select; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.Select); inkCanvas.Select(new StrokeCollection()); } } @@ -492,7 +496,8 @@ namespace Ink_Canvas forceEraser = false; forcePointEraser = false; drawingShapeMode = 0; - inkCanvas.EditingMode = InkCanvasEditingMode.Select; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.Select); SetCursorBasedOnEditingMode(inkCanvas); } @@ -502,7 +507,8 @@ namespace Ink_Canvas forceEraser = false; forcePointEraser = false; drawingShapeMode = 0; - inkCanvas.EditingMode = InkCanvasEditingMode.Select; + // 使用集中化的工具模式切换方法 + SetCurrentToolMode(InkCanvasEditingMode.Select); inkCanvas.IsManipulationEnabled = true; SetCursorBasedOnEditingMode(inkCanvas); } From 8867fde3f2bf11d6785ee6906a73ce1c267e065a Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 30 Aug 2025 11:29:16 +0800 Subject: [PATCH 28/39] fix:issue #141 --- Ink Canvas/MainWindow.xaml.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index 27d2234e..869ab27e 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -274,8 +274,6 @@ namespace Ink_Canvas drawingAttributes.FitToCurve = Settings.Canvas.FitToCurve; } - // 使用集中化的工具模式切换方法 - SetCurrentToolMode(InkCanvasEditingMode.Ink); inkCanvas.Gesture += InkCanvas_Gesture; } catch { } @@ -2026,9 +2024,11 @@ namespace Ink_Canvas try { _globalHotkeyManager = new GlobalHotkeyManager(this); - // 启动时加载快捷键,默认启用 + // 启动时加载快捷键,但默认为鼠标模式,禁用快捷键以放行键盘操作 _globalHotkeyManager.EnableHotkeyRegistration(); - LogHelper.WriteLogToFile("全局快捷键管理器已初始化并加载快捷键", LogHelper.LogType.Event); + // 启动时默认为鼠标模式,禁用快捷键 + _globalHotkeyManager.UpdateHotkeyStateForToolMode(true); + LogHelper.WriteLogToFile("全局快捷键管理器已初始化,启动时默认为鼠标模式并禁用快捷键", LogHelper.LogType.Event); } catch (Exception ex) { From 19fe7223fb555c8f949eadad0fc872ea761dbb0b Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 30 Aug 2025 11:34:29 +0800 Subject: [PATCH 29/39] =?UTF-8?q?improve:=E5=BF=AB=E6=8D=B7=E9=94=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow.xaml | 70 -------------------------- Ink Canvas/MainWindow_cs/MW_Hotkeys.cs | 11 +--- 2 files changed, 2 insertions(+), 79 deletions(-) diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml index e3d92bfa..4013c6ab 100644 --- a/Ink Canvas/MainWindow.xaml +++ b/Ink Canvas/MainWindow.xaml @@ -16,7 +16,6 @@ ShowInTaskbar="False" Title="InkCanvasforClass" Topmost="True" - KeyDown="Window_KeyDown" Closing="Window_Closing" Closed="Window_Closed" PreviewKeyDown="Main_Grid_PreviewKeyDown" @@ -43,25 +42,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs b/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs index edcbbbb1..a0cbc550 100644 --- a/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs +++ b/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs @@ -44,15 +44,8 @@ namespace Ink_Canvas } } - private void Window_KeyDown(object sender, KeyEventArgs e) - { - if (e.Key == Key.Escape) KeyExit(null, null); - } - - private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e) - { - e.CanExecute = true; - } + // 保留PPT翻页快捷键处理 + // 以下方法保留供全局快捷键调用 private void HotKey_Undo(object sender, ExecutedRoutedEventArgs e) { From 4a86d1aa059a6bde21f174ad52ac557b1c77b7e1 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 30 Aug 2025 14:11:39 +0800 Subject: [PATCH 30/39] =?UTF-8?q?improve:=E8=87=AA=E5=8A=A8=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/App.xaml | 2 +- Ink Canvas/App.xaml.cs | 194 ++++++++- Ink Canvas/AssemblyInfo.cs | 4 +- Ink Canvas/Helpers/AutoUpdateHelper.cs | 579 +++++++++++++++++++++---- Ink Canvas/Properties/AssemblyInfo.cs | 8 +- 5 files changed, 674 insertions(+), 113 deletions(-) diff --git a/Ink Canvas/App.xaml b/Ink Canvas/App.xaml index 6575dacc..92169636 100644 --- a/Ink Canvas/App.xaml +++ b/Ink Canvas/App.xaml @@ -4,7 +4,7 @@ xmlns:local="clr-namespace:Ink_Canvas" xmlns:tb="http://www.hardcodet.net/taskbar" xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern" - StartupUri="MainWindow.xaml"> +>