using Ink_Canvas.Helpers; using System; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Ink; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Controls; using Newtonsoft.Json; using System.Collections.Generic; using System.IO; namespace Ink_Canvas { public partial class MainWindow : Window { private StrokeCollection[] strokeCollections = new StrokeCollection[101]; private bool[] whiteboadLastModeIsRedo = new bool[101]; private StrokeCollection lastTouchDownStrokeCollection = new StrokeCollection(); private int CurrentWhiteboardIndex = 1; private int WhiteboardTotalCount = 1; private TimeMachineHistory[][] TimeMachineHistories = new TimeMachineHistory[101][]; //最多99页,0用来存储非白板时的墨迹以便还原 // 保存每页白板图片信息 private void SaveStrokes(bool isBackupMain = false) { if (isBackupMain) { var timeMachineHistory = timeMachine.ExportTimeMachineHistory(); TimeMachineHistories[0] = timeMachineHistory; timeMachine.ClearStrokeHistory(); } else { // 新增:提交所有图片元素到时间机器历史记录 foreach (var child in inkCanvas.Children) { if (child is Image img) { timeMachine.CommitElementInsertHistory(img); } } var timeMachineHistory = timeMachine.ExportTimeMachineHistory(); TimeMachineHistories[CurrentWhiteboardIndex] = timeMachineHistory; timeMachine.ClearStrokeHistory(); // 保存当前页图片信息 var elementInfos = new List(); foreach (var child in inkCanvas.Children) { if (child is Image img && img.Source is BitmapImage bmp) { elementInfos.Add(new CanvasElementInfo { Type = "Image", SourcePath = bmp.UriSource?.LocalPath ?? "", Left = InkCanvas.GetLeft(img), Top = InkCanvas.GetTop(img), Width = img.Width, Height = img.Height }); } } var savePath = Settings.Automation.AutoSavedStrokesLocation; if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath); File.WriteAllText(System.IO.Path.Combine(savePath, $"elements_page{CurrentWhiteboardIndex}.json"), JsonConvert.SerializeObject(elementInfos, Formatting.Indented)); } } private void ClearStrokes(bool isErasedByCode) { _currentCommitType = CommitReason.ClearingCanvas; if (isErasedByCode) _currentCommitType = CommitReason.CodeInput; inkCanvas.Strokes.Clear(); _currentCommitType = CommitReason.UserInput; } // 恢复每页白板图片信息 private void RestoreStrokes(bool isBackupMain = false) { try { if (TimeMachineHistories[CurrentWhiteboardIndex] == null) return; //防止白板打开后不居中 if (isBackupMain) { timeMachine.ImportTimeMachineHistory(TimeMachineHistories[0]); foreach (var item in TimeMachineHistories[0]) ApplyHistoryToCanvas(item); } else { timeMachine.ImportTimeMachineHistory(TimeMachineHistories[CurrentWhiteboardIndex]); // 新增:通过时间机器历史恢复图片 foreach (var item in TimeMachineHistories[CurrentWhiteboardIndex]) { if (item.CommitType == TimeMachineHistoryType.ElementInsert) { inkCanvas.Children.Add(item.InsertedElement); } } foreach (var item in TimeMachineHistories[CurrentWhiteboardIndex]) ApplyHistoryToCanvas(item); // 恢复当前页图片信息 inkCanvas.Children.Clear(); var savePath = Settings.Automation.AutoSavedStrokesLocation; var elementsFile = System.IO.Path.Combine(savePath, $"elements_page{CurrentWhiteboardIndex}.json"); if (File.Exists(elementsFile)) { var elementInfos = JsonConvert.DeserializeObject>(File.ReadAllText(elementsFile)); foreach (var info in elementInfos) { if (info.Type == "Image" && File.Exists(info.SourcePath)) { var img = new Image { Source = new BitmapImage(new Uri(info.SourcePath)), Width = info.Width, Height = info.Height, Stretch = Enum.TryParse(info.Stretch, out var stretch) ? stretch : Stretch.Fill }; InkCanvas.SetLeft(img, info.Left); InkCanvas.SetTop(img, info.Top); inkCanvas.Children.Add(img); } } } } } catch { // ignored } } private async void BtnWhiteBoardPageIndex_Click(object sender, EventArgs e) { if (sender == BtnLeftPageListWB) { if (BoardBorderLeftPageListView.Visibility == Visibility.Visible) { AnimationsHelper.HideWithSlideAndFade(BoardBorderLeftPageListView); } else { AnimationsHelper.HideWithSlideAndFade(BoardBorderRightPageListView); RefreshBlackBoardSidePageListView(); AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardBorderLeftPageListView); await Task.Delay(1); ScrollViewToVerticalTop( (ListViewItem)BlackBoardLeftSidePageListView.ItemContainerGenerator.ContainerFromIndex( CurrentWhiteboardIndex - 1), BlackBoardLeftSidePageListScrollViewer); } } else if (sender == BtnRightPageListWB) { if (BoardBorderRightPageListView.Visibility == Visibility.Visible) { AnimationsHelper.HideWithSlideAndFade(BoardBorderRightPageListView); } else { AnimationsHelper.HideWithSlideAndFade(BoardBorderLeftPageListView); RefreshBlackBoardSidePageListView(); AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardBorderRightPageListView); await Task.Delay(1); ScrollViewToVerticalTop( (ListViewItem)BlackBoardRightSidePageListView.ItemContainerGenerator.ContainerFromIndex( CurrentWhiteboardIndex - 1), BlackBoardRightSidePageListScrollViewer); } } } private void BtnWhiteBoardSwitchPrevious_Click(object sender, EventArgs e) { if (CurrentWhiteboardIndex <= 1) return; SaveStrokes(); ClearStrokes(true); CurrentWhiteboardIndex--; RestoreStrokes(); UpdateIndexInfoDisplay(); } private void BtnWhiteBoardSwitchNext_Click(object sender, EventArgs e) { Trace.WriteLine("113223234"); if (Settings.Automation.IsAutoSaveStrokesAtClear && inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) SaveScreenShot(true); if (CurrentWhiteboardIndex >= WhiteboardTotalCount) { // 在最后一页时,点击“新页面”按钮直接新增一页 BtnWhiteBoardAdd_Click(sender, e); return; } SaveStrokes(); ClearStrokes(true); CurrentWhiteboardIndex++; RestoreStrokes(); UpdateIndexInfoDisplay(); } private void BtnWhiteBoardAdd_Click(object sender, EventArgs e) { if (WhiteboardTotalCount >= 99) return; if (Settings.Automation.IsAutoSaveStrokesAtClear && inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) SaveScreenShot(true); SaveStrokes(); ClearStrokes(true); WhiteboardTotalCount++; CurrentWhiteboardIndex++; if (CurrentWhiteboardIndex != WhiteboardTotalCount) for (var i = WhiteboardTotalCount; i > CurrentWhiteboardIndex; i--) TimeMachineHistories[i] = TimeMachineHistories[i - 1]; UpdateIndexInfoDisplay(); if (WhiteboardTotalCount >= 99) BtnWhiteBoardAdd.IsEnabled = false; if (BlackBoardLeftSidePageListView.Visibility == Visibility.Visible) { RefreshBlackBoardSidePageListView(); } } private void BtnWhiteBoardDelete_Click(object sender, RoutedEventArgs e) { ClearStrokes(true); if (CurrentWhiteboardIndex != WhiteboardTotalCount) for (var i = CurrentWhiteboardIndex; i <= WhiteboardTotalCount; i++) TimeMachineHistories[i] = TimeMachineHistories[i + 1]; else CurrentWhiteboardIndex--; WhiteboardTotalCount--; RestoreStrokes(); UpdateIndexInfoDisplay(); if (WhiteboardTotalCount < 99) BtnWhiteBoardAdd.IsEnabled = true; } private void UpdateIndexInfoDisplay() { TextBlockWhiteBoardIndexInfo.Text = $"{CurrentWhiteboardIndex}/{WhiteboardTotalCount}"; bool isLastPage = CurrentWhiteboardIndex == WhiteboardTotalCount; bool isMaxPage = WhiteboardTotalCount >= 99; // 设置按钮文本 BtnLeftWhiteBoardSwitchNextLabel.Text = isLastPage ? "新页面" : "下一页"; BtnRightWhiteBoardSwitchNextLabel.Text = isLastPage ? "新页面" : "下一页"; // 始终允许点击“下一页/新页面”按钮(除非已达最大页数) BtnWhiteBoardSwitchNext.IsEnabled = !isMaxPage; // 保持按钮常亮(高亮) BtnLeftWhiteBoardSwitchNextGeometry.Brush = new SolidColorBrush(Color.FromArgb(255, 24, 24, 27)); BtnLeftWhiteBoardSwitchNextLabel.Opacity = 1; BtnRightWhiteBoardSwitchNextGeometry.Brush = new SolidColorBrush(Color.FromArgb(255, 24, 24, 27)); BtnRightWhiteBoardSwitchNextLabel.Opacity = 1; BtnWhiteBoardSwitchPrevious.IsEnabled = true; if (CurrentWhiteboardIndex == 1) { BtnWhiteBoardSwitchPrevious.IsEnabled = false; BtnLeftWhiteBoardSwitchPreviousGeometry.Brush = new SolidColorBrush(Color.FromArgb(127, 24, 24, 27)); BtnLeftWhiteBoardSwitchPreviousLabel.Opacity = 0.5; BtnRightWhiteBoardSwitchPreviousGeometry.Brush = new SolidColorBrush(Color.FromArgb(127, 24, 24, 27)); BtnRightWhiteBoardSwitchPreviousLabel.Opacity = 0.5; } else { BtnLeftWhiteBoardSwitchPreviousGeometry.Brush = new SolidColorBrush(Color.FromArgb(255, 24, 24, 27)); BtnLeftWhiteBoardSwitchPreviousLabel.Opacity = 1; BtnRightWhiteBoardSwitchPreviousGeometry.Brush = new SolidColorBrush(Color.FromArgb(255, 24, 24, 27)); BtnRightWhiteBoardSwitchPreviousLabel.Opacity = 1; } BtnWhiteBoardDelete.IsEnabled = WhiteboardTotalCount != 1; } } }