Files
community/Ink Canvas/MainWindow.xaml.cs
T
2025-06-18 09:08:38 +08:00

618 lines
26 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern;
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Media;
using System.Diagnostics;
using File = System.IO.File;
using MessageBox = System.Windows.MessageBox;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using System.Windows.Controls.Primitives;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Win32;
using System.Windows.Input;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media.Animation;
namespace Ink_Canvas {
public partial class MainWindow : Window {
#region Window Initialization
public MainWindow() {
/*
处于画板模式内:Topmost == false / currentMode != 0
处于 PPT 放映内:BtnPPTSlideShowEnd.Visibility
*/
InitializeComponent();
BlackboardLeftSide.Visibility = Visibility.Collapsed;
BlackboardCenterSide.Visibility = Visibility.Collapsed;
BlackboardRightSide.Visibility = Visibility.Collapsed;
BorderTools.Visibility = Visibility.Collapsed;
BorderSettings.Visibility = Visibility.Collapsed;
LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
BorderSettings.Margin = new Thickness(0, 0, 0, 0);
TwoFingerGestureBorder.Visibility = Visibility.Collapsed;
BoardTwoFingerGestureBorder.Visibility = Visibility.Collapsed;
BorderDrawShape.Visibility = Visibility.Collapsed;
BoardBorderDrawShape.Visibility = Visibility.Collapsed;
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
//if (!App.StartArgs.Contains("-o"))
ViewBoxStackPanelMain.Visibility = Visibility.Collapsed;
ViewBoxStackPanelShapes.Visibility = Visibility.Collapsed;
var workingArea = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
ViewboxFloatingBar.Margin = new Thickness(
(workingArea.Width - 284) / 2,
workingArea.Bottom - 60 - workingArea.Top,
-2000, -200);
ViewboxFloatingBarMarginAnimation(100, true);
try {
if (File.Exists("debug.ini")) Label.Visibility = Visibility.Visible;
}
catch (Exception ex) {
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
}
try {
if (File.Exists("Log.txt")) {
var fileInfo = new FileInfo("Log.txt");
var fileSizeInKB = fileInfo.Length / 1024;
if (fileSizeInKB > 512)
try {
File.Delete("Log.txt");
LogHelper.WriteLogToFile(
"The Log.txt file has been successfully deleted. Original file size: " + fileSizeInKB +
" KB", LogHelper.LogType.Info);
}
catch (Exception ex) {
LogHelper.WriteLogToFile(
ex + " | Can not delete the Log.txt file. File size: " + fileSizeInKB + " KB",
LogHelper.LogType.Error);
}
}
}
catch (Exception ex) {
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
}
InitTimers();
timeMachine.OnRedoStateChanged += TimeMachine_OnRedoStateChanged;
timeMachine.OnUndoStateChanged += TimeMachine_OnUndoStateChanged;
inkCanvas.Strokes.StrokesChanged += StrokesOnStrokesChanged;
Microsoft.Win32.SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
try {
if (File.Exists("SpecialVersion.ini")) SpecialVersionResetToSuggestion_Click();
}
catch (Exception ex) {
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
}
CheckColorTheme(true);
CheckPenTypeUIState();
// 注册输入事件
inkCanvas.PreviewMouseDown += inkCanvas_PreviewMouseDown;
inkCanvas.StylusDown += inkCanvas_StylusDown;
inkCanvas.TouchDown += inkCanvas_TouchDown;
inkCanvas.TouchUp += inkCanvas_TouchUp;
}
#endregion
#region Ink Canvas Functions
private System.Windows.Media.Color Ink_DefaultColor = Colors.Red;
private DrawingAttributes drawingAttributes;
private void loadPenCanvas() {
try {
//drawingAttributes = new DrawingAttributes();
drawingAttributes = inkCanvas.DefaultDrawingAttributes;
drawingAttributes.Color = Ink_DefaultColor;
drawingAttributes.Height = 2.5;
drawingAttributes.Width = 2.5;
drawingAttributes.IsHighlighter = false;
drawingAttributes.FitToCurve = Settings.Canvas.FitToCurve;
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
inkCanvas.Gesture += InkCanvas_Gesture;
}
catch { }
}
//ApplicationGesture lastApplicationGesture = ApplicationGesture.AllGestures;
private DateTime lastGestureTime = DateTime.Now;
private void InkCanvas_Gesture(object sender, InkCanvasGestureEventArgs e) {
var gestures = e.GetGestureRecognitionResults();
try {
foreach (var gest in gestures)
//Trace.WriteLine(string.Format("Gesture: {0}, Confidence: {1}", gest.ApplicationGesture, gest.RecognitionConfidence));
if (StackPanelPPTControls.Visibility == Visibility.Visible) {
if (gest.ApplicationGesture == ApplicationGesture.Left)
BtnPPTSlidesDown_Click(BtnPPTSlidesDown, null);
if (gest.ApplicationGesture == ApplicationGesture.Right)
BtnPPTSlidesUp_Click(BtnPPTSlidesUp, null);
}
}
catch { }
}
private void inkCanvas_EditingModeChanged(object sender, RoutedEventArgs e) {
var inkCanvas1 = sender as InkCanvas;
if (inkCanvas1 == null) return;
// 使用辅助方法设置光标
SetCursorBasedOnEditingMode(inkCanvas1);
if (inkCanvas1.EditingMode == InkCanvasEditingMode.Ink) forcePointEraser = !forcePointEraser;
}
#endregion Ink Canvas
#region Definations and Loading
public static Settings Settings = new Settings();
public static string settingsFileName = "Settings.json";
private bool isLoaded = false;
private void Window_Loaded(object sender, RoutedEventArgs e) {
loadPenCanvas();
//加载设置
LoadSettings(true);
// HasNewUpdateWindow hasNewUpdateWindow = new HasNewUpdateWindow();
if (Environment.Is64BitProcess) GroupBoxInkRecognition.Visibility = Visibility.Collapsed;
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
SystemEvents_UserPreferenceChanged(null, null);
//TextBlockVersion.Text = Assembly.GetExecutingAssembly().GetName().Version.ToString();
LogHelper.WriteLogToFile("Ink Canvas Loaded", LogHelper.LogType.Event);
isLoaded = true;
BlackBoardLeftSidePageListView.ItemsSource = blackBoardSidePageListViewObservableCollection;
BlackBoardRightSidePageListView.ItemsSource = blackBoardSidePageListViewObservableCollection;
BtnLeftWhiteBoardSwitchPreviousGeometry.Brush =
new SolidColorBrush(System.Windows.Media.Color.FromArgb(127, 24, 24, 27));
BtnLeftWhiteBoardSwitchPreviousLabel.Opacity = 0.5;
BtnRightWhiteBoardSwitchPreviousGeometry.Brush =
new SolidColorBrush(System.Windows.Media.Color.FromArgb(127, 24, 24, 27));
BtnRightWhiteBoardSwitchPreviousLabel.Opacity = 0.5;
BtnWhiteBoardSwitchPrevious.IsEnabled = CurrentWhiteboardIndex != 1;
BorderInkReplayToolBox.Visibility = Visibility.Collapsed;
// 提前加载IA库,优化第一笔等待时间
if (Settings.InkToShape.IsInkToShapeEnabled && !Environment.Is64BitProcess) {
var strokeEmpty = new StrokeCollection();
InkRecognizeHelper.RecognizeShape(strokeEmpty);
}
SystemEvents.DisplaySettingsChanged += SystemEventsOnDisplaySettingsChanged;
// 自动收纳到侧边栏
if (Settings.Startup.IsFoldAtStartup)
{
FoldFloatingBar_MouseUp(null, null);
}
// 恢复崩溃后操作设置
if (App.CrashAction == App.CrashActionType.SilentRestart)
RadioCrashSilentRestart.IsChecked = true;
else
RadioCrashNoAction.IsChecked = true;
}
private void SystemEventsOnDisplaySettingsChanged(object sender, EventArgs e) {
if (!Settings.Advanced.IsEnableResolutionChangeDetection) return;
ShowNotification($"检测到显示器信息变化,变为{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width}x{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height}");
new Thread(() => {
var isFloatingBarOutsideScreen = false;
var isInPPTPresentationMode = false;
Dispatcher.Invoke(() => {
isFloatingBarOutsideScreen = IsOutsideOfScreenHelper.IsOutsideOfScreen(ViewboxFloatingBar);
isInPPTPresentationMode = BtnPPTSlideShowEnd.Visibility == Visibility.Visible;
});
if (isFloatingBarOutsideScreen) dpiChangedDelayAction.DebounceAction(3000, null, () => {
if (!isFloatingBarFolded)
{
if (isInPPTPresentationMode) ViewboxFloatingBarMarginAnimation(60);
else ViewboxFloatingBarMarginAnimation(100, true);
}
});
}).Start();
}
public DelayAction dpiChangedDelayAction = new DelayAction();
private void MainWindow_OnDpiChanged(object sender, DpiChangedEventArgs e)
{
if (e.OldDpi.DpiScaleX != e.NewDpi.DpiScaleX && e.OldDpi.DpiScaleY != e.NewDpi.DpiScaleY && Settings.Advanced.IsEnableDPIChangeDetection)
{
ShowNotification($"系统DPI发生变化,从 {e.OldDpi.DpiScaleX}x{e.OldDpi.DpiScaleY} 变化为 {e.NewDpi.DpiScaleX}x{e.NewDpi.DpiScaleY}");
new Thread(() => {
var isFloatingBarOutsideScreen = false;
var isInPPTPresentationMode = false;
Dispatcher.Invoke(() => {
isFloatingBarOutsideScreen = IsOutsideOfScreenHelper.IsOutsideOfScreen(ViewboxFloatingBar);
isInPPTPresentationMode = BtnPPTSlideShowEnd.Visibility == Visibility.Visible;
});
if (isFloatingBarOutsideScreen) dpiChangedDelayAction.DebounceAction(3000,null, () => {
if (!isFloatingBarFolded)
{
if (isInPPTPresentationMode) ViewboxFloatingBarMarginAnimation(60);
else ViewboxFloatingBarMarginAnimation(100, true);
}
});
}).Start();
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
LogHelper.WriteLogToFile("Ink Canvas closing", LogHelper.LogType.Event);
if (!CloseIsFromButton && Settings.Advanced.IsSecondConfirmWhenShutdownApp) {
e.Cancel = true;
if (MessageBox.Show("是否继续关闭 InkCanvasForClass,这将丢失当前未保存的墨迹。", "InkCanvasForClass",
MessageBoxButton.OKCancel, MessageBoxImage.Warning) == MessageBoxResult.OK)
if (MessageBox.Show("真的狠心关闭 InkCanvasForClass吗?", "InkCanvasForClass", MessageBoxButton.OKCancel,
MessageBoxImage.Error) == MessageBoxResult.OK)
if (MessageBox.Show("是否取消关闭 InkCanvasForClass", "InkCanvasForClass", MessageBoxButton.OKCancel,
MessageBoxImage.Error) != MessageBoxResult.OK)
e.Cancel = false;
}
if (e.Cancel) LogHelper.WriteLogToFile("Ink Canvas closing cancelled", LogHelper.LogType.Event);
}
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
private void MainWindow_OnSizeChanged(object sender, SizeChangedEventArgs e) {
if (Settings.Advanced.IsEnableForceFullScreen) {
if (isLoaded) ShowNotification(
$"检测到窗口大小变化,已自动恢复到全屏:{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width}x{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height}(缩放比例为{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth}x{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height / SystemParameters.PrimaryScreenHeight}");
WindowState = WindowState.Maximized;
MoveWindow(new WindowInteropHelper(this).Handle, 0, 0,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, true);
}
}
private void Window_Closed(object sender, EventArgs e) {
SystemEvents.DisplaySettingsChanged -= SystemEventsOnDisplaySettingsChanged;
LogHelper.WriteLogToFile("Ink Canvas closed", LogHelper.LogType.Event);
}
private async void AutoUpdate() {
AvailableLatestVersion = await AutoUpdateHelper.CheckForUpdates();
if (AvailableLatestVersion != null) {
var IsDownloadSuccessful = false;
IsDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFileAndSaveStatus(AvailableLatestVersion);
if (IsDownloadSuccessful) {
if (!Settings.Startup.IsAutoUpdateWithSilence) {
if (MessageBox.Show("InkCanvasForClass 新版本安装包已下载完成,是否立即更新?",
"InkCanvasForClass New Version Available", MessageBoxButton.YesNo,
MessageBoxImage.Question) ==
MessageBoxResult.Yes) AutoUpdateHelper.InstallNewVersionApp(AvailableLatestVersion, false);
} else {
timerCheckAutoUpdateWithSilence.Start();
}
}
} else {
AutoUpdateHelper.DeleteUpdatesFolder();
}
}
// 新增:崩溃后操作设置按钮事件
private void RadioCrashAction_Checked(object sender, RoutedEventArgs e)
{
if (RadioCrashSilentRestart != null && RadioCrashSilentRestart.IsChecked == true)
{
App.CrashAction = App.CrashActionType.SilentRestart;
}
else if (RadioCrashNoAction != null && RadioCrashNoAction.IsChecked == true)
{
App.CrashAction = App.CrashActionType.NoAction;
}
SaveSettingsToFile();
}
// 添加一个辅助方法,根据当前编辑模式设置光标
private void SetCursorBasedOnEditingMode(InkCanvas canvas)
{
if (Settings.Canvas.IsShowCursor) {
canvas.UseCustomCursor = true;
canvas.ForceCursor = true;
// 根据编辑模式设置不同的光标
if (canvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
canvas.Cursor = Cursors.Cross;
} else if (canvas.EditingMode == InkCanvasEditingMode.Ink) {
var sri = Application.GetResourceStream(new Uri("Resources/Cursors/Pen.cur", UriKind.Relative));
if (sri != null)
canvas.Cursor = new Cursor(sri.Stream);
} else if (canvas.EditingMode == InkCanvasEditingMode.Select) {
canvas.Cursor = Cursors.Cross;
}
System.Windows.Forms.Cursor.Show();
} else {
canvas.UseCustomCursor = false;
canvas.ForceCursor = false;
System.Windows.Forms.Cursor.Show();
}
}
// 鼠标输入
private void inkCanvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
// 使用辅助方法设置光标
SetCursorBasedOnEditingMode(inkCanvas);
}
// 手写笔输入
private void inkCanvas_StylusDown(object sender, StylusDownEventArgs e)
{
// 使用辅助方法设置光标
SetCursorBasedOnEditingMode(inkCanvas);
}
// 触摸输入,不隐藏光标
private void inkCanvas_TouchDown(object sender, TouchEventArgs e)
{
// 使用辅助方法设置光标
SetCursorBasedOnEditingMode(inkCanvas);
}
// 触摸结束,恢复光标
private void inkCanvas_TouchUp(object sender, TouchEventArgs e)
{
// 使用辅助方法设置光标
SetCursorBasedOnEditingMode(inkCanvas);
}
#endregion Definations and Loading
#region Navigation Sidebar Methods
// 侧边栏导航按钮事件处理
private void NavStartup_Click(object sender, RoutedEventArgs e)
{
// 切换到启动设置页面
ShowSettingsSection("startup");
}
private void NavCanvas_Click(object sender, RoutedEventArgs e)
{
// 切换到画布设置页面
ShowSettingsSection("canvas");
}
private void NavGesture_Click(object sender, RoutedEventArgs e)
{
// 切换到手势设置页面
ShowSettingsSection("gesture");
}
private void NavInkRecognition_Click(object sender, RoutedEventArgs e)
{
// 切换到墨迹识别设置页面
ShowSettingsSection("inkrecognition");
}
private void NavCrashAction_Click(object sender, RoutedEventArgs e)
{
// 切换到崩溃处理设置页面
ShowSettingsSection("crashaction");
}
private void NavPPT_Click(object sender, RoutedEventArgs e)
{
// 切换到PPT设置页面
ShowSettingsSection("ppt");
}
private void NavAdvanced_Click(object sender, RoutedEventArgs e)
{
// 切换到高级设置页面
ShowSettingsSection("advanced");
}
private void NavAutomation_Click(object sender, RoutedEventArgs e)
{
// 切换到自动化设置页面
ShowSettingsSection("automation");
}
private void NavRandomWindow_Click(object sender, RoutedEventArgs e)
{
// 切换到随机窗口设置页面
ShowSettingsSection("randomwindow");
}
private void NavAbout_Click(object sender, RoutedEventArgs e)
{
// 切换到关于页面
ShowSettingsSection("about");
}
// 新增:个性化设置
private void NavTheme_Click(object sender, RoutedEventArgs e)
{
// 切换到个性化设置页面
ShowSettingsSection("theme");
}
// 新增:快捷键设置
private void NavShortcuts_Click(object sender, RoutedEventArgs e)
{
// 切换到快捷键设置页面
ShowSettingsSection("shortcuts");
// 如果设置部分尚未快捷键
MessageBox.Show("设置功能正在开发中", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}
private void BtnCloseSettings_Click(object sender, RoutedEventArgs e)
{
// 关闭设置面板
BorderSettings.Visibility = Visibility.Collapsed;
BorderSettingsMask.IsHitTestVisible = false;
}
// 新增:折叠侧边栏
private void CollapseNavSidebar_Click(object sender, RoutedEventArgs e)
{
// 折叠/展开侧边栏
var columnDefinitions = ((Grid)BorderSettings.Child).ColumnDefinitions;
if (columnDefinitions[0].Width.Value == 50)
{
// 折叠侧边栏
columnDefinitions[0].Width = new GridLength(0);
}
else
{
// 展开侧边栏
columnDefinitions[0].Width = new GridLength(50);
}
}
// 新增:显示侧边栏
private void ShowNavSidebar_Click(object sender, RoutedEventArgs e)
{
// 确保侧边栏展开
var columnDefinitions = ((Grid)BorderSettings.Child).ColumnDefinitions;
columnDefinitions[0].Width = new GridLength(50);
}
// 辅助方法:显示指定的设置部分
private void ShowSettingsSection(string sectionTag)
{
// 显示设置面板
BorderSettings.Visibility = Visibility.Visible;
BorderSettingsMask.IsHitTestVisible = true;
// 获取SettingsPanelScrollViewer中的所有GroupBox
var stackPanel = SettingsPanelScrollViewer.Content as StackPanel;
if (stackPanel == null) return;
// 首先隐藏所有GroupBox
foreach (var child in stackPanel.Children)
{
if (child is GroupBox groupBox)
{
groupBox.Visibility = Visibility.Collapsed;
}
}
// 根据传入的sectionTag显示相应的设置部分
switch (sectionTag.ToLower())
{
case "startup":
// 显示启动设置
ShowGroupBoxByHeader(stackPanel, "启动");
break;
case "canvas":
// 显示画板和墨迹设置
ShowGroupBoxByHeader(stackPanel, "画板和墨迹");
break;
case "gesture":
// 显示手势设置
ShowGroupBoxByHeader(stackPanel, "手势");
break;
case "inkrecognition":
// 显示墨迹纠正设置
ShowGroupBoxByHeader(stackPanel, "墨迹纠正");
if (GroupBoxInkRecognition != null)
GroupBoxInkRecognition.Visibility = Visibility.Visible;
break;
case "crashaction":
// 显示崩溃后操作设置
ShowGroupBoxByHeader(stackPanel, "崩溃后操作");
break;
case "ppt":
// 显示PPT联动设置
ShowGroupBoxByHeader(stackPanel, "PPT联动");
break;
case "advanced":
// 显示高级设置
// 这里可能需要根据实际情况调整
break;
case "automation":
// 显示自动化设置
// 这里可能需要根据实际情况调整
break;
case "randomwindow":
// 显示随机窗口设置
if (GroupBoxRandWindow != null)
GroupBoxRandWindow.Visibility = Visibility.Visible;
break;
case "theme":
// 显示主题设置
if (GroupBoxAppearanceNewUI != null)
GroupBoxAppearanceNewUI.Visibility = Visibility.Visible;
break;
case "shortcuts":
// 显示快捷键设置
// 快捷键设置部分可能尚未实现
break;
case "about":
// 显示关于页面
ShowGroupBoxByHeader(stackPanel, "关于");
break;
default:
// 默认显示第一个GroupBox
if (stackPanel.Children.Count > 0 && stackPanel.Children[0] is GroupBox firstGroupBox)
{
firstGroupBox.Visibility = Visibility.Visible;
}
break;
}
// 滚动到顶部
SettingsPanelScrollViewer.ScrollToTop();
}
// 根据Header文本查找并显示GroupBox
private void ShowGroupBoxByHeader(StackPanel parent, string headerText)
{
foreach (var child in parent.Children)
{
if (child is GroupBox groupBox)
{
// 查找GroupBox的Header
if (groupBox.Header is TextBlock headerTextBlock &&
headerTextBlock.Text != null &&
headerTextBlock.Text.Contains(headerText))
{
groupBox.Visibility = Visibility.Visible;
return;
}
}
}
}
#endregion Navigation Sidebar Methods
}
}