diff --git a/Ink Canvas/InkCanvasForClass_mlbp2gn0_wpftmp.csproj b/Ink Canvas/InkCanvasForClass_mlbp2gn0_wpftmp.csproj index 97db535e..ddd440ee 100644 --- a/Ink Canvas/InkCanvasForClass_mlbp2gn0_wpftmp.csproj +++ b/Ink Canvas/InkCanvasForClass_mlbp2gn0_wpftmp.csproj @@ -134,6 +134,7 @@ + @@ -405,6 +406,7 @@ + diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml index af843d29..23e01666 100644 --- a/Ink Canvas/MainWindow.xaml +++ b/Ink Canvas/MainWindow.xaml @@ -2323,7 +2323,7 @@ FontFamily="Microsoft YaHei UI" FontWeight="Bold" Toggled="ToggleSwitchSaveFullPageStrokes_Toggled" /> - + diff --git a/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs b/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs index 17d5356e..41d013a0 100644 --- a/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs +++ b/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs @@ -10,6 +10,8 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Forms; using OpenFileDialog = Microsoft.Win32.OpenFileDialog; +using System.Collections.Generic; +using System.Windows.Controls; namespace Ink_Canvas { public partial class MainWindow : Window { @@ -38,76 +40,75 @@ namespace Ink_Canvas { //savePathWithName = savePath + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".icstk"; savePathWithName = savePath + @"\" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss-fff") + ".icstk"; - var fs = new FileStream(savePathWithName, FileMode.Create); - if (Settings.Automation.IsSaveFullPageStrokes) { - // 全页面保存模式 - 保存整个墨迹页面的图像 - var bitmap = new System.Drawing.Bitmap( - (int)System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, - (int)System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height); + // 全页面保存模式 - 检查是否存在多页面墨迹 + bool hasMultiplePages = false; + List allPageStrokes = new List(); - using (var g = System.Drawing.Graphics.FromImage(bitmap)) + // 检查PPT放映模式下的多页面墨迹 + if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible && pptApplication != null) { - // 创建黑色或透明背景 - System.Drawing.Color bgColor = Settings.Canvas.UsingWhiteboard - ? System.Drawing.Color.White - : System.Drawing.Color.FromArgb(22, 41, 36); // 黑板背景色 - g.Clear(bgColor); - - // 将InkCanvas墨迹渲染到Visual - var visual = new DrawingVisual(); - using (var dc = visual.RenderOpen()) + hasMultiplePages = true; + // 收集PPT放映模式下的所有页面墨迹 + for (int i = 1; i <= pptApplication.SlideShowWindows[1].Presentation.Slides.Count; i++) { - // 创建一个VisualBrush,使用inkCanvas作为源 - var visualBrush = new VisualBrush(inkCanvas); - // 绘制矩形并填充为inkCanvas的内容 - dc.DrawRectangle(visualBrush, null, new Rect(0, 0, inkCanvas.ActualWidth, inkCanvas.ActualHeight)); + if (memoryStreams[i] != null && memoryStreams[i].Length > 8) + { + memoryStreams[i].Position = 0; + allPageStrokes.Add(new StrokeCollection(memoryStreams[i])); + } + else if (i == previousSlideID && inkCanvas.Strokes.Count > 0) + { + // 当前页面的墨迹 + allPageStrokes.Add(inkCanvas.Strokes.Clone()); + } + else + { + allPageStrokes.Add(new StrokeCollection()); // 空页面 + } } - - // 创建适合墨迹画布尺寸的渲染位图 - var rtb = new RenderTargetBitmap( - (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight, - 96, 96, - PixelFormats.Pbgra32); - rtb.Render(visual); - - // 转换为GDI+ Bitmap并保存 - var encoder = new PngBitmapEncoder(); - encoder.Frames.Add(BitmapFrame.Create(rtb)); - - using (var ms = new MemoryStream()) + } + // 检查白板模式下的多页面墨迹 + else if (currentMode != 0 && WhiteboardTotalCount > 1) + { + hasMultiplePages = true; + // 收集白板模式下的所有页面墨迹 + for (int i = 1; i <= WhiteboardTotalCount; i++) { - encoder.Save(ms); - ms.Seek(0, SeekOrigin.Begin); - var imgBitmap = new System.Drawing.Bitmap(ms); - - // 将生成的墨迹图像绘制到屏幕截图上 - // 居中绘制,确保墨迹位于屏幕中央 - int x = (bitmap.Width - imgBitmap.Width) / 2; - int y = (bitmap.Height - imgBitmap.Height) / 2; - g.DrawImage(imgBitmap, x, y); - - // 保存为PNG - string imagePathWithName = Path.ChangeExtension(savePathWithName, "png"); - bitmap.Save(imagePathWithName, System.Drawing.Imaging.ImageFormat.Png); - - // 仍然保存墨迹文件以兼容旧版本 - inkCanvas.Strokes.Save(fs); + if (TimeMachineHistories[i] != null) + { + // 从历史记录中恢复墨迹 + var strokes = ApplyHistoriesToNewStrokeCollection(TimeMachineHistories[i]); + allPageStrokes.Add(strokes); + } + else + { + allPageStrokes.Add(new StrokeCollection()); // 空页面 + } } } - // 显示提示 - if (newNotice) ShowNotification("墨迹成功全页面保存至 " + Path.ChangeExtension(savePathWithName, "png")); + if (hasMultiplePages && allPageStrokes.Count > 0) + { + // 多页面墨迹保存为压缩包 + string zipFileName = Path.ChangeExtension(savePathWithName, "zip"); + SaveMultiPageStrokesAsZip(allPageStrokes, zipFileName, newNotice); + } + else + { + // 单页面墨迹保存为图像 + SaveSinglePageStrokesAsImage(savePathWithName, newNotice); + } } else { // 常规保存模式 - 仅保存墨迹对象 + var fs = new FileStream(savePathWithName, FileMode.Create); inkCanvas.Strokes.Save(fs); + fs.Close(); if (newNotice) ShowNotification("墨迹成功保存至 " + savePathWithName); } - - fs.Close(); } catch (Exception ex) { ShowNotification("墨迹保存失败"); @@ -115,6 +116,193 @@ namespace Ink_Canvas { } } + /// + /// 将多页面墨迹保存为压缩包 + /// + private void SaveMultiPageStrokesAsZip(List allPageStrokes, string zipFileName, bool newNotice) + { + try + { + // 创建临时目录来存放文件 + string tempDir = Path.Combine(Path.GetTempPath(), $"InkCanvas_MultiPage_{DateTime.Now:yyyyMMdd_HHmmss}"); + Directory.CreateDirectory(tempDir); + + try + { + // 保存所有页面的文件到临时目录 + for (int i = 0; i < allPageStrokes.Count; i++) + { + var strokes = allPageStrokes[i]; + if (strokes.Count > 0) + { + // 保存墨迹文件 + string strokeFileName = Path.Combine(tempDir, $"page_{i + 1:D4}.icstk"); + using (var fs = new FileStream(strokeFileName, FileMode.Create)) + { + strokes.Save(fs); + } + + // 保存页面图像 + string imageFileName = Path.Combine(tempDir, $"page_{i + 1:D4}.png"); + using (var fs = new FileStream(imageFileName, FileMode.Create)) + { + SavePageAsImage(strokes, fs); + } + } + } + + // 保存元数据信息 + string metadataFile = Path.Combine(tempDir, "metadata.txt"); + using (var writer = new StreamWriter(metadataFile, false, System.Text.Encoding.UTF8)) + { + writer.WriteLine($"保存时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); + writer.WriteLine($"总页数: {allPageStrokes.Count}"); + writer.WriteLine($"模式: {(currentMode == 0 ? "PPT放映" : "白板")}"); + if (currentMode != 0) + { + writer.WriteLine($"当前页面: {CurrentWhiteboardIndex}"); + writer.WriteLine($"总页面数: {WhiteboardTotalCount}"); + } + else if (pptApplication != null) + { + writer.WriteLine($"PPT名称: {pptApplication.SlideShowWindows[1].Presentation.Name}"); + writer.WriteLine($"PPT总页数: {pptApplication.SlideShowWindows[1].Presentation.Slides.Count}"); + } + + for (int i = 0; i < allPageStrokes.Count; i++) + { + writer.WriteLine($"页面 {i + 1}: {allPageStrokes[i].Count} 条墨迹"); + } + } + + // 使用.NET Framework内置的压缩功能创建ZIP文件 + if (File.Exists(zipFileName)) + File.Delete(zipFileName); + + // 使用System.IO.Compression.FileSystem来创建ZIP + System.IO.Compression.ZipFile.CreateFromDirectory(tempDir, zipFileName); + + if (newNotice) ShowNotification($"多页面墨迹成功保存至压缩包 {zipFileName}"); + } + finally + { + // 清理临时目录 + try + { + if (Directory.Exists(tempDir)) + Directory.Delete(tempDir, true); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"清理临时目录失败: {ex.ToString()}", LogHelper.LogType.Warning); + } + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"保存多页面墨迹压缩包失败: {ex.ToString()}", LogHelper.LogType.Error); + throw; + } + } + + /// + /// 将单页面墨迹保存为图像 + /// + private void SaveSinglePageStrokesAsImage(string savePathWithName, bool newNotice) + { + // 全页面保存模式 - 保存整个墨迹页面的图像 + var bitmap = new System.Drawing.Bitmap( + (int)System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, + (int)System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height); + + using (var g = System.Drawing.Graphics.FromImage(bitmap)) + { + // 创建黑色或透明背景 + System.Drawing.Color bgColor = Settings.Canvas.UsingWhiteboard + ? System.Drawing.Color.White + : System.Drawing.Color.FromArgb(22, 41, 36); // 黑板背景色 + g.Clear(bgColor); + + // 将InkCanvas墨迹渲染到Visual + var visual = new DrawingVisual(); + using (var dc = visual.RenderOpen()) + { + // 创建一个VisualBrush,使用inkCanvas作为源 + var visualBrush = new VisualBrush(inkCanvas); + // 绘制矩形并填充为inkCanvas的内容 + dc.DrawRectangle(visualBrush, null, new Rect(0, 0, inkCanvas.ActualWidth, inkCanvas.ActualHeight)); + } + + // 创建适合墨迹画布尺寸的渲染位图 + var rtb = new RenderTargetBitmap( + (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight, + 96, 96, + PixelFormats.Pbgra32); + rtb.Render(visual); + + // 转换为GDI+ Bitmap并保存 + var encoder = new PngBitmapEncoder(); + encoder.Frames.Add(BitmapFrame.Create(rtb)); + + using (var ms = new MemoryStream()) + { + encoder.Save(ms); + ms.Seek(0, SeekOrigin.Begin); + var imgBitmap = new System.Drawing.Bitmap(ms); + + // 将生成的墨迹图像绘制到屏幕截图上 + // 居中绘制,确保墨迹位于屏幕中央 + int x = (bitmap.Width - imgBitmap.Width) / 2; + int y = (bitmap.Height - imgBitmap.Height) / 2; + g.DrawImage(imgBitmap, x, y); + + // 保存为PNG + string imagePathWithName = Path.ChangeExtension(savePathWithName, "png"); + bitmap.Save(imagePathWithName, System.Drawing.Imaging.ImageFormat.Png); + + // 仍然保存墨迹文件以兼容旧版本 + var fs = new FileStream(savePathWithName, FileMode.Create); + inkCanvas.Strokes.Save(fs); + fs.Close(); + } + } + + // 显示提示 + if (newNotice) ShowNotification("墨迹成功全页面保存至 " + Path.ChangeExtension(savePathWithName, "png")); + } + + /// + /// 将指定墨迹集合保存为图像到指定流 + /// + private void SavePageAsImage(StrokeCollection strokes, Stream outputStream) + { + try + { + // 创建临时InkCanvas来渲染墨迹 + var tempCanvas = new InkCanvas(); + tempCanvas.Strokes = strokes; + tempCanvas.Width = inkCanvas.ActualWidth; + tempCanvas.Height = inkCanvas.ActualHeight; + + // 创建渲染位图 + var rtb = new RenderTargetBitmap( + (int)tempCanvas.Width, (int)tempCanvas.Height, + 96, 96, + PixelFormats.Pbgra32); + rtb.Render(tempCanvas); + + // 保存为PNG + var encoder = new PngBitmapEncoder(); + encoder.Frames.Add(BitmapFrame.Create(rtb)); + encoder.Save(outputStream); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"保存页面图像失败: {ex.ToString()}", LogHelper.LogType.Error); + throw; + } + } + private void SymbolIconOpenStrokes_MouseUp(object sender, MouseButtonEventArgs e) { if (lastBorderMouseDownObject != sender) return; AnimationsHelper.HideWithSlideAndFade(BorderTools);