Compare commits

..

29 Commits

Author SHA1 Message Date
CJK_mkp 865415a6c0 Merge pull request #113 from InkCanvasForClass/beta
ICC CE 1.7.5.0
2025-07-28 19:16:24 +08:00
CJKmkp 32e8324275 更新日志 2025-07-28 19:12:12 +08:00
CJKmkp 842f6dd726 更新版本号 2025-07-28 19:10:51 +08:00
CJKmkp 59f7d11df3 improve:单文件 2025-07-28 19:08:06 +08:00
CJKmkp dcd2f52c59 improve:插入图片 2025-07-28 19:02:45 +08:00
CJKmkp b45413c232 fix:墨迹纠正失效 2025-07-28 18:29:22 +08:00
CJKmkp b4481ff680 fix:issue #111 2025-07-28 18:23:07 +08:00
CJKmkp d7d7a3919f improve:日志输出 2025-07-28 18:11:20 +08:00
CJKmkp f8e4732dcd fix:issue #110 2025-07-28 17:44:15 +08:00
CJKmkp 1b92ed66b7 更新README 2025-07-28 16:19:19 +08:00
CJKmkp 9ba74b9504 更新版本号 2025-07-28 16:12:40 +08:00
CJKmkp 8cd49f12d1 更新README 2025-07-28 16:10:40 +08:00
CJKmkp c48ca9ee89 fix:issue #93 2025-07-28 16:04:36 +08:00
CJKmkp 43bcf71bf5 fix:issue #93 2025-07-28 15:47:18 +08:00
CJKmkp ee48813df1 fix:issue #93 2025-07-28 15:18:33 +08:00
CJKmkp f4a67e2822 fix:issue #93 2025-07-28 14:45:37 +08:00
CJKmkp f03733da04 优化代码 2025-07-28 14:40:44 +08:00
CJK_mkp 207560bcc7 Merge pull request #109 from InkCanvasForClass/beta
ICC CE 1.7.4.1
2025-07-28 11:46:23 +08:00
CJKmkp f38313ff2c 更新版本号 2025-07-28 11:37:58 +08:00
CJKmkp b5d9e21f37 improve:用户体验分级 2025-07-28 11:35:47 +08:00
CJKmkp 5d42a8957e fix:issue #93 2025-07-28 11:15:35 +08:00
CJK_mkp b276c60909 Merge pull request #108 from InkCanvasForClass/all-contributors/add-PrefacedCorg
docs: add PrefacedCorg as a contributor for code
2025-07-28 02:05:44 +08:00
allcontributors[bot] d03564bce9 docs: update .all-contributorsrc 2025-07-27 18:05:04 +00:00
allcontributors[bot] 41409c39d5 docs: update README.md 2025-07-27 18:05:03 +00:00
CJK_mkp aa9c5107d0 Merge pull request #107 from PrefacedCorg/beta
fix:issue #93
2025-07-28 02:02:57 +08:00
PrefacedCorg 7a141822e7 fix:issue #93 2025-07-28 01:49:54 +08:00
CJKmkp a4fd301d5a fix:issue #93 2025-07-28 00:48:50 +08:00
CJKmkp b2ef8b96ef fix:issue #93 2025-07-27 22:52:04 +08:00
CJKmkp baa9e1003e fix:issue #93 2025-07-27 22:00:37 +08:00
82 changed files with 2830 additions and 1526 deletions
+9
View File
@@ -79,6 +79,15 @@
"contributions": [ "contributions": [
"doc" "doc"
] ]
},
{
"login": "PrefacedCorg",
"name": "PrefacedCorg",
"avatar_url": "https://avatars.githubusercontent.com/u/129855423?v=4",
"profile": "https://github.com/PrefacedCorg",
"contributions": [
"code"
]
} }
] ]
} }
+1 -1
View File
@@ -1 +1 @@
1.7.4.0 1.7.5.0
+83 -67
View File
@@ -1,19 +1,26 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Threading;
using Hardcodet.Wpf.TaskbarNotification; using Hardcodet.Wpf.TaskbarNotification;
using Ink_Canvas.Helpers; using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern.Controls; using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Diagnostics;
using System.Threading;
using Microsoft.Win32; using Microsoft.Win32;
using System.Security; using Newtonsoft.Json;
using System.IO; using Application = System.Windows.Application;
using System.Linq;
using System.Reflection;
using System.Windows;
using MessageBox = System.Windows.MessageBox; using MessageBox = System.Windows.MessageBox;
using System.Collections.Generic; using Timer = System.Threading.Timer;
using System.Runtime.InteropServices;
using System.Net;
namespace Ink_Canvas namespace Ink_Canvas
{ {
@@ -22,17 +29,17 @@ namespace Ink_Canvas
/// </summary> /// </summary>
public partial class App : Application public partial class App : Application
{ {
System.Threading.Mutex mutex; Mutex mutex;
public static string[] StartArgs = null; public static string[] StartArgs;
public static string RootPath = Environment.GetEnvironmentVariable("APPDATA") + "\\Ink Canvas\\"; public static string RootPath = Environment.GetEnvironmentVariable("APPDATA") + "\\Ink Canvas\\";
// 新增:保存看门狗进程对象 // 新增:保存看门狗进程对象
private static Process watchdogProcess = null; private static Process watchdogProcess;
// 新增:标记是否为软件内主动退出 // 新增:标记是否为软件内主动退出
public static bool IsAppExitByUser = false; public static bool IsAppExitByUser;
// 新增:退出信号文件路径 // 新增:退出信号文件路径
private static string watchdogExitSignalFile = Path.Combine(Path.GetTempPath(), "icc_watchdog_exit_" + System.Diagnostics.Process.GetCurrentProcess().Id + ".flag"); private static string watchdogExitSignalFile = Path.Combine(Path.GetTempPath(), "icc_watchdog_exit_" + Process.GetCurrentProcess().Id + ".flag");
// 新增:崩溃日志文件路径 // 新增:崩溃日志文件路径
private static string crashLogFile = Path.Combine(Environment.GetEnvironmentVariable("APPDATA"), "Ink Canvas", "crash_logs"); private static string crashLogFile = Path.Combine(Environment.GetEnvironmentVariable("APPDATA"), "Ink Canvas", "crash_logs");
// 新增:进程ID // 新增:进程ID
@@ -42,7 +49,7 @@ namespace Ink_Canvas
// 新增:最后一次错误信息 // 新增:最后一次错误信息
private static string lastErrorMessage = string.Empty; private static string lastErrorMessage = string.Empty;
// 新增:是否已初始化崩溃监听器 // 新增:是否已初始化崩溃监听器
private static bool crashListenersInitialized = false; private static bool crashListenersInitialized;
public App() public App()
{ {
@@ -61,8 +68,8 @@ namespace Ink_Canvas
// 启动时优先同步设置,确保CrashAction为最新 // 启动时优先同步设置,确保CrashAction为最新
SyncCrashActionFromSettings(); SyncCrashActionFromSettings();
this.Startup += new StartupEventHandler(App_Startup); Startup += App_Startup;
this.DispatcherUnhandledException += App_DispatcherUnhandledException; DispatcherUnhandledException += App_DispatcherUnhandledException;
StartHeartbeatMonitor(); StartHeartbeatMonitor();
// 新增:初始化全局异常和进程结束处理 // 新增:初始化全局异常和进程结束处理
@@ -73,7 +80,7 @@ namespace Ink_Canvas
{ {
StartWatchdogIfNeeded(); StartWatchdogIfNeeded();
} }
this.Exit += App_Exit; // 注册退出事件 Exit += App_Exit; // 注册退出事件
} }
// 新增:配置TLS协议以支持Windows 7 // 新增:配置TLS协议以支持Windows 7
@@ -87,7 +94,7 @@ namespace Ink_Canvas
if (isWindows7) if (isWindows7)
{ {
LogHelper.WriteLogToFile("检测到Windows 7系统,配置TLS协议支持", LogHelper.LogType.Info); LogHelper.WriteLogToFile("检测到Windows 7系统,配置TLS协议支持");
// 启用所有TLS版本以支持Windows 7 // 启用所有TLS版本以支持Windows 7
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
@@ -97,12 +104,12 @@ namespace Ink_Canvas
ServicePointManager.Expect100Continue = false; ServicePointManager.Expect100Continue = false;
ServicePointManager.UseNagleAlgorithm = false; ServicePointManager.UseNagleAlgorithm = false;
LogHelper.WriteLogToFile("TLS协议配置完成,已启用TLS 1.2/1.1/1.0支持", LogHelper.LogType.Info); LogHelper.WriteLogToFile("TLS协议配置完成,已启用TLS 1.2/1.1/1.0支持");
} }
else else
{ {
// 对于更新的Windows版本,不进行任何TLS配置,使用系统默认设置 // 对于更新的Windows版本,不进行任何TLS配置,使用系统默认设置
LogHelper.WriteLogToFile($"检测到Windows版本: {osVersion.VersionString},使用系统默认TLS配置", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"检测到Windows版本: {osVersion.VersionString},使用系统默认TLS配置");
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -151,7 +158,7 @@ namespace Ink_Canvas
} }
crashListenersInitialized = true; crashListenersInitialized = true;
LogHelper.WriteLogToFile("已初始化崩溃监听器", LogHelper.LogType.Info); LogHelper.WriteLogToFile("已初始化崩溃监听器");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -204,7 +211,7 @@ namespace Ink_Canvas
var startMethod = watcherType.GetMethod("Start"); var startMethod = watcherType.GetMethod("Start");
startMethod.Invoke(watcher, null); startMethod.Invoke(watcher, null);
LogHelper.WriteLogToFile("已成功启动WMI进程监控", LogHelper.LogType.Info); LogHelper.WriteLogToFile("已成功启动WMI进程监控");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -346,7 +353,7 @@ namespace Ink_Canvas
string logFileName = Path.Combine(crashLogFile, $"crash_{DateTime.Now:yyyyMMdd}.log"); string logFileName = Path.Combine(crashLogFile, $"crash_{DateTime.Now:yyyyMMdd}.log");
// 收集系统状态信息 // 收集系统状态信息
string memoryUsage = (Process.GetCurrentProcess().WorkingSet64 / (1024 * 1024)).ToString() + " MB"; string memoryUsage = (Process.GetCurrentProcess().WorkingSet64 / (1024 * 1024)) + " MB";
string cpuTime = Process.GetCurrentProcess().TotalProcessorTime.ToString(); string cpuTime = Process.GetCurrentProcess().TotalProcessorTime.ToString();
string processUptime = (DateTime.Now - Process.GetCurrentProcess().StartTime).ToString(); string processUptime = (DateTime.Now - Process.GetCurrentProcess().StartTime).ToString();
@@ -377,7 +384,7 @@ namespace Ink_Canvas
if (File.Exists(settingsPath)) if (File.Exists(settingsPath))
{ {
var json = File.ReadAllText(settingsPath); var json = File.ReadAllText(settingsPath);
dynamic obj = Newtonsoft.Json.JsonConvert.DeserializeObject(json); dynamic obj = JsonConvert.DeserializeObject(json);
int crashAction = 0; int crashAction = 0;
try { crashAction = (int)(obj["startup"]["crashAction"] ?? 0); } catch { } try { crashAction = (int)(obj["startup"]["crashAction"] ?? 0); } catch { }
CrashAction = (CrashActionType)crashAction; CrashAction = (CrashActionType)crashAction;
@@ -391,9 +398,9 @@ namespace Ink_Canvas
catch { } catch { }
} }
private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{ {
Ink_Canvas.MainWindow.ShowNewMessage("抱歉,出现未预期的异常,可能导致 InkCanvasForClass 运行不稳定。\n建议保存墨迹后重启应用。", true); Ink_Canvas.MainWindow.ShowNewMessage("抱歉,出现未预期的异常,可能导致 InkCanvasForClass 运行不稳定。\n建议保存墨迹后重启应用。");
LogHelper.NewLog(e.Exception.ToString()); LogHelper.NewLog(e.Exception.ToString());
// 新增:记录到崩溃日志 // 新增:记录到崩溃日志
@@ -415,8 +422,8 @@ namespace Ink_Canvas
} }
try try
{ {
string exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; string exePath = Process.GetCurrentProcess().MainModule.FileName;
System.Diagnostics.Process.Start(exePath); Process.Start(exePath, "-m");
} }
catch { } catch { }
Environment.Exit(1); Environment.Exit(1);
@@ -430,7 +437,17 @@ namespace Ink_Canvas
{ {
/*if (!StoreHelper.IsStoreApp) */RootPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; /*if (!StoreHelper.IsStoreApp) */RootPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
LogHelper.NewLog(string.Format("Ink Canvas Starting (Version: {0})", Assembly.GetExecutingAssembly().GetName().Version.ToString())); LogHelper.NewLog(string.Format("Ink Canvas Starting (Version: {0})", Assembly.GetExecutingAssembly().GetName().Version));
// 在应用启动时自动释放IACore相关DLL
try
{
Helpers.IACoreDllExtractor.ExtractIACoreDlls();
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"释放IACore DLL时出错: {ex.Message}", LogHelper.LogType.Error);
}
// 记录应用启动(设备标识符) // 记录应用启动(设备标识符)
DeviceIdentifier.RecordAppLaunch(); DeviceIdentifier.RecordAppLaunch();
@@ -439,7 +456,7 @@ namespace Ink_Canvas
LogHelper.WriteLogToFile($"App | 更新优先级: {DeviceIdentifier.GetUpdatePriority()}"); LogHelper.WriteLogToFile($"App | 更新优先级: {DeviceIdentifier.GetUpdatePriority()}");
bool ret; bool ret;
mutex = new System.Threading.Mutex(true, "InkCanvasForClass", out ret); mutex = new Mutex(true, "InkCanvasForClass", out ret);
if (!ret && !e.Args.Contains("-m")) //-m multiple if (!ret && !e.Args.Contains("-m")) //-m multiple
{ {
@@ -490,7 +507,7 @@ namespace Ink_Canvas
try try
{ {
using (Microsoft.Win32.RegistryKey baseKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(regPath)) using (RegistryKey baseKey = Registry.CurrentUser.OpenSubKey(regPath))
{ {
if (baseKey == null) if (baseKey == null)
{ {
@@ -498,12 +515,12 @@ namespace Ink_Canvas
// 尝试创建路径 // 尝试创建路径
try try
{ {
using (Microsoft.Win32.RegistryKey createKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(regPath, true)) using (RegistryKey createKey = Registry.CurrentUser.CreateSubKey(regPath, true))
{ {
if (createKey != null) if (createKey != null)
{ {
createKey.SetValue("DisableProtectedView", 1, Microsoft.Win32.RegistryValueKind.DWord); createKey.SetValue("DisableProtectedView", 1, RegistryValueKind.DWord);
LogHelper.WriteLogToFile($"创建并设置注册表路径: {regPath}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"创建并设置注册表路径: {regPath}");
} }
} }
} }
@@ -528,11 +545,11 @@ namespace Ink_Canvas
LogHelper.WriteLogToFile($"创建备份文件: {backupFile}"); LogHelper.WriteLogToFile($"创建备份文件: {backupFile}");
// 使用UTF8编码写入注册表文件 // 使用UTF8编码写入注册表文件
using (StreamWriter sw = new StreamWriter(backupFile, false, System.Text.Encoding.UTF8)) using (StreamWriter sw = new StreamWriter(backupFile, false, Encoding.UTF8))
{ {
sw.WriteLine("Windows Registry Editor Version 5.00\n"); sw.WriteLine("Windows Registry Editor Version 5.00\n");
sw.WriteLine(); sw.WriteLine();
sw.WriteLine($"[{Microsoft.Win32.Registry.CurrentUser.Name}\\{regPath}]"); sw.WriteLine($"[{Registry.CurrentUser.Name}\\{regPath}]");
foreach (string valueName in baseKey.GetValueNames()) foreach (string valueName in baseKey.GetValueNames())
{ {
@@ -542,13 +559,13 @@ namespace Ink_Canvas
} }
} }
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(regPath, true)) using (RegistryKey key = Registry.CurrentUser.CreateSubKey(regPath, true))
{ {
// 仅在值不存在或不等于1时更新 // 仅在值不存在或不等于1时更新
object currentValue = key.GetValue("DisableProtectedView"); object currentValue = key.GetValue("DisableProtectedView");
if (currentValue == null || (int)currentValue != 1) if (currentValue == null || (int)currentValue != 1)
{ {
key.SetValue("DisableProtectedView", 1, Microsoft.Win32.RegistryValueKind.DWord); key.SetValue("DisableProtectedView", 1, RegistryValueKind.DWord);
LogHelper.WriteLogToFile($"Office {version} 注册表值已设置: DisableProtectedView = 1"); LogHelper.WriteLogToFile($"Office {version} 注册表值已设置: DisableProtectedView = 1");
} }
else else
@@ -561,7 +578,6 @@ namespace Ink_Canvas
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"处理Office版本 {version} 时出错: {ex.Message}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"处理Office版本 {version} 时出错: {ex.Message}", LogHelper.LogType.Error);
continue;
} }
} }
@@ -581,21 +597,21 @@ namespace Ink_Canvas
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"未知错误: {ex.GetType().FullName} - {ex.Message}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"未知错误: {ex.GetType().FullName} - {ex.Message}", LogHelper.LogType.Error);
LogHelper.WriteLogToFile(ex.StackTrace, LogHelper.LogType.Info); LogHelper.WriteLogToFile(ex.StackTrace);
} }
} }
private void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e) private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{ {
try try
{ {
if (System.Windows.Forms.SystemInformation.MouseWheelScrollLines == -1) if (SystemInformation.MouseWheelScrollLines == -1)
e.Handled = false; e.Handled = false;
else else
try try
{ {
ScrollViewerEx SenderScrollViewer = (ScrollViewerEx)sender; ScrollViewerEx SenderScrollViewer = (ScrollViewerEx)sender;
SenderScrollViewer.ScrollToVerticalOffset(SenderScrollViewer.VerticalOffset - e.Delta * 10 * System.Windows.Forms.SystemInformation.MouseWheelScrollLines / (double)120); SenderScrollViewer.ScrollToVerticalOffset(SenderScrollViewer.VerticalOffset - e.Delta * 10 * SystemInformation.MouseWheelScrollLines / (double)120);
e.Handled = true; e.Handled = true;
} }
catch { } catch { }
@@ -638,7 +654,7 @@ namespace Ink_Canvas
try try
{ {
string exePath = Process.GetCurrentProcess().MainModule.FileName; string exePath = Process.GetCurrentProcess().MainModule.FileName;
Process.Start(exePath); Process.Start(exePath, "-m");
} }
catch { } catch { }
Environment.Exit(1); Environment.Exit(1);
@@ -698,7 +714,7 @@ namespace Ink_Canvas
Environment.Exit(1); Environment.Exit(1);
} }
string exePath = Process.GetCurrentProcess().MainModule.FileName; string exePath = Process.GetCurrentProcess().MainModule.FileName;
Process.Start(exePath); Process.Start(exePath, "-m");
} }
// CrashActionType.NoAction 时不重启,直接退出 // CrashActionType.NoAction 时不重启,直接退出
} }
@@ -758,60 +774,60 @@ namespace Ink_Canvas
{ {
// 检查多个可能的注册表路径 // 检查多个可能的注册表路径
// 1. 检查传统的Office版本 // 1. 检查传统的Office版本
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office")) using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office"))
{ {
if (key != null && key.GetSubKeyNames().Any(name => name.Contains(".0"))) if (key != null && key.GetSubKeyNames().Any(name => name.Contains(".0")))
{ {
LogHelper.WriteLogToFile("检测到传统Office安装", LogHelper.LogType.Info); LogHelper.WriteLogToFile("检测到传统Office安装");
return true; return true;
} }
} }
// 2. 检查64位注册表中的Office // 2. 检查64位注册表中的Office
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\Microsoft\\Office")) using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\Microsoft\\Office"))
{ {
if (key != null && key.GetSubKeyNames().Any(name => name.Contains(".0"))) if (key != null && key.GetSubKeyNames().Any(name => name.Contains(".0")))
{ {
LogHelper.WriteLogToFile("检测到64位注册表中的Office安装", LogHelper.LogType.Info); LogHelper.WriteLogToFile("检测到64位注册表中的Office安装");
return true; return true;
} }
} }
// 3. 检查Office 365/Click-to-Run安装 // 3. 检查Office 365/Click-to-Run安装
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun")) using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun"))
{ {
if (key != null) if (key != null)
{ {
LogHelper.WriteLogToFile("检测到Office 365 Click-to-Run", LogHelper.LogType.Info); LogHelper.WriteLogToFile("检测到Office 365 Click-to-Run");
return true; return true;
} }
} }
// 4. 检查Office 365部署配置 // 4. 检查Office 365部署配置
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\15.0\\ClickToRun")) using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\15.0\\ClickToRun"))
{ {
if (key != null) if (key != null)
{ {
LogHelper.WriteLogToFile("检测到Office 365 (15.0)", LogHelper.LogType.Info); LogHelper.WriteLogToFile("检测到Office 365 (15.0)");
return true; return true;
} }
} }
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\16.0\\ClickToRun")) using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\16.0\\ClickToRun"))
{ {
if (key != null) if (key != null)
{ {
LogHelper.WriteLogToFile("检测到Office 365 (16.0)", LogHelper.LogType.Info); LogHelper.WriteLogToFile("检测到Office 365 (16.0)");
return true; return true;
} }
} }
// 5. 检查Office 365零售订阅信息 // 5. 检查Office 365零售订阅信息
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun\\Configuration")) using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun\\Configuration"))
{ {
if (key != null) if (key != null)
{ {
LogHelper.WriteLogToFile("检测到Office 365配置", LogHelper.LogType.Info); LogHelper.WriteLogToFile("检测到Office 365配置");
return true; return true;
} }
} }
@@ -833,7 +849,7 @@ namespace Ink_Canvas
{ {
const string message = "需要管理员权限才能完成此操作\n请以管理员身份重新启动应用程序"; const string message = "需要管理员权限才能完成此操作\n请以管理员身份重新启动应用程序";
LogHelper.WriteLogToFile(message, LogHelper.LogType.Error); LogHelper.WriteLogToFile(message, LogHelper.LogType.Error);
System.Windows.MessageBox.Show(message, "权限错误", MessageBoxButton.OK, MessageBoxImage.Error); MessageBox.Show(message, "权限错误", MessageBoxButton.OK, MessageBoxImage.Error);
} }
/// <summary> /// <summary>
@@ -1058,11 +1074,11 @@ namespace Ink_Canvas
LogHelper.WriteLogToFile($"创建Office 365 {app}备份文件: {backupFile}"); LogHelper.WriteLogToFile($"创建Office 365 {app}备份文件: {backupFile}");
// 使用UTF8编码写入注册表文件 // 使用UTF8编码写入注册表文件
using (StreamWriter sw = new StreamWriter(backupFile, false, System.Text.Encoding.UTF8)) using (StreamWriter sw = new StreamWriter(backupFile, false, Encoding.UTF8))
{ {
sw.WriteLine("Windows Registry Editor Version 5.00\n"); sw.WriteLine("Windows Registry Editor Version 5.00\n");
sw.WriteLine(); sw.WriteLine();
sw.WriteLine($"[{Microsoft.Win32.Registry.CurrentUser.Name}\\{regPath}]"); sw.WriteLine($"[{Registry.CurrentUser.Name}\\{regPath}]");
foreach (string valueName in baseKey.GetValueNames()) foreach (string valueName in baseKey.GetValueNames())
{ {
@@ -1114,11 +1130,11 @@ namespace Ink_Canvas
LogHelper.WriteLogToFile($"创建信任中心备份文件: {backupFile}"); LogHelper.WriteLogToFile($"创建信任中心备份文件: {backupFile}");
// 使用UTF8编码写入注册表文件 // 使用UTF8编码写入注册表文件
using (StreamWriter sw = new StreamWriter(backupFile, false, System.Text.Encoding.UTF8)) using (StreamWriter sw = new StreamWriter(backupFile, false, Encoding.UTF8))
{ {
sw.WriteLine("Windows Registry Editor Version 5.00\n"); sw.WriteLine("Windows Registry Editor Version 5.00\n");
sw.WriteLine(); sw.WriteLine();
sw.WriteLine($"[{Microsoft.Win32.Registry.CurrentUser.Name}\\{trustCenterPath}]"); sw.WriteLine($"[{Registry.CurrentUser.Name}\\{trustCenterPath}]");
foreach (string valueName in baseKey.GetValueNames()) foreach (string valueName in baseKey.GetValueNames())
{ {
@@ -1158,11 +1174,11 @@ namespace Ink_Canvas
LogHelper.WriteLogToFile($"创建策略备份文件: {backupFile}"); LogHelper.WriteLogToFile($"创建策略备份文件: {backupFile}");
// 使用UTF8编码写入注册表文件 // 使用UTF8编码写入注册表文件
using (StreamWriter sw = new StreamWriter(backupFile, false, System.Text.Encoding.UTF8)) using (StreamWriter sw = new StreamWriter(backupFile, false, Encoding.UTF8))
{ {
sw.WriteLine("Windows Registry Editor Version 5.00\n"); sw.WriteLine("Windows Registry Editor Version 5.00\n");
sw.WriteLine(); sw.WriteLine();
sw.WriteLine($"[{Microsoft.Win32.Registry.CurrentUser.Name}\\{policyPath}]"); sw.WriteLine($"[{Registry.CurrentUser.Name}\\{policyPath}]");
foreach (string valueName in baseKey.GetValueNames()) foreach (string valueName in baseKey.GetValueNames())
{ {
+2 -2
View File
@@ -49,5 +49,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.7.4.0")] [assembly: AssemblyVersion("1.7.5.0")]
[assembly: AssemblyFileVersion("1.7.4.0")] [assembly: AssemblyFileVersion("1.7.5.0")]
+1 -1
View File
@@ -1,3 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Costura /> <Costura ExcludeAssemblies="IACore|IALoader|IAWinFX" />
</Weavers> </Weavers>
+151 -163
View File
@@ -1,16 +1,21 @@
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Net.Http; using System.IO.Compression;
using System.Threading.Tasks;
using System.Reflection;
using System.Windows;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Windows.Controls; using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Text; using System.Text;
using System.Collections.Generic; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
@@ -21,7 +26,7 @@ namespace Ink_Canvas.Helpers
// 定义超时时间为10秒 // 定义超时时间为10秒
private static readonly TimeSpan RequestTimeout = TimeSpan.FromSeconds(10); private static readonly TimeSpan RequestTimeout = TimeSpan.FromSeconds(10);
private static readonly string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate"); private static readonly string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
private static string statusFilePath = null; private static string statusFilePath;
// 线路组结构体(包含版本、下载、日志地址) // 线路组结构体(包含版本、下载、日志地址)
public class UpdateLineGroup public class UpdateLineGroup
@@ -209,7 +214,7 @@ namespace Ink_Canvas.Helpers
if (zhiJiaoGroup != null) if (zhiJiaoGroup != null)
{ {
orderedGroups.Insert(0, zhiJiaoGroup); orderedGroups.Insert(0, zhiJiaoGroup);
LogHelper.WriteLogToFile($"AutoUpdate | 智教联盟线路组已插入到首位"); LogHelper.WriteLogToFile("AutoUpdate | 智教联盟线路组已插入到首位");
} }
// 将"inkeys"线路组插入到第二位(如果存在) // 将"inkeys"线路组插入到第二位(如果存在)
@@ -217,7 +222,7 @@ namespace Ink_Canvas.Helpers
if (inkeysGroup != null) if (inkeysGroup != null)
{ {
orderedGroups.Insert(1, inkeysGroup); orderedGroups.Insert(1, inkeysGroup);
LogHelper.WriteLogToFile($"AutoUpdate | inkeys线路组已插入到第二位"); LogHelper.WriteLogToFile("AutoUpdate | inkeys线路组已插入到第二位");
} }
if (orderedGroups.Count > 0) if (orderedGroups.Count > 0)
@@ -278,7 +283,7 @@ namespace Ink_Canvas.Helpers
// 如果内容包含HTML(可能是GitHub页面而不是原始内容),尝试提取版本号 // 如果内容包含HTML(可能是GitHub页面而不是原始内容),尝试提取版本号
if (content.Contains("<html") || content.Contains("<!DOCTYPE")) if (content.Contains("<html") || content.Contains("<!DOCTYPE"))
{ {
LogHelper.WriteLogToFile($"AutoUpdate | 收到HTML内容而不是原始版本号 - 尝试提取版本"); LogHelper.WriteLogToFile("AutoUpdate | 收到HTML内容而不是原始版本号 - 尝试提取版本");
int startPos = content.IndexOf("<table"); int startPos = content.IndexOf("<table");
if (startPos > 0) if (startPos > 0)
{ {
@@ -286,7 +291,7 @@ namespace Ink_Canvas.Helpers
if (endPos > startPos) if (endPos > startPos)
{ {
string tableContent = content.Substring(startPos, endPos - startPos); string tableContent = content.Substring(startPos, endPos - startPos);
var match = System.Text.RegularExpressions.Regex.Match(tableContent, @"(\d+\.\d+\.\d+(\.\d+)?)"); var match = Regex.Match(tableContent, @"(\d+\.\d+\.\d+(\.\d+)?)");
if (match.Success) if (match.Success)
{ {
content = match.Groups[1].Value; content = match.Groups[1].Value;
@@ -294,7 +299,7 @@ namespace Ink_Canvas.Helpers
} }
else else
{ {
LogHelper.WriteLogToFile($"AutoUpdate | 无法从HTML内容提取版本"); LogHelper.WriteLogToFile("AutoUpdate | 无法从HTML内容提取版本");
return null; return null;
} }
} }
@@ -321,77 +326,75 @@ namespace Ink_Canvas.Helpers
return null; return null;
} }
} }
else
{
// 其他Windows版本使用标准配置
using (HttpClient client = new HttpClient())
{
try
{
client.Timeout = RequestTimeout;
LogHelper.WriteLogToFile($"AutoUpdate | 发送HTTP请求到: {fileUrl}");
var downloadTask = client.GetAsync(fileUrl);
var timeoutTask = Task.Delay(RequestTimeout);
var completedTask = await Task.WhenAny(downloadTask, timeoutTask);
if (completedTask == timeoutTask)
{
LogHelper.WriteLogToFile($"AutoUpdate | 请求超时 ({RequestTimeout.TotalSeconds}秒)", LogHelper.LogType.Error);
return null;
}
HttpResponseMessage response = await downloadTask;
LogHelper.WriteLogToFile($"AutoUpdate | HTTP响应状态: {response.StatusCode}");
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync(); // 其他Windows版本使用标准配置
content = content.Trim(); using (HttpClient client = new HttpClient())
{
try
{
client.Timeout = RequestTimeout;
LogHelper.WriteLogToFile($"AutoUpdate | 发送HTTP请求到: {fileUrl}");
// 如果内容包含HTML(可能是GitHub页面而不是原始内容),尝试提取版本号 var downloadTask = client.GetAsync(fileUrl);
if (content.Contains("<html") || content.Contains("<!DOCTYPE")) var timeoutTask = Task.Delay(RequestTimeout);
var completedTask = await Task.WhenAny(downloadTask, timeoutTask);
if (completedTask == timeoutTask)
{
LogHelper.WriteLogToFile($"AutoUpdate | 请求超时 ({RequestTimeout.TotalSeconds}秒)", LogHelper.LogType.Error);
return null;
}
HttpResponseMessage response = await downloadTask;
LogHelper.WriteLogToFile($"AutoUpdate | HTTP响应状态: {response.StatusCode}");
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync();
content = content.Trim();
// 如果内容包含HTML(可能是GitHub页面而不是原始内容),尝试提取版本号
if (content.Contains("<html") || content.Contains("<!DOCTYPE"))
{
LogHelper.WriteLogToFile("AutoUpdate | 收到HTML内容而不是原始版本号 - 尝试提取版本");
int startPos = content.IndexOf("<table");
if (startPos > 0)
{ {
LogHelper.WriteLogToFile($"AutoUpdate | 收到HTML内容而不是原始版本号 - 尝试提取版本"); int endPos = content.IndexOf("</table>", startPos);
int startPos = content.IndexOf("<table"); if (endPos > startPos)
if (startPos > 0)
{ {
int endPos = content.IndexOf("</table>", startPos); string tableContent = content.Substring(startPos, endPos - startPos);
if (endPos > startPos) var match = Regex.Match(tableContent, @"(\d+\.\d+\.\d+(\.\d+)?)");
if (match.Success)
{ {
string tableContent = content.Substring(startPos, endPos - startPos); content = match.Groups[1].Value;
var match = System.Text.RegularExpressions.Regex.Match(tableContent, @"(\d+\.\d+\.\d+(\.\d+)?)"); LogHelper.WriteLogToFile($"AutoUpdate | 从HTML提取版本: {content}");
if (match.Success) }
{ else
content = match.Groups[1].Value; {
LogHelper.WriteLogToFile($"AutoUpdate | 从HTML提取版本: {content}"); LogHelper.WriteLogToFile("AutoUpdate | 无法从HTML内容提取版本");
} return null;
else
{
LogHelper.WriteLogToFile($"AutoUpdate | 无法从HTML内容提取版本");
return null;
}
} }
} }
} }
}
LogHelper.WriteLogToFile($"AutoUpdate | 响应内容: {content}"); LogHelper.WriteLogToFile($"AutoUpdate | 响应内容: {content}");
return content; return content;
}
catch (HttpRequestException ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | HTTP请求错误: {ex.Message}", LogHelper.LogType.Error);
}
catch (TaskCanceledException ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | 请求超时: {ex.Message}", LogHelper.LogType.Error);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | 错误: {ex.Message}", LogHelper.LogType.Error);
}
return null;
} }
catch (HttpRequestException ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | HTTP请求错误: {ex.Message}", LogHelper.LogType.Error);
}
catch (TaskCanceledException ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | 请求超时: {ex.Message}", LogHelper.LogType.Error);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | 错误: {ex.Message}", LogHelper.LogType.Error);
}
return null;
} }
} }
@@ -484,7 +487,7 @@ namespace Ink_Canvas.Helpers
LogHelper.WriteLogToFile($"AutoUpdate | 本地版本: {localVersion}"); LogHelper.WriteLogToFile($"AutoUpdate | 本地版本: {localVersion}");
LogHelper.WriteLogToFile($"AutoUpdate | 设备ID: {DeviceIdentifier.GetDeviceId()}"); LogHelper.WriteLogToFile($"AutoUpdate | 设备ID: {DeviceIdentifier.GetDeviceId()}");
LogHelper.WriteLogToFile($"AutoUpdate | 更新优先级: {DeviceIdentifier.GetUpdatePriority()}"); LogHelper.WriteLogToFile($"AutoUpdate | 更新优先级: {DeviceIdentifier.GetUpdatePriority()}");
LogHelper.WriteLogToFile($"AutoUpdate | 优先通过GitHub Releases API检测..."); LogHelper.WriteLogToFile("AutoUpdate | 优先通过GitHub Releases API检测...");
// 1. 优先通过GitHub Releases API获取 // 1. 优先通过GitHub Releases API获取
var (apiVersion, _, apiReleaseNotes, apiReleaseTime) = await GetLatestGithubRelease(channel); var (apiVersion, _, apiReleaseNotes, apiReleaseTime) = await GetLatestGithubRelease(channel);
@@ -518,7 +521,7 @@ namespace Ink_Canvas.Helpers
} }
else else
{ {
LogHelper.WriteLogToFile($"AutoUpdate | 版本修复模式,跳过分级策略检查"); LogHelper.WriteLogToFile("AutoUpdate | 版本修复模式,跳过分级策略检查");
} }
LogHelper.WriteLogToFile($"AutoUpdate | 根据用户优先级,推送更新 {apiVersion}"); LogHelper.WriteLogToFile($"AutoUpdate | 根据用户优先级,推送更新 {apiVersion}");
@@ -528,13 +531,13 @@ namespace Ink_Canvas.Helpers
} }
else else
{ {
LogHelper.WriteLogToFile($"AutoUpdate | 当前版本已是最新 (GitHub Releases API)"); LogHelper.WriteLogToFile("AutoUpdate | 当前版本已是最新 (GitHub Releases API)");
var availableGroup = (await GetAvailableLineGroupsOrdered(channel)).FirstOrDefault(); var availableGroup = (await GetAvailableLineGroupsOrdered(channel)).FirstOrDefault();
return (null, availableGroup, apiReleaseNotes); return (null, availableGroup, apiReleaseNotes);
} }
} }
// 2. 回退到原有txt方案 // 2. 回退到原有txt方案
LogHelper.WriteLogToFile($"AutoUpdate | GitHub Releases API获取失败,回退到txt方案..."); LogHelper.WriteLogToFile("AutoUpdate | GitHub Releases API获取失败,回退到txt方案...");
var availableGroups = await GetAvailableLineGroupsOrdered(channel); var availableGroups = await GetAvailableLineGroupsOrdered(channel);
if (availableGroups.Count == 0) if (availableGroups.Count == 0)
{ {
@@ -570,22 +573,18 @@ namespace Ink_Canvas.Helpers
} }
else else
{ {
LogHelper.WriteLogToFile($"AutoUpdate | 版本修复模式,跳过分级策略检查"); LogHelper.WriteLogToFile("AutoUpdate | 版本修复模式,跳过分级策略检查");
} }
LogHelper.WriteLogToFile($"AutoUpdate | 根据用户优先级,推送更新 {remoteVersion}"); LogHelper.WriteLogToFile($"AutoUpdate | 根据用户优先级,推送更新 {remoteVersion}");
return (remoteVersion, group, null); return (remoteVersion, group, null);
} }
else
{ LogHelper.WriteLogToFile("AutoUpdate | 当前版本已是最新");
LogHelper.WriteLogToFile($"AutoUpdate | 当前版本已是最新"); return (null, group, null);
return (null, group, null);
}
}
else
{
LogHelper.WriteLogToFile($"AutoUpdate | 线路组 {group.GroupName} 获取版本失败,尝试下一个线路组", LogHelper.LogType.Warning);
} }
LogHelper.WriteLogToFile($"AutoUpdate | 线路组 {group.GroupName} 获取版本失败,尝试下一个线路组", LogHelper.LogType.Warning);
} }
LogHelper.WriteLogToFile("AutoUpdate | 所有线路组均无法获取版本信息", LogHelper.LogType.Error); LogHelper.WriteLogToFile("AutoUpdate | 所有线路组均无法获取版本信息", LogHelper.LogType.Error);
return (null, null, null); return (null, null, null);
@@ -614,7 +613,7 @@ namespace Ink_Canvas.Helpers
client.Timeout = RequestTimeout; client.Timeout = RequestTimeout;
var resp = await client.GetAsync(url); var resp = await client.GetAsync(url);
// 优先取Location头 // 优先取Location头
if (resp.StatusCode == System.Net.HttpStatusCode.Found || resp.StatusCode == System.Net.HttpStatusCode.Redirect || resp.StatusCode == System.Net.HttpStatusCode.MovedPermanently) if (resp.StatusCode == HttpStatusCode.Found || resp.StatusCode == HttpStatusCode.Redirect || resp.StatusCode == HttpStatusCode.MovedPermanently)
{ {
if (resp.Headers.Location != null) if (resp.Headers.Location != null)
{ {
@@ -675,12 +674,12 @@ namespace Ink_Canvas.Helpers
if (zhiJiaoGroup != null) if (zhiJiaoGroup != null)
{ {
priorityGroups.Add(zhiJiaoGroup); priorityGroups.Add(zhiJiaoGroup);
LogHelper.WriteLogToFile($"AutoUpdate | 下载时优先尝试智教联盟线路组"); LogHelper.WriteLogToFile("AutoUpdate | 下载时优先尝试智教联盟线路组");
} }
if (inkeysGroup != null) if (inkeysGroup != null)
{ {
priorityGroups.Add(inkeysGroup); priorityGroups.Add(inkeysGroup);
LogHelper.WriteLogToFile($"AutoUpdate | 下载时优先尝试inkeys线路组"); LogHelper.WriteLogToFile("AutoUpdate | 下载时优先尝试inkeys线路组");
} }
groups = priorityGroups.Concat(groups.Where(g => g.GroupName != "智教联盟" && g.GroupName != "inkeys")).ToList(); groups = priorityGroups.Concat(groups.Where(g => g.GroupName != "智教联盟" && g.GroupName != "inkeys")).ToList();
} }
@@ -696,7 +695,7 @@ namespace Ink_Canvas.Helpers
var realUrl = await GetZhijiaoRealDownloadUrl(url); var realUrl = await GetZhijiaoRealDownloadUrl(url);
if (string.IsNullOrEmpty(realUrl)) if (string.IsNullOrEmpty(realUrl))
{ {
LogHelper.WriteLogToFile($"AutoUpdate | 智教联盟真实下载地址获取失败,跳过", LogHelper.LogType.Warning); LogHelper.WriteLogToFile("AutoUpdate | 智教联盟真实下载地址获取失败,跳过", LogHelper.LogType.Warning);
progressCallback?.Invoke(0, "智教联盟真实下载地址获取失败,跳过"); progressCallback?.Invoke(0, "智教联盟真实下载地址获取失败,跳过");
continue; continue;
} }
@@ -719,10 +718,8 @@ namespace Ink_Canvas.Helpers
progressCallback?.Invoke(100, "下载完成"); progressCallback?.Invoke(100, "下载完成");
return true; return true;
} }
else
{ LogHelper.WriteLogToFile($"AutoUpdate | 线路组 {group.GroupName} 下载失败,尝试下一个线路组", LogHelper.LogType.Warning);
LogHelper.WriteLogToFile($"AutoUpdate | 线路组 {group.GroupName} 下载失败,尝试下一个线路组", LogHelper.LogType.Warning);
}
} }
LogHelper.WriteLogToFile("AutoUpdate | 所有线路组下载均失败", LogHelper.LogType.Error); LogHelper.WriteLogToFile("AutoUpdate | 所有线路组下载均失败", LogHelper.LogType.Error);
@@ -749,7 +746,7 @@ namespace Ink_Canvas.Helpers
LogHelper.WriteLogToFile($"AutoUpdate | 正在尝试多线程下载: {fileUrl}"); LogHelper.WriteLogToFile($"AutoUpdate | 正在尝试多线程下载: {fileUrl}");
int maxRetry = 3; int maxRetry = 3;
// 降低并发数,减少网络压力 // 降低并发数,减少网络压力
int[] threadOptions = new int[] { 32, 16, 8, 4, 1 }; int[] threadOptions = { 32, 16, 8, 4, 1 };
// 检查服务器是否支持Range分块下载 // 检查服务器是否支持Range分块下载
bool supportRange = false; bool supportRange = false;
@@ -760,9 +757,9 @@ namespace Ink_Canvas.Helpers
{ {
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"); client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
var req = new HttpRequestMessage(HttpMethod.Head, fileUrl); var req = new HttpRequestMessage(HttpMethod.Head, fileUrl);
req.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(0, 0); req.Headers.Range = new RangeHeaderValue(0, 0);
var resp = await client.SendAsync(req); var resp = await client.SendAsync(req);
if (resp.StatusCode == System.Net.HttpStatusCode.PartialContent) if (resp.StatusCode == HttpStatusCode.PartialContent)
{ {
supportRange = true; supportRange = true;
if (resp.Content.Headers.ContentRange != null && resp.Content.Headers.ContentRange.Length.HasValue) if (resp.Content.Headers.ContentRange != null && resp.Content.Headers.ContentRange.Length.HasValue)
@@ -774,7 +771,7 @@ namespace Ink_Canvas.Helpers
totalSize = resp.Content.Headers.ContentLength.Value; totalSize = resp.Content.Headers.ContentLength.Value;
} }
} }
else if (resp.StatusCode == System.Net.HttpStatusCode.OK) else if (resp.StatusCode == HttpStatusCode.OK)
{ {
supportRange = false; supportRange = false;
if (resp.Content.Headers.ContentLength.HasValue) if (resp.Content.Headers.ContentLength.HasValue)
@@ -791,7 +788,7 @@ namespace Ink_Canvas.Helpers
if (!supportRange) if (!supportRange)
{ {
LogHelper.WriteLogToFile($"AutoUpdate | 服务器不支持分块下载,自动降级为单线程下载"); LogHelper.WriteLogToFile("AutoUpdate | 服务器不支持分块下载,自动降级为单线程下载");
progressCallback?.Invoke(0, "服务器不支持分块下载,自动降级为单线程下载"); progressCallback?.Invoke(0, "服务器不支持分块下载,自动降级为单线程下载");
return await DownloadSingleThread(fileUrl, destinationPath, totalSize, progressCallback); return await DownloadSingleThread(fileUrl, destinationPath, totalSize, progressCallback);
} }
@@ -818,8 +815,8 @@ namespace Ink_Canvas.Helpers
LogHelper.WriteLogToFile($"AutoUpdate | 文件大小: {totalSize}, 分块数: {blockCount}, 分块大小: {blockSize}"); LogHelper.WriteLogToFile($"AutoUpdate | 文件大小: {totalSize}, 分块数: {blockCount}, 分块大小: {blockSize}");
var blockQueue = new System.Collections.Concurrent.ConcurrentQueue<BlockTask>(); var blockQueue = new ConcurrentQueue<BlockTask>();
var finishedBlocks = new System.Collections.Concurrent.ConcurrentDictionary<int, bool>(); var finishedBlocks = new ConcurrentDictionary<int, bool>();
long[] blockDownloaded = new long[blockCount]; long[] blockDownloaded = new long[blockCount];
for (int i = 0; i < blockCount; i++) for (int i = 0; i < blockCount; i++)
@@ -849,7 +846,7 @@ namespace Ink_Canvas.Helpers
{ {
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"); client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
var req = new HttpRequestMessage(HttpMethod.Get, fileUrl); var req = new HttpRequestMessage(HttpMethod.Get, fileUrl);
req.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(block.Start, block.End); req.Headers.Range = new RangeHeaderValue(block.Start, block.End);
// 增加连接超时设置 // 增加连接超时设置
client.Timeout = TimeSpan.FromSeconds(30); client.Timeout = TimeSpan.FromSeconds(30);
@@ -967,16 +964,14 @@ namespace Ink_Canvas.Helpers
if (threadCount == threadOptions.Last()) if (threadCount == threadOptions.Last())
{ {
// 已经是最后一次尝试,降级为单线程 // 已经是最后一次尝试,降级为单线程
LogHelper.WriteLogToFile($"AutoUpdate | 所有多线程尝试失败,降级为单线程下载"); LogHelper.WriteLogToFile("AutoUpdate | 所有多线程尝试失败,降级为单线程下载");
progressCallback?.Invoke(0, "所有多线程尝试失败,降级为单线程下载"); progressCallback?.Invoke(0, "所有多线程尝试失败,降级为单线程下载");
return await DownloadSingleThread(fileUrl, destinationPath, totalSize, progressCallback); return await DownloadSingleThread(fileUrl, destinationPath, totalSize, progressCallback);
} }
else
{ LogHelper.WriteLogToFile($"AutoUpdate | {threadCount}线程下载失败,尝试降级为{threadOptions[Array.IndexOf(threadOptions, threadCount) + 1]}线程");
LogHelper.WriteLogToFile($"AutoUpdate | {threadCount}线程下载失败,尝试降级为{threadOptions[Array.IndexOf(threadOptions, threadCount) + 1]}线程"); progressCallback?.Invoke(0, $"{threadCount}线程下载失败,尝试降级为{threadOptions[Array.IndexOf(threadOptions, threadCount) + 1]}线程");
progressCallback?.Invoke(0, $"{threadCount}线程下载失败,尝试降级为{threadOptions[Array.IndexOf(threadOptions, threadCount) + 1]}线程"); continue;
continue;
}
} }
// 合并所有块 // 合并所有块
@@ -1018,7 +1013,7 @@ namespace Ink_Canvas.Helpers
{ {
try try
{ {
System.IO.Compression.ZipFile.OpenRead(destinationPath).Dispose(); ZipFile.OpenRead(destinationPath).Dispose();
} }
catch catch
{ {
@@ -1086,7 +1081,7 @@ namespace Ink_Canvas.Helpers
} }
progressCallback?.Invoke(100, "单线程下载完成"); progressCallback?.Invoke(100, "单线程下载完成");
LogHelper.WriteLogToFile($"AutoUpdate | 单线程下载完成"); LogHelper.WriteLogToFile("AutoUpdate | 单线程下载完成");
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
@@ -1149,7 +1144,7 @@ namespace Ink_Canvas.Helpers
if (!Directory.Exists(backupDir)) if (!Directory.Exists(backupDir))
{ {
Directory.CreateDirectory(backupDir); Directory.CreateDirectory(backupDir);
LogHelper.WriteLogToFile($"创建备份目录: {backupDir}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"创建备份目录: {backupDir}");
} }
string backupFileName = $"Settings_BeforeUpdate_v{version}_{DateTime.Now:yyyyMMdd_HHmmss}.json"; string backupFileName = $"Settings_BeforeUpdate_v{version}_{DateTime.Now:yyyyMMdd_HHmmss}.json";
@@ -1158,11 +1153,11 @@ namespace Ink_Canvas.Helpers
string settingsJson = JsonConvert.SerializeObject(MainWindow.Settings, Formatting.Indented); string settingsJson = JsonConvert.SerializeObject(MainWindow.Settings, Formatting.Indented);
File.WriteAllText(backupPath, settingsJson); File.WriteAllText(backupPath, settingsJson);
LogHelper.WriteLogToFile($"更新前自动备份设置成功: {backupPath}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"更新前自动备份设置成功: {backupPath}");
} }
else else
{ {
LogHelper.WriteLogToFile("更新前自动备份功能已禁用,跳过备份", LogHelper.LogType.Info); LogHelper.WriteLogToFile("更新前自动备份功能已禁用,跳过备份");
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -1182,7 +1177,7 @@ namespace Ink_Canvas.Helpers
FileInfo fileInfo = new FileInfo(zipFilePath); FileInfo fileInfo = new FileInfo(zipFilePath);
if (fileInfo.Length == 0) if (fileInfo.Length == 0)
{ {
LogHelper.WriteLogToFile($"AutoUpdate | ZIP文件为空,无法继续", LogHelper.LogType.Error); LogHelper.WriteLogToFile("AutoUpdate | ZIP文件为空,无法继续", LogHelper.LogType.Error);
return; return;
} }
LogHelper.WriteLogToFile($"AutoUpdate | ZIP文件大小: {fileInfo.Length} 字节"); LogHelper.WriteLogToFile($"AutoUpdate | ZIP文件大小: {fileInfo.Length} 字节");
@@ -1203,7 +1198,7 @@ namespace Ink_Canvas.Helpers
batchContent.AppendLine("echo Set objShell = CreateObject(\"WScript.Shell\") > \"%temp%\\hideme.vbs\""); 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 objShell.Run \"cmd /c \"\"\" ^& WScript.Arguments(0) ^& \"\"\"\", 0, True >> \"%temp%\\hideme.vbs\"");
batchContent.AppendLine($"echo Wscript.Sleep 100 >> \"%temp%\\hideme.vbs\""); batchContent.AppendLine("echo Wscript.Sleep 100 >> \"%temp%\\hideme.vbs\"");
string updateBatPath = Path.Combine(Path.GetTempPath(), "ICCUpdate_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat"); string updateBatPath = Path.Combine(Path.GetTempPath(), "ICCUpdate_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat");
batchContent.AppendLine($"echo @echo off > \"{updateBatPath}\""); batchContent.AppendLine($"echo @echo off > \"{updateBatPath}\"");
@@ -1283,7 +1278,7 @@ namespace Ink_Canvas.Helpers
batchContent.AppendLine("exit"); batchContent.AppendLine("exit");
File.WriteAllText(batchFilePath, batchContent.ToString()); File.WriteAllText(batchFilePath, batchContent.ToString());
LogHelper.WriteLogToFile($"AutoUpdate | 创建更新批处理文件完成"); LogHelper.WriteLogToFile("AutoUpdate | 创建更新批处理文件完成");
Process.Start(new ProcessStartInfo Process.Start(new ProcessStartInfo
{ {
@@ -1293,7 +1288,7 @@ namespace Ink_Canvas.Helpers
WindowStyle = ProcessWindowStyle.Hidden WindowStyle = ProcessWindowStyle.Hidden
}); });
LogHelper.WriteLogToFile($"AutoUpdate | 启动更新批处理进程(隐藏窗口)"); LogHelper.WriteLogToFile("AutoUpdate | 启动更新批处理进程(隐藏窗口)");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -1356,43 +1351,41 @@ namespace Ink_Canvas.Helpers
return null; return null;
} }
} }
else
// 其他Windows版本使用标准配置
using (HttpClient client = new HttpClient())
{ {
// 其他Windows版本使用标准配置 try
using (HttpClient client = new HttpClient())
{ {
try client.Timeout = RequestTimeout;
LogHelper.WriteLogToFile($"AutoUpdate | 发送HTTP请求到: {fileUrl}");
var downloadTask = client.GetAsync(fileUrl);
var timeoutTask = Task.Delay(RequestTimeout);
var completedTask = await Task.WhenAny(downloadTask, timeoutTask);
if (completedTask == timeoutTask)
{ {
client.Timeout = RequestTimeout; LogHelper.WriteLogToFile($"AutoUpdate | 请求超时 ({RequestTimeout.TotalSeconds}秒)", LogHelper.LogType.Error);
LogHelper.WriteLogToFile($"AutoUpdate | 发送HTTP请求到: {fileUrl}"); return null;
var downloadTask = client.GetAsync(fileUrl);
var timeoutTask = Task.Delay(RequestTimeout);
var completedTask = await Task.WhenAny(downloadTask, timeoutTask);
if (completedTask == timeoutTask)
{
LogHelper.WriteLogToFile($"AutoUpdate | 请求超时 ({RequestTimeout.TotalSeconds}秒)", LogHelper.LogType.Error);
return null;
}
HttpResponseMessage response = await downloadTask;
LogHelper.WriteLogToFile($"AutoUpdate | HTTP响应状态: {response.StatusCode}");
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync();
return content;
} }
catch (HttpRequestException ex) HttpResponseMessage response = await downloadTask;
{ LogHelper.WriteLogToFile($"AutoUpdate | HTTP响应状态: {response.StatusCode}");
LogHelper.WriteLogToFile($"AutoUpdate | HTTP请求错误: {ex.Message}", LogHelper.LogType.Error); response.EnsureSuccessStatusCode();
} string content = await response.Content.ReadAsStringAsync();
catch (TaskCanceledException ex) return content;
{
LogHelper.WriteLogToFile($"AutoUpdate | 请求超时: {ex.Message}", LogHelper.LogType.Error);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | 错误: {ex.Message}", LogHelper.LogType.Error);
}
return null;
} }
catch (HttpRequestException ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | HTTP请求错误: {ex.Message}", LogHelper.LogType.Error);
}
catch (TaskCanceledException ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | 请求超时: {ex.Message}", LogHelper.LogType.Error);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | 错误: {ex.Message}", LogHelper.LogType.Error);
}
return null;
} }
} }
@@ -1513,7 +1506,7 @@ namespace Ink_Canvas.Helpers
if (!isWindows7) if (!isWindows7)
{ {
LogHelper.WriteLogToFile("AutoUpdate | 当前系统不是Windows 7,跳过TLS连接测试", LogHelper.LogType.Info); LogHelper.WriteLogToFile("AutoUpdate | 当前系统不是Windows 7,跳过TLS连接测试");
return true; // 非Windows 7系统直接返回成功 return true; // 非Windows 7系统直接返回成功
} }
@@ -1536,11 +1529,9 @@ namespace Ink_Canvas.Helpers
LogHelper.WriteLogToFile("AutoUpdate | Windows 7 TLS连接测试成功"); LogHelper.WriteLogToFile("AutoUpdate | Windows 7 TLS连接测试成功");
return true; return true;
} }
else
{ LogHelper.WriteLogToFile($"AutoUpdate | Windows 7 TLS连接测试失败,状态码: {response.StatusCode}", LogHelper.LogType.Error);
LogHelper.WriteLogToFile($"AutoUpdate | Windows 7 TLS连接测试失败,状态码: {response.StatusCode}", LogHelper.LogType.Error); return false;
return false;
}
} }
} }
} }
@@ -1632,11 +1623,8 @@ namespace Ink_Canvas.Helpers
if (StartTime <= EndTime) if (StartTime <= EndTime)
{ // 单日时间段 { // 单日时间段
return currentTime >= StartTime && currentTime <= EndTime; return currentTime >= StartTime && currentTime <= EndTime;
} } // 跨越两天的时间段
else return currentTime >= StartTime || currentTime <= EndTime;
{ // 跨越两天的时间段
return currentTime >= StartTime || currentTime <= EndTime;
}
} }
} }
} }
+6 -5
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows; using System.Windows;
using System.Windows.Forms;
using System.Windows.Interop; using System.Windows.Interop;
namespace Ink_Canvas.Helpers namespace Ink_Canvas.Helpers
@@ -8,7 +9,7 @@ namespace Ink_Canvas.Helpers
/// <summary> /// <summary>
/// 防止窗口进入全屏状态的辅助类 /// 防止窗口进入全屏状态的辅助类
/// </summary> /// </summary>
public static partial class AvoidFullScreenHelper public static class AvoidFullScreenHelper
{ {
private static readonly DependencyProperty IsAvoidFullScreenEnabledProperty = private static readonly DependencyProperty IsAvoidFullScreenEnabledProperty =
DependencyProperty.RegisterAttached( DependencyProperty.RegisterAttached(
@@ -16,7 +17,7 @@ namespace Ink_Canvas.Helpers
typeof(bool), typeof(bool),
typeof(AvoidFullScreenHelper)); typeof(AvoidFullScreenHelper));
private static bool _isBoardMode = false; private static bool _isBoardMode;
public static void SetBoardMode(bool isBoardMode) public static void SetBoardMode(bool isBoardMode)
{ {
_isBoardMode = isBoardMode; _isBoardMode = isBoardMode;
@@ -120,10 +121,10 @@ namespace Ink_Canvas.Helpers
private static Rect GetWorkingArea(Rect windowRect) private static Rect GetWorkingArea(Rect windowRect)
{ {
// 获取所有显示器 // 获取所有显示器
var screens = System.Windows.Forms.Screen.AllScreens; var screens = Screen.AllScreens;
// 确定窗口主要位于哪个显示器上 // 确定窗口主要位于哪个显示器上
System.Windows.Forms.Screen targetScreen = null; Screen targetScreen = null;
double maxIntersection = 0; double maxIntersection = 0;
foreach (var screen in screens) foreach (var screen in screens)
@@ -144,7 +145,7 @@ namespace Ink_Canvas.Helpers
// 如果没找到,使用主显示器 // 如果没找到,使用主显示器
if (targetScreen == null) if (targetScreen == null)
targetScreen = System.Windows.Forms.Screen.PrimaryScreen; targetScreen = Screen.PrimaryScreen;
return new Rect( return new Rect(
targetScreen.WorkingArea.X, targetScreen.WorkingArea.X,
+29 -47
View File
@@ -9,125 +9,107 @@ namespace Ink_Canvas.Converter
{ {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
if ((bool)value == true) if ((bool)value)
{ {
return Visibility.Visible; return Visibility.Visible;
} }
else
{ return Visibility.Collapsed;
return Visibility.Collapsed;
}
} }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{ {
if ((bool)value == true) if ((bool)value)
{ {
return Visibility.Visible; return Visibility.Visible;
} }
else
{ return Visibility.Collapsed;
return Visibility.Collapsed;
}
} }
} }
public class VisibilityConverter : IValueConverter public class VisibilityConverter : IValueConverter
{ {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
Visibility visibility = (Visibility)value; Visibility visibility = (Visibility)value;
if (visibility == Visibility.Visible) if (visibility == Visibility.Visible)
{ {
return Visibility.Collapsed; return Visibility.Collapsed;
} }
else
{ return Visibility.Visible;
return Visibility.Visible;
}
} }
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{ {
Visibility visibility = (Visibility)value; Visibility visibility = (Visibility)value;
if (visibility == Visibility.Visible) if (visibility == Visibility.Visible)
{ {
return Visibility.Collapsed; return Visibility.Collapsed;
} }
else
{ return Visibility.Visible;
return Visibility.Visible;
}
} }
} }
public class IntNumberToString : IValueConverter public class IntNumberToString : IValueConverter
{ {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
if ((double)value == 0) if ((double)value == 0)
{ {
return "无限制"; return "无限制";
} }
else
{ return ((double)value) + "人";
return ((double)value).ToString() + "人";
}
} }
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{ {
if ((double)value == 0) if ((double)value == 0)
{ {
return "无限制"; return "无限制";
} }
else
{ return ((double)value) + "人";
return ((double)value).ToString() + "人";
}
} }
} }
public class IntNumberToString2 : IValueConverter public class IntNumberToString2 : IValueConverter
{ {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
if ((double)value == 0) if ((double)value == 0)
{ {
return "自动截图"; return "自动截图";
} }
else
{ return ((double)value) + "条";
return ((double)value).ToString() + "条";
}
} }
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{ {
if ((double)value == 0) if ((double)value == 0)
{ {
return "自动截图"; return "自动截图";
} }
else
{ return ((double)value) + "条";
return ((double)value).ToString() + "条";
}
} }
} }
public class IsEnabledToOpacityConverter : IValueConverter public class IsEnabledToOpacityConverter : IValueConverter
{ {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
bool isChecked = (bool)value; bool isChecked = (bool)value;
if (isChecked == true) if (isChecked)
{ {
return 1d; return 1d;
} }
else
{ return 0.35;
return 0.35;
}
} }
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }
} }
} }
+2 -2
View File
@@ -26,14 +26,14 @@ namespace Ink_Canvas.Helpers {
} }
} }
} catch (Exception ex) { } catch (Exception ex) {
LogHelper.WriteLogToFile("DelAutoSavedFiles | 处理文件时出错: " + ex.ToString(), LogHelper.LogType.Error); LogHelper.WriteLogToFile("DelAutoSavedFiles | 处理文件时出错: " + ex, LogHelper.LogType.Error);
} }
} }
try { // 递归删除空文件夹 try { // 递归删除空文件夹
DeleteEmptyFolders(directoryPath); DeleteEmptyFolders(directoryPath);
} catch (Exception ex) { } catch (Exception ex) {
LogHelper.WriteLogToFile("DelAutoSavedFiles | 处理文件时出错: " + ex.ToString(), LogHelper.LogType.Error); LogHelper.WriteLogToFile("DelAutoSavedFiles | 处理文件时出错: " + ex, LogHelper.LogType.Error);
} }
} }
} }
File diff suppressed because it is too large Load Diff
+9 -8
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
namespace Ink_Canvas.Helpers namespace Ink_Canvas.Helpers
{ {
@@ -70,7 +71,7 @@ namespace Ink_Canvas.Helpers
[FieldOffset(8)] [FieldOffset(8)]
private DateTime date; private DateTime date;
[FieldOffset(8)] [FieldOffset(8)]
private System.Runtime.InteropServices.ComTypes.FILETIME filetime; private FILETIME filetime;
[FieldOffset(8)] [FieldOffset(8)]
private Blob blobVal; private Blob blobVal;
@@ -115,7 +116,7 @@ namespace Ink_Canvas.Helpers
case VarEnum.VT_BLOB: case VarEnum.VT_BLOB:
return GetBlob(); return GetBlob();
} }
throw new NotImplementedException("PropVariant " + ve.ToString()); throw new NotImplementedException("PropVariant " + ve);
} }
} }
} }
@@ -144,17 +145,17 @@ namespace Ink_Canvas.Helpers
#region "Interfaces" #region "Interfaces"
[ComImport(), Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [ComImport, Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPropertyStore public interface IPropertyStore
{ {
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetCount([Out(), In()] ref uint cProps); void GetCount([Out, In] ref uint cProps);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetAt([In()] uint iProp, ref PropertyKey pkey); void GetAt([In] uint iProp, ref PropertyKey pkey);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetValue([In()] ref PropertyKey key, ref PropVariant pv); void GetValue([In] ref PropertyKey key, ref PropVariant pv);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void SetValue([In()] ref PropertyKey key, [In()] ref PropVariant pv); void SetValue([In] ref PropertyKey key, [In] ref PropVariant pv);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void Commit(); void Commit();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+2 -1
View File
@@ -2,6 +2,7 @@
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Windows.Forms;
namespace Ink_Canvas.Helpers namespace Ink_Canvas.Helpers
{ {
@@ -94,7 +95,7 @@ namespace Ink_Canvas.Helpers
} }
} }
public static double GetTaskbarHeight(System.Windows.Forms.Screen screen, double dpiScaleY) public static double GetTaskbarHeight(Screen screen, double dpiScaleY)
{ {
// 获取工作区和屏幕高度的差值 // 获取工作区和屏幕高度的差值
var workingArea = screen.WorkingArea; var workingArea = screen.WorkingArea;
+8 -8
View File
@@ -264,8 +264,8 @@ namespace Ink_Canvas.Helpers
/// </summary> /// </summary>
public int Width public int Width
{ {
get { return unchecked((int) (Right - Left)); } get { return unchecked(Right - Left); }
set { Right = unchecked((int) (Left + value)); } set { Right = unchecked(Left + value); }
} }
/// <summary> /// <summary>
@@ -273,8 +273,8 @@ namespace Ink_Canvas.Helpers
/// </summary> /// </summary>
public int Height public int Height
{ {
get { return unchecked((int) (Bottom - Top)); } get { return unchecked(Bottom - Top); }
set { Bottom = unchecked((int) (Top + value)); } set { Bottom = unchecked(Top + value); }
} }
public bool Equals(Rectangle other) public bool Equals(Rectangle other)
@@ -296,10 +296,10 @@ namespace Ink_Canvas.Helpers
{ {
unchecked unchecked
{ {
var hashCode = (int) Left; var hashCode = Left;
hashCode = (hashCode * 397) ^ (int) Top; hashCode = (hashCode * 397) ^ Top;
hashCode = (hashCode * 397) ^ (int) Right; hashCode = (hashCode * 397) ^ Right;
hashCode = (hashCode * 397) ^ (int) Bottom; hashCode = (hashCode * 397) ^ Bottom;
return hashCode; return hashCode;
} }
} }
+1 -4
View File
@@ -278,10 +278,7 @@ namespace Ink_Canvas.Helpers
window.Width = logicalSize.X; window.Width = logicalSize.X;
window.Height = logicalSize.Y; window.Height = logicalSize.Y;
} }
else //这个hwnd是前面从Window来的,如果现在他不是Window...... 你信么
{
//这个hwnd是前面从Window来的,如果现在他不是Window...... 你信么
}
} }
//将修改后的结构体拷贝回去 //将修改后的结构体拷贝回去
@@ -1,12 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Ink; using System.Windows.Ink;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
namespace Ink_Canvas.Helpers namespace Ink_Canvas.Helpers
@@ -19,7 +17,7 @@ namespace Ink_Canvas.Helpers
private readonly RenderTargetBitmap _renderTarget; private readonly RenderTargetBitmap _renderTarget;
private readonly DrawingVisual _drawingVisual; private readonly DrawingVisual _drawingVisual;
private readonly DrawingContext _drawingContext; private readonly DrawingContext _drawingContext;
private bool _isInitialized = false; private bool _isInitialized;
public HardwareAcceleratedInkProcessor(int width = 1920, int height = 1080) public HardwareAcceleratedInkProcessor(int width = 1920, int height = 1080)
{ {
+168
View File
@@ -0,0 +1,168 @@
using System;
using System.IO;
using System.Reflection;
using System.Windows;
namespace Ink_Canvas.Helpers
{
/// <summary>
/// IACore DLL自动释放器
/// 在应用启动时自动释放IACore相关的DLL文件到应用程序目录
/// </summary>
public static class IACoreDllExtractor
{
private static readonly string[] RequiredDlls = {
"IACore.dll",
"IALoader.dll",
"IAWinFX.dll"
};
/// <summary>
/// 在应用启动时释放IACore相关DLL
/// </summary>
public static void ExtractIACoreDlls()
{
try
{
string appDirectory = AppDomain.CurrentDomain.BaseDirectory;
LogHelper.WriteLogToFile("开始检查并释放IACore相关DLL文件");
foreach (string dllName in RequiredDlls)
{
string targetPath = Path.Combine(appDirectory, dllName);
// 检查文件是否已存在且有效
if (File.Exists(targetPath) && IsValidDll(targetPath))
{
LogHelper.WriteLogToFile($"{dllName} 已存在且有效,跳过释放");
continue;
}
// 从嵌入资源中释放DLL
if (ExtractDllFromResource(dllName, targetPath))
{
LogHelper.WriteLogToFile($"成功释放 {dllName} 到 {targetPath}");
}
else
{
LogHelper.WriteLogToFile($"警告:无法释放 {dllName},可能影响形状识别功能", LogHelper.LogType.Warning);
}
}
LogHelper.WriteLogToFile("IACore DLL释放检查完成");
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"释放IACore DLL时出错: {ex.Message}", LogHelper.LogType.Error);
}
}
/// <summary>
/// 从嵌入资源中提取DLL文件
/// </summary>
private static bool ExtractDllFromResource(string dllName, string targetPath)
{
try
{
Assembly assembly = Assembly.GetExecutingAssembly();
string resourceName = $"Ink_Canvas.Resources.IACore.{dllName}";
using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
{
if (resourceStream == null)
{
LogHelper.WriteLogToFile($"未找到嵌入资源: {resourceName}", LogHelper.LogType.Warning);
return false;
}
// 确保目标目录存在
string targetDirectory = Path.GetDirectoryName(targetPath);
if (!Directory.Exists(targetDirectory))
{
Directory.CreateDirectory(targetDirectory);
}
// 写入文件
using (FileStream fileStream = new FileStream(targetPath, FileMode.Create, FileAccess.Write))
{
resourceStream.CopyTo(fileStream);
}
return true;
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"从资源提取 {dllName} 失败: {ex.Message}", LogHelper.LogType.Error);
return false;
}
}
/// <summary>
/// 检查DLL文件是否有效
/// </summary>
private static bool IsValidDll(string filePath)
{
try
{
if (!File.Exists(filePath))
return false;
FileInfo fileInfo = new FileInfo(filePath);
// 检查文件大小(空文件或过小的文件可能无效)
if (fileInfo.Length < 1024) // 小于1KB可能无效
return false;
// 简单检查PE头(DLL文件应该以MZ开头)
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[2];
if (fs.Read(buffer, 0, 2) == 2)
{
return buffer[0] == 0x4D && buffer[1] == 0x5A; // "MZ"
}
}
return false;
}
catch
{
return false;
}
}
/// <summary>
/// 清理释放的DLL文件(可选,在应用退出时调用)
/// </summary>
public static void CleanupExtractedDlls()
{
try
{
string appDirectory = AppDomain.CurrentDomain.BaseDirectory;
foreach (string dllName in RequiredDlls)
{
string filePath = Path.Combine(appDirectory, dllName);
if (File.Exists(filePath))
{
try
{
File.Delete(filePath);
LogHelper.WriteLogToFile($"已清理 {dllName}");
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"清理 {dllName} 失败: {ex.Message}", LogHelper.LogType.Warning);
}
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"清理IACore DLL时出错: {ex.Message}", LogHelper.LogType.Error);
}
}
}
}
+1 -1
View File
@@ -15,7 +15,7 @@ namespace Ink_Canvas.Helpers
var analyzer = new InkAnalyzer(); var analyzer = new InkAnalyzer();
analyzer.AddStrokes(strokes); analyzer.AddStrokes(strokes);
analyzer.SetStrokesType(strokes, System.Windows.Ink.StrokeType.Drawing); analyzer.SetStrokesType(strokes, StrokeType.Drawing);
AnalysisAlternate analysisAlternate = null; AnalysisAlternate analysisAlternate = null;
int strokesCount = strokes.Count; int strokesCount = strokes.Count;
+5 -4
View File
@@ -3,6 +3,7 @@ using System.Diagnostics;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Ink; using System.Windows.Ink;
using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
namespace Ink_Canvas.Helpers namespace Ink_Canvas.Helpers
@@ -17,7 +18,7 @@ namespace Ink_Canvas.Helpers
private readonly InkSmoothingPerformanceMonitor _performanceMonitor; private readonly InkSmoothingPerformanceMonitor _performanceMonitor;
private readonly InkSmoothingConfig _config; private readonly InkSmoothingConfig _config;
private readonly Dispatcher _uiDispatcher; private readonly Dispatcher _uiDispatcher;
private bool _disposed = false; private bool _disposed;
public InkSmoothingManager(Dispatcher uiDispatcher) public InkSmoothingManager(Dispatcher uiDispatcher)
{ {
@@ -81,7 +82,7 @@ namespace Ink_Canvas.Helpers
} }
catch (Exception ex) catch (Exception ex)
{ {
System.Diagnostics.Debug.WriteLine($"墨迹平滑失败: {ex.Message}"); Debug.WriteLine($"墨迹平滑失败: {ex.Message}");
result = originalStroke; result = originalStroke;
} }
finally finally
@@ -122,7 +123,7 @@ namespace Ink_Canvas.Helpers
} }
catch (Exception ex) catch (Exception ex)
{ {
System.Diagnostics.Debug.WriteLine($"同步墨迹平滑失败: {ex.Message}"); Debug.WriteLine($"同步墨迹平滑失败: {ex.Message}");
result = originalStroke; result = originalStroke;
} }
finally finally
@@ -174,7 +175,7 @@ namespace Ink_Canvas.Helpers
{ {
try try
{ {
return System.Windows.Media.RenderCapability.Tier >= 0x00020000; return RenderCapability.Tier >= 0x00020000;
} }
catch catch
{ {
@@ -1,6 +1,9 @@
using System.Linq; using System.Drawing;
using System.Windows.Interop; using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Forms;
using System.Windows.Interop;
using Point = System.Windows.Point;
namespace Ink_Canvas.Helpers { namespace Ink_Canvas.Helpers {
internal class IsOutsideOfScreenHelper { internal class IsOutsideOfScreenHelper {
@@ -13,16 +16,16 @@ namespace Ink_Canvas.Helpers {
var hWnd = hwndSource.Handle; var hWnd = hwndSource.Handle;
var targetBounds = GetPixelBoundsToScreen(target); var targetBounds = GetPixelBoundsToScreen(target);
var screens = System.Windows.Forms.Screen.AllScreens; var screens = Screen.AllScreens;
return !screens.Any(x => x.Bounds.IntersectsWith(targetBounds)); return !screens.Any(x => x.Bounds.IntersectsWith(targetBounds));
System.Drawing.Rectangle GetPixelBoundsToScreen(FrameworkElement visual) { Rectangle GetPixelBoundsToScreen(FrameworkElement visual) {
var pixelBoundsToScreen = Rect.Empty; var pixelBoundsToScreen = Rect.Empty;
pixelBoundsToScreen.Union(visual.PointToScreen(new Point(0, 0))); pixelBoundsToScreen.Union(visual.PointToScreen(new Point(0, 0)));
pixelBoundsToScreen.Union(visual.PointToScreen(new Point(visual.ActualWidth, 0))); pixelBoundsToScreen.Union(visual.PointToScreen(new Point(visual.ActualWidth, 0)));
pixelBoundsToScreen.Union(visual.PointToScreen(new Point(0, visual.ActualHeight))); pixelBoundsToScreen.Union(visual.PointToScreen(new Point(0, visual.ActualHeight)));
pixelBoundsToScreen.Union(visual.PointToScreen(new Point(visual.ActualWidth, visual.ActualHeight))); pixelBoundsToScreen.Union(visual.PointToScreen(new Point(visual.ActualWidth, visual.ActualHeight)));
return new System.Drawing.Rectangle( return new Rectangle(
(int)pixelBoundsToScreen.X, (int)pixelBoundsToScreen.Y, (int)pixelBoundsToScreen.X, (int)pixelBoundsToScreen.Y,
(int)pixelBoundsToScreen.Width, (int)pixelBoundsToScreen.Height); (int)pixelBoundsToScreen.Width, (int)pixelBoundsToScreen.Height);
} }
+1 -1
View File
@@ -14,7 +14,7 @@ namespace Ink_Canvas.Helpers
public static void NewLog(string str) public static void NewLog(string str)
{ {
WriteLogToFile(str, LogType.Info); WriteLogToFile(str);
} }
public static void NewLog(Exception ex) public static void NewLog(Exception ex)
+1 -1
View File
@@ -32,7 +32,7 @@ namespace Ink_Canvas.Helpers
/// <summary> /// <summary>
/// 创建显示笔迹的类 /// 创建显示笔迹的类
/// </summary> /// </summary>
public StrokeVisual() : this(new DrawingAttributes() public StrokeVisual() : this(new DrawingAttributes
{ {
Color = Colors.Red, Color = Colors.Red,
//FitToCurve = true, //FitToCurve = true,
@@ -36,7 +36,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
try try
{ {
_plugin = plugin; _plugin = plugin;
LogHelper.WriteLogToFile("开始创建启动台按钮", LogHelper.LogType.Info); LogHelper.WriteLogToFile("开始创建启动台按钮");
// 创建SimpleStackPanel // 创建SimpleStackPanel
_panel = new SimpleStackPanel _panel = new SimpleStackPanel
@@ -49,7 +49,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
Background = Brushes.Transparent Background = Brushes.Transparent
}; };
LogHelper.WriteLogToFile("创建SimpleStackPanel完成", LogHelper.LogType.Info); LogHelper.WriteLogToFile("创建SimpleStackPanel完成");
// 添加图标 // 添加图标
var image = CreateIconImage(); var image = CreateIconImage();
@@ -77,7 +77,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
// 设置工具提示 // 设置工具提示
_panel.ToolTip = "启动台"; _panel.ToolTip = "启动台";
LogHelper.WriteLogToFile("启动台按钮创建完成", LogHelper.LogType.Info); LogHelper.WriteLogToFile("启动台按钮创建完成");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -112,8 +112,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
// 保存配置 // 保存配置
_plugin.SaveConfig(); _plugin.SaveConfig();
LogHelper.WriteLogToFile($"通过右键菜单切换启动台按钮位置为: {_plugin.Config.ButtonPosition}", LogHelper.WriteLogToFile($"通过右键菜单切换启动台按钮位置为: {_plugin.Config.ButtonPosition}");
LogHelper.LogType.Info);
}; };
menu.Items.Add(positionMenuItem); menu.Items.Add(positionMenuItem);
@@ -133,7 +132,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
if (method != null) if (method != null)
{ {
method.Invoke(mainWindow, null); method.Invoke(mainWindow, null);
LogHelper.WriteLogToFile("已打开插件设置窗口", LogHelper.LogType.Info); LogHelper.WriteLogToFile("已打开插件设置窗口");
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -218,7 +217,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
{ {
// 提供反馈 // 提供反馈
_panel.Background = new SolidColorBrush(Color.FromArgb(40, 0, 0, 0)); _panel.Background = new SolidColorBrush(Color.FromArgb(40, 0, 0, 0));
LogHelper.WriteLogToFile("启动台按钮鼠标按下", LogHelper.LogType.Info); LogHelper.WriteLogToFile("启动台按钮鼠标按下");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -241,7 +240,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
// 恢复背景 // 恢复背景
_panel.Background = Brushes.Transparent; _panel.Background = Brushes.Transparent;
LogHelper.WriteLogToFile("启动台按钮鼠标抬起,准备显示启动台窗口", LogHelper.LogType.Info); LogHelper.WriteLogToFile("启动台按钮鼠标抬起,准备显示启动台窗口");
// 获取按钮在屏幕上的位置 // 获取按钮在屏幕上的位置
Point buttonPosition = _panel.PointToScreen(new Point(_panel.ActualWidth / 2, 0)); Point buttonPosition = _panel.PointToScreen(new Point(_panel.ActualWidth / 2, 0));
@@ -1,12 +1,15 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Runtime.InteropServices;
using System.Windows; using System.Windows;
using System.Windows.Interop; using System.Windows.Interop;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using Microsoft.Win32; using Microsoft.Win32;
using Newtonsoft.Json;
namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
{ {
@@ -75,13 +78,13 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
/// <summary> /// <summary>
/// 图标缓存 /// 图标缓存
/// </summary> /// </summary>
[Newtonsoft.Json.JsonIgnore] [JsonIgnore]
private ImageSource _iconCache; private ImageSource _iconCache;
/// <summary> /// <summary>
/// 获取应用程序图标 /// 获取应用程序图标
/// </summary> /// </summary>
[Newtonsoft.Json.JsonIgnore] [JsonIgnore]
public ImageSource Icon public ImageSource Icon
{ {
get get
@@ -241,28 +244,28 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
} }
// 检查文件是否存在 // 检查文件是否存在
if (!System.IO.File.Exists(Path) && !Path.Contains(":\\")) if (!File.Exists(Path) && !Path.Contains(":\\"))
{ {
// 可能是系统命令,如explorer.exe // 可能是系统命令,如explorer.exe
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo ProcessStartInfo psi = new ProcessStartInfo
{ {
FileName = Path, FileName = Path,
UseShellExecute = true UseShellExecute = true
}; };
System.Diagnostics.Process.Start(psi); Process.Start(psi);
} }
else else
{ {
// 使用Process.Start启动应用程序 // 使用Process.Start启动应用程序
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo ProcessStartInfo psi = new ProcessStartInfo
{ {
FileName = Path, FileName = Path,
UseShellExecute = true UseShellExecute = true
}; };
System.Diagnostics.Process.Start(psi); Process.Start(psi);
} }
LogHelper.WriteLogToFile($"已启动应用程序: {Path}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已启动应用程序: {Path}");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -315,15 +318,15 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
} }
} }
[System.Runtime.InteropServices.DllImport("Shell32.dll", EntryPoint = "ExtractIconEx")] [DllImport("Shell32.dll", EntryPoint = "ExtractIconEx")]
private static extern int ExtractIconEx( private static extern int ExtractIconEx(
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)] string lpszFile, [MarshalAs(UnmanagedType.LPStr)] string lpszFile,
int nIconIndex, int nIconIndex,
out IntPtr phiconLarge, out IntPtr phiconLarge,
out IntPtr phiconSmall, out IntPtr phiconSmall,
int nIcons); int nIcons);
[System.Runtime.InteropServices.DllImport("User32.dll")] [DllImport("User32.dll")]
private static extern int DestroyIcon(IntPtr hIcon); private static extern int DestroyIcon(IntPtr hIcon);
} }
} }
@@ -1,9 +1,10 @@
using Microsoft.Win32;
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.IO;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using Ink_Canvas.Windows; using Ink_Canvas.Windows;
using Microsoft.Win32;
namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
{ {
@@ -77,7 +78,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
// 保存配置 // 保存配置
_plugin.SaveConfig(); _plugin.SaveConfig();
LogHelper.WriteLogToFile($"启动台按钮位置已更改为: {_plugin.Config.ButtonPosition}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"启动台按钮位置已更改为: {_plugin.Config.ButtonPosition}");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -283,9 +284,9 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
pathTextBox.Text = dialog.FileName; pathTextBox.Text = dialog.FileName;
// 如果选择的是.exe文件,自动获取文件名填入名称字段 // 如果选择的是.exe文件,自动获取文件名填入名称字段
if (System.IO.Path.GetExtension(dialog.FileName).ToLower() == ".exe") if (Path.GetExtension(dialog.FileName).ToLower() == ".exe")
{ {
string fileName = System.IO.Path.GetFileNameWithoutExtension(dialog.FileName); string fileName = Path.GetFileNameWithoutExtension(dialog.FileName);
// 只有在名称字段为空或者是新建项目时才自动填入 // 只有在名称字段为空或者是新建项目时才自动填入
if (string.IsNullOrWhiteSpace(nameTextBox.Text) || isNew) if (string.IsNullOrWhiteSpace(nameTextBox.Text) || isNew)
{ {
@@ -1,10 +1,16 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Threading;
namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
{ {
@@ -21,7 +27,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
/// <summary> /// <summary>
/// 是否处于固定模式 /// 是否处于固定模式
/// </summary> /// </summary>
private bool _isFixMode = false; private bool _isFixMode;
/// <summary> /// <summary>
/// 应用项按钮列表 /// 应用项按钮列表
@@ -51,11 +57,11 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
LoadLauncherItems(); LoadLauncherItems();
// 添加鼠标按下事件(用于拖动窗口) // 添加鼠标按下事件(用于拖动窗口)
this.MouseDown += (s, e) => MouseDown += (s, e) =>
{ {
if (e.ChangedButton == MouseButton.Left && e.ButtonState == MouseButtonState.Pressed) if (e.ChangedButton == MouseButton.Left && e.ButtonState == MouseButtonState.Pressed)
{ {
this.DragMove(); DragMove();
} }
}; };
@@ -145,18 +151,18 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
string appPath = item.Path; string appPath = item.Path;
string appName = item.Name; string appName = item.Name;
LogHelper.WriteLogToFile($"点击启动应用: {appName}, 路径: {appPath}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"点击启动应用: {appName}, 路径: {appPath}");
// 首先标记窗口正在关闭 // 首先标记窗口正在关闭
IsClosing = true; IsClosing = true;
// 创建一个应用启动任务 // 创建一个应用启动任务
var launchTask = new System.Threading.Tasks.Task(() => var launchTask = new Task(() =>
{ {
try try
{ {
// 等待一段时间,确保窗口关闭流程已经开始 // 等待一段时间,确保窗口关闭流程已经开始
System.Threading.Thread.Sleep(200); Thread.Sleep(200);
// 使用UI线程启动应用 // 使用UI线程启动应用
Application.Current.Dispatcher.Invoke(() => Application.Current.Dispatcher.Invoke(() =>
@@ -164,18 +170,18 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
try try
{ {
// 检查应用路径是否存在 // 检查应用路径是否存在
if (System.IO.File.Exists(appPath) || !appPath.Contains(":\\")) if (File.Exists(appPath) || !appPath.Contains(":\\"))
{ {
// 创建进程启动信息 // 创建进程启动信息
var psi = new System.Diagnostics.ProcessStartInfo var psi = new ProcessStartInfo
{ {
FileName = appPath, FileName = appPath,
UseShellExecute = true, UseShellExecute = true,
}; };
// 启动应用程序 // 启动应用程序
var process = System.Diagnostics.Process.Start(psi); var process = Process.Start(psi);
LogHelper.WriteLogToFile($"应用程序 {appName} 已启动", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"应用程序 {appName} 已启动");
} }
else else
{ {
@@ -205,7 +211,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
// 启动应用程序任务 // 启动应用程序任务
launchTask.Start(); launchTask.Start();
}), System.Windows.Threading.DispatcherPriority.Background); }), DispatcherPriority.Background);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -406,7 +412,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
{ {
LogHelper.WriteLogToFile($"延迟关闭窗口时出错: {ex.Message}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"延迟关闭窗口时出错: {ex.Message}", LogHelper.LogType.Error);
} }
}), System.Windows.Threading.DispatcherPriority.Background); }), DispatcherPriority.Background);
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -418,12 +424,12 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
/// <summary> /// <summary>
/// 窗口是否正在关闭 /// 窗口是否正在关闭
/// </summary> /// </summary>
private bool IsClosing { get; set; } = false; private bool IsClosing { get; set; }
/// <summary> /// <summary>
/// 重写OnClosing方法,标记窗口正在关闭 /// 重写OnClosing方法,标记窗口正在关闭
/// </summary> /// </summary>
protected override void OnClosing(System.ComponentModel.CancelEventArgs e) protected override void OnClosing(CancelEventArgs e)
{ {
IsClosing = true; IsClosing = true;
base.OnClosing(e); base.OnClosing(e);
@@ -1,5 +1,3 @@
using Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher;
using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@@ -7,6 +5,8 @@ using System.IO;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media; using System.Windows.Media;
using Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher;
using Newtonsoft.Json;
namespace Ink_Canvas.Helpers.Plugins.BuiltIn namespace Ink_Canvas.Helpers.Plugins.BuiltIn
{ {
@@ -59,7 +59,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn
/// <summary> /// <summary>
/// 标记是否已添加到浮动栏 /// 标记是否已添加到浮动栏
/// </summary> /// </summary>
private bool _isAddedToFloatingBar = false; private bool _isAddedToFloatingBar;
#endregion #endregion
@@ -81,7 +81,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn
// 加载配置 // 加载配置
LoadConfig(); LoadConfig();
LogHelper.WriteLogToFile("超级启动台插件已初始化", LogHelper.LogType.Info); LogHelper.WriteLogToFile("超级启动台插件已初始化");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -100,7 +100,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn
if (_launcherButton == null) if (_launcherButton == null)
{ {
_launcherButton = new LauncherButton(this); _launcherButton = new LauncherButton(this);
LogHelper.WriteLogToFile("超级启动台按钮已创建", LogHelper.LogType.Info); LogHelper.WriteLogToFile("超级启动台按钮已创建");
} }
// 添加启动台按钮到浮动栏 // 添加启动台按钮到浮动栏
@@ -112,7 +112,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn
// 保存插件配置 // 保存插件配置
SavePluginSettings(); SavePluginSettings();
LogHelper.WriteLogToFile("超级启动台插件已启用", LogHelper.LogType.Info); LogHelper.WriteLogToFile("超级启动台插件已启用");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -143,7 +143,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn
// 保存插件配置 // 保存插件配置
SavePluginSettings(); SavePluginSettings();
LogHelper.WriteLogToFile("超级启动台插件已禁用", LogHelper.LogType.Info); LogHelper.WriteLogToFile("超级启动台插件已禁用");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -193,7 +193,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn
// 保存配置 // 保存配置
SaveConfig(); SaveConfig();
LogHelper.WriteLogToFile($"超级启动台插件设置已保存", LogHelper.LogType.Info); LogHelper.WriteLogToFile("超级启动台插件设置已保存");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -250,7 +250,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn
string json = JsonConvert.SerializeObject(Config, Formatting.Indented); string json = JsonConvert.SerializeObject(Config, Formatting.Indented);
File.WriteAllText(_configPath, json); File.WriteAllText(_configPath, json);
LogHelper.WriteLogToFile("超级启动台配置已保存", LogHelper.LogType.Info); LogHelper.WriteLogToFile("超级启动台配置已保存");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -332,12 +332,12 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn
if (Config.ButtonPosition == LauncherButtonPosition.Left) if (Config.ButtonPosition == LauncherButtonPosition.Left)
{ {
floatingBar.Children.Insert(0, buttonElement); floatingBar.Children.Insert(0, buttonElement);
LogHelper.WriteLogToFile("启动台按钮已添加到浮动栏左侧", LogHelper.LogType.Info); LogHelper.WriteLogToFile("启动台按钮已添加到浮动栏左侧");
} }
else else
{ {
floatingBar.Children.Add(buttonElement); floatingBar.Children.Add(buttonElement);
LogHelper.WriteLogToFile("启动台按钮已添加到浮动栏右侧", LogHelper.LogType.Info); LogHelper.WriteLogToFile("启动台按钮已添加到浮动栏右侧");
} }
_isAddedToFloatingBar = true; _isAddedToFloatingBar = true;
@@ -424,7 +424,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn
if (floatingBar.Children.Contains(buttonElement)) if (floatingBar.Children.Contains(buttonElement))
{ {
floatingBar.Children.Remove(buttonElement); floatingBar.Children.Remove(buttonElement);
LogHelper.WriteLogToFile("启动台按钮已从浮动栏移除", LogHelper.LogType.Info); LogHelper.WriteLogToFile("启动台按钮已从浮动栏移除");
} }
_isAddedToFloatingBar = false; _isAddedToFloatingBar = false;
@@ -448,7 +448,7 @@ namespace Ink_Canvas.Helpers.Plugins.BuiltIn
{ {
RemoveLauncherButtonFromFloatingBar(); RemoveLauncherButtonFromFloatingBar();
AddLauncherButtonToFloatingBar(); AddLauncherButtonToFloatingBar();
LogHelper.WriteLogToFile($"启动台按钮位置已更新为: {Config.ButtonPosition}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"启动台按钮位置已更新为: {Config.ButtonPosition}");
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -12,7 +12,7 @@ namespace Ink_Canvas.Helpers.Plugins
private readonly string _pluginPath; private readonly string _pluginPath;
private readonly string _pluginName; private readonly string _pluginName;
private readonly Version _pluginVersion; private readonly Version _pluginVersion;
private bool _isInitialized = false; private bool _isInitialized;
/// <summary> /// <summary>
/// 创建 ICCPP 插件适配器 /// 创建 ICCPP 插件适配器
@@ -104,7 +104,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 这里可以添加 .iccpp 插件的初始化逻辑 // 这里可以添加 .iccpp 插件的初始化逻辑
// 例如,根据文件格式加载特定资源 // 例如,根据文件格式加载特定资源
LogHelper.WriteLogToFile($"ICCPP 插件 {Name} 已初始化", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"ICCPP 插件 {Name} 已初始化");
_isInitialized = true; _isInitialized = true;
} }
catch (Exception ex) catch (Exception ex)
@@ -126,7 +126,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 例如,加载动态库、注册事件等 // 例如,加载动态库、注册事件等
base.Enable(); // 设置启用状态并触发事件 base.Enable(); // 设置启用状态并触发事件
LogHelper.WriteLogToFile($"ICCPP 插件 {Name} 已启用", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"ICCPP 插件 {Name} 已启用");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -147,7 +147,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 例如,卸载动态库、注销事件等 // 例如,卸载动态库、注销事件等
base.Disable(); // 设置禁用状态并触发事件 base.Disable(); // 设置禁用状态并触发事件
LogHelper.WriteLogToFile($"ICCPP 插件 {Name} 已禁用", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"ICCPP 插件 {Name} 已禁用");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -165,7 +165,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 这里可以添加 .iccpp 插件的清理逻辑 // 这里可以添加 .iccpp 插件的清理逻辑
// 例如,释放资源等 // 例如,释放资源等
LogHelper.WriteLogToFile($"ICCPP 插件 {Name} 已清理资源", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"ICCPP 插件 {Name} 已清理资源");
} }
catch (Exception ex) catch (Exception ex)
{ {
+6 -6
View File
@@ -11,7 +11,7 @@ namespace Ink_Canvas.Helpers.Plugins
/// <summary> /// <summary>
/// 插件状态(私有字段) /// 插件状态(私有字段)
/// </summary> /// </summary>
private bool _isEnabled = false; private bool _isEnabled;
/// <summary> /// <summary>
/// 插件状态(公共属性) /// 插件状态(公共属性)
@@ -80,7 +80,7 @@ namespace Ink_Canvas.Helpers.Plugins
try try
{ {
string name = Name; string name = Name;
LogHelper.WriteLogToFile($"初始化插件: ID={Id}, 名称={name ?? ""}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"初始化插件: ID={Id}, 名称={name ?? ""}");
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
{ {
@@ -92,7 +92,7 @@ namespace Ink_Canvas.Helpers.Plugins
LogHelper.WriteLogToFile($"获取插件名称时出错: {ex.Message}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"获取插件名称时出错: {ex.Message}", LogHelper.LogType.Error);
} }
LogHelper.WriteLogToFile($"插件 {Name} 已初始化", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {Name} 已初始化");
} }
/// <summary> /// <summary>
@@ -103,7 +103,7 @@ namespace Ink_Canvas.Helpers.Plugins
if (!IsEnabled) if (!IsEnabled)
{ {
IsEnabled = true; IsEnabled = true;
LogHelper.WriteLogToFile($"插件 {Name} 已启用", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {Name} 已启用");
} }
} }
@@ -115,7 +115,7 @@ namespace Ink_Canvas.Helpers.Plugins
if (IsEnabled) if (IsEnabled)
{ {
IsEnabled = false; IsEnabled = false;
LogHelper.WriteLogToFile($"插件 {Name} 已禁用", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {Name} 已禁用");
} }
} }
@@ -134,7 +134,7 @@ namespace Ink_Canvas.Helpers.Plugins
/// </summary> /// </summary>
public virtual void Cleanup() public virtual void Cleanup()
{ {
LogHelper.WriteLogToFile($"插件 {Name} 已卸载", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {Name} 已卸载");
} }
/// <summary> /// <summary>
+69 -69
View File
@@ -8,6 +8,9 @@ using System.Security.Cryptography;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using Ink_Canvas.Windows;
using Newtonsoft.Json;
using Timer = System.Timers.Timer;
namespace Ink_Canvas.Helpers.Plugins namespace Ink_Canvas.Helpers.Plugins
{ {
@@ -51,12 +54,12 @@ namespace Ink_Canvas.Helpers.Plugins
/// <summary> /// <summary>
/// 配置是否已更改但未保存 /// 配置是否已更改但未保存
/// </summary> /// </summary>
private bool _configDirty = false; private bool _configDirty;
/// <summary> /// <summary>
/// 配置自动保存计时器 /// 配置自动保存计时器
/// </summary> /// </summary>
private System.Timers.Timer _autoSaveTimer; private Timer _autoSaveTimer;
/// <summary> /// <summary>
/// 加载的程序集缓存 /// 加载的程序集缓存
@@ -80,7 +83,7 @@ namespace Ink_Canvas.Helpers.Plugins
LoadConfig(); LoadConfig();
// 初始化自动保存计时器(3秒) // 初始化自动保存计时器(3秒)
_autoSaveTimer = new System.Timers.Timer(3000); _autoSaveTimer = new Timer(3000);
_autoSaveTimer.Elapsed += (s, e) => _autoSaveTimer.Elapsed += (s, e) =>
{ {
if (_configDirty) if (_configDirty)
@@ -108,22 +111,22 @@ namespace Ink_Canvas.Helpers.Plugins
{ {
try try
{ {
LogHelper.WriteLogToFile("开始初始化插件系统", LogHelper.LogType.Info); LogHelper.WriteLogToFile("开始初始化插件系统");
// 加载配置 // 加载配置
LoadConfig(); LoadConfig();
LogHelper.WriteLogToFile($"已从配置文件加载 {PluginStates.Count} 个插件状态记录", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已从配置文件加载 {PluginStates.Count} 个插件状态记录");
// 加载内置插件 // 加载内置插件
LogHelper.WriteLogToFile("正在加载内置插件...", LogHelper.LogType.Info); LogHelper.WriteLogToFile("正在加载内置插件...");
LoadBuiltInPlugins(); LoadBuiltInPlugins();
// 加载外部插件 // 加载外部插件
LogHelper.WriteLogToFile("正在加载外部插件...", LogHelper.LogType.Info); LogHelper.WriteLogToFile("正在加载外部插件...");
LoadExternalPlugins(); LoadExternalPlugins();
// 启用已配置为启用的插件 // 启用已配置为启用的插件
LogHelper.WriteLogToFile("正在应用配置的插件状态...", LogHelper.LogType.Info); LogHelper.WriteLogToFile("正在应用配置的插件状态...");
EnableConfiguredPlugins(); EnableConfiguredPlugins();
// 设置定期检查热重载 // 设置定期检查热重载
@@ -132,7 +135,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 保存初始化后的配置(可能有新插件) // 保存初始化后的配置(可能有新插件)
SaveConfig(); SaveConfig();
LogHelper.WriteLogToFile($"插件系统初始化完成,共加载 {Plugins.Count} 个插件", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件系统初始化完成,共加载 {Plugins.Count} 个插件");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -166,7 +169,7 @@ namespace Ink_Canvas.Helpers.Plugins
{ {
plugin.Initialize(); plugin.Initialize();
Plugins.Add(plugin); Plugins.Add(plugin);
LogHelper.WriteLogToFile($"已加载内置插件: {plugin.Name} v{plugin.Version}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已加载内置插件: {plugin.Name} v{plugin.Version}");
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -200,7 +203,7 @@ namespace Ink_Canvas.Helpers.Plugins
.Concat(Directory.GetFiles(PluginsDirectory, "*.dll", SearchOption.TopDirectoryOnly)) .Concat(Directory.GetFiles(PluginsDirectory, "*.dll", SearchOption.TopDirectoryOnly))
.ToArray(); .ToArray();
LogHelper.WriteLogToFile($"发现 {pluginFiles.Length} 个外部插件文件", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"发现 {pluginFiles.Length} 个外部插件文件");
foreach (var pluginFile in pluginFiles) foreach (var pluginFile in pluginFiles)
{ {
@@ -258,8 +261,7 @@ namespace Ink_Canvas.Helpers.Plugins
plugin.Initialize(); plugin.Initialize();
Plugins.Add(plugin); Plugins.Add(plugin);
LogHelper.WriteLogToFile($"已加载外部插件: {plugin.Name} v{plugin.Version} 来自 {Path.GetFileName(pluginPath)}", LogHelper.WriteLogToFile($"已加载外部插件: {plugin.Name} v{plugin.Version} 来自 {Path.GetFileName(pluginPath)}");
LogHelper.LogType.Info);
return plugin; return plugin;
} }
@@ -297,8 +299,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 添加到插件列表 // 添加到插件列表
Plugins.Add(pluginAdapter); Plugins.Add(pluginAdapter);
LogHelper.WriteLogToFile($"已创建 ICCPP 插件适配器: {pluginAdapter.Name} 来自 {Path.GetFileName(pluginPath)}", LogHelper.WriteLogToFile($"已创建 ICCPP 插件适配器: {pluginAdapter.Name} 来自 {Path.GetFileName(pluginPath)}");
LogHelper.LogType.Info);
return pluginAdapter; return pluginAdapter;
} }
@@ -371,13 +372,13 @@ namespace Ink_Canvas.Helpers.Plugins
{ {
plugin.Enable(); plugin.Enable();
enabledCount++; enabledCount++;
LogHelper.WriteLogToFile($"根据配置启用插件: {plugin.Name}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"根据配置启用插件: {plugin.Name}");
} }
else else
{ {
plugin.Disable(); plugin.Disable();
disabledCount++; disabledCount++;
LogHelper.WriteLogToFile($"根据配置禁用插件: {plugin.Name}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"根据配置禁用插件: {plugin.Name}");
} }
} }
else else
@@ -406,7 +407,7 @@ namespace Ink_Canvas.Helpers.Plugins
{ {
plugin.Disable(); plugin.Disable();
disabledCount++; disabledCount++;
LogHelper.WriteLogToFile($"插件不在配置中,默认禁用: {plugin.Name}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件不在配置中,默认禁用: {plugin.Name}");
} }
} }
} }
@@ -423,7 +424,7 @@ namespace Ink_Canvas.Helpers.Plugins
TriggerAutoSave(); TriggerAutoSave();
} }
LogHelper.WriteLogToFile($"已应用插件配置: 启用 {enabledCount} 个,禁用 {disabledCount} 个,错误 {errorCount} 个", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已应用插件配置: 启用 {enabledCount} 个,禁用 {disabledCount} 个,错误 {errorCount} 个");
} }
/// <summary> /// <summary>
@@ -443,11 +444,11 @@ namespace Ink_Canvas.Helpers.Plugins
PluginStates[pluginTypeName] = isEnabled; PluginStates[pluginTypeName] = isEnabled;
_configDirty = true; _configDirty = true;
LogHelper.WriteLogToFile($"插件状态变更: {plugin.Name} = {(isEnabled ? "" : "")}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件状态变更: {plugin.Name} = {(isEnabled ? "" : "")}");
// 立即同步保存配置(不再使用延迟自动保存) // 立即同步保存配置(不再使用延迟自动保存)
SaveConfig(); SaveConfig();
LogHelper.WriteLogToFile($"插件 {plugin.Name} 状态已立即保存到配置文件", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {plugin.Name} 状态已立即保存到配置文件");
} }
} }
} }
@@ -534,14 +535,14 @@ namespace Ink_Canvas.Helpers.Plugins
return; return;
} }
LogHelper.WriteLogToFile($"开始热重载插件: {plugin.Name} ({Path.GetFileName(pluginPath)})", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"开始热重载插件: {plugin.Name} ({Path.GetFileName(pluginPath)})");
// 保存插件的当前状态 // 保存插件的当前状态
bool wasEnabled = plugin.IsEnabled; bool wasEnabled = plugin.IsEnabled;
string pluginTypeName = plugin.GetType().FullName; string pluginTypeName = plugin.GetType().FullName;
// 卸载插件 // 卸载插件
UnloadPlugin(plugin, false); UnloadPlugin(plugin);
// 从加载缓存中移除 // 从加载缓存中移除
if (_loadedAssemblies.ContainsKey(pluginPath)) if (_loadedAssemblies.ContainsKey(pluginPath))
@@ -575,7 +576,7 @@ namespace Ink_Canvas.Helpers.Plugins
SaveConfig(); SaveConfig();
} }
LogHelper.WriteLogToFile($"插件 {newPlugin.Name} v{newPlugin.Version} 热重载成功", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {newPlugin.Name} v{newPlugin.Version} 热重载成功");
// 通知UI刷新 // 通知UI刷新
NotifyUIRefresh(); NotifyUIRefresh();
@@ -626,7 +627,7 @@ namespace Ink_Canvas.Helpers.Plugins
} }
} }
LogHelper.WriteLogToFile($"已卸载插件: {pluginName}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已卸载插件: {pluginName}");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -677,7 +678,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 保存配置 // 保存配置
SaveConfig(); SaveConfig();
LogHelper.WriteLogToFile($"已删除插件: {pluginName}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已删除插件: {pluginName}");
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
@@ -701,7 +702,7 @@ namespace Ink_Canvas.Helpers.Plugins
if (currentState == enable) if (currentState == enable)
{ {
// 已经是目标状态,无需操作 // 已经是目标状态,无需操作
LogHelper.WriteLogToFile($"插件 {plugin.Name} 已经是 {(enable ? "" : "")} 状态,无需切换", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {plugin.Name} 已经是 {(enable ? "" : "")} 状态,无需切换");
return; return;
} }
@@ -709,7 +710,7 @@ namespace Ink_Canvas.Helpers.Plugins
string pluginName = plugin.Name; string pluginName = plugin.Name;
string pluginTypeName = plugin.GetType().FullName; string pluginTypeName = plugin.GetType().FullName;
LogHelper.WriteLogToFile($"开始切换插件 {pluginName} 状态为: {(enable ? "" : "")}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"开始切换插件 {pluginName} 状态为: {(enable ? "" : "")}");
// 首先更新配置状态 // 首先更新配置状态
PluginStates[pluginTypeName] = enable; PluginStates[pluginTypeName] = enable;
@@ -731,13 +732,13 @@ namespace Ink_Canvas.Helpers.Plugins
if (enable) if (enable)
{ {
plugin.Enable(); plugin.Enable();
LogHelper.WriteLogToFile($"插件 {pluginName} 已启用", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {pluginName} 已启用");
} }
else else
{ {
// 禁用前先记录是否为内置插件 // 禁用前先记录是否为内置插件
bool isBuiltIn = plugin.IsBuiltIn; bool isBuiltIn = plugin.IsBuiltIn;
LogHelper.WriteLogToFile($"尝试禁用{(isBuiltIn ? "" : "")}插件 {pluginName}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"尝试禁用{(isBuiltIn ? "" : "")}插件 {pluginName}");
// 禁用插件 // 禁用插件
plugin.Disable(); plugin.Disable();
@@ -762,13 +763,13 @@ namespace Ink_Canvas.Helpers.Plugins
if (enabledProperty != null) if (enabledProperty != null)
{ {
enabledProperty.SetValue(pb4, false); enabledProperty.SetValue(pb4, false);
LogHelper.WriteLogToFile($"已通过反射强制设置插件 {pluginName} 为禁用状态", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已通过反射强制设置插件 {pluginName} 为禁用状态");
} }
} }
} }
} }
LogHelper.WriteLogToFile($"插件 {pluginName} 已禁用", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {pluginName} 已禁用");
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -785,7 +786,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 对于内置插件,执行专门的处理 // 对于内置插件,执行专门的处理
if (pluginInstance.IsBuiltIn) if (pluginInstance.IsBuiltIn)
{ {
LogHelper.WriteLogToFile($"处理内置插件 {pluginName} 状态变更", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"处理内置插件 {pluginName} 状态变更");
// 对于内置插件,我们需要确保状态正确应用 // 对于内置插件,我们需要确保状态正确应用
bool finalState = pluginInstance.IsEnabled; bool finalState = pluginInstance.IsEnabled;
@@ -811,7 +812,7 @@ namespace Ink_Canvas.Helpers.Plugins
if (enabledProperty != null) if (enabledProperty != null)
{ {
enabledProperty.SetValue(pluginInstance, expectedState); enabledProperty.SetValue(pluginInstance, expectedState);
LogHelper.WriteLogToFile($"已通过反射强制设置内置插件 {pluginName} 状态为 {(expectedState ? "" : "")}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已通过反射强制设置内置插件 {pluginName} 状态为 {(expectedState ? "" : "")}");
} }
} }
} }
@@ -827,7 +828,7 @@ namespace Ink_Canvas.Helpers.Plugins
{ {
if (!string.IsNullOrEmpty(pluginInstance.PluginPath) && File.Exists(pluginInstance.PluginPath)) if (!string.IsNullOrEmpty(pluginInstance.PluginPath) && File.Exists(pluginInstance.PluginPath))
{ {
LogHelper.WriteLogToFile($"开始重载外部插件 {pluginName}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"开始重载外部插件 {pluginName}");
// 使用调度器确保在UI线程执行热重载 // 使用调度器确保在UI线程执行热重载
if (Application.Current != null && Application.Current.Dispatcher != null) if (Application.Current != null && Application.Current.Dispatcher != null)
@@ -835,14 +836,14 @@ namespace Ink_Canvas.Helpers.Plugins
Application.Current.Dispatcher.BeginInvoke(new Action(() => Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{ {
ReloadPlugin(pluginInstance); ReloadPlugin(pluginInstance);
LogHelper.WriteLogToFile($"插件 {pluginName} 已重载以应用{(enable ? "" : "")}状态", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {pluginName} 已重载以应用{(enable ? "" : "")}状态");
})); }));
} }
else else
{ {
// 当前不在UI线程,直接重载 // 当前不在UI线程,直接重载
ReloadPlugin(pluginInstance); ReloadPlugin(pluginInstance);
LogHelper.WriteLogToFile($"插件 {pluginName} 已重载以应用{(enable ? "" : "")}状态", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {pluginName} 已重载以应用{(enable ? "" : "")}状态");
} }
} }
else else
@@ -865,7 +866,7 @@ namespace Ink_Canvas.Helpers.Plugins
NotifyUIRefresh(); NotifyUIRefresh();
} }
LogHelper.WriteLogToFile($"插件 {pluginName} 状态切换完成", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {pluginName} 状态切换完成");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -889,12 +890,12 @@ namespace Ink_Canvas.Helpers.Plugins
if (enable) if (enable)
{ {
plugin.Enable(); plugin.Enable();
LogHelper.WriteLogToFile($"实时应用: 已启用插件 {plugin.Name}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"实时应用: 已启用插件 {plugin.Name}");
} }
else else
{ {
plugin.Disable(); plugin.Disable();
LogHelper.WriteLogToFile($"实时应用: 已禁用插件 {plugin.Name}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"实时应用: 已禁用插件 {plugin.Name}");
} }
// 同步状态到插件自身的配置 // 同步状态到插件自身的配置
@@ -904,7 +905,7 @@ namespace Ink_Canvas.Helpers.Plugins
{ {
// 保存插件设置(与启用状态无关) // 保存插件设置(与启用状态无关)
pluginSettings.SavePluginSettings(); pluginSettings.SavePluginSettings();
LogHelper.WriteLogToFile($"实时应用: 已保存插件 {plugin.Name} 设置", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"实时应用: 已保存插件 {plugin.Name} 设置");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -940,7 +941,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 执行热重载 // 执行热重载
ReloadPlugin(externalPlugin); ReloadPlugin(externalPlugin);
LogHelper.WriteLogToFile($"插件 {plugin.Name} 已成功热重载以应用实时状态", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {plugin.Name} 已成功热重载以应用实时状态");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -964,7 +965,7 @@ namespace Ink_Canvas.Helpers.Plugins
} }
} }
LogHelper.WriteLogToFile($"插件 {plugin.Name} 实时状态已应用: {(enable ? "" : "")}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {plugin.Name} 实时状态已应用: {(enable ? "" : "")}");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -986,7 +987,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 通知任何可能打开的插件设置窗口刷新 // 通知任何可能打开的插件设置窗口刷新
foreach (Window window in Application.Current.Windows) foreach (Window window in Application.Current.Windows)
{ {
if (window is Windows.PluginSettingsWindow pluginWindow) if (window is PluginSettingsWindow pluginWindow)
{ {
pluginWindow.RefreshPluginList(); pluginWindow.RefreshPluginList();
break; break;
@@ -1009,7 +1010,7 @@ namespace Ink_Canvas.Helpers.Plugins
const int maxRetries = 3; // 最大重试次数 const int maxRetries = 3; // 最大重试次数
const int retryDelayMs = 300; // 重试延迟时间(毫秒) const int retryDelayMs = 300; // 重试延迟时间(毫秒)
LogHelper.WriteLogToFile($"开始从配置文件加载插件状态: {PluginConfigFile}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"开始从配置文件加载插件状态: {PluginConfigFile}");
// 确保至少有一个默认配置 // 确保至少有一个默认配置
Dictionary<string, bool> defaultConfig = new Dictionary<string, bool>(); Dictionary<string, bool> defaultConfig = new Dictionary<string, bool>();
@@ -1033,14 +1034,13 @@ namespace Ink_Canvas.Helpers.Plugins
json = reader.ReadToEnd(); json = reader.ReadToEnd();
} }
var loadedStates = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, bool>>(json); var loadedStates = JsonConvert.DeserializeObject<Dictionary<string, bool>>(json);
if (loadedStates != null && loadedStates.Count > 0) if (loadedStates != null && loadedStates.Count > 0)
{ {
PluginStates = loadedStates; PluginStates = loadedStates;
_configDirty = false; // 重置脏标记 _configDirty = false; // 重置脏标记
LogHelper.WriteLogToFile($"成功从配置文件加载了 {PluginStates.Count} 个插件状态", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"成功从配置文件加载了 {PluginStates.Count} 个插件状态");
return; // 成功加载,提前退出
} }
else else
{ {
@@ -1051,13 +1051,13 @@ namespace Ink_Canvas.Helpers.Plugins
try try
{ {
string backupJson = File.ReadAllText(PluginConfigBackupFile); string backupJson = File.ReadAllText(PluginConfigBackupFile);
var backupStates = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, bool>>(backupJson); var backupStates = JsonConvert.DeserializeObject<Dictionary<string, bool>>(backupJson);
if (backupStates != null && backupStates.Count > 0) if (backupStates != null && backupStates.Count > 0)
{ {
PluginStates = backupStates; PluginStates = backupStates;
_configDirty = true; // 从备份加载,需要重新保存主配置 _configDirty = true; // 从备份加载,需要重新保存主配置
LogHelper.WriteLogToFile($"已从备份恢复 {PluginStates.Count} 个插件状态", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已从备份恢复 {PluginStates.Count} 个插件状态");
return; // 成功从备份加载,提前退出 return; // 成功从备份加载,提前退出
} }
} }
@@ -1082,13 +1082,13 @@ namespace Ink_Canvas.Helpers.Plugins
try try
{ {
string backupJson = File.ReadAllText(PluginConfigBackupFile); string backupJson = File.ReadAllText(PluginConfigBackupFile);
var backupStates = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, bool>>(backupJson); var backupStates = JsonConvert.DeserializeObject<Dictionary<string, bool>>(backupJson);
if (backupStates != null && backupStates.Count > 0) if (backupStates != null && backupStates.Count > 0)
{ {
PluginStates = backupStates; PluginStates = backupStates;
_configDirty = true; // 从备份加载,需要重新保存主配置 _configDirty = true; // 从备份加载,需要重新保存主配置
LogHelper.WriteLogToFile($"已从备份恢复 {PluginStates.Count} 个插件状态", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已从备份恢复 {PluginStates.Count} 个插件状态");
return; // 成功从备份加载,提前退出 return; // 成功从备份加载,提前退出
} }
} }
@@ -1111,7 +1111,7 @@ namespace Ink_Canvas.Helpers.Plugins
if (attempt < maxRetries) if (attempt < maxRetries)
{ {
LogHelper.WriteLogToFile($"加载配置失败 (尝试 {attempt}/{maxRetries}): {ex.Message},将在 {retryDelayMs}ms 后重试", LogHelper.LogType.Warning); LogHelper.WriteLogToFile($"加载配置失败 (尝试 {attempt}/{maxRetries}): {ex.Message},将在 {retryDelayMs}ms 后重试", LogHelper.LogType.Warning);
System.Threading.Thread.Sleep(retryDelayMs); Thread.Sleep(retryDelayMs);
} }
else else
{ {
@@ -1178,10 +1178,10 @@ namespace Ink_Canvas.Helpers.Plugins
try try
{ {
LogHelper.WriteLogToFile($"开始保存插件配置到: {PluginConfigFile}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"开始保存插件配置到: {PluginConfigFile}");
// 生成JSON数据 // 生成JSON数据
string json = Newtonsoft.Json.JsonConvert.SerializeObject(PluginStates, Newtonsoft.Json.Formatting.Indented); string json = JsonConvert.SerializeObject(PluginStates, Formatting.Indented);
string tempFile = PluginConfigFile + ".temp"; // 临时文件路径 string tempFile = PluginConfigFile + ".temp"; // 临时文件路径
// 确保目录存在 // 确保目录存在
@@ -1189,7 +1189,7 @@ namespace Ink_Canvas.Helpers.Plugins
if (!Directory.Exists(configDir)) if (!Directory.Exists(configDir))
{ {
Directory.CreateDirectory(configDir); Directory.CreateDirectory(configDir);
LogHelper.WriteLogToFile($"创建配置目录: {configDir}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"创建配置目录: {configDir}");
} }
// 先备份当前配置 // 先备份当前配置
@@ -1217,7 +1217,7 @@ namespace Ink_Canvas.Helpers.Plugins
{ {
// 重置脏标记 // 重置脏标记
_configDirty = false; _configDirty = false;
LogHelper.WriteLogToFile($"插件配置已成功保存到磁盘: {PluginConfigFile}, 共 {PluginStates.Count} 个插件状态", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件配置已成功保存到磁盘: {PluginConfigFile}, 共 {PluginStates.Count} 个插件状态");
return; return;
} }
} }
@@ -1226,7 +1226,7 @@ namespace Ink_Canvas.Helpers.Plugins
if (attempt < maxRetries) if (attempt < maxRetries)
{ {
LogHelper.WriteLogToFile($"保存配置失败 (尝试 {attempt}/{maxRetries}): {ex.Message},将在 {retryDelayMs}ms 后重试", LogHelper.LogType.Warning); LogHelper.WriteLogToFile($"保存配置失败 (尝试 {attempt}/{maxRetries}): {ex.Message},将在 {retryDelayMs}ms 后重试", LogHelper.LogType.Warning);
System.Threading.Thread.Sleep(retryDelayMs); Thread.Sleep(retryDelayMs);
} }
else else
{ {
@@ -1255,7 +1255,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 重置脏标记 // 重置脏标记
_configDirty = false; _configDirty = false;
LogHelper.WriteLogToFile($"使用临时文件方式成功保存配置: {PluginConfigFile}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"使用临时文件方式成功保存配置: {PluginConfigFile}");
return; return;
} }
catch (Exception fallbackEx) catch (Exception fallbackEx)
@@ -1302,7 +1302,7 @@ namespace Ink_Canvas.Helpers.Plugins
{ {
try try
{ {
LogHelper.WriteLogToFile("开始从配置文件重新加载插件状态", LogHelper.LogType.Info); LogHelper.WriteLogToFile("开始从配置文件重新加载插件状态");
// 保存当前配置状态,以便在加载失败时回滚 // 保存当前配置状态,以便在加载失败时回滚
Dictionary<string, bool> previousStates = new Dictionary<string, bool>(PluginStates); Dictionary<string, bool> previousStates = new Dictionary<string, bool>(PluginStates);
@@ -1318,7 +1318,7 @@ namespace Ink_Canvas.Helpers.Plugins
return; return;
} }
LogHelper.WriteLogToFile($"已加载 {PluginStates.Count} 个插件状态,开始应用...", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已加载 {PluginStates.Count} 个插件状态,开始应用...");
// 对比配置,查找变更的插件 // 对比配置,查找变更的插件
foreach (var plugin in Plugins.ToList()) // 创建副本进行遍历,避免集合修改异常 foreach (var plugin in Plugins.ToList()) // 创建副本进行遍历,避免集合修改异常
@@ -1333,7 +1333,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 如果状态需要变更 // 如果状态需要变更
if (currentlyEnabled != shouldBeEnabled) if (currentlyEnabled != shouldBeEnabled)
{ {
LogHelper.WriteLogToFile($"应用插件 {plugin.Name} 的配置状态: {(shouldBeEnabled ? "" : "")}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"应用插件 {plugin.Name} 的配置状态: {(shouldBeEnabled ? "" : "")}");
if (shouldBeEnabled) if (shouldBeEnabled)
{ {
@@ -1352,7 +1352,7 @@ namespace Ink_Canvas.Helpers.Plugins
{ {
// 记录禁用信息,特别是内置插件 // 记录禁用信息,特别是内置插件
bool isBuiltIn = plugin.IsBuiltIn; bool isBuiltIn = plugin.IsBuiltIn;
LogHelper.WriteLogToFile($"尝试禁用{(isBuiltIn ? "" : "")}插件 {plugin.Name}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"尝试禁用{(isBuiltIn ? "" : "")}插件 {plugin.Name}");
// 禁用插件 // 禁用插件
plugin.Disable(); plugin.Disable();
@@ -1368,7 +1368,7 @@ namespace Ink_Canvas.Helpers.Plugins
if (enabledProperty != null) if (enabledProperty != null)
{ {
enabledProperty.SetValue(builtInPluginBase, false); enabledProperty.SetValue(builtInPluginBase, false);
LogHelper.WriteLogToFile($"已通过反射强制禁用内置插件 {plugin.Name}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已通过反射强制禁用内置插件 {plugin.Name}");
} }
} }
} }
@@ -1397,7 +1397,7 @@ namespace Ink_Canvas.Helpers.Plugins
{ {
// 插件不在配置中,将其添加为禁用状态 // 插件不在配置中,将其添加为禁用状态
PluginStates[pluginTypeName] = false; PluginStates[pluginTypeName] = false;
LogHelper.WriteLogToFile($"插件 {plugin.Name} 不在配置中,默认设置为禁用状态", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {plugin.Name} 不在配置中,默认设置为禁用状态");
// 如果当前是启用状态,则禁用它 // 如果当前是启用状态,则禁用它
if (plugin is PluginBase pluginBase && pluginBase.IsEnabled) if (plugin is PluginBase pluginBase && pluginBase.IsEnabled)
@@ -1405,7 +1405,7 @@ namespace Ink_Canvas.Helpers.Plugins
try try
{ {
bool isBuiltIn = plugin.IsBuiltIn; bool isBuiltIn = plugin.IsBuiltIn;
LogHelper.WriteLogToFile($"尝试禁用未配置的{(isBuiltIn ? "" : "")}插件 {plugin.Name}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"尝试禁用未配置的{(isBuiltIn ? "" : "")}插件 {plugin.Name}");
plugin.Disable(); plugin.Disable();
@@ -1418,7 +1418,7 @@ namespace Ink_Canvas.Helpers.Plugins
if (enabledProperty != null) if (enabledProperty != null)
{ {
enabledProperty.SetValue(pluginBase, false); enabledProperty.SetValue(pluginBase, false);
LogHelper.WriteLogToFile($"已通过反射强制禁用未配置的内置插件 {plugin.Name}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已通过反射强制禁用未配置的内置插件 {plugin.Name}");
} }
} }
} }
@@ -1440,7 +1440,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 通知任何可能打开的插件设置窗口刷新 // 通知任何可能打开的插件设置窗口刷新
foreach (Window window in Application.Current.Windows) foreach (Window window in Application.Current.Windows)
{ {
if (window is Windows.PluginSettingsWindow pluginWindow) if (window is PluginSettingsWindow pluginWindow)
{ {
pluginWindow.RefreshPluginList(); pluginWindow.RefreshPluginList();
} }
@@ -1448,7 +1448,7 @@ namespace Ink_Canvas.Helpers.Plugins
}); });
} }
LogHelper.WriteLogToFile("插件状态已从配置文件重新加载完成", LogHelper.LogType.Info); LogHelper.WriteLogToFile("插件状态已从配置文件重新加载完成");
} }
catch (Exception ex) catch (Exception ex)
{ {
+5 -5
View File
@@ -53,7 +53,7 @@ namespace Ink_Canvas.Helpers.Plugins
// TODO: 在这里进行插件初始化工作 // TODO: 在这里进行插件初始化工作
// 示例:记录初始化信息 // 示例:记录初始化信息
LogHelper.WriteLogToFile($"插件 {Name} 开始初始化", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {Name} 开始初始化");
// 示例:加载配置 // 示例:加载配置
LoadConfig(); LoadConfig();
@@ -61,7 +61,7 @@ namespace Ink_Canvas.Helpers.Plugins
// 示例:注册自定义事件 // 示例:注册自定义事件
// MainWindow.Instance.SomeEvent += OnSomeEvent; // MainWindow.Instance.SomeEvent += OnSomeEvent;
LogHelper.WriteLogToFile($"插件 {Name} 初始化完成", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {Name} 初始化完成");
} }
/// <summary> /// <summary>
@@ -75,7 +75,7 @@ namespace Ink_Canvas.Helpers.Plugins
// TODO: 在这里启用插件功能 // TODO: 在这里启用插件功能
LogHelper.WriteLogToFile($"插件 {Name} 已启用", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {Name} 已启用");
} }
/// <summary> /// <summary>
@@ -89,7 +89,7 @@ namespace Ink_Canvas.Helpers.Plugins
// TODO: 在这里禁用插件功能 // TODO: 在这里禁用插件功能
LogHelper.WriteLogToFile($"插件 {Name} 已禁用", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {Name} 已禁用");
} }
/// <summary> /// <summary>
@@ -270,7 +270,7 @@ namespace Ink_Canvas.Helpers.Plugins
panel.Children.Add(button); panel.Children.Add(button);
// 设置控件内容 // 设置控件内容
this.Content = panel; Content = panel;
} }
} }
} }
+6 -8
View File
@@ -1,7 +1,8 @@
using Microsoft.Win32; using System;
using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace Ink_Canvas.Helpers namespace Ink_Canvas.Helpers
{ {
@@ -27,10 +28,7 @@ namespace Ink_Canvas.Helpers
//MessageBox.Show("启动失败: " + ex.Message); //MessageBox.Show("启动失败: " + ex.Message);
} }
} }
else //Console.WriteLine(softwareName + " 未找到可执行文件路径。");
{
//Console.WriteLine(softwareName + " 未找到可执行文件路径。");
}
} }
private static string FindEasiCameraExecutablePath(string softwareName) private static string FindEasiCameraExecutablePath(string softwareName)
@@ -51,7 +49,7 @@ namespace Ink_Canvas.Helpers
{ {
if (!string.IsNullOrEmpty(installLocation)) if (!string.IsNullOrEmpty(installLocation))
{ {
executablePath = System.IO.Path.Combine(installLocation, "sweclauncher.exe"); executablePath = Path.Combine(installLocation, "sweclauncher.exe");
} }
else if (!string.IsNullOrEmpty(uninstallString)) else if (!string.IsNullOrEmpty(uninstallString))
{ {
@@ -59,7 +57,7 @@ namespace Ink_Canvas.Helpers
if (lastSlashIndex >= 0) if (lastSlashIndex >= 0)
{ {
string folderPath = uninstallString.Substring(0, lastSlashIndex); string folderPath = uninstallString.Substring(0, lastSlashIndex);
executablePath = System.IO.Path.Combine(folderPath, "sweclauncher", "sweclauncher.exe"); executablePath = Path.Combine(folderPath, "sweclauncher", "sweclauncher.exe");
} }
} }
break; break;
+17 -2
View File
@@ -1,8 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows;
using System.Windows.Ink; using System.Windows.Ink;
using System.Windows.Input; using System.Windows.Input;
using System.Windows; // Added for UIElement
// Added for UIElement
namespace Ink_Canvas.Helpers namespace Ink_Canvas.Helpers
{ {
@@ -133,7 +135,7 @@ namespace Ink_Canvas.Helpers
public class TimeMachineHistory public class TimeMachineHistory
{ {
public TimeMachineHistoryType CommitType; public TimeMachineHistoryType CommitType;
public bool StrokeHasBeenCleared = false; public bool StrokeHasBeenCleared;
public StrokeCollection CurrentStroke; public StrokeCollection CurrentStroke;
public StrokeCollection ReplacedStroke; public StrokeCollection ReplacedStroke;
//这里说一下 Tuple的 Value1 是初始值 ; Value 2 是改变值 //这里说一下 Tuple的 Value1 是初始值 ; Value 2 是改变值
@@ -193,5 +195,18 @@ namespace Ink_Canvas.Helpers
_currentIndex = _currentStrokeHistory.Count - 1; _currentIndex = _currentStrokeHistory.Count - 1;
NotifyUndoRedoState(); NotifyUndoRedoState();
} }
public void CommitElementRemoveHistory(UIElement element)
{
if (_currentIndex + 1 < _currentStrokeHistory.Count)
{
_currentStrokeHistory.RemoveRange(_currentIndex + 1, (_currentStrokeHistory.Count - 1) - _currentIndex);
}
var history = new TimeMachineHistory(element, TimeMachineHistoryType.ElementInsert);
history.StrokeHasBeenCleared = true; // 标记为已清除
_currentStrokeHistory.Add(history);
_currentIndex = _currentStrokeHistory.Count - 1;
NotifyUndoRedoState();
}
} }
} }
+8
View File
@@ -113,12 +113,15 @@
<ItemGroup> <ItemGroup>
<Reference Include="IACore"> <Reference Include="IACore">
<HintPath>.\IACore.dll</HintPath> <HintPath>.\IACore.dll</HintPath>
<Private>False</Private>
</Reference> </Reference>
<Reference Include="IALoader"> <Reference Include="IALoader">
<HintPath>.\IALoader.dll</HintPath> <HintPath>.\IALoader.dll</HintPath>
<Private>False</Private>
</Reference> </Reference>
<Reference Include="IAWinFX"> <Reference Include="IAWinFX">
<HintPath>.\IAWinFX.dll</HintPath> <HintPath>.\IAWinFX.dll</HintPath>
<Private>False</Private>
</Reference> </Reference>
<Reference Include="Microsoft.VisualBasic" /> <Reference Include="Microsoft.VisualBasic" />
<Reference Include="netstandard" /> <Reference Include="netstandard" />
@@ -187,6 +190,11 @@
<ItemGroup> <ItemGroup>
<None Include="Resources\TimerDownNotice.wav" /> <None Include="Resources\TimerDownNotice.wav" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\IACore\IACore.dll" />
<EmbeddedResource Include="Resources\IACore\IALoader.dll" />
<EmbeddedResource Include="Resources\IACore\IAWinFX.dll" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\Cursor.cur" /> <Resource Include="Resources\Cursors\Cursor.cur" />
<Resource Include="Resources\Cursors\Pen.cur" /> <Resource Include="Resources\Cursors\Pen.cur" />
+52 -1
View File
@@ -774,6 +774,12 @@
FontFamily="Microsoft YaHei UI" FontWeight="Bold" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
Toggled="ToggleSwitchClearCanvasAndClearTimeMachine_Toggled" /> Toggled="ToggleSwitchClearCanvasAndClearTimeMachine_Toggled" />
</ui:SimpleStackPanel> </ui:SimpleStackPanel>
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Foreground="#fafafa" Text="清空画布时同时清空图片" VerticalAlignment="Center" FontSize="14" Margin="0,0,16,0" />
<ui:ToggleSwitch OnContent="" OffContent="" Name="ToggleSwitchClearCanvasAlsoClearImages"
IsOn="False" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
Toggled="ToggleSwitchClearCanvasAlsoClearImages_Toggled" />
</ui:SimpleStackPanel>
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left"> <ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Foreground="#fafafa" Text="插入图片时自动压缩(大于1920x1080" VerticalAlignment="Center" FontSize="14" Margin="0,0,16,0" /> <TextBlock Foreground="#fafafa" Text="插入图片时自动压缩(大于1920x1080" VerticalAlignment="Center" FontSize="14" Margin="0,0,16,0" />
<ui:ToggleSwitch OnContent="" OffContent="" Name="ToggleSwitchCompressPicturesUploaded" <ui:ToggleSwitch OnContent="" OffContent="" Name="ToggleSwitchCompressPicturesUploaded"
@@ -3143,6 +3149,52 @@
</ui:SimpleStackPanel> </ui:SimpleStackPanel>
</Viewbox> </Viewbox>
</Border> </Border>
<!-- 图片选择工具栏 -->
<Border Name="BorderImageSelectionControl"
HorizontalAlignment="Left" VerticalAlignment="Top" Margin="800,900,0,0"
CornerRadius="5" Height="80"
Background="{DynamicResource FloatBarBackground}"
Visibility="Collapsed"
BorderThickness="1" BorderBrush="{DynamicResource FloatBarBorderBrush}">
<Viewbox Margin="0,-2.5">
<ui:SimpleStackPanel Orientation="Horizontal" Spacing="10" Height="60">
<Border Name="BorderImageRotateLeft" Margin="0,2,-9,2" Background="Transparent"
CornerRadius="{Binding ElementName=BorderImageSelectionControl, Path=CornerRadius}"
Width="40" MouseDown="Border_MouseDown" MouseUp="BorderImageRotateLeft_MouseUp">
<ui:SimpleStackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Image Source="/Resources/Icons-Fluent/ic_fluent_flip_horizontal_24_regular.png"
RenderOptions.BitmapScalingMode="HighQuality" Height="25" Width="25" />
<TextBlock Text="左转" FontSize="10" Foreground="{DynamicResource FloatBarForeground}"
HorizontalAlignment="Center" />
</ui:SimpleStackPanel>
</Border>
<Border Name="BorderImageRotateRight" Margin="0,2,-9,2" Background="Transparent"
CornerRadius="{Binding ElementName=BorderImageSelectionControl, Path=CornerRadius}"
Width="40" MouseDown="Border_MouseDown" MouseUp="BorderImageRotateRight_MouseUp">
<ui:SimpleStackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Image Source="/Resources/Icons-Fluent/ic_fluent_flip_vertical_24_regular.png"
RenderOptions.BitmapScalingMode="HighQuality" Height="25" Width="25" />
<TextBlock Text="右转" FontSize="10" Foreground="{DynamicResource FloatBarForeground}"
HorizontalAlignment="Center" />
</ui:SimpleStackPanel>
</Border>
<Border Width="1" Height="45" BorderBrush="{DynamicResource FloatBarForeground}"
Background="{DynamicResource FloatBarForeground}" />
<Border Name="BorderImageDelete" Margin="-8,0,0,0"
CornerRadius="{Binding ElementName=BorderImageSelectionControl, Path=CornerRadius}"
Width="40" MouseDown="Border_MouseDown" MouseUp="BorderImageDelete_MouseUp">
<ui:SimpleStackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Image Source="/Resources/Icons-Fluent/ic_fluent_delete_24_regular.png"
RenderOptions.BitmapScalingMode="HighQuality" Height="25" Width="25" />
<TextBlock Margin="0,5,0,0" Text="删除" FontSize="10"
Foreground="{DynamicResource FloatBarForeground}"
HorizontalAlignment="Center" />
</ui:SimpleStackPanel>
</Border>
</ui:SimpleStackPanel>
</Viewbox>
</Border>
</Grid> </Grid>
<Grid Visibility="Collapsed"> <Grid Visibility="Collapsed">
@@ -5787,7 +5839,6 @@
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
FontSize="10" Text="/ 999" Name="PPTBtnPageTotal" /> FontSize="10" Text="/ 999" Name="PPTBtnPageTotal" />
</ui:SimpleStackPanel> </ui:SimpleStackPanel>
</Grid> </Grid>
</Border> </Border>
<Border Width="50" Height="50" MouseUp="GridPPTControlNext_MouseUp" <Border Width="50" Height="50" MouseUp="GridPPTControlNext_MouseUp"
+97 -66
View File
@@ -1,33 +1,44 @@
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern;
using System; using System;
using System.IO; using System.Collections.Generic;
using System.Windows; using System.ComponentModel;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Media;
using System.Diagnostics; using System.Diagnostics;
using File = System.IO.File; using System.IO;
using MessageBox = System.Windows.MessageBox; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows.Interop;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Win32; using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Ink;
using System.Windows.Input; using System.Windows.Input;
using System.Reflection; using System.Windows.Interop;
using Brushes = System.Windows.Media.Brushes; using System.Windows.Media;
using Point = System.Windows.Point; using System.Windows.Threading;
using System.Collections.Generic; using Ink_Canvas.Helpers;
using Ink_Canvas.Helpers.Plugins;
using Ink_Canvas.Windows;
using iNKORE.UI.WPF.Modern;
using iNKORE.UI.WPF.Modern.Controls; using iNKORE.UI.WPF.Modern.Controls;
using Microsoft.Win32;
using Application = System.Windows.Application;
using File = System.IO.File;
using MessageBox = System.Windows.MessageBox;
using Brushes = System.Windows.Media.Brushes;
using Button = System.Windows.Controls.Button;
using Cursor = System.Windows.Input.Cursor;
using Cursors = System.Windows.Input.Cursors;
using DpiChangedEventArgs = System.Windows.DpiChangedEventArgs;
using GroupBox = System.Windows.Controls.GroupBox;
using Point = System.Windows.Point;
namespace Ink_Canvas { namespace Ink_Canvas {
public partial class MainWindow : Window { public partial class MainWindow : Window {
// 新增:每一页一个Canvas对象 // 新增:每一页一个Canvas对象
private List<System.Windows.Controls.Canvas> whiteboardPages = new List<System.Windows.Controls.Canvas>(); private List<System.Windows.Controls.Canvas> whiteboardPages = new List<System.Windows.Controls.Canvas>();
private int currentPageIndex = 0; private int currentPageIndex;
private System.Windows.Controls.Canvas currentCanvas = null; private System.Windows.Controls.Canvas currentCanvas;
private AutoUpdateHelper.UpdateLineGroup AvailableLatestLineGroup = null; private AutoUpdateHelper.UpdateLineGroup AvailableLatestLineGroup;
@@ -58,7 +69,7 @@ namespace Ink_Canvas {
ViewBoxStackPanelMain.Visibility = Visibility.Collapsed; ViewBoxStackPanelMain.Visibility = Visibility.Collapsed;
ViewBoxStackPanelShapes.Visibility = Visibility.Collapsed; ViewBoxStackPanelShapes.Visibility = Visibility.Collapsed;
var workingArea = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea; var workingArea = Screen.PrimaryScreen.WorkingArea;
ViewboxFloatingBar.Margin = new Thickness( ViewboxFloatingBar.Margin = new Thickness(
(workingArea.Width - 284) / 2, (workingArea.Width - 284) / 2,
workingArea.Bottom - 60 - workingArea.Top, workingArea.Bottom - 60 - workingArea.Top,
@@ -81,7 +92,7 @@ namespace Ink_Canvas {
File.Delete("Log.txt"); File.Delete("Log.txt");
LogHelper.WriteLogToFile( LogHelper.WriteLogToFile(
"The Log.txt file has been successfully deleted. Original file size: " + fileSizeInKB + "The Log.txt file has been successfully deleted. Original file size: " + fileSizeInKB +
" KB", LogHelper.LogType.Info); " KB");
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile( LogHelper.WriteLogToFile(
@@ -99,7 +110,7 @@ namespace Ink_Canvas {
timeMachine.OnUndoStateChanged += TimeMachine_OnUndoStateChanged; timeMachine.OnUndoStateChanged += TimeMachine_OnUndoStateChanged;
inkCanvas.Strokes.StrokesChanged += StrokesOnStrokesChanged; inkCanvas.Strokes.StrokesChanged += StrokesOnStrokesChanged;
Microsoft.Win32.SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged; SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
try { try {
if (File.Exists("SpecialVersion.ini")) SpecialVersionResetToSuggestion_Click(); if (File.Exists("SpecialVersion.ini")) SpecialVersionResetToSuggestion_Click();
} }
@@ -111,7 +122,7 @@ namespace Ink_Canvas {
CheckPenTypeUIState(); CheckPenTypeUIState();
// 初始化墨迹平滑管理器 // 初始化墨迹平滑管理器
_inkSmoothingManager = new Helpers.InkSmoothingManager(Dispatcher); _inkSmoothingManager = new InkSmoothingManager(Dispatcher);
// 注册输入事件 // 注册输入事件
inkCanvas.PreviewMouseDown += inkCanvas_PreviewMouseDown; inkCanvas.PreviewMouseDown += inkCanvas_PreviewMouseDown;
@@ -182,10 +193,10 @@ namespace Ink_Canvas {
#region Ink Canvas Functions #region Ink Canvas Functions
private System.Windows.Media.Color Ink_DefaultColor = Colors.Red; private Color Ink_DefaultColor = Colors.Red;
private DrawingAttributes drawingAttributes; private DrawingAttributes drawingAttributes;
private Helpers.InkSmoothingManager _inkSmoothingManager; private InkSmoothingManager _inkSmoothingManager;
private void loadPenCanvas() { private void loadPenCanvas() {
try { try {
@@ -256,7 +267,7 @@ namespace Ink_Canvas {
if (inkCanvas1.EditingMode == InkCanvasEditingMode.Ink) forcePointEraser = !forcePointEraser; if (inkCanvas1.EditingMode == InkCanvasEditingMode.Ink) forcePointEraser = !forcePointEraser;
// 处理高级橡皮擦覆盖层的启用/禁用 // 处理高级橡皮擦覆盖层的启用/禁用
var eraserOverlay = this.FindName("AdvancedEraserOverlay") as Border; var eraserOverlay = FindName("AdvancedEraserOverlay") as Border;
if (eraserOverlay != null) { if (eraserOverlay != null) {
if (inkCanvas1.EditingMode == InkCanvasEditingMode.EraseByPoint) { if (inkCanvas1.EditingMode == InkCanvasEditingMode.EraseByPoint) {
// 橡皮擦模式下启用覆盖层 // 橡皮擦模式下启用覆盖层
@@ -278,8 +289,8 @@ namespace Ink_Canvas {
public static Settings Settings = new Settings(); public static Settings Settings = new Settings();
public static string settingsFileName = "Settings.json"; public static string settingsFileName = "Settings.json";
private bool isLoaded = false; private bool isLoaded;
private bool forcePointEraser = false; private bool forcePointEraser;
private void Window_Loaded(object sender, RoutedEventArgs e) { private void Window_Loaded(object sender, RoutedEventArgs e) {
loadPenCanvas(); loadPenCanvas();
@@ -290,7 +301,7 @@ namespace Ink_Canvas {
{ {
string savePath = Settings.Automation.AutoSavedStrokesLocation; string savePath = Settings.Automation.AutoSavedStrokesLocation;
bool needFix = false; bool needFix = false;
if (string.IsNullOrWhiteSpace(savePath) || !System.IO.Directory.Exists(savePath)) if (string.IsNullOrWhiteSpace(savePath) || !Directory.Exists(savePath))
{ {
needFix = true; needFix = true;
} }
@@ -299,9 +310,9 @@ namespace Ink_Canvas {
// 检查是否可写 // 检查是否可写
try try
{ {
string testFile = System.IO.Path.Combine(savePath, "test.tmp"); string testFile = Path.Combine(savePath, "test.tmp");
System.IO.File.WriteAllText(testFile, "test"); File.WriteAllText(testFile, "test");
System.IO.File.Delete(testFile); File.Delete(testFile);
} }
catch catch
{ {
@@ -310,10 +321,10 @@ namespace Ink_Canvas {
} }
if (needFix) if (needFix)
{ {
string newPath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "saves"); string newPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "saves");
Settings.Automation.AutoSavedStrokesLocation = newPath; Settings.Automation.AutoSavedStrokesLocation = newPath;
if (!System.IO.Directory.Exists(newPath)) if (!Directory.Exists(newPath))
System.IO.Directory.CreateDirectory(newPath); Directory.CreateDirectory(newPath);
SaveSettingsToFile(); SaveSettingsToFile();
LogHelper.WriteLogToFile($"自动修正保存路径为: {newPath}"); LogHelper.WriteLogToFile($"自动修正保存路径为: {newPath}");
} }
@@ -347,10 +358,10 @@ namespace Ink_Canvas {
BlackBoardRightSidePageListView.ItemsSource = blackBoardSidePageListViewObservableCollection; BlackBoardRightSidePageListView.ItemsSource = blackBoardSidePageListViewObservableCollection;
BtnLeftWhiteBoardSwitchPreviousGeometry.Brush = BtnLeftWhiteBoardSwitchPreviousGeometry.Brush =
new SolidColorBrush(System.Windows.Media.Color.FromArgb(127, 24, 24, 27)); new SolidColorBrush(Color.FromArgb(127, 24, 24, 27));
BtnLeftWhiteBoardSwitchPreviousLabel.Opacity = 0.5; BtnLeftWhiteBoardSwitchPreviousLabel.Opacity = 0.5;
BtnRightWhiteBoardSwitchPreviousGeometry.Brush = BtnRightWhiteBoardSwitchPreviousGeometry.Brush =
new SolidColorBrush(System.Windows.Media.Color.FromArgb(127, 24, 24, 27)); new SolidColorBrush(Color.FromArgb(127, 24, 24, 27));
BtnRightWhiteBoardSwitchPreviousLabel.Opacity = 0.5; BtnRightWhiteBoardSwitchPreviousLabel.Opacity = 0.5;
// 应用颜色主题,这将考虑自定义背景色 // 应用颜色主题,这将考虑自定义背景色
@@ -396,7 +407,7 @@ namespace Ink_Canvas {
// 确保背景颜色正确设置为黑板颜色 // 确保背景颜色正确设置为黑板颜色
CheckColorTheme(true); CheckColorTheme(true);
}), System.Windows.Threading.DispatcherPriority.Loaded); }), DispatcherPriority.Loaded);
} }
// 初始化插件系统 // 初始化插件系统
@@ -404,11 +415,14 @@ namespace Ink_Canvas {
// 确保开关和设置同步 // 确保开关和设置同步
ToggleSwitchNoFocusMode.IsOn = Settings.Advanced.IsNoFocusMode; ToggleSwitchNoFocusMode.IsOn = Settings.Advanced.IsNoFocusMode;
ApplyNoFocusMode(); ApplyNoFocusMode();
// 初始化UIElement选择系统
InitializeUIElementSelection();
} }
private void SystemEventsOnDisplaySettingsChanged(object sender, EventArgs e) { private void SystemEventsOnDisplaySettingsChanged(object sender, EventArgs e) {
if (!Settings.Advanced.IsEnableResolutionChangeDetection) return; if (!Settings.Advanced.IsEnableResolutionChangeDetection) return;
ShowNotification($"检测到显示器信息变化,变为{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width}x{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height}"); ShowNotification($"检测到显示器信息变化,变为{Screen.PrimaryScreen.Bounds.Width}x{Screen.PrimaryScreen.Bounds.Height}");
new Thread(() => { new Thread(() => {
var isFloatingBarOutsideScreen = false; var isFloatingBarOutsideScreen = false;
var isInPPTPresentationMode = false; var isInPPTPresentationMode = false;
@@ -452,7 +466,7 @@ namespace Ink_Canvas {
} }
} }
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { private void Window_Closing(object sender, CancelEventArgs e) {
LogHelper.WriteLogToFile("Ink Canvas closing", LogHelper.LogType.Event); LogHelper.WriteLogToFile("Ink Canvas closing", LogHelper.LogType.Event);
if (!CloseIsFromButton && Settings.Advanced.IsSecondConfirmWhenShutdownApp) { if (!CloseIsFromButton && Settings.Advanced.IsSecondConfirmWhenShutdownApp) {
e.Cancel = true; e.Cancel = true;
@@ -474,11 +488,11 @@ namespace Ink_Canvas {
private void MainWindow_OnSizeChanged(object sender, SizeChangedEventArgs e) { private void MainWindow_OnSizeChanged(object sender, SizeChangedEventArgs e) {
if (Settings.Advanced.IsEnableForceFullScreen) { if (Settings.Advanced.IsEnableForceFullScreen) {
if (isLoaded) ShowNotification( 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}"); $"检测到窗口大小变化,已自动恢复到全屏:{Screen.PrimaryScreen.Bounds.Width}x{Screen.PrimaryScreen.Bounds.Height}(缩放比例为{Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth}x{Screen.PrimaryScreen.Bounds.Height / SystemParameters.PrimaryScreenHeight}");
WindowState = WindowState.Maximized; WindowState = WindowState.Maximized;
MoveWindow(new WindowInteropHelper(this).Handle, 0, 0, MoveWindow(new WindowInteropHelper(this).Handle, 0, 0,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Width,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, true); Screen.PrimaryScreen.Bounds.Height, true);
} }
} }
@@ -946,23 +960,12 @@ namespace Ink_Canvas {
} }
UpdatePriorityTextBlock.Text = priorityText; UpdatePriorityTextBlock.Text = priorityText;
// 获取使用统计 // 获取使用统计(秒级精度)
var (launchCount, totalMinutes, avgSession, _) = DeviceIdentifier.GetUsageStats(); var (launchCount, totalSeconds, avgSessionSeconds, _) = DeviceIdentifier.GetUsageStats();
LaunchCountTextBlock.Text = launchCount.ToString(); LaunchCountTextBlock.Text = launchCount.ToString();
string totalUsageText; // 使用新的格式化方法显示秒级精度的使用时长
if (totalMinutes < 60) string totalUsageText = DeviceIdentifier.FormatDuration(totalSeconds);
{
totalUsageText = $"{totalMinutes}分钟";
}
else if (totalMinutes < 1440)
{
totalUsageText = $"{totalMinutes / 60}小时{totalMinutes % 60}分钟";
}
else
{
totalUsageText = $"{totalMinutes / 1440}天{(totalMinutes % 1440) / 60}小时";
}
TotalUsageTextBlock.Text = totalUsageText; TotalUsageTextBlock.Text = totalUsageText;
LogHelper.WriteLogToFile($"MainWindow | 设备信息已刷新 - ID: {deviceId}, 频率: {frequencyText}, 优先级: {priorityText}"); LogHelper.WriteLogToFile($"MainWindow | 设备信息已刷新 - ID: {deviceId}, 频率: {frequencyText}, 优先级: {priorityText}");
@@ -1012,7 +1015,7 @@ namespace Ink_Canvas {
BorderSettings.Visibility = Visibility.Visible; BorderSettings.Visibility = Visibility.Visible;
// 设置蒙版为可点击,并添加半透明背景 // 设置蒙版为可点击,并添加半透明背景
BorderSettingsMask.IsHitTestVisible = true; BorderSettingsMask.IsHitTestVisible = true;
BorderSettingsMask.Background = new SolidColorBrush(System.Windows.Media.Color.FromArgb(1, 0, 0, 0)); BorderSettingsMask.Background = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0));
// 获取SettingsPanelScrollViewer中的所有GroupBox // 获取SettingsPanelScrollViewer中的所有GroupBox
var stackPanel = SettingsPanelScrollViewer.Content as StackPanel; var stackPanel = SettingsPanelScrollViewer.Content as StackPanel;
@@ -1028,7 +1031,7 @@ namespace Ink_Canvas {
} }
// 确保UI完全更新 // 确保UI完全更新
await Dispatcher.InvokeAsync(() => {}, System.Windows.Threading.DispatcherPriority.Render); await Dispatcher.InvokeAsync(() => {}, DispatcherPriority.Render);
// 根据传入的sectionTag滚动到相应的设置部分 // 根据传入的sectionTag滚动到相应的设置部分
GroupBox targetGroupBox = null; GroupBox targetGroupBox = null;
@@ -1161,7 +1164,7 @@ namespace Ink_Canvas {
// 重新启用滚动事件处理 // 重新启用滚动事件处理
SettingsPanelScrollViewer.ScrollChanged += SettingsPanelScrollViewer_ScrollChanged; SettingsPanelScrollViewer.ScrollChanged += SettingsPanelScrollViewer_ScrollChanged;
} }
}, System.Windows.Threading.DispatcherPriority.Render); }, DispatcherPriority.Render);
} }
catch (Exception) catch (Exception)
{ {
@@ -1171,7 +1174,7 @@ namespace Ink_Canvas {
} }
// 滚动条变化事件处理 // 滚动条变化事件处理
private void SettingsPanelScrollViewer_ScrollChanged(object sender, System.Windows.Controls.ScrollChangedEventArgs e) private void SettingsPanelScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{ {
// 可以在这里添加滚动事件的处理逻辑,如果需要的话 // 可以在这里添加滚动事件的处理逻辑,如果需要的话
} }
@@ -1316,8 +1319,8 @@ namespace Ink_Canvas {
try try
{ {
// 初始化插件管理器 // 初始化插件管理器
Helpers.Plugins.PluginManager.Instance.Initialize(); PluginManager.Instance.Initialize();
LogHelper.WriteLogToFile("插件系统已初始化", LogHelper.LogType.Info); LogHelper.WriteLogToFile("插件系统已初始化");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -1341,7 +1344,7 @@ namespace Ink_Canvas {
BorderSettingsMask.Visibility = Visibility.Hidden; BorderSettingsMask.Visibility = Visibility.Hidden;
// 创建并显示插件设置窗口 // 创建并显示插件设置窗口
Windows.PluginSettingsWindow pluginSettingsWindow = new Windows.PluginSettingsWindow(); PluginSettingsWindow pluginSettingsWindow = new PluginSettingsWindow();
// 设置窗口关闭事件,用于在插件管理窗口关闭后恢复设置面板 // 设置窗口关闭事件,用于在插件管理窗口关闭后恢复设置面板
pluginSettingsWindow.Closed += (s, args) => pluginSettingsWindow.Closed += (s, args) =>
@@ -1401,7 +1404,7 @@ namespace Ink_Canvas {
// 只切换可见性 // 只切换可见性
for (int i = 0; i < whiteboardPages.Count; i++) for (int i = 0; i < whiteboardPages.Count; i++)
{ {
whiteboardPages[i].Visibility = (i == index) ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed; whiteboardPages[i].Visibility = (i == index) ? Visibility.Visible : Visibility.Collapsed;
} }
currentCanvas = whiteboardPages[index]; currentCanvas = whiteboardPages[index];
currentPageIndex = index; currentPageIndex = index;
@@ -1472,5 +1475,33 @@ namespace Ink_Canvas {
SaveSettingsToFile(); SaveSettingsToFile();
ApplyNoFocusMode(); ApplyNoFocusMode();
} }
#region Image Toolbar Event Handlers
private void BorderImageRotateLeft_MouseUp(object sender, MouseButtonEventArgs e)
{
if (selectedUIElement is Image image)
{
RotateImage(image, -90);
}
}
private void BorderImageRotateRight_MouseUp(object sender, MouseButtonEventArgs e)
{
if (selectedUIElement is Image image)
{
RotateImage(image, 90);
}
}
private void BorderImageDelete_MouseUp(object sender, MouseButtonEventArgs e)
{
if (selectedUIElement is Image image)
{
DeleteImage(image);
}
}
#endregion
} }
} }
+11 -11
View File
@@ -1,6 +1,4 @@
using Ink_Canvas.Helpers; using System;
using iNKORE.UI.WPF.Modern;
using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
@@ -8,11 +6,13 @@ using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Animation; using System.Windows.Media.Animation;
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern;
namespace Ink_Canvas { namespace Ink_Canvas {
public partial class MainWindow : Window { public partial class MainWindow : Window {
public bool isFloatingBarFolded = false; public bool isFloatingBarFolded;
private bool isFloatingBarChangingHideMode = false; private bool isFloatingBarChangingHideMode;
private void CloseWhiteboardImmediately() { private void CloseWhiteboardImmediately() {
if (isDisplayingOrHidingBlackboard) return; if (isDisplayingOrHidingBlackboard) return;
@@ -28,10 +28,10 @@ namespace Ink_Canvas {
BtnSwitch_Click(BtnSwitch, null); BtnSwitch_Click(BtnSwitch, null);
BtnExit.Foreground = Brushes.White; BtnExit.Foreground = Brushes.White;
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark; ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
new Thread(new ThreadStart(() => { new Thread(() => {
Thread.Sleep(200); Thread.Sleep(200);
Application.Current.Dispatcher.Invoke(() => { isDisplayingOrHidingBlackboard = false; }); Application.Current.Dispatcher.Invoke(() => { isDisplayingOrHidingBlackboard = false; });
})).Start(); }).Start();
} }
public async void FoldFloatingBar_MouseUp(object sender, MouseButtonEventArgs e) { public async void FoldFloatingBar_MouseUp(object sender, MouseButtonEventArgs e) {
@@ -98,7 +98,7 @@ namespace Ink_Canvas {
} }
private async void LeftUnFoldButtonDisplayQuickPanel_MouseUp(object sender, MouseButtonEventArgs e) { private async void LeftUnFoldButtonDisplayQuickPanel_MouseUp(object sender, MouseButtonEventArgs e) {
if (Settings.Appearance.IsShowQuickPanel == true) { if (Settings.Appearance.IsShowQuickPanel) {
HideRightQuickPanel(); HideRightQuickPanel();
LeftUnFoldButtonQuickPanel.Visibility = Visibility.Visible; LeftUnFoldButtonQuickPanel.Visibility = Visibility.Visible;
await Dispatcher.InvokeAsync(() => { await Dispatcher.InvokeAsync(() => {
@@ -122,7 +122,7 @@ namespace Ink_Canvas {
} }
private async void RightUnFoldButtonDisplayQuickPanel_MouseUp(object sender, MouseButtonEventArgs e) { private async void RightUnFoldButtonDisplayQuickPanel_MouseUp(object sender, MouseButtonEventArgs e) {
if (Settings.Appearance.IsShowQuickPanel == true) { if (Settings.Appearance.IsShowQuickPanel) {
HideLeftQuickPanel(); HideLeftQuickPanel();
RightUnFoldButtonQuickPanel.Visibility = Visibility.Visible; RightUnFoldButtonQuickPanel.Visibility = Visibility.Visible;
await Dispatcher.InvokeAsync(() => { await Dispatcher.InvokeAsync(() => {
@@ -249,13 +249,13 @@ namespace Ink_Canvas {
if (MarginFromEdge == -10) LeftSidePanel.Visibility = Visibility.Visible; if (MarginFromEdge == -10) LeftSidePanel.Visibility = Visibility.Visible;
var LeftSidePanelmarginAnimation = new ThicknessAnimation { var LeftSidePanelmarginAnimation = new ThicknessAnimation {
Duration = isNoAnimation == true ? TimeSpan.FromSeconds(0) : TimeSpan.FromSeconds(0.175), Duration = isNoAnimation ? TimeSpan.FromSeconds(0) : TimeSpan.FromSeconds(0.175),
From = LeftSidePanel.Margin, From = LeftSidePanel.Margin,
To = new Thickness(MarginFromEdge, 0, 0, -150) To = new Thickness(MarginFromEdge, 0, 0, -150)
}; };
LeftSidePanelmarginAnimation.EasingFunction = new CubicEase(); LeftSidePanelmarginAnimation.EasingFunction = new CubicEase();
var RightSidePanelmarginAnimation = new ThicknessAnimation { var RightSidePanelmarginAnimation = new ThicknessAnimation {
Duration = isNoAnimation == true ? TimeSpan.FromSeconds(0) : TimeSpan.FromSeconds(0.175), Duration = isNoAnimation ? TimeSpan.FromSeconds(0) : TimeSpan.FromSeconds(0.175),
From = RightSidePanel.Margin, From = RightSidePanel.Margin,
To = new Thickness(0, 0, MarginFromEdge, -150) To = new Thickness(0, 0, MarginFromEdge, -150)
}; };
+5 -3
View File
@@ -1,6 +1,8 @@
using System; using System;
using System.Windows; using System.Windows;
using IWshRuntimeLibrary; using IWshRuntimeLibrary;
using Application = System.Windows.Forms.Application;
using File = System.IO.File;
namespace Ink_Canvas { namespace Ink_Canvas {
public partial class MainWindow : Window { public partial class MainWindow : Window {
@@ -10,7 +12,7 @@ namespace Ink_Canvas {
var shortcut = (IWshShortcut)shell.CreateShortcut( var shortcut = (IWshShortcut)shell.CreateShortcut(
Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + exeName + ".lnk"); Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + exeName + ".lnk");
//设置快捷方式的目标所在的位置(源程序完整路径) //设置快捷方式的目标所在的位置(源程序完整路径)
shortcut.TargetPath = System.Windows.Forms.Application.ExecutablePath; shortcut.TargetPath = Application.ExecutablePath;
//应用程序的工作目录 //应用程序的工作目录
//当用户没有指定一个具体的目录时,快捷方式的目标应用程序将使用该属性所指定的目录来装载或保存文件。 //当用户没有指定一个具体的目录时,快捷方式的目标应用程序将使用该属性所指定的目录来装载或保存文件。
shortcut.WorkingDirectory = Environment.CurrentDirectory; shortcut.WorkingDirectory = Environment.CurrentDirectory;
@@ -30,8 +32,8 @@ namespace Ink_Canvas {
public static bool StartAutomaticallyDel(string exeName) { public static bool StartAutomaticallyDel(string exeName) {
try { try {
System.IO.File.Delete(Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + exeName + File.Delete(Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + exeName +
".lnk"); ".lnk");
return true; return true;
} }
catch (Exception) { } catch (Exception) { }
+11 -11
View File
@@ -1,8 +1,8 @@
using Microsoft.Win32; using System;
using iNKORE.UI.WPF.Modern;
using System;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using iNKORE.UI.WPF.Modern;
using Microsoft.Win32;
using Application = System.Windows.Application; using Application = System.Windows.Application;
namespace Ink_Canvas { namespace Ink_Canvas {
@@ -11,19 +11,19 @@ namespace Ink_Canvas {
private void SetTheme(string theme) { private void SetTheme(string theme) {
if (theme == "Light") { if (theme == "Light") {
var rd1 = new ResourceDictionary() var rd1 = new ResourceDictionary
{ Source = new Uri("Resources/Styles/Light.xaml", UriKind.Relative) }; { Source = new Uri("Resources/Styles/Light.xaml", UriKind.Relative) };
Application.Current.Resources.MergedDictionaries.Add(rd1); Application.Current.Resources.MergedDictionaries.Add(rd1);
var rd2 = new ResourceDictionary() var rd2 = new ResourceDictionary
{ Source = new Uri("Resources/DrawShapeImageDictionary.xaml", UriKind.Relative) }; { Source = new Uri("Resources/DrawShapeImageDictionary.xaml", UriKind.Relative) };
Application.Current.Resources.MergedDictionaries.Add(rd2); Application.Current.Resources.MergedDictionaries.Add(rd2);
var rd3 = new ResourceDictionary() var rd3 = new ResourceDictionary
{ Source = new Uri("Resources/SeewoImageDictionary.xaml", UriKind.Relative) }; { Source = new Uri("Resources/SeewoImageDictionary.xaml", UriKind.Relative) };
Application.Current.Resources.MergedDictionaries.Add(rd3); Application.Current.Resources.MergedDictionaries.Add(rd3);
var rd4 = new ResourceDictionary() var rd4 = new ResourceDictionary
{ Source = new Uri("Resources/IconImageDictionary.xaml", UriKind.Relative) }; { Source = new Uri("Resources/IconImageDictionary.xaml", UriKind.Relative) };
Application.Current.Resources.MergedDictionaries.Add(rd4); Application.Current.Resources.MergedDictionaries.Add(rd4);
@@ -32,18 +32,18 @@ namespace Ink_Canvas {
FloatBarForegroundColor = (Color)Application.Current.FindResource("FloatBarForegroundColor"); FloatBarForegroundColor = (Color)Application.Current.FindResource("FloatBarForegroundColor");
} }
else if (theme == "Dark") { else if (theme == "Dark") {
var rd1 = new ResourceDictionary() { Source = new Uri("Resources/Styles/Dark.xaml", UriKind.Relative) }; var rd1 = new ResourceDictionary { Source = new Uri("Resources/Styles/Dark.xaml", UriKind.Relative) };
Application.Current.Resources.MergedDictionaries.Add(rd1); Application.Current.Resources.MergedDictionaries.Add(rd1);
var rd2 = new ResourceDictionary() var rd2 = new ResourceDictionary
{ Source = new Uri("Resources/DrawShapeImageDictionary.xaml", UriKind.Relative) }; { Source = new Uri("Resources/DrawShapeImageDictionary.xaml", UriKind.Relative) };
Application.Current.Resources.MergedDictionaries.Add(rd2); Application.Current.Resources.MergedDictionaries.Add(rd2);
var rd3 = new ResourceDictionary() var rd3 = new ResourceDictionary
{ Source = new Uri("Resources/SeewoImageDictionary.xaml", UriKind.Relative) }; { Source = new Uri("Resources/SeewoImageDictionary.xaml", UriKind.Relative) };
Application.Current.Resources.MergedDictionaries.Add(rd3); Application.Current.Resources.MergedDictionaries.Add(rd3);
var rd4 = new ResourceDictionary() var rd4 = new ResourceDictionary
{ Source = new Uri("Resources/IconImageDictionary.xaml", UriKind.Relative) }; { Source = new Uri("Resources/IconImageDictionary.xaml", UriKind.Relative) };
Application.Current.Resources.MergedDictionaries.Add(rd4); Application.Current.Resources.MergedDictionaries.Add(rd4);
+37 -44
View File
@@ -32,69 +32,46 @@ namespace Ink_Canvas {
var timeMachineHistory = timeMachine.ExportTimeMachineHistory(); var timeMachineHistory = timeMachine.ExportTimeMachineHistory();
TimeMachineHistories[CurrentWhiteboardIndex] = timeMachineHistory; TimeMachineHistories[CurrentWhiteboardIndex] = timeMachineHistory;
timeMachine.ClearStrokeHistory(); timeMachine.ClearStrokeHistory();
// 保存当前页图片信息
var elementInfos = new List<CanvasElementInfo>();
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) { private void ClearStrokes(bool isErasedByCode) {
_currentCommitType = CommitReason.ClearingCanvas; _currentCommitType = CommitReason.ClearingCanvas;
if (isErasedByCode) _currentCommitType = CommitReason.CodeInput; if (isErasedByCode) _currentCommitType = CommitReason.CodeInput;
// 取消任何UI元素的选择,隐藏拉伸控件
DeselectUIElement();
// 只清除笔画,不清除图片元素
// 图片元素的清除由调用方决定
inkCanvas.Strokes.Clear(); inkCanvas.Strokes.Clear();
_currentCommitType = CommitReason.UserInput; _currentCommitType = CommitReason.UserInput;
} }
// 恢复每页白板图片信息 // 恢复每页白板图片信息
private void RestoreStrokes(bool isBackupMain = false) { private void RestoreStrokes(bool isBackupMain = false) {
try { try {
if (TimeMachineHistories[CurrentWhiteboardIndex] == null) return; //防止白板打开后不居中 var targetIndex = isBackupMain ? 0 : CurrentWhiteboardIndex;
// 先清空当前画布的所有内容(墨迹和图片)
// 这里必须清除图片,因为页面切换时需要完全重置画布状态
inkCanvas.Strokes.Clear();
inkCanvas.Children.Clear();
// 如果历史记录为空,直接返回(新页面或空页面)
if (TimeMachineHistories[targetIndex] == null) {
timeMachine.ClearStrokeHistory();
return;
}
if (isBackupMain) { if (isBackupMain) {
timeMachine.ImportTimeMachineHistory(TimeMachineHistories[0]); timeMachine.ImportTimeMachineHistory(TimeMachineHistories[0]);
foreach (var item in TimeMachineHistories[0]) ApplyHistoryToCanvas(item); foreach (var item in TimeMachineHistories[0]) ApplyHistoryToCanvas(item);
} else { } else {
timeMachine.ImportTimeMachineHistory(TimeMachineHistories[CurrentWhiteboardIndex]); timeMachine.ImportTimeMachineHistory(TimeMachineHistories[CurrentWhiteboardIndex]);
// 通过时间机器历史恢复所有内容(墨迹和图片)
foreach (var item in TimeMachineHistories[CurrentWhiteboardIndex]) ApplyHistoryToCanvas(item); 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<List<CanvasElementInfo>>(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
};
InkCanvas.SetLeft(img, info.Left);
InkCanvas.SetTop(img, info.Top);
inkCanvas.Children.Add(img);
}
}
}
} }
} }
catch { catch {
@@ -135,6 +112,9 @@ namespace Ink_Canvas {
private void BtnWhiteBoardSwitchPrevious_Click(object sender, EventArgs e) { private void BtnWhiteBoardSwitchPrevious_Click(object sender, EventArgs e) {
if (CurrentWhiteboardIndex <= 1) return; if (CurrentWhiteboardIndex <= 1) return;
// 取消任何UI元素的选择
DeselectUIElement();
SaveStrokes(); SaveStrokes();
ClearStrokes(true); ClearStrokes(true);
@@ -156,6 +136,9 @@ namespace Ink_Canvas {
return; return;
} }
// 取消任何UI元素的选择
DeselectUIElement();
SaveStrokes(); SaveStrokes();
ClearStrokes(true); ClearStrokes(true);
@@ -170,6 +153,10 @@ namespace Ink_Canvas {
if (WhiteboardTotalCount >= 99) return; if (WhiteboardTotalCount >= 99) return;
if (Settings.Automation.IsAutoSaveStrokesAtClear && if (Settings.Automation.IsAutoSaveStrokesAtClear &&
inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) SaveScreenShot(true); inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) SaveScreenShot(true);
// 取消任何UI元素的选择
DeselectUIElement();
SaveStrokes(); SaveStrokes();
ClearStrokes(true); ClearStrokes(true);
@@ -180,6 +167,12 @@ namespace Ink_Canvas {
for (var i = WhiteboardTotalCount; i > CurrentWhiteboardIndex; i--) for (var i = WhiteboardTotalCount; i > CurrentWhiteboardIndex; i--)
TimeMachineHistories[i] = TimeMachineHistories[i - 1]; TimeMachineHistories[i] = TimeMachineHistories[i - 1];
// 确保新页面的历史记录为空
TimeMachineHistories[CurrentWhiteboardIndex] = null;
// 恢复新页面(这会清空画布,因为历史记录为null)
RestoreStrokes();
UpdateIndexInfoDisplay(); UpdateIndexInfoDisplay();
if (WhiteboardTotalCount >= 99) BtnWhiteBoardAdd.IsEnabled = false; if (WhiteboardTotalCount >= 99) BtnWhiteBoardAdd.IsEnabled = false;
+46 -13
View File
@@ -1,11 +1,12 @@
using Ink_Canvas.Helpers; using System;
using System;
using System.Diagnostics; using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Ink; using System.Windows.Ink;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging;
using Ink_Canvas.Helpers;
namespace Ink_Canvas { namespace Ink_Canvas {
public partial class MainWindow : Window { public partial class MainWindow : Window {
@@ -138,7 +139,7 @@ namespace Ink_Canvas {
}; };
// 确保面板显示在顶层 // 确保面板显示在顶层
System.Windows.Controls.Panel.SetZIndex(BackgroundPalette, 1000); Panel.SetZIndex(BackgroundPalette, 1000);
// 创建面板内容 // 创建面板内容
var stackPanel = new StackPanel(); var stackPanel = new StackPanel();
@@ -169,9 +170,9 @@ namespace Ink_Canvas {
titleCanvas.Children.Add(titleText); titleCanvas.Children.Add(titleText);
// 关闭按钮 // 关闭按钮
var closeImage = new System.Windows.Controls.Image var closeImage = new Image
{ {
Source = new System.Windows.Media.Imaging.BitmapImage(new Uri("/Resources/new-icons/close-white.png", UriKind.Relative)), Source = new BitmapImage(new Uri("/Resources/new-icons/close-white.png", UriKind.Relative)),
Height = 16, Height = 16,
Width = 16 Width = 16
}; };
@@ -370,7 +371,7 @@ namespace Ink_Canvas {
// R滑块和文本框 // R滑块和文本框
var rPanel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(10, 0, 10, 5) }; var rPanel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(10, 0, 10, 5) };
var rLabel = new TextBlock { Text = "R:", Width = 20, VerticalAlignment = VerticalAlignment.Center }; var rLabel = new TextBlock { Text = "R:", Width = 20, VerticalAlignment = VerticalAlignment.Center };
var rSlider = new System.Windows.Controls.Slider var rSlider = new Slider
{ {
Minimum = 0, Minimum = 0,
Maximum = 255, Maximum = 255,
@@ -390,7 +391,7 @@ namespace Ink_Canvas {
// G滑块和文本框 // G滑块和文本框
var gPanel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(10, 0, 10, 5) }; var gPanel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(10, 0, 10, 5) };
var gLabel = new TextBlock { Text = "G:", Width = 20, VerticalAlignment = VerticalAlignment.Center }; var gLabel = new TextBlock { Text = "G:", Width = 20, VerticalAlignment = VerticalAlignment.Center };
var gSlider = new System.Windows.Controls.Slider var gSlider = new Slider
{ {
Minimum = 0, Minimum = 0,
Maximum = 255, Maximum = 255,
@@ -410,7 +411,7 @@ namespace Ink_Canvas {
// B滑块和文本框 // B滑块和文本框
var bPanel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(10, 0, 10, 5) }; var bPanel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(10, 0, 10, 5) };
var bLabel = new TextBlock { Text = "B:", Width = 20, VerticalAlignment = VerticalAlignment.Center }; var bLabel = new TextBlock { Text = "B:", Width = 20, VerticalAlignment = VerticalAlignment.Center };
var bSlider = new System.Windows.Controls.Slider var bSlider = new Slider
{ {
Minimum = 0, Minimum = 0,
Maximum = 255, Maximum = 255,
@@ -575,7 +576,7 @@ namespace Ink_Canvas {
/// <summary> /// <summary>
/// 更新颜色预览框的颜色 /// 更新颜色预览框的颜色
/// </summary> /// </summary>
private void UpdateColorPreview(Border colorPreview, System.Windows.Controls.Slider rSlider, System.Windows.Controls.Slider gSlider, System.Windows.Controls.Slider bSlider) private void UpdateColorPreview(Border colorPreview, Slider rSlider, Slider gSlider, Slider bSlider)
{ {
Color previewColor = Color.FromRgb( Color previewColor = Color.FromRgb(
(byte)rSlider.Value, (byte)rSlider.Value,
@@ -716,12 +717,44 @@ namespace Ink_Canvas {
private void BoardSymbolIconDelete_MouseUp(object sender, RoutedEventArgs e) { private void BoardSymbolIconDelete_MouseUp(object sender, RoutedEventArgs e) {
PenIcon_Click(null, null); PenIcon_Click(null, null);
SymbolIconDelete_MouseUp(null, null); SymbolIconDelete_MouseUp(null, null);
// 根据设置决定是否清空图片
if (Settings.Canvas.ClearCanvasAlsoClearImages) {
// 如果设置为清空图片,则直接清空所有子元素
Debug.WriteLine("BoardSymbolIconDelete: Clearing all children including images");
inkCanvas.Children.Clear();
} else {
// 保存非笔画元素(如图片)
Debug.WriteLine("BoardSymbolIconDelete: Preserving non-stroke elements (images)");
var preservedElements = PreserveNonStrokeElements();
Debug.WriteLine($"BoardSymbolIconDelete: Preserved elements count: {preservedElements.Count}");
inkCanvas.Children.Clear();
// 恢复非笔画元素
RestoreNonStrokeElements(preservedElements);
Debug.WriteLine($"BoardSymbolIconDelete: inkCanvas.Children.Count after restore: {inkCanvas.Children.Count}");
}
} }
private void BoardSymbolIconDeleteInkAndHistories_MouseUp(object sender, RoutedEventArgs e) private void BoardSymbolIconDeleteInkAndHistories_MouseUp(object sender, RoutedEventArgs e)
{ {
PenIcon_Click(null, null); PenIcon_Click(null, null);
SymbolIconDelete_MouseUp(null, null); SymbolIconDelete_MouseUp(null, null);
if (Settings.Canvas.ClearCanvasAndClearTimeMachine == false) timeMachine.ClearStrokeHistory(); if (Settings.Canvas.ClearCanvasAndClearTimeMachine == false) timeMachine.ClearStrokeHistory();
// 根据设置决定是否清空图片
if (Settings.Canvas.ClearCanvasAlsoClearImages) {
// 如果设置为清空图片,则直接清空所有子元素
Debug.WriteLine("BoardSymbolIconDeleteInkAndHistories: Clearing all children including images");
inkCanvas.Children.Clear();
} else {
// 保存非笔画元素(如图片)
Debug.WriteLine("BoardSymbolIconDeleteInkAndHistories: Preserving non-stroke elements (images)");
var preservedElements = PreserveNonStrokeElements();
Debug.WriteLine($"BoardSymbolIconDeleteInkAndHistories: Preserved elements count: {preservedElements.Count}");
inkCanvas.Children.Clear();
// 恢复非笔画元素
RestoreNonStrokeElements(preservedElements);
Debug.WriteLine($"BoardSymbolIconDeleteInkAndHistories: inkCanvas.Children.Count after restore: {inkCanvas.Children.Count}");
}
} }
private void BoardLaunchEasiCamera_MouseUp(object sender, MouseButtonEventArgs e) { private void BoardLaunchEasiCamera_MouseUp(object sender, MouseButtonEventArgs e) {
@@ -745,9 +778,9 @@ namespace Ink_Canvas {
if (stackPanel.Children.Count > 1 && stackPanel.Children[1] is StackPanel contentPanel) if (stackPanel.Children.Count > 1 && stackPanel.Children[1] is StackPanel contentPanel)
{ {
// 查找RGB滑块 // 查找RGB滑块
System.Windows.Controls.Slider rSlider = null; Slider rSlider = null;
System.Windows.Controls.Slider gSlider = null; Slider gSlider = null;
System.Windows.Controls.Slider bSlider = null; Slider bSlider = null;
// 遍历面板查找RGB滑块 // 遍历面板查找RGB滑块
foreach (var child in contentPanel.Children) foreach (var child in contentPanel.Children)
@@ -756,7 +789,7 @@ namespace Ink_Canvas {
{ {
foreach (var panelChild in panel.Children) foreach (var panelChild in panel.Children)
{ {
if (panelChild is System.Windows.Controls.Slider slider) if (panelChild is Slider slider)
{ {
if (panel.Children.Count > 0 && panel.Children[0] is TextBlock label) if (panel.Children.Count > 0 && panel.Children[0] is TextBlock label)
{ {
+8 -9
View File
@@ -1,15 +1,14 @@
using Ink_Canvas.Helpers; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Ink; using System.Windows.Ink;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation; using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using Ink_Canvas.Helpers;
namespace Ink_Canvas { namespace Ink_Canvas {
public partial class MainWindow : Window { public partial class MainWindow : Window {
@@ -59,8 +58,8 @@ namespace Ink_Canvas {
isLongPressSelected = false; isLongPressSelected = false;
} }
private bool isUselightThemeColor = false, isDesktopUselightThemeColor = false; private bool isUselightThemeColor, isDesktopUselightThemeColor;
private int penType = 0; // 0是签字笔,1是荧光笔 private int penType; // 0是签字笔,1是荧光笔
private int lastDesktopInkColor = 1, lastBoardInkColor = 5; private int lastDesktopInkColor = 1, lastBoardInkColor = 5;
private int highlighterColor = 102; private int highlighterColor = 102;
@@ -388,7 +387,7 @@ namespace Ink_Canvas {
} }
private void CheckLastColor(int inkColor, bool isHighlighter = false) { private void CheckLastColor(int inkColor, bool isHighlighter = false) {
if (isHighlighter == true) { if (isHighlighter) {
highlighterColor = inkColor; highlighterColor = inkColor;
} }
else { else {
@@ -41,6 +41,10 @@ namespace Ink_Canvas
inkCanvas.Children.Add(image); inkCanvas.Children.Add(image);
// 添加鼠标事件处理,使图片可以被选择
image.MouseDown += UIElement_MouseDown;
image.IsManipulationEnabled = true;
timeMachine.CommitElementInsertHistory(image); timeMachine.CommitElementInsertHistory(image);
} }
} }
@@ -72,6 +76,9 @@ namespace Ink_Canvas
int height = bitmapImage.PixelHeight; int height = bitmapImage.PixelHeight;
Image image = new Image(); Image image = new Image();
// 设置拉伸模式为Fill,支持任意比例缩放
image.Stretch = Stretch.Fill;
if (isLoaded && Settings.Canvas.IsCompressPicturesUploaded && (width > 1920 || height > 1080)) if (isLoaded && Settings.Canvas.IsCompressPicturesUploaded && (width > 1920 || height > 1080))
{ {
double scaleX = 1920.0 / width; double scaleX = 1920.0 / width;
@@ -116,6 +123,10 @@ namespace Ink_Canvas
InkCanvas.SetTop(mediaElement, 0); InkCanvas.SetTop(mediaElement, 0);
inkCanvas.Children.Add(mediaElement); inkCanvas.Children.Add(mediaElement);
// 添加鼠标事件处理,使媒体元素可以被选择
mediaElement.MouseDown += UIElement_MouseDown;
mediaElement.IsManipulationEnabled = true;
mediaElement.LoadedBehavior = MediaState.Manual; mediaElement.LoadedBehavior = MediaState.Manual;
mediaElement.UnloadedBehavior = MediaState.Manual; mediaElement.UnloadedBehavior = MediaState.Manual;
mediaElement.Loaded += async (_, args) => mediaElement.Loaded += async (_, args) =>
@@ -160,5 +171,90 @@ namespace Ink_Canvas
}); });
} }
#endregion #endregion
#region Image Operations
/// <summary>
/// 旋转图片
/// </summary>
/// <param name="image">要旋转的图片</param>
/// <param name="angle">旋转角度(正数为顺时针,负数为逆时针)</param>
private void RotateImage(Image image, double angle)
{
if (image == null) return;
try
{
// 获取当前的变换
var transformGroup = image.RenderTransform as TransformGroup ?? new TransformGroup();
// 查找现有的旋转变换
RotateTransform rotateTransform = null;
foreach (Transform transform in transformGroup.Children)
{
if (transform is RotateTransform rt)
{
rotateTransform = rt;
break;
}
}
// 如果没有旋转变换,创建一个新的
if (rotateTransform == null)
{
rotateTransform = new RotateTransform();
transformGroup.Children.Add(rotateTransform);
}
// 设置旋转中心为图片中心
rotateTransform.CenterX = image.ActualWidth / 2;
rotateTransform.CenterY = image.ActualHeight / 2;
// 累加旋转角度
rotateTransform.Angle = (rotateTransform.Angle + angle) % 360;
// 应用变换
image.RenderTransform = transformGroup;
// 提交到时间机器以支持撤销
// 注意:旋转操作目前不支持撤销,因为需要更复杂的历史记录机制
}
catch (Exception ex)
{
// 记录错误但不中断程序
System.Diagnostics.Debug.WriteLine($"旋转图片时发生错误: {ex.Message}");
}
}
/// <summary>
/// 删除图片
/// </summary>
/// <param name="image">要删除的图片</param>
private void DeleteImage(Image image)
{
if (image == null) return;
try
{
// 从画布中移除图片
if (inkCanvas.Children.Contains(image))
{
inkCanvas.Children.Remove(image);
// 取消选择
DeselectUIElement();
// 提交到时间机器以支持撤销
timeMachine.CommitElementRemoveHistory(image);
}
}
catch (Exception ex)
{
// 记录错误但不中断程序
System.Diagnostics.Debug.WriteLine($"删除图片时发生错误: {ex.Message}");
}
}
#endregion
} }
} }
+26 -25
View File
@@ -12,18 +12,18 @@ namespace Ink_Canvas {
public partial class MainWindow : Window { public partial class MainWindow : Window {
// 新橡皮擦系统的核心变量 // 新橡皮擦系统的核心变量
public bool isUsingAdvancedEraser = false; public bool isUsingAdvancedEraser;
private IncrementalStrokeHitTester advancedHitTester = null; private IncrementalStrokeHitTester advancedHitTester;
// 橡皮擦配置 // 橡皮擦配置
public double currentEraserSize = 64; public double currentEraserSize = 64;
public bool isCurrentEraserCircle = false; public bool isCurrentEraserCircle;
public bool isUsingStrokeEraser = false; public bool isUsingStrokeEraser;
// 视觉反馈相关 // 视觉反馈相关
private Matrix eraserTransformMatrix = new Matrix(); private Matrix eraserTransformMatrix;
private Point lastEraserPosition = new Point(); private Point lastEraserPosition;
private bool isEraserVisible = false; private bool isEraserVisible;
// 性能优化相关 // 性能优化相关
private DateTime lastEraserUpdate = DateTime.Now; private DateTime lastEraserUpdate = DateTime.Now;
@@ -35,7 +35,7 @@ namespace Ink_Canvas {
// 橡皮擦视觉反馈控件 // 橡皮擦视觉反馈控件
private DrawingVisual eraserVisual = new DrawingVisual(); private DrawingVisual eraserVisual = new DrawingVisual();
private VisualCanvas eraserOverlayCanvas = null; private VisualCanvas eraserOverlayCanvas = null;
private Border eraserVisualBorder = null; // 用于显示橡皮擦视觉反馈的Border private Border eraserVisualBorder; // 用于显示橡皮擦视觉反馈的Border
// 兼容性属性:模拟原有的EraserOverlay_DrawingVisual // 兼容性属性:模拟原有的EraserOverlay_DrawingVisual
private VisualCanvas EraserOverlay_DrawingVisual => eraserOverlayCanvas; private VisualCanvas EraserOverlay_DrawingVisual => eraserOverlayCanvas;
@@ -102,7 +102,7 @@ namespace Ink_Canvas {
UpdateEraserSize(); UpdateEraserSize();
// 获取inkCanvas引用 // 获取inkCanvas引用
var inkCanvas = this.FindName("inkCanvas") as InkCanvas; var inkCanvas = FindName("inkCanvas") as InkCanvas;
if (inkCanvas == null) return; if (inkCanvas == null) return;
// 根据橡皮擦形状创建碰撞检测器 // 根据橡皮擦形状创建碰撞检测器
@@ -117,13 +117,14 @@ namespace Ink_Canvas {
/// <summary> /// <summary>
/// 创建橡皮擦形状 /// 创建橡皮擦形状
/// </summary> /// </summary>
private StylusShape CreateEraserShape() { private StylusShape CreateEraserShape()
{
if (isCurrentEraserCircle) { if (isCurrentEraserCircle) {
return new EllipseStylusShape(currentEraserSize, currentEraserSize); return new EllipseStylusShape(currentEraserSize, currentEraserSize);
} else {
// 矩形橡皮擦,使用与原来相同的逻辑
return new RectangleStylusShape(currentEraserSize, currentEraserSize / 0.6);
} }
// 矩形橡皮擦,使用与原来相同的逻辑
return new RectangleStylusShape(currentEraserSize, currentEraserSize / 0.6);
} }
/// <summary> /// <summary>
@@ -231,7 +232,7 @@ namespace Ink_Canvas {
/// </summary> /// </summary>
private void OnAdvancedEraserStrokeHit(object sender, StrokeHitEventArgs args) { private void OnAdvancedEraserStrokeHit(object sender, StrokeHitEventArgs args) {
try { try {
var inkCanvas = this.FindName("inkCanvas") as InkCanvas; var inkCanvas = FindName("inkCanvas") as InkCanvas;
if (inkCanvas == null) return; if (inkCanvas == null) return;
var eraseResult = args.GetPointEraseResults(); var eraseResult = args.GetPointEraseResults();
@@ -296,7 +297,7 @@ namespace Ink_Canvas {
/// </summary> /// </summary>
private void ProcessStrokeEraserAtPosition(Point position) { private void ProcessStrokeEraserAtPosition(Point position) {
try { try {
var inkCanvas = this.FindName("inkCanvas") as InkCanvas; var inkCanvas = FindName("inkCanvas") as InkCanvas;
if (inkCanvas == null) return; if (inkCanvas == null) return;
var hitStrokes = inkCanvas.Strokes.HitTest(position) var hitStrokes = inkCanvas.Strokes.HitTest(position)
@@ -343,7 +344,7 @@ namespace Ink_Canvas {
Panel.SetZIndex(eraserVisualBorder, 1001); Panel.SetZIndex(eraserVisualBorder, 1001);
// 将Border添加到InkCanvasGridForInkReplay中 // 将Border添加到InkCanvasGridForInkReplay中
var inkCanvasGrid = this.FindName("InkCanvasGridForInkReplay") as Grid; var inkCanvasGrid = FindName("InkCanvasGridForInkReplay") as Grid;
if (inkCanvasGrid != null) { if (inkCanvasGrid != null) {
inkCanvasGrid.Children.Add(eraserVisualBorder); inkCanvasGrid.Children.Add(eraserVisualBorder);
Trace.WriteLine("Advanced Eraser: Visual feedback border added to grid"); Trace.WriteLine("Advanced Eraser: Visual feedback border added to grid");
@@ -401,7 +402,7 @@ namespace Ink_Canvas {
string resourceKey = isCurrentEraserCircle ? "EraserCircleDrawingGroup" : "EraserDrawingGroup"; string resourceKey = isCurrentEraserCircle ? "EraserCircleDrawingGroup" : "EraserDrawingGroup";
// 尝试从资源字典中获取DrawingGroup // 尝试从资源字典中获取DrawingGroup
var drawingGroup = this.TryFindResource(resourceKey) as DrawingGroup; var drawingGroup = TryFindResource(resourceKey) as DrawingGroup;
if (drawingGroup == null) { if (drawingGroup == null) {
// 如果找不到资源,创建默认的橡皮擦图像 // 如果找不到资源,创建默认的橡皮擦图像
return CreateDefaultEraserImage(); return CreateDefaultEraserImage();
@@ -525,7 +526,7 @@ namespace Ink_Canvas {
/// 获取当前橡皮擦状态信息(用于调试) /// 获取当前橡皮擦状态信息(用于调试)
/// </summary> /// </summary>
public string GetEraserStatusInfo() { public string GetEraserStatusInfo() {
return $"Advanced Eraser Status:\n" + return "Advanced Eraser Status:\n" +
$"- Active: {isUsingAdvancedEraser}\n" + $"- Active: {isUsingAdvancedEraser}\n" +
$"- Size: {currentEraserSize:F1}\n" + $"- Size: {currentEraserSize:F1}\n" +
$"- Shape: {(isCurrentEraserCircle ? "Circle" : "Rectangle")}\n" + $"- Shape: {(isCurrentEraserCircle ? "Circle" : "Rectangle")}\n" +
@@ -551,7 +552,7 @@ namespace Ink_Canvas {
// 清理视觉反馈Border // 清理视觉反馈Border
if (eraserVisualBorder != null) { if (eraserVisualBorder != null) {
var inkCanvasGrid = this.FindName("InkCanvasGridForInkReplay") as Grid; var inkCanvasGrid = FindName("InkCanvasGridForInkReplay") as Grid;
if (inkCanvasGrid != null) { if (inkCanvasGrid != null) {
inkCanvasGrid.Children.Remove(eraserVisualBorder); inkCanvasGrid.Children.Remove(eraserVisualBorder);
} }
@@ -564,7 +565,7 @@ namespace Ink_Canvas {
/// </summary> /// </summary>
public void ApplyAdvancedEraserShape() { public void ApplyAdvancedEraserShape() {
try { try {
var inkCanvas = this.FindName("inkCanvas") as InkCanvas; var inkCanvas = FindName("inkCanvas") as InkCanvas;
if (inkCanvas == null) return; if (inkCanvas == null) return;
// 更新橡皮擦尺寸和形状 // 更新橡皮擦尺寸和形状
@@ -595,7 +596,7 @@ namespace Ink_Canvas {
public void EnableAdvancedEraserSystem() { public void EnableAdvancedEraserSystem() {
try { try {
// 获取橡皮擦覆盖层 // 获取橡皮擦覆盖层
var eraserOverlay = this.FindName("AdvancedEraserOverlay") as Border; var eraserOverlay = FindName("AdvancedEraserOverlay") as Border;
if (eraserOverlay != null) { if (eraserOverlay != null) {
// 启用覆盖层的交互 // 启用覆盖层的交互
eraserOverlay.IsHitTestVisible = true; eraserOverlay.IsHitTestVisible = true;
@@ -607,7 +608,7 @@ namespace Ink_Canvas {
} }
// 设置覆盖层的大小以覆盖整个InkCanvas // 设置覆盖层的大小以覆盖整个InkCanvas
var inkCanvasControl = this.FindName("inkCanvas") as InkCanvas; var inkCanvasControl = FindName("inkCanvas") as InkCanvas;
if (inkCanvasControl != null) { if (inkCanvasControl != null) {
eraserOverlay.Width = inkCanvasControl.ActualWidth; eraserOverlay.Width = inkCanvasControl.ActualWidth;
eraserOverlay.Height = inkCanvasControl.ActualHeight; eraserOverlay.Height = inkCanvasControl.ActualHeight;
@@ -649,7 +650,7 @@ namespace Ink_Canvas {
overlay.MouseMove += (sender, e) => { overlay.MouseMove += (sender, e) => {
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) { if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
var position = e.GetPosition((UIElement)this.FindName("inkCanvas")); var position = e.GetPosition((UIElement)FindName("inkCanvas"));
Trace.WriteLine($"Advanced Eraser: Mouse move event triggered at ({position.X:F1}, {position.Y:F1})"); Trace.WriteLine($"Advanced Eraser: Mouse move event triggered at ({position.X:F1}, {position.Y:F1})");
UpdateAdvancedEraserPosition(sender, position); UpdateAdvancedEraserPosition(sender, position);
} else { } else {
@@ -681,7 +682,7 @@ namespace Ink_Canvas {
overlay.StylusMove += (sender, e) => { overlay.StylusMove += (sender, e) => {
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) { if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
e.Handled = true; e.Handled = true;
var position = e.GetPosition((UIElement)this.FindName("inkCanvas")); var position = e.GetPosition((UIElement)FindName("inkCanvas"));
UpdateAdvancedEraserPosition(sender, position); UpdateAdvancedEraserPosition(sender, position);
Trace.WriteLine($"Advanced Eraser: Stylus move at ({position.X:F1}, {position.Y:F1})"); Trace.WriteLine($"Advanced Eraser: Stylus move at ({position.X:F1}, {position.Y:F1})");
} }
@@ -702,7 +703,7 @@ namespace Ink_Canvas {
ResetEraserState(); ResetEraserState();
// 获取橡皮擦覆盖层并禁用 // 获取橡皮擦覆盖层并禁用
var eraserOverlay = this.FindName("AdvancedEraserOverlay") as Border; var eraserOverlay = FindName("AdvancedEraserOverlay") as Border;
if (eraserOverlay != null) { if (eraserOverlay != null) {
eraserOverlay.IsHitTestVisible = false; eraserOverlay.IsHitTestVisible = false;
} }
+111 -55
View File
@@ -1,23 +1,27 @@
using Ink_Canvas.Helpers;
using System; using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Ink; using System.Windows.Ink;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Animation; using System.Windows.Media.Animation;
using System.Windows.Threading;
using System.Windows.Interop;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern; using iNKORE.UI.WPF.Modern;
using System.Threading;
using Application = System.Windows.Application; using Application = System.Windows.Application;
using Button = System.Windows.Controls.Button;
using HorizontalAlignment = System.Windows.HorizontalAlignment;
using Point = System.Windows.Point; using Point = System.Windows.Point;
using System.Diagnostics;
using System.Xml.Linq;
using Image = System.Windows.Controls.Image; using Image = System.Windows.Controls.Image;
using MessageBox = iNKORE.UI.WPF.Modern.Controls.MessageBox; using MessageBox = iNKORE.UI.WPF.Modern.Controls.MessageBox;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
using Panel = System.Windows.Controls.Panel;
namespace Ink_Canvas { namespace Ink_Canvas {
public partial class MainWindow : Window { public partial class MainWindow : Window {
@@ -113,7 +117,7 @@ namespace Ink_Canvas {
|| BorderFloatingBarMainControls.Visibility != Visibility.Visible) { || BorderFloatingBarMainControls.Visibility != Visibility.Visible) {
EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed; EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed;
} }
else if (isVisible == true) { else if (isVisible) {
if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible)
EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed; EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed;
else EnableTwoFingerGestureBorder.Visibility = Visibility.Visible; else EnableTwoFingerGestureBorder.Visibility = Visibility.Visible;
@@ -127,9 +131,9 @@ namespace Ink_Canvas {
#region #region
private bool isDragDropInEffect = false; private bool isDragDropInEffect;
private Point pos = new Point(); private Point pos;
private Point downPos = new Point(); private Point downPos;
private Point pointDesktop = new Point(-1, -1); //用于记录上次在桌面时的坐标 private Point pointDesktop = new Point(-1, -1); //用于记录上次在桌面时的坐标
private Point pointPPT = new Point(-1, -1); //用于记录上次在PPT中的坐标 private Point pointPPT = new Point(-1, -1); //用于记录上次在PPT中的坐标
@@ -295,7 +299,7 @@ namespace Ink_Canvas {
To = BorderSettings.RenderTransform.Value.OffsetX - 440, To = BorderSettings.RenderTransform.Value.OffsetX - 440,
Duration = TimeSpan.FromSeconds(0.6) Duration = TimeSpan.FromSeconds(0.6)
}; };
slideAnimation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut }; slideAnimation.EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut };
Storyboard.SetTargetProperty(slideAnimation, Storyboard.SetTargetProperty(slideAnimation,
new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)")); new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));
@@ -310,7 +314,7 @@ namespace Ink_Canvas {
BorderSettings.RenderTransform = new TranslateTransform(); BorderSettings.RenderTransform = new TranslateTransform();
isOpeningOrHidingSettingsPane = true; isOpeningOrHidingSettingsPane = true;
sb.Begin((FrameworkElement)BorderSettings); sb.Begin(BorderSettings);
} }
AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder); AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder);
@@ -420,7 +424,7 @@ namespace Ink_Canvas {
await Task.Delay(50); await Task.Delay(50);
ViewboxFloatingBarMarginAnimation(60); ViewboxFloatingBarMarginAnimation(60);
} }
else if (Topmost == true) //非黑板 else if (Topmost) //非黑板
{ {
await Task.Delay(50); await Task.Delay(50);
ViewboxFloatingBarMarginAnimation(100, true); ViewboxFloatingBarMarginAnimation(100, true);
@@ -469,7 +473,7 @@ namespace Ink_Canvas {
#region 退 #region 退
//private bool Not_Enter_Blackboard_fir_Mouse_Click = true; //private bool Not_Enter_Blackboard_fir_Mouse_Click = true;
private bool isDisplayingOrHidingBlackboard = false; private bool isDisplayingOrHidingBlackboard;
private void ImageBlackboard_MouseUp(object sender, MouseButtonEventArgs e) private void ImageBlackboard_MouseUp(object sender, MouseButtonEventArgs e)
{ {
@@ -504,10 +508,10 @@ namespace Ink_Canvas {
Not_Enter_Blackboard_fir_Mouse_Click = false; Not_Enter_Blackboard_fir_Mouse_Click = false;
} }
*/ */
new Thread(new ThreadStart(() => { new Thread(() => {
Thread.Sleep(100); Thread.Sleep(100);
Application.Current.Dispatcher.Invoke(() => { ViewboxFloatingBarMarginAnimation(60); }); Application.Current.Dispatcher.Invoke(() => { ViewboxFloatingBarMarginAnimation(60); });
})).Start(); }).Start();
HideSubPanels(); HideSubPanels();
@@ -531,7 +535,7 @@ namespace Ink_Canvas {
if (isInMultiTouchMode) ToggleSwitchEnableMultiTouchMode.IsOn = false; if (isInMultiTouchMode) ToggleSwitchEnableMultiTouchMode.IsOn = false;
} }
if (Settings.Appearance.EnableTimeDisplayInWhiteboardMode == true) if (Settings.Appearance.EnableTimeDisplayInWhiteboardMode)
{ {
WaterMarkTime.Visibility = Visibility.Visible; WaterMarkTime.Visibility = Visibility.Visible;
WaterMarkDate.Visibility = Visibility.Visible; WaterMarkDate.Visibility = Visibility.Visible;
@@ -540,7 +544,7 @@ namespace Ink_Canvas {
WaterMarkDate.Visibility = Visibility.Collapsed; WaterMarkDate.Visibility = Visibility.Collapsed;
} }
if (Settings.Appearance.EnableChickenSoupInWhiteboardMode == true) if (Settings.Appearance.EnableChickenSoupInWhiteboardMode)
{ {
BlackBoardWaterMark.Visibility = Visibility.Visible; BlackBoardWaterMark.Visibility = Visibility.Visible;
} else { } else {
@@ -597,15 +601,15 @@ namespace Ink_Canvas {
inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) SaveScreenShot(true); inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) SaveScreenShot(true);
if (BtnPPTSlideShowEnd.Visibility == Visibility.Collapsed) if (BtnPPTSlideShowEnd.Visibility == Visibility.Collapsed)
new Thread(new ThreadStart(() => { new Thread(() => {
Thread.Sleep(300); Thread.Sleep(300);
Application.Current.Dispatcher.Invoke(() => { ViewboxFloatingBarMarginAnimation(100, true); }); Application.Current.Dispatcher.Invoke(() => { ViewboxFloatingBarMarginAnimation(100, true); });
})).Start(); }).Start();
else else
new Thread(new ThreadStart(() => { new Thread(() => {
Thread.Sleep(300); Thread.Sleep(300);
Application.Current.Dispatcher.Invoke(() => { ViewboxFloatingBarMarginAnimation(60); }); Application.Current.Dispatcher.Invoke(() => { ViewboxFloatingBarMarginAnimation(60); });
})).Start(); }).Start();
if (System.Windows.Controls.Canvas.GetLeft(FloatingbarSelectionBG)!=28) PenIcon_Click(null, null); if (System.Windows.Controls.Canvas.GetLeft(FloatingbarSelectionBG)!=28) PenIcon_Click(null, null);
@@ -628,10 +632,10 @@ namespace Ink_Canvas {
BtnExit.Foreground = Brushes.White; BtnExit.Foreground = Brushes.White;
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark; ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
new Thread(new ThreadStart(() => { new Thread(() => {
Thread.Sleep(200); Thread.Sleep(200);
Application.Current.Dispatcher.Invoke(() => { isDisplayingOrHidingBlackboard = false; }); Application.Current.Dispatcher.Invoke(() => { isDisplayingOrHidingBlackboard = false; });
})).Start(); }).Start();
SwitchToDefaultPen(null, null); SwitchToDefaultPen(null, null);
CheckColorTheme(true); CheckColorTheme(true);
@@ -715,7 +719,7 @@ namespace Ink_Canvas {
} }
private void SymbolIconSettings_Click(object sender, RoutedEventArgs e) { private void SymbolIconSettings_Click(object sender, RoutedEventArgs e) {
if (isOpeningOrHidingSettingsPane != false) return; if (isOpeningOrHidingSettingsPane) return;
HideSubPanels(); HideSubPanels();
BtnSettings_Click(null, null); BtnSettings_Click(null, null);
} }
@@ -827,7 +831,7 @@ namespace Ink_Canvas {
// 检查是否启用了直接调用ClassIsland点名功能 // 检查是否启用了直接调用ClassIsland点名功能
if (Settings.RandSettings.DirectCallCiRand) { if (Settings.RandSettings.DirectCallCiRand) {
try { try {
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { Process.Start(new ProcessStartInfo {
FileName = "classisland://plugins/IslandCaller/Run", FileName = "classisland://plugins/IslandCaller/Run",
UseShellExecute = true UseShellExecute = true
}); });
@@ -961,9 +965,9 @@ namespace Ink_Canvas {
}).Start(); }).Start();
} }
private bool isStopInkReplay = false; private bool isStopInkReplay;
private bool isPauseInkReplay = false; private bool isPauseInkReplay;
private bool isRestartInkReplay = false; private bool isRestartInkReplay;
private double inkReplaySpeed = 1; private double inkReplaySpeed = 1;
private void InkCanvasForInkReplay_MouseDown(object sender, MouseButtonEventArgs e) { private void InkCanvasForInkReplay_MouseDown(object sender, MouseButtonEventArgs e) {
@@ -1078,7 +1082,7 @@ namespace Ink_Canvas {
} }
} }
private bool isViewboxFloatingBarMarginAnimationRunning = false; private bool isViewboxFloatingBarMarginAnimationRunning;
public async void ViewboxFloatingBarMarginAnimation(int MarginFromEdge, public async void ViewboxFloatingBarMarginAnimation(int MarginFromEdge,
bool PosXCaculatedWithTaskbarHeight = false) { bool PosXCaculatedWithTaskbarHeight = false) {
@@ -1098,7 +1102,7 @@ namespace Ink_Canvas {
} }
var windowHandle = new WindowInteropHelper(this).Handle; var windowHandle = new WindowInteropHelper(this).Handle;
var screen = System.Windows.Forms.Screen.FromHandle(windowHandle); var screen = Screen.FromHandle(windowHandle);
double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY; double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY;
// 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响 // 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响
var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY); var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY);
@@ -1110,21 +1114,21 @@ namespace Ink_Canvas {
if (toolbarHeight == 0) if (toolbarHeight == 0)
{ {
pos.Y = screenHeight - MarginFromEdge * ViewboxFloatingBarScaleTransform.ScaleY; pos.Y = screenHeight - MarginFromEdge * ViewboxFloatingBarScaleTransform.ScaleY;
LogHelper.WriteLogToFile($"任务栏隐藏,使用固定边距: {MarginFromEdge}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"任务栏隐藏,使用固定边距: {MarginFromEdge}");
} }
else else
{ {
pos.Y = screenHeight - MarginFromEdge * ViewboxFloatingBarScaleTransform.ScaleY; pos.Y = screenHeight - MarginFromEdge * ViewboxFloatingBarScaleTransform.ScaleY;
} }
} }
else if (PosXCaculatedWithTaskbarHeight == true) else if (PosXCaculatedWithTaskbarHeight)
{ {
// 如果任务栏高度为0(隐藏状态),则使用固定高度 // 如果任务栏高度为0(隐藏状态),则使用固定高度
if (toolbarHeight == 0) if (toolbarHeight == 0)
{ {
pos.Y = screenHeight - ViewboxFloatingBar.ActualHeight * ViewboxFloatingBarScaleTransform.ScaleY - pos.Y = screenHeight - ViewboxFloatingBar.ActualHeight * ViewboxFloatingBarScaleTransform.ScaleY -
3 * ViewboxFloatingBarScaleTransform.ScaleY; 3 * ViewboxFloatingBarScaleTransform.ScaleY;
LogHelper.WriteLogToFile($"任务栏隐藏,使用固定高度: {ViewboxFloatingBar.ActualHeight}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"任务栏隐藏,使用固定高度: {ViewboxFloatingBar.ActualHeight}");
} }
else else
{ {
@@ -1184,7 +1188,7 @@ namespace Ink_Canvas {
} }
var windowHandle = new WindowInteropHelper(this).Handle; var windowHandle = new WindowInteropHelper(this).Handle;
var screen = System.Windows.Forms.Screen.FromHandle(windowHandle); var screen = Screen.FromHandle(windowHandle);
double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY; double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY;
// 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响 // 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响
var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY); var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY);
@@ -1195,7 +1199,7 @@ namespace Ink_Canvas {
{ {
pos.Y = screenHeight - ViewboxFloatingBar.ActualHeight * ViewboxFloatingBarScaleTransform.ScaleY - pos.Y = screenHeight - ViewboxFloatingBar.ActualHeight * ViewboxFloatingBarScaleTransform.ScaleY -
3 * ViewboxFloatingBarScaleTransform.ScaleY; 3 * ViewboxFloatingBarScaleTransform.ScaleY;
LogHelper.WriteLogToFile($"任务栏隐藏,使用固定高度: {ViewboxFloatingBar.ActualHeight}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"任务栏隐藏,使用固定高度: {ViewboxFloatingBar.ActualHeight}");
} }
else else
{ {
@@ -1237,7 +1241,7 @@ namespace Ink_Canvas {
} }
var windowHandle = new WindowInteropHelper(this).Handle; var windowHandle = new WindowInteropHelper(this).Handle;
var screen = System.Windows.Forms.Screen.FromHandle(windowHandle); var screen = Screen.FromHandle(windowHandle);
double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY; double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY;
// 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响 // 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响
var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY); var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY);
@@ -1321,7 +1325,14 @@ namespace Ink_Canvas {
if (currentMode != 0) { if (currentMode != 0) {
SaveStrokes(); SaveStrokes();
RestoreStrokes(true); // 检查是否在PPT放映模式,如果不在则不恢复可能包含PPT墨迹的备份
if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) {
RestoreStrokes(true);
} else {
// 不在PPT模式时,清空备份以避免显示已结束PPT的墨迹
TimeMachineHistories[0] = null;
timeMachine.ClearStrokeHistory();
}
} }
if (BtnSwitchTheme.Content.ToString() == "浅色") if (BtnSwitchTheme.Content.ToString() == "浅色")
@@ -1565,7 +1576,7 @@ namespace Ink_Canvas {
} }
private void DrawShapePromptToPen() { private void DrawShapePromptToPen() {
if (isLongPressSelected == true) { if (isLongPressSelected) {
// 如果是长按选中的状态,只隐藏面板,不切换到笔模式 // 如果是长按选中的状态,只隐藏面板,不切换到笔模式
HideSubPanels("shape"); HideSubPanels("shape");
} }
@@ -1629,7 +1640,7 @@ namespace Ink_Canvas {
#region Right Side Panel #region Right Side Panel
public static bool CloseIsFromButton = false; public static bool CloseIsFromButton;
public void BtnExit_Click(object sender, RoutedEventArgs e) { public void BtnExit_Click(object sender, RoutedEventArgs e) {
App.IsAppExitByUser = true; App.IsAppExitByUser = true;
@@ -1639,14 +1650,18 @@ namespace Ink_Canvas {
} }
public void BtnRestart_Click(object sender, RoutedEventArgs e) { public void BtnRestart_Click(object sender, RoutedEventArgs e) {
Process.Start(System.Windows.Forms.Application.ExecutablePath, "-m"); try {
App.IsAppExitByUser = true; Process.Start(System.Windows.Forms.Application.ExecutablePath, "-m");
CloseIsFromButton = true; App.IsAppExitByUser = true;
Application.Current.Shutdown(); CloseIsFromButton = true;
Application.Current.Shutdown();
} catch (Exception ex) {
LogHelper.NewLog($"重启程序时出错: {ex.Message}");
}
} }
private void SettingsOverlayClick(object sender, MouseButtonEventArgs e) { private void SettingsOverlayClick(object sender, MouseButtonEventArgs e) {
if (isOpeningOrHidingSettingsPane == true) return; if (isOpeningOrHidingSettingsPane) return;
// 获取点击的位置 // 获取点击的位置
Point clickPoint = e.GetPosition(BorderSettingsMask); Point clickPoint = e.GetPosition(BorderSettingsMask);
@@ -1666,7 +1681,7 @@ namespace Ink_Canvas {
} }
} }
private bool isOpeningOrHidingSettingsPane = false; private bool isOpeningOrHidingSettingsPane;
private void BtnSettings_Click(object sender, RoutedEventArgs e) { private void BtnSettings_Click(object sender, RoutedEventArgs e) {
if (BorderSettings.Visibility == Visibility.Visible) { if (BorderSettings.Visibility == Visibility.Visible) {
@@ -1685,7 +1700,7 @@ namespace Ink_Canvas {
To = 0, To = 0,
Duration = TimeSpan.FromSeconds(0.6) Duration = TimeSpan.FromSeconds(0.6)
}; };
slideAnimation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut }; slideAnimation.EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut };
Storyboard.SetTargetProperty(slideAnimation, Storyboard.SetTargetProperty(slideAnimation,
new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)")); new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));
@@ -1697,13 +1712,13 @@ namespace Ink_Canvas {
BorderSettings.RenderTransform = new TranslateTransform(); BorderSettings.RenderTransform = new TranslateTransform();
isOpeningOrHidingSettingsPane = true; isOpeningOrHidingSettingsPane = true;
sb.Begin((FrameworkElement)BorderSettings); sb.Begin(BorderSettings);
} }
} }
private void BtnThickness_Click(object sender, RoutedEventArgs e) { } private void BtnThickness_Click(object sender, RoutedEventArgs e) { }
private bool forceEraser = false; private bool forceEraser;
private void BtnClear_Click(object sender, RoutedEventArgs e) { private void BtnClear_Click(object sender, RoutedEventArgs e) {
@@ -1726,14 +1741,18 @@ namespace Ink_Canvas {
} }
ClearStrokes(false); ClearStrokes(false);
// 保存非笔画元素(如图片)
var preservedElements = PreserveNonStrokeElements();
inkCanvas.Children.Clear(); inkCanvas.Children.Clear();
// 恢复非笔画元素
RestoreNonStrokeElements(preservedElements);
CancelSingleFingerDragMode(); CancelSingleFingerDragMode();
if (Settings.Canvas.ClearCanvasAndClearTimeMachine) timeMachine.ClearStrokeHistory(); if (Settings.Canvas.ClearCanvasAndClearTimeMachine) timeMachine.ClearStrokeHistory();
} }
private bool lastIsInMultiTouchMode = false; private bool lastIsInMultiTouchMode;
private void CancelSingleFingerDragMode() { private void CancelSingleFingerDragMode() {
if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) CollapseBorderDrawShape(); if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) CollapseBorderDrawShape();
@@ -1751,7 +1770,7 @@ namespace Ink_Canvas {
StackPanelControl.Visibility = Visibility.Visible; StackPanelControl.Visibility = Visibility.Visible;
} }
private int currentMode = 0; private int currentMode;
private void BtnSwitch_Click(object sender, RoutedEventArgs e) { private void BtnSwitch_Click(object sender, RoutedEventArgs e) {
if (GridTransparencyFakeBackground.Background == Brushes.Transparent) { if (GridTransparencyFakeBackground.Background == Brushes.Transparent) {
@@ -1762,9 +1781,22 @@ namespace Ink_Canvas {
AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide); AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide); AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
// 取消任何UI元素的选择
DeselectUIElement();
SaveStrokes(true); SaveStrokes(true);
ClearStrokes(true); ClearStrokes(true);
RestoreStrokes();
// 检查是否在PPT放映模式,如果不在则不恢复可能包含PPT墨迹的备份
if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) {
LogHelper.WriteLogToFile("退出白板:当前在PPT放映模式,恢复备份墨迹", LogHelper.LogType.Trace);
RestoreStrokes();
} else {
// 不在PPT模式时,清空备份以避免显示已结束PPT的墨迹
LogHelper.WriteLogToFile("退出白板:当前不在PPT放映模式,清空备份以避免显示已结束PPT的墨迹", LogHelper.LogType.Trace);
TimeMachineHistories[0] = null;
timeMachine.ClearStrokeHistory();
}
// 退出白板时清空图片 // 退出白板时清空图片
inkCanvas.Children.Clear(); inkCanvas.Children.Clear();
@@ -1800,9 +1832,20 @@ namespace Ink_Canvas {
AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide); AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide); AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
// 取消任何UI元素的选择
DeselectUIElement();
SaveStrokes(); SaveStrokes();
ClearStrokes(true); ClearStrokes(true);
RestoreStrokes(true);
// 检查是否在PPT放映模式,如果不在则不恢复可能包含PPT墨迹的备份
if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) {
RestoreStrokes(true);
} else {
// 不在PPT模式时,清空备份以避免显示已结束PPT的墨迹
TimeMachineHistories[0] = null;
timeMachine.ClearStrokeHistory();
}
// 退出白板时清空图片 // 退出白板时清空图片
inkCanvas.Children.Clear(); inkCanvas.Children.Clear();
@@ -1834,9 +1877,20 @@ namespace Ink_Canvas {
AnimationsHelper.ShowWithSlideFromBottomAndFade(BlackboardCenterSide); AnimationsHelper.ShowWithSlideFromBottomAndFade(BlackboardCenterSide);
AnimationsHelper.ShowWithSlideFromBottomAndFade(BlackboardRightSide); AnimationsHelper.ShowWithSlideFromBottomAndFade(BlackboardRightSide);
// 取消任何UI元素的选择
DeselectUIElement();
SaveStrokes(true); SaveStrokes(true);
ClearStrokes(true); ClearStrokes(true);
RestoreStrokes();
// 检查是否在PPT放映模式,如果不在则不恢复可能包含PPT墨迹的备份
if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) {
RestoreStrokes();
} else {
// 不在PPT模式时,清空备份以避免显示已结束PPT的墨迹
TimeMachineHistories[0] = null;
timeMachine.ClearStrokeHistory();
}
BtnSwitch.Content = "屏幕"; BtnSwitch.Content = "屏幕";
if (BtnSwitchTheme.Content.ToString() == "浅色") { if (BtnSwitchTheme.Content.ToString() == "浅色") {
@@ -1991,7 +2045,7 @@ namespace Ink_Canvas {
private async void InsertImage_MouseUp(object sender, MouseButtonEventArgs e) private async void InsertImage_MouseUp(object sender, MouseButtonEventArgs e)
{ {
var dialog = new Microsoft.Win32.OpenFileDialog var dialog = new OpenFileDialog
{ {
Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif" Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif"
}; };
@@ -2021,5 +2075,7 @@ namespace Ink_Canvas {
} }
} }
} }
} }
} }
+5 -5
View File
@@ -1,12 +1,12 @@
using Ink_Canvas.Helpers; using System;
using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Windows; using System.Windows;
using Ink_Canvas.Helpers;
namespace Ink_Canvas { namespace Ink_Canvas {
public partial class MainWindow : Window { public partial class MainWindow : Window {
private int lastNotificationShowTime = 0; private int lastNotificationShowTime;
private int notificationShowTime = 2500; private int notificationShowTime = 2500;
public static void ShowNewMessage(string notice, bool isShowImmediately = true) { public static void ShowNewMessage(string notice, bool isShowImmediately = true) {
@@ -21,13 +21,13 @@ namespace Ink_Canvas {
TextBlockNotice.Text = notice; TextBlockNotice.Text = notice;
AnimationsHelper.ShowWithSlideFromBottomAndFade(GridNotifications); AnimationsHelper.ShowWithSlideFromBottomAndFade(GridNotifications);
new Thread(new ThreadStart(() => { new Thread(() => {
Thread.Sleep(notificationShowTime + 300); Thread.Sleep(notificationShowTime + 300);
if (Environment.TickCount - lastNotificationShowTime >= notificationShowTime) if (Environment.TickCount - lastNotificationShowTime >= notificationShowTime)
Application.Current.Dispatcher.Invoke(() => { Application.Current.Dispatcher.Invoke(() => {
AnimationsHelper.HideWithSlideAndFade(GridNotifications); AnimationsHelper.HideWithSlideAndFade(GridNotifications);
}); });
})).Start(); }).Start();
} }
catch { } catch { }
} }
+110 -103
View File
@@ -1,25 +1,31 @@
using Ink_Canvas.Helpers; using System;
using Microsoft.Office.Interop.PowerPoint;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Timers; using System.Timers;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Ink; using System.Windows.Ink;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.PowerPoint;
using Application = System.Windows.Application; using Application = System.Windows.Application;
using File = System.IO.File; using File = System.IO.File;
using MessageBox = System.Windows.MessageBox; using MessageBox = System.Windows.MessageBox;
using iNKORE.UI.WPF.Modern; using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using Microsoft.Office.Core; using Point = System.Drawing.Point;
using Timer = System.Timers.Timer;
namespace Ink_Canvas { namespace Ink_Canvas {
public partial class MainWindow : Window { public partial class MainWindow : Window {
@@ -30,7 +36,7 @@ namespace Ink_Canvas {
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")] [DllImport("user32.dll")]
private static extern int GetWindowText(IntPtr hWnd, System.Text.StringBuilder lpString, int nMaxCount); private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll")] [DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId, out uint lpdwThreadId); private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId, out uint lpdwThreadId);
@@ -60,7 +66,7 @@ namespace Ink_Canvas {
private static extern bool GetWindowRect(IntPtr hWnd, out ForegroundWindowInfo.RECT lpRect); private static extern bool GetWindowRect(IntPtr hWnd, out ForegroundWindowInfo.RECT lpRect);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetClassName(IntPtr hWnd, System.Text.StringBuilder lpClassName, int nMaxCount); private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
private const int GWL_STYLE = -16; private const int GWL_STYLE = -16;
private const int WS_VISIBLE = 0x10000000; private const int WS_VISIBLE = 0x10000000;
@@ -72,14 +78,14 @@ namespace Ink_Canvas {
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
public static Microsoft.Office.Interop.PowerPoint.Application pptApplication = null; public static Microsoft.Office.Interop.PowerPoint.Application pptApplication;
public static Presentation presentation = null; public static Presentation presentation;
public static Slides slides = null; public static Slides slides;
public static Slide slide = null; public static Slide slide;
public static int slidescount = 0; public static int slidescount;
// 在类中添加字段 // 在类中添加字段
private bool wasFloatingBarFoldedWhenEnterSlideShow = false; private bool wasFloatingBarFoldedWhenEnterSlideShow;
// 新增:用于控制WPS强制关闭提示只弹一次 // 新增:用于控制WPS强制关闭提示只弹一次
private static bool hasShownWpsForceCloseWarning = false; private static bool hasShownWpsForceCloseWarning = false;
@@ -115,7 +121,7 @@ namespace Ink_Canvas {
} }
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"获取当前幻灯片失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"获取当前幻灯片失败: {ex}", LogHelper.LogType.Error);
} }
} }
} }
@@ -125,7 +131,7 @@ namespace Ink_Canvas {
StackPanelPPTControls.Visibility = Visibility.Visible; StackPanelPPTControls.Visibility = Visibility.Visible;
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"检查PPT应用程序失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"检查PPT应用程序失败: {ex}", LogHelper.LogType.Error);
//BtnCheckPPT.Visibility = Visibility.Visible; //BtnCheckPPT.Visibility = Visibility.Visible;
StackPanelPPTControls.Visibility = Visibility.Collapsed; StackPanelPPTControls.Visibility = Visibility.Collapsed;
LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed; LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
@@ -145,16 +151,16 @@ namespace Ink_Canvas {
private static bool isWPSSupportOn => Settings.PowerPointSettings.IsSupportWPS; private static bool isWPSSupportOn => Settings.PowerPointSettings.IsSupportWPS;
public static bool IsShowingRestoreHiddenSlidesWindow = false; public static bool IsShowingRestoreHiddenSlidesWindow;
private static bool IsShowingAutoplaySlidesWindow = false; private static bool IsShowingAutoplaySlidesWindow;
// WPP 相关变量 // WPP 相关变量
private static Process wppProcess = null; private static Process wppProcess;
private static bool hasWppProcessID = false; private static bool hasWppProcessID;
private static System.Timers.Timer wppProcessCheckTimer = null; private static Timer wppProcessCheckTimer;
private static DateTime wppProcessRecordTime = DateTime.MinValue; // 记录进程时间 private static DateTime wppProcessRecordTime = DateTime.MinValue; // 记录进程时间
private static int wppProcessCheckCount = 0; // 检查次数计数器 private static int wppProcessCheckCount; // 检查次数计数器
private static WpsWindowInfo lastForegroundWpsWindow = null; // 记录上次检测到的前台WPS窗口 private static WpsWindowInfo lastForegroundWpsWindow; // 记录上次检测到的前台WPS窗口
private static DateTime lastWindowCheckTime = DateTime.MinValue; // 记录上次窗口检查时间 private static DateTime lastWindowCheckTime = DateTime.MinValue; // 记录上次窗口检查时间
@@ -191,7 +197,7 @@ namespace Ink_Canvas {
} }
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"获取当前幻灯片失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"获取当前幻灯片失败: {ex}", LogHelper.LogType.Error);
} }
} }
@@ -215,14 +221,14 @@ namespace Ink_Canvas {
PptApplication_SlideShowBegin(pptApplication.SlideShowWindows[1]); PptApplication_SlideShowBegin(pptApplication.SlideShowWindows[1]);
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"启动幻灯片放映失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"启动幻灯片放映失败: {ex}", LogHelper.LogType.Error);
} }
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
// 忽略常见的COM对象失效错误 // 忽略常见的COM对象失效错误
if (ex is System.Runtime.InteropServices.COMException comEx) if (ex is COMException comEx)
{ {
uint hr = (uint)comEx.HResult; uint hr = (uint)comEx.HResult;
// 0x800401E3: 操作无法使用 // 0x800401E3: 操作无法使用
@@ -237,7 +243,7 @@ namespace Ink_Canvas {
return; return;
} }
} }
LogHelper.WriteLogToFile($"检查PPT状态失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"检查PPT状态失败: {ex}", LogHelper.LogType.Error);
Application.Current.Dispatcher.Invoke(() => { BtnPPTSlideShow.Visibility = Visibility.Collapsed; }); Application.Current.Dispatcher.Invoke(() => { BtnPPTSlideShow.Visibility = Visibility.Collapsed; });
timerCheckPPT.Start(); timerCheckPPT.Start();
} }
@@ -262,7 +268,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"跳转到首页失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"跳转到首页失败: {ex}", LogHelper.LogType.Error);
} }
}), DispatcherPriority.Normal); }), DispatcherPriority.Normal);
} }
@@ -295,16 +301,16 @@ namespace Ink_Canvas {
presentation.Windows[1].View.GotoSlide(page); presentation.Windows[1].View.GotoSlide(page);
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"跳转到指定页面失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"跳转到指定页面失败: {ex}", LogHelper.LogType.Error);
} }
}).ShowDialog(); }).ShowDialog();
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"读取上次播放位置失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"读取上次播放位置失败: {ex}", LogHelper.LogType.Error);
} }
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"处理上次播放页跳转失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"处理上次播放页跳转失败: {ex}", LogHelper.LogType.Error);
} }
}), DispatcherPriority.Normal); }), DispatcherPriority.Normal);
@@ -316,7 +322,7 @@ namespace Ink_Canvas {
if (slides != null) if (slides != null)
{ {
foreach (Slide slide in slides) foreach (Slide slide in slides)
if (slide.SlideShowTransition.Hidden == Microsoft.Office.Core.MsoTriState.msoTrue) { if (slide.SlideShowTransition.Hidden == MsoTriState.msoTrue) {
isHaveHiddenSlide = true; isHaveHiddenSlide = true;
break; break;
} }
@@ -332,13 +338,13 @@ namespace Ink_Canvas {
{ {
foreach (Slide slide in slides) foreach (Slide slide in slides)
if (slide.SlideShowTransition.Hidden == if (slide.SlideShowTransition.Hidden ==
Microsoft.Office.Core.MsoTriState.msoTrue) MsoTriState.msoTrue)
slide.SlideShowTransition.Hidden = slide.SlideShowTransition.Hidden =
Microsoft.Office.Core.MsoTriState.msoFalse; MsoTriState.msoFalse;
} }
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"取消隐藏幻灯片失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"取消隐藏幻灯片失败: {ex}", LogHelper.LogType.Error);
} }
finally { finally {
IsShowingRestoreHiddenSlidesWindow = false; IsShowingRestoreHiddenSlidesWindow = false;
@@ -351,7 +357,7 @@ namespace Ink_Canvas {
}), DispatcherPriority.Normal); }), DispatcherPriority.Normal);
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"检查隐藏幻灯片失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"检查隐藏幻灯片失败: {ex}", LogHelper.LogType.Error);
} }
} }
@@ -386,7 +392,7 @@ namespace Ink_Canvas {
} }
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"设置手动播放模式失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"设置手动播放模式失败: {ex}", LogHelper.LogType.Error);
} }
finally { finally {
IsShowingAutoplaySlidesWindow = false; IsShowingAutoplaySlidesWindow = false;
@@ -402,12 +408,12 @@ namespace Ink_Canvas {
} }
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"设置演示文稿播放模式失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"设置演示文稿播放模式失败: {ex}", LogHelper.LogType.Error);
} }
} }
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"检查自动播放设置失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"检查自动播放设置失败: {ex}", LogHelper.LogType.Error);
} }
} }
} }
@@ -433,8 +439,8 @@ namespace Ink_Canvas {
} }
} }
private bool isPresentationHaveBlackSpace = false; private bool isPresentationHaveBlackSpace;
private string pptName = null; private string pptName;
private void UpdatePPTBtnStyleSettingsStatus() { private void UpdatePPTBtnStyleSettingsStatus() {
try { try {
@@ -600,7 +606,7 @@ namespace Ink_Canvas {
else RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed; else RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"更新PPT按钮显示状态失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"更新PPT按钮显示状态失败: {ex}", LogHelper.LogType.Error);
} }
} }
@@ -630,7 +636,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"放映开始时跳转首页失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"放映开始时跳转首页失败: {ex}", LogHelper.LogType.Error);
} }
} }
@@ -644,9 +650,8 @@ namespace Ink_Canvas {
//Light //Light
BtnExit.Foreground = Brushes.White; BtnExit.Foreground = Brushes.White;
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark; ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
} else {
//Dark
} }
//Dark
} }
} else if (screenRatio == -256 / 135) { } } else if (screenRatio == -256 / 135) { }
@@ -658,7 +663,7 @@ namespace Ink_Canvas {
pptName = Wn.Presentation.Name; pptName = Wn.Presentation.Name;
LogHelper.NewLog("Name: " + Wn.Presentation.Name); LogHelper.NewLog("Name: " + Wn.Presentation.Name);
LogHelper.NewLog("Slides Count: " + slidescount.ToString()); LogHelper.NewLog("Slides Count: " + slidescount);
//检查是否有已有墨迹,并加载 //检查是否有已有墨迹,并加载
if (Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint) if (Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint)
@@ -685,7 +690,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile( LogHelper.WriteLogToFile(
$"Failed to load strokes on Slide {i}\n{ex.ToString()}", $"Failed to load strokes on Slide {i}\n{ex}",
LogHelper.LogType.Error); LogHelper.LogType.Error);
} }
} }
@@ -743,16 +748,16 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"加载当前页墨迹失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"加载当前页墨迹失败: {ex}", LogHelper.LogType.Error);
} }
if (!isFloatingBarFolded) { if (!isFloatingBarFolded) {
new Thread(new ThreadStart(() => { new Thread(() => {
Thread.Sleep(100); Thread.Sleep(100);
Application.Current.Dispatcher.Invoke(() => { Application.Current.Dispatcher.Invoke(() => {
ViewboxFloatingBarMarginAnimation(60); ViewboxFloatingBarMarginAnimation(60);
}); });
})).Start(); }).Start();
} }
}); });
await Application.Current.Dispatcher.InvokeAsync(() => { await Application.Current.Dispatcher.InvokeAsync(() => {
@@ -763,12 +768,12 @@ namespace Ink_Canvas {
}); });
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile("PowerPoint Application Slide Show Begin Error: " + ex.ToString(), LogHelper.LogType.Error); LogHelper.WriteLogToFile("PowerPoint Application Slide Show Begin Error: " + ex, LogHelper.LogType.Error);
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error); LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
} }
} }
private bool isEnteredSlideShowEndEvent = false; //防止重复调用本函数导致墨迹保存失效 private bool isEnteredSlideShowEndEvent; //防止重复调用本函数导致墨迹保存失效
private async void PptApplication_SlideShowEnd(Presentation Pres) { private async void PptApplication_SlideShowEnd(Presentation Pres) {
try { try {
@@ -834,11 +839,11 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"记录WPS进程失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"记录WPS进程失败: {ex}", LogHelper.LogType.Error);
} }
} }
LogHelper.WriteLogToFile(string.Format("PowerPoint Slide Show End"), LogHelper.LogType.Event); LogHelper.WriteLogToFile("PowerPoint Slide Show End", LogHelper.LogType.Event);
if (isEnteredSlideShowEndEvent) { if (isEnteredSlideShowEndEvent) {
LogHelper.WriteLogToFile("Detected previous entrance, returning"); LogHelper.WriteLogToFile("Detected previous entrance, returning");
return; return;
@@ -878,7 +883,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile( LogHelper.WriteLogToFile(
$"Failed to save strokes for Slide {i}\n{ex.ToString()}", $"Failed to save strokes for Slide {i}\n{ex}",
LogHelper.LogType.Error); LogHelper.LogType.Error);
if (File.Exists(folderPath + @"\" + i.ToString("0000") + ".icstk")) if (File.Exists(folderPath + @"\" + i.ToString("0000") + ".icstk"))
File.Delete(folderPath + @"\" + i.ToString("0000") + ".icstk"); File.Delete(folderPath + @"\" + i.ToString("0000") + ".icstk");
@@ -893,10 +898,9 @@ namespace Ink_Canvas {
//Light //Light
BtnExit.Foreground = Brushes.Black; BtnExit.Foreground = Brushes.Black;
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light; ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
} else {
//Dark
} }
//Dark
BtnPPTSlideShow.Visibility = Visibility.Visible; BtnPPTSlideShow.Visibility = Visibility.Visible;
BtnPPTSlideShowEnd.Visibility = Visibility.Collapsed; BtnPPTSlideShowEnd.Visibility = Visibility.Collapsed;
StackPanelPPTControls.Visibility = Visibility.Collapsed; StackPanelPPTControls.Visibility = Visibility.Collapsed;
@@ -914,6 +918,9 @@ namespace Ink_Canvas {
ClearStrokes(true); ClearStrokes(true);
// 清空备份历史记录,防止退出白板时恢复已结束PPT的墨迹
TimeMachineHistories[0] = null;
if (GridTransparencyFakeBackground.Background != Brushes.Transparent) if (GridTransparencyFakeBackground.Background != Brushes.Transparent)
BtnHideInkCanvas_Click(BtnHideInkCanvas, null); BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
@@ -941,11 +948,11 @@ namespace Ink_Canvas {
} }
} }
private int previousSlideID = 0; private int previousSlideID;
private MemoryStream[] memoryStreams = new MemoryStream[50]; private MemoryStream[] memoryStreams = new MemoryStream[50];
private DateTime inkLockUntil = DateTime.MinValue; private DateTime inkLockUntil = DateTime.MinValue;
private int lockedSlideIndex = 0; private int lockedSlideIndex;
private const int InkLockMilliseconds = 500; private const int InkLockMilliseconds = 500;
private void PptApplication_SlideShowNextSlide(SlideShowWindow Wn) { private void PptApplication_SlideShowNextSlide(SlideShowWindow Wn) {
@@ -980,11 +987,11 @@ namespace Ink_Canvas {
}); });
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"幻灯片切换事件处理失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"幻灯片切换事件处理失败: {ex}", LogHelper.LogType.Error);
} }
} }
private bool _isPptClickingBtnTurned = false; private bool _isPptClickingBtnTurned;
private void BtnPPTSlidesUp_Click(object sender, RoutedEventArgs e) { private void BtnPPTSlidesUp_Click(object sender, RoutedEventArgs e) {
Application.Current.Dispatcher.Invoke(() => { Application.Current.Dispatcher.Invoke(() => {
@@ -1023,7 +1030,7 @@ namespace Ink_Canvas {
} }
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"PPT上一页操作异常: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"PPT上一页操作异常: {ex}", LogHelper.LogType.Error);
StackPanelPPTControls.Visibility = Visibility.Collapsed; StackPanelPPTControls.Visibility = Visibility.Collapsed;
LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed; LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed; RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
@@ -1070,7 +1077,7 @@ namespace Ink_Canvas {
} }
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"PPT下一页操作异常: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"PPT下一页操作异常: {ex}", LogHelper.LogType.Error);
StackPanelPPTControls.Visibility = Visibility.Collapsed; StackPanelPPTControls.Visibility = Visibility.Collapsed;
LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed; LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed; RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
@@ -1177,7 +1184,7 @@ namespace Ink_Canvas {
} }
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"设置PPT导航可见性失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"设置PPT导航可见性失败: {ex}", LogHelper.LogType.Error);
} }
// 控制居中 // 控制居中
@@ -1188,17 +1195,17 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"PPT翻页控件操作失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"PPT翻页控件操作失败: {ex}", LogHelper.LogType.Error);
} }
} }
private void BtnPPTSlideShow_Click(object sender, RoutedEventArgs e) { private void BtnPPTSlideShow_Click(object sender, RoutedEventArgs e) {
new Thread(new ThreadStart(() => { new Thread(() => {
try { try {
presentation.SlideShowSettings.Run(); presentation.SlideShowSettings.Run();
} }
catch { } catch { }
})).Start(); }).Start();
} }
private async void BtnPPTSlideShowEnd_Click(object sender, RoutedEventArgs e) { private async void BtnPPTSlideShowEnd_Click(object sender, RoutedEventArgs e) {
@@ -1240,11 +1247,11 @@ namespace Ink_Canvas {
} }
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"保存当前页面墨迹失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"保存当前页面墨迹失败: {ex}", LogHelper.LogType.Error);
} }
}); });
new Thread(new ThreadStart(() => { new Thread(() => {
try { try {
// 安全访问SlideShowWindows[1] // 安全访问SlideShowWindows[1]
if (pptApplication.SlideShowWindows.Count >= 1) if (pptApplication.SlideShowWindows.Count >= 1)
@@ -1257,9 +1264,9 @@ namespace Ink_Canvas {
} }
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"退出PPT放映失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"退出PPT放映失败: {ex}", LogHelper.LogType.Error);
} }
})).Start(); }).Start();
HideSubPanels("cursor"); HideSubPanels("cursor");
await Task.Delay(150); await Task.Delay(150);
@@ -1267,7 +1274,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"结束PPT放映操作异常: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"结束PPT放映操作异常: {ex}", LogHelper.LogType.Error);
} }
await Application.Current.Dispatcher.InvokeAsync(() => { await Application.Current.Dispatcher.InvokeAsync(() => {
// 隐藏侧边栏退出按钮 // 隐藏侧边栏退出按钮
@@ -1289,7 +1296,7 @@ namespace Ink_Canvas {
LogHelper.WriteLogToFile("手动隐藏所有放映模式按钮", LogHelper.LogType.Trace); LogHelper.WriteLogToFile("手动隐藏所有放映模式按钮", LogHelper.LogType.Trace);
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"手动隐藏放映模式按钮失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"手动隐藏放映模式按钮失败: {ex}", LogHelper.LogType.Error);
} }
}); });
} }
@@ -1411,13 +1418,13 @@ namespace Ink_Canvas {
wppProcessCheckTimer.Dispose(); wppProcessCheckTimer.Dispose();
} }
wppProcessCheckTimer = new System.Timers.Timer(500); // 改为500ms检查一次,提高响应速度 wppProcessCheckTimer = new Timer(500); // 改为500ms检查一次,提高响应速度
wppProcessCheckTimer.Elapsed += WppProcessCheckTimer_Elapsed; wppProcessCheckTimer.Elapsed += WppProcessCheckTimer_Elapsed;
wppProcessCheckTimer.Start(); wppProcessCheckTimer.Start();
LogHelper.WriteLogToFile("启动 WPP 进程检测定时器(前台窗口监控模式)", LogHelper.LogType.Trace); LogHelper.WriteLogToFile("启动 WPP 进程检测定时器(前台窗口监控模式)", LogHelper.LogType.Trace);
} }
private void WppProcessCheckTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) private void WppProcessCheckTimer_Elapsed(object sender, ElapsedEventArgs e)
{ {
// 新增:WPS联动未启用时不查杀wpp进程 // 新增:WPS联动未启用时不查杀wpp进程
if (!Settings.PowerPointSettings.IsSupportWPS) if (!Settings.PowerPointSettings.IsSupportWPS)
@@ -1487,7 +1494,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"检查WPS文档保存状态失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"检查WPS文档保存状态失败: {ex}", LogHelper.LogType.Error);
allSaved = false; // 出错时默认不安全 allSaved = false; // 出错时默认不安全
} }
@@ -1515,7 +1522,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"结束WPP进程失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"结束WPP进程失败: {ex}", LogHelper.LogType.Error);
// 如果常规方法失败,尝试强制结束 // 如果常规方法失败,尝试强制结束
try try
@@ -1533,7 +1540,7 @@ namespace Ink_Canvas {
} }
catch (Exception forceKillEx) catch (Exception forceKillEx)
{ {
LogHelper.WriteLogToFile($"强制结束WPP进程也失败: {forceKillEx.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"强制结束WPP进程也失败: {forceKillEx}", LogHelper.LogType.Error);
} }
} }
finally finally
@@ -1543,7 +1550,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"WPP 进程检测失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"WPP 进程检测失败: {ex}", LogHelper.LogType.Error);
StopWppProcessCheckTimer(); StopWppProcessCheckTimer();
} }
} }
@@ -1568,7 +1575,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"检查WPP窗口失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"检查WPP窗口失败: {ex}", LogHelper.LogType.Error);
} }
return false; // 出错时,默认允许Kill return false; // 出错时,默认允许Kill
} }
@@ -1619,14 +1626,14 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"枚举窗口时出错: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"枚举窗口时出错: {ex}", LogHelper.LogType.Error);
} }
return true; return true;
}, IntPtr.Zero); }, IntPtr.Zero);
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"获取WPS窗口失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"获取WPS窗口失败: {ex}", LogHelper.LogType.Error);
} }
return wpsWindows; return wpsWindows;
@@ -1646,12 +1653,12 @@ namespace Ink_Canvas {
}; };
// 获取窗口标题 // 获取窗口标题
var windowTitle = new System.Text.StringBuilder(256); var windowTitle = new StringBuilder(256);
GetWindowText(hWnd, windowTitle, 256); GetWindowText(hWnd, windowTitle, 256);
windowInfo.Title = windowTitle.ToString().Trim(); windowInfo.Title = windowTitle.ToString().Trim();
// 获取窗口类名 // 获取窗口类名
var className = new System.Text.StringBuilder(256); var className = new StringBuilder(256);
GetClassName(hWnd, className, 256); GetClassName(hWnd, className, 256);
windowInfo.ClassName = className.ToString().Trim(); windowInfo.ClassName = className.ToString().Trim();
@@ -1668,7 +1675,7 @@ namespace Ink_Canvas {
windowInfo.ProcessName = ""; windowInfo.ProcessName = "";
try try
{ {
var proc = System.Diagnostics.Process.GetProcessById((int)processId); var proc = Process.GetProcessById((int)processId);
windowInfo.ProcessName = proc.ProcessName.ToLower(); windowInfo.ProcessName = proc.ProcessName.ToLower();
} }
catch { } catch { }
@@ -1730,7 +1737,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"获取前台WPS窗口失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"获取前台WPS窗口失败: {ex}", LogHelper.LogType.Error);
} }
return null; return null;
} }
@@ -1805,7 +1812,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"检查前台WPS窗口状态失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"检查前台WPS窗口状态失败: {ex}", LogHelper.LogType.Error);
return false; return false;
} }
} }
@@ -1837,9 +1844,9 @@ namespace Ink_Canvas {
} }
// 按窗口位置排序,优先选择屏幕中央的窗口 // 按窗口位置排序,优先选择屏幕中央的窗口
var screenCenter = new System.Drawing.Point( var screenCenter = new Point(
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / 2, Screen.PrimaryScreen.Bounds.Width / 2,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height / 2 Screen.PrimaryScreen.Bounds.Height / 2
); );
var sortedWindows = allWpsWindows var sortedWindows = allWpsWindows
@@ -1854,7 +1861,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"获取顶级WPS窗口失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"获取顶级WPS窗口失败: {ex}", LogHelper.LogType.Error);
} }
return topLevelWindows; return topLevelWindows;
@@ -1915,7 +1922,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"第{attempt}次尝试检查活跃WPS窗口失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"第{attempt}次尝试检查活跃WPS窗口失败: {ex}", LogHelper.LogType.Error);
// 如果还有重试机会,等待一小段时间再重试 // 如果还有重试机会,等待一小段时间再重试
if (attempt < maxRetries) if (attempt < maxRetries)
@@ -1959,13 +1966,13 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"检查进程{process.ProcessName}失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"检查进程{process.ProcessName}失败: {ex}", LogHelper.LogType.Error);
} }
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"获取WPS进程失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"获取WPS进程失败: {ex}", LogHelper.LogType.Error);
} }
return wpsProcesses; return wpsProcesses;
} }
@@ -1995,7 +2002,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"调试窗口时出错: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"调试窗口时出错: {ex}", LogHelper.LogType.Error);
} }
return true; return true;
}, IntPtr.Zero); }, IntPtr.Zero);
@@ -2004,7 +2011,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"调试窗口失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"调试窗口失败: {ex}", LogHelper.LogType.Error);
} }
} }
@@ -2015,7 +2022,7 @@ namespace Ink_Canvas {
var wpsWindowCount = 0; var wpsWindowCount = 0;
var currentProcessId = wppProcess?.Id ?? 0; var currentProcessId = wppProcess?.Id ?? 0;
EnumWindows((IntPtr hWnd, IntPtr lParam) => EnumWindows((hWnd, lParam) =>
{ {
try try
{ {
@@ -2025,7 +2032,7 @@ namespace Ink_Canvas {
// 检查是否是WPP进程的窗口 // 检查是否是WPP进程的窗口
if (windowProcessId == currentProcessId) if (windowProcessId == currentProcessId)
{ {
var windowTitle = new System.Text.StringBuilder(256); var windowTitle = new StringBuilder(256);
GetWindowText(hWnd, windowTitle, 256); GetWindowText(hWnd, windowTitle, 256);
var title = windowTitle.ToString().Trim(); var title = windowTitle.ToString().Trim();
@@ -2040,7 +2047,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"枚举窗口时出错: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"枚举窗口时出错: {ex}", LogHelper.LogType.Error);
} }
return true; // 继续枚举 return true; // 继续枚举
@@ -2056,7 +2063,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"通过枚举检查WPS窗口失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"通过枚举检查WPS窗口失败: {ex}", LogHelper.LogType.Error);
return false; return false;
} }
} }
@@ -2092,15 +2099,15 @@ namespace Ink_Canvas {
return "unknown"; return "unknown";
// 使用文件路径的哈希值作为唯一标识符 // 使用文件路径的哈希值作为唯一标识符
using (var md5 = System.Security.Cryptography.MD5.Create()) using (var md5 = MD5.Create())
{ {
byte[] hashBytes = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(filePath)); byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(filePath));
return BitConverter.ToString(hashBytes).Replace("-", "").Substring(0, 8); return BitConverter.ToString(hashBytes).Replace("-", "").Substring(0, 8);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"计算文件哈希值失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"计算文件哈希值失败: {ex}", LogHelper.LogType.Error);
return "error"; return "error";
} }
} }
@@ -2130,7 +2137,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"保存当前页面墨迹失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"保存当前页面墨迹失败: {ex}", LogHelper.LogType.Error);
} }
} }
+29 -13
View File
@@ -28,7 +28,7 @@ namespace Ink_Canvas
{ {
var st = ApplyHistoriesToNewStrokeCollection(TimeMachineHistories[index]); var st = ApplyHistoriesToNewStrokeCollection(TimeMachineHistories[index]);
st.Clip(new Rect(0, 0, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight)); st.Clip(new Rect(0, 0, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight));
var pitem = new PageListViewItem() var pitem = new PageListViewItem
{ {
Index = index, Index = index,
Strokes = st, Strokes = st,
@@ -40,7 +40,7 @@ namespace Ink_Canvas
foreach (int index in Enumerable.Range(1, WhiteboardTotalCount)) { foreach (int index in Enumerable.Range(1, WhiteboardTotalCount)) {
var st = ApplyHistoriesToNewStrokeCollection(TimeMachineHistories[index]); var st = ApplyHistoriesToNewStrokeCollection(TimeMachineHistories[index]);
st.Clip(new Rect(0,0, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight)); st.Clip(new Rect(0,0, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight));
var pitem = new PageListViewItem() var pitem = new PageListViewItem
{ {
Index = index, Index = index,
Strokes = st, Strokes = st,
@@ -51,7 +51,7 @@ namespace Ink_Canvas
var _st = inkCanvas.Strokes.Clone(); var _st = inkCanvas.Strokes.Clone();
_st.Clip(new Rect(0, 0, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight)); _st.Clip(new Rect(0, 0, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight));
var _pitem = new PageListViewItem() var _pitem = new PageListViewItem
{ {
Index = CurrentWhiteboardIndex, Index = CurrentWhiteboardIndex,
Strokes = _st, Strokes = _st,
@@ -78,11 +78,19 @@ namespace Ink_Canvas
var index = BlackBoardLeftSidePageListView.SelectedIndex; var index = BlackBoardLeftSidePageListView.SelectedIndex;
if (item != null) if (item != null)
{ {
SaveStrokes(); // 只有当选择的页面与当前页面不同时才进行切换
ClearStrokes(true); if (index + 1 != CurrentWhiteboardIndex)
CurrentWhiteboardIndex= index+1; {
RestoreStrokes(); // 取消任何UI元素的选择(只在真正切换页面时)
UpdateIndexInfoDisplay(); DeselectUIElement();
SaveStrokes();
ClearStrokes(true);
CurrentWhiteboardIndex = index + 1;
RestoreStrokes();
UpdateIndexInfoDisplay();
}
// 无论是否切换页面,都更新选择索引
BlackBoardLeftSidePageListView.SelectedIndex = index; BlackBoardLeftSidePageListView.SelectedIndex = index;
} }
} }
@@ -95,11 +103,19 @@ namespace Ink_Canvas
var index = BlackBoardRightSidePageListView.SelectedIndex; var index = BlackBoardRightSidePageListView.SelectedIndex;
if (item != null) if (item != null)
{ {
SaveStrokes(); // 只有当选择的页面与当前页面不同时才进行切换
ClearStrokes(true); if (index + 1 != CurrentWhiteboardIndex)
CurrentWhiteboardIndex = index + 1; {
RestoreStrokes(); // 取消任何UI元素的选择(只在真正切换页面时)
UpdateIndexInfoDisplay(); DeselectUIElement();
SaveStrokes();
ClearStrokes(true);
CurrentWhiteboardIndex = index + 1;
RestoreStrokes();
UpdateIndexInfoDisplay();
}
// 无论是否切换页面,都更新选择索引
BlackBoardRightSidePageListView.SelectedIndex = index; BlackBoardRightSidePageListView.SelectedIndex = index;
} }
} }
@@ -22,6 +22,7 @@ namespace Ink_Canvas {
public double Top { get; set; } public double Top { get; set; }
public double Width { get; set; } public double Width { get; set; }
public double Height { get; set; } public double Height { get; set; }
public string Stretch { get; set; } = "Fill"; // 默认为Fill
} }
public partial class MainWindow : Window { public partial class MainWindow : Window {
private void SymbolIconSaveStrokes_MouseUp(object sender, MouseButtonEventArgs e) { private void SymbolIconSaveStrokes_MouseUp(object sender, MouseButtonEventArgs e) {
@@ -129,7 +130,8 @@ namespace Ink_Canvas {
Left = InkCanvas.GetLeft(img), Left = InkCanvas.GetLeft(img),
Top = InkCanvas.GetTop(img), Top = InkCanvas.GetTop(img),
Width = img.Width, Width = img.Width,
Height = img.Height Height = img.Height,
Stretch = img.Stretch.ToString()
}); });
} }
} }
@@ -612,7 +614,8 @@ namespace Ink_Canvas {
{ {
Source = new BitmapImage(new Uri(info.SourcePath)), Source = new BitmapImage(new Uri(info.SourcePath)),
Width = info.Width, Width = info.Width,
Height = info.Height Height = info.Height,
Stretch = Enum.TryParse<Stretch>(info.Stretch, out var stretch) ? stretch : Stretch.Fill
}; };
InkCanvas.SetLeft(img, info.Left); InkCanvas.SetLeft(img, info.Left);
InkCanvas.SetTop(img, info.Top); InkCanvas.SetTop(img, info.Top);
+8 -6
View File
@@ -1,7 +1,9 @@
using System; using System;
using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Windows; using System.Windows;
using System.Windows.Forms;
namespace Ink_Canvas { namespace Ink_Canvas {
public partial class MainWindow : Window { public partial class MainWindow : Window {
@@ -13,7 +15,7 @@ namespace Ink_Canvas {
CaptureAndSaveScreenshot(savePath, isHideNotification); CaptureAndSaveScreenshot(savePath, isHideNotification);
if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) if (Settings.Automation.IsAutoSaveStrokesAtScreenshot)
SaveInkCanvasStrokes(false, false); SaveInkCanvasStrokes(false);
} }
private void SaveScreenShotToDesktop() { private void SaveScreenShotToDesktop() {
@@ -24,16 +26,16 @@ namespace Ink_Canvas {
CaptureAndSaveScreenshot(desktopPath, false); CaptureAndSaveScreenshot(desktopPath, false);
if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) if (Settings.Automation.IsAutoSaveStrokesAtScreenshot)
SaveInkCanvasStrokes(false, false); SaveInkCanvasStrokes(false);
} }
// 提取公共的截图和保存逻辑 // 提取公共的截图和保存逻辑
private void CaptureAndSaveScreenshot(string savePath, bool isHideNotification) { private void CaptureAndSaveScreenshot(string savePath, bool isHideNotification) {
var rc = System.Windows.Forms.SystemInformation.VirtualScreen; var rc = SystemInformation.VirtualScreen;
using (var bitmap = new System.Drawing.Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb)) using (var bitmap = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb))
using (var memoryGraphics = System.Drawing.Graphics.FromImage(bitmap)) { using (var memoryGraphics = Graphics.FromImage(bitmap)) {
memoryGraphics.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, System.Drawing.CopyPixelOperation.SourceCopy); memoryGraphics.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, CopyPixelOperation.SourceCopy);
// 确保目录存在 // 确保目录存在
var directory = Path.GetDirectoryName(savePath); var directory = Path.GetDirectoryName(savePath);
@@ -1,4 +1,3 @@
using iNKORE.UI.WPF.Modern.Controls;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows; using System.Windows;
@@ -6,6 +5,8 @@ using System.Windows.Controls;
using System.Windows.Ink; using System.Windows.Ink;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Shapes;
using iNKORE.UI.WPF.Modern.Controls;
using Point = System.Windows.Point; using Point = System.Windows.Point;
namespace Ink_Canvas { namespace Ink_Canvas {
@@ -25,7 +26,7 @@ namespace Ink_Canvas {
lastBorderMouseDownObject = sender; lastBorderMouseDownObject = sender;
} }
private bool isStrokeSelectionCloneOn = false; private bool isStrokeSelectionCloneOn;
private void BorderStrokeSelectionClone_MouseUp(object sender, MouseButtonEventArgs e) { private void BorderStrokeSelectionClone_MouseUp(object sender, MouseButtonEventArgs e) {
if (lastBorderMouseDownObject != sender) return; if (lastBorderMouseDownObject != sender) return;
@@ -228,7 +229,7 @@ namespace Ink_Canvas {
#endregion #endregion
private bool isGridInkCanvasSelectionCoverMouseDown = false; private bool isGridInkCanvasSelectionCoverMouseDown;
private StrokeCollection StrokesSelectionClone = new StrokeCollection(); private StrokeCollection StrokesSelectionClone = new StrokeCollection();
private void GridInkCanvasSelectionCover_MouseDown(object sender, MouseButtonEventArgs e) { private void GridInkCanvasSelectionCover_MouseDown(object sender, MouseButtonEventArgs e) {
@@ -266,18 +267,37 @@ namespace Ink_Canvas {
private double BorderStrokeSelectionControlWidth = 490.0; private double BorderStrokeSelectionControlWidth = 490.0;
private double BorderStrokeSelectionControlHeight = 80.0; private double BorderStrokeSelectionControlHeight = 80.0;
private bool isProgramChangeStrokeSelection = false; private bool isProgramChangeStrokeSelection;
private void inkCanvas_SelectionChanged(object sender, EventArgs e) { private void inkCanvas_SelectionChanged(object sender, EventArgs e) {
if (isProgramChangeStrokeSelection) return; if (isProgramChangeStrokeSelection) return;
if (inkCanvas.GetSelectedStrokes().Count == 0) { if (inkCanvas.GetSelectedStrokes().Count == 0) {
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed; GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
// 当没有选中笔画时,检查是否有选中的UIElement
CheckUIElementSelection();
} }
else { else {
GridInkCanvasSelectionCover.Visibility = Visibility.Visible; GridInkCanvasSelectionCover.Visibility = Visibility.Visible;
BorderStrokeSelectionClone.Background = Brushes.Transparent; BorderStrokeSelectionClone.Background = Brushes.Transparent;
isStrokeSelectionCloneOn = false; isStrokeSelectionCloneOn = false;
updateBorderStrokeSelectionControlLocation(); updateBorderStrokeSelectionControlLocation();
// 当选中笔画时,取消UIElement选择
DeselectUIElement();
}
}
private void CheckUIElementSelection()
{
// 检查InkCanvas中的UIElement是否被选中
var selectedElements = inkCanvas.GetSelectedElements();
if (selectedElements.Count > 0)
{
var element = selectedElements[0];
SelectUIElement(element);
}
else
{
DeselectUIElement();
} }
} }
@@ -436,5 +456,432 @@ namespace Ink_Canvas {
inkCanvas.IsManipulationEnabled = true; inkCanvas.IsManipulationEnabled = true;
SetCursorBasedOnEditingMode(inkCanvas); SetCursorBasedOnEditingMode(inkCanvas);
} }
#region UIElement Selection and Resize
private UIElement selectedUIElement;
private System.Windows.Controls.Canvas resizeHandlesCanvas;
private readonly List<Rectangle> resizeHandles = new List<Rectangle>();
private bool isResizing;
private ResizeDirection currentResizeDirection = ResizeDirection.None;
private Point resizeStartPoint;
private Rect originalElementBounds;
// 图片工具栏相关
private Border borderImageSelectionControl;
private double BorderImageSelectionControlWidth = 200.0;
private double BorderImageSelectionControlHeight = 80.0;
private enum ResizeDirection
{
None,
TopLeft,
TopCenter,
TopRight,
MiddleLeft,
MiddleRight,
BottomLeft,
BottomCenter,
BottomRight
}
private void InitializeUIElementSelection()
{
// 创建拖拽手柄画布
if (resizeHandlesCanvas == null)
{
resizeHandlesCanvas = new System.Windows.Controls.Canvas
{
Background = Brushes.Transparent,
IsHitTestVisible = true,
Visibility = Visibility.Collapsed
};
// 将手柄画布添加到主网格中,确保它在InkCanvas之上
var mainGrid = inkCanvas.Parent as Grid;
if (mainGrid != null)
{
mainGrid.Children.Add(resizeHandlesCanvas);
Panel.SetZIndex(resizeHandlesCanvas, 1000); // 确保在最上层
}
}
// 初始化图片工具栏引用
if (borderImageSelectionControl == null)
{
borderImageSelectionControl = FindName("BorderImageSelectionControl") as Border;
}
// 创建8个拖拽手柄
CreateResizeHandles();
}
private void CreateResizeHandles()
{
resizeHandles.Clear();
resizeHandlesCanvas.Children.Clear();
var directions = new[]
{
ResizeDirection.TopLeft, ResizeDirection.TopCenter, ResizeDirection.TopRight,
ResizeDirection.MiddleLeft, ResizeDirection.MiddleRight,
ResizeDirection.BottomLeft, ResizeDirection.BottomCenter, ResizeDirection.BottomRight
};
foreach (var direction in directions)
{
var handle = new Rectangle
{
Width = 12,
Height = 12,
Fill = Brushes.White,
Stroke = Brushes.DodgerBlue,
StrokeThickness = 2,
Cursor = GetCursorForDirection(direction),
Tag = direction
};
handle.MouseDown += ResizeHandle_MouseDown;
handle.MouseMove += ResizeHandle_MouseMove;
handle.MouseUp += ResizeHandle_MouseUp;
resizeHandles.Add(handle);
resizeHandlesCanvas.Children.Add(handle);
}
}
private Cursor GetCursorForDirection(ResizeDirection direction)
{
switch (direction)
{
case ResizeDirection.TopLeft:
case ResizeDirection.BottomRight:
return Cursors.SizeNWSE;
case ResizeDirection.TopRight:
case ResizeDirection.BottomLeft:
return Cursors.SizeNESW;
case ResizeDirection.TopCenter:
case ResizeDirection.BottomCenter:
return Cursors.SizeNS;
case ResizeDirection.MiddleLeft:
case ResizeDirection.MiddleRight:
return Cursors.SizeWE;
default:
return Cursors.Arrow;
}
}
private void SelectUIElement(UIElement element)
{
if (selectedUIElement == element) return;
// 取消之前的选择
DeselectUIElement();
// 清除笔画选择
if (inkCanvas.GetSelectedStrokes().Count > 0)
{
isProgramChangeStrokeSelection = true;
inkCanvas.Select(new StrokeCollection());
isProgramChangeStrokeSelection = false;
}
selectedUIElement = element;
if (element != null)
{
// 初始化选择系统(如果还没有初始化)
if (resizeHandlesCanvas == null)
{
InitializeUIElementSelection();
}
// 根据元素类型显示不同的工具栏
if (element is Image)
{
ShowImageToolbar();
}
else
{
// 对于其他UI元素,显示拖拽手柄
ShowResizeHandles();
}
}
}
private void DeselectUIElement()
{
selectedUIElement = null;
HideResizeHandles();
HideImageToolbar();
}
private void ShowResizeHandles()
{
if (selectedUIElement == null || resizeHandlesCanvas == null) return;
var bounds = GetUIElementBounds(selectedUIElement);
UpdateResizeHandlesPosition(bounds);
resizeHandlesCanvas.Visibility = Visibility.Visible;
}
private void HideResizeHandles()
{
if (resizeHandlesCanvas != null)
{
resizeHandlesCanvas.Visibility = Visibility.Collapsed;
}
}
private void ShowImageToolbar()
{
if (selectedUIElement == null || borderImageSelectionControl == null) return;
var bounds = GetUIElementBounds(selectedUIElement);
UpdateImageToolbarPosition(bounds);
borderImageSelectionControl.Visibility = Visibility.Visible;
}
private void HideImageToolbar()
{
if (borderImageSelectionControl != null)
{
borderImageSelectionControl.Visibility = Visibility.Collapsed;
}
}
private void UpdateImageToolbarPosition(Rect bounds)
{
if (borderImageSelectionControl == null) return;
// 计算工具栏位置,类似于墨迹选择工具栏的逻辑
var toolbarX = bounds.X + bounds.Width / 2 - BorderImageSelectionControlWidth / 2;
var toolbarY = bounds.Y + bounds.Height + 10; // 在图片下方10像素处
// 确保工具栏不会超出画布边界
if (toolbarX < 0) toolbarX = 0;
if (toolbarX + BorderImageSelectionControlWidth > inkCanvas.ActualWidth)
toolbarX = inkCanvas.ActualWidth - BorderImageSelectionControlWidth;
if (toolbarY + BorderImageSelectionControlHeight > inkCanvas.ActualHeight)
toolbarY = bounds.Y - BorderImageSelectionControlHeight - 10; // 如果下方空间不够,显示在上方
borderImageSelectionControl.Margin = new Thickness(toolbarX, toolbarY, 0, 0);
}
private Rect GetUIElementBounds(UIElement element)
{
var left = InkCanvas.GetLeft(element);
var top = InkCanvas.GetTop(element);
if (double.IsNaN(left)) left = 0;
if (double.IsNaN(top)) top = 0;
var width = 0.0;
var height = 0.0;
if (element is FrameworkElement fe)
{
width = fe.ActualWidth > 0 ? fe.ActualWidth : fe.Width;
height = fe.ActualHeight > 0 ? fe.ActualHeight : fe.Height;
}
return new Rect(left, top, width, height);
}
private void UpdateResizeHandlesPosition(Rect bounds)
{
if (resizeHandles.Count != 8) return;
var handleSize = 12.0;
var halfHandle = handleSize / 2;
// 计算手柄位置
var positions = new[]
{
new Point(bounds.Left - halfHandle, bounds.Top - halfHandle), // TopLeft
new Point(bounds.Left + bounds.Width / 2 - halfHandle, bounds.Top - halfHandle), // TopCenter
new Point(bounds.Right - halfHandle, bounds.Top - halfHandle), // TopRight
new Point(bounds.Left - halfHandle, bounds.Top + bounds.Height / 2 - halfHandle), // MiddleLeft
new Point(bounds.Right - halfHandle, bounds.Top + bounds.Height / 2 - halfHandle), // MiddleRight
new Point(bounds.Left - halfHandle, bounds.Bottom - halfHandle), // BottomLeft
new Point(bounds.Left + bounds.Width / 2 - halfHandle, bounds.Bottom - halfHandle), // BottomCenter
new Point(bounds.Right - halfHandle, bounds.Bottom - halfHandle) // BottomRight
};
for (int i = 0; i < resizeHandles.Count && i < positions.Length; i++)
{
System.Windows.Controls.Canvas.SetLeft(resizeHandles[i], positions[i].X);
System.Windows.Controls.Canvas.SetTop(resizeHandles[i], positions[i].Y);
}
}
private void ResizeHandle_MouseDown(object sender, MouseButtonEventArgs e)
{
if (selectedUIElement == null) return;
var handle = sender as Rectangle;
if (handle?.Tag is ResizeDirection direction)
{
isResizing = true;
currentResizeDirection = direction;
resizeStartPoint = e.GetPosition(inkCanvas);
originalElementBounds = GetUIElementBounds(selectedUIElement);
handle.CaptureMouse();
e.Handled = true;
}
}
private void ResizeHandle_MouseMove(object sender, MouseEventArgs e)
{
if (!isResizing || selectedUIElement == null) return;
var currentPoint = e.GetPosition(inkCanvas);
var deltaX = currentPoint.X - resizeStartPoint.X;
var deltaY = currentPoint.Y - resizeStartPoint.Y;
ResizeUIElement(deltaX, deltaY);
e.Handled = true;
}
private void ResizeHandle_MouseUp(object sender, MouseButtonEventArgs e)
{
if (isResizing)
{
isResizing = false;
currentResizeDirection = ResizeDirection.None;
var handle = sender as Rectangle;
handle?.ReleaseMouseCapture();
e.Handled = true;
}
}
private void ResizeUIElement(double deltaX, double deltaY)
{
if (selectedUIElement == null) return;
var newBounds = originalElementBounds;
const double minSize = 20.0;
switch (currentResizeDirection)
{
case ResizeDirection.TopLeft:
var newWidth = originalElementBounds.Width - deltaX;
var newHeight = originalElementBounds.Height - deltaY;
if (newWidth >= minSize && newHeight >= minSize)
{
newBounds.X = originalElementBounds.X + deltaX;
newBounds.Y = originalElementBounds.Y + deltaY;
newBounds.Width = newWidth;
newBounds.Height = newHeight;
}
break;
case ResizeDirection.TopCenter:
var newHeightTC = originalElementBounds.Height - deltaY;
if (newHeightTC >= minSize)
{
newBounds.Y = originalElementBounds.Y + deltaY;
newBounds.Height = newHeightTC;
}
break;
case ResizeDirection.TopRight:
var newWidthTR = originalElementBounds.Width + deltaX;
var newHeightTR = originalElementBounds.Height - deltaY;
if (newWidthTR >= minSize && newHeightTR >= minSize)
{
newBounds.Y = originalElementBounds.Y + deltaY;
newBounds.Width = newWidthTR;
newBounds.Height = newHeightTR;
}
break;
case ResizeDirection.MiddleLeft:
var newWidthML = originalElementBounds.Width - deltaX;
if (newWidthML >= minSize)
{
newBounds.X = originalElementBounds.X + deltaX;
newBounds.Width = newWidthML;
}
break;
case ResizeDirection.MiddleRight:
var newWidthMR = originalElementBounds.Width + deltaX;
if (newWidthMR >= minSize)
{
newBounds.Width = newWidthMR;
}
break;
case ResizeDirection.BottomLeft:
var newWidthBL = originalElementBounds.Width - deltaX;
var newHeightBL = originalElementBounds.Height + deltaY;
if (newWidthBL >= minSize && newHeightBL >= minSize)
{
newBounds.X = originalElementBounds.X + deltaX;
newBounds.Width = newWidthBL;
newBounds.Height = newHeightBL;
}
break;
case ResizeDirection.BottomCenter:
var newHeightBC = originalElementBounds.Height + deltaY;
if (newHeightBC >= minSize)
{
newBounds.Height = newHeightBC;
}
break;
case ResizeDirection.BottomRight:
var newWidthBR = originalElementBounds.Width + deltaX;
var newHeightBR = originalElementBounds.Height + deltaY;
if (newWidthBR >= minSize && newHeightBR >= minSize)
{
newBounds.Width = newWidthBR;
newBounds.Height = newHeightBR;
}
break;
}
// 应用新的尺寸和位置
ApplyUIElementBounds(selectedUIElement, newBounds);
// 更新手柄位置
UpdateResizeHandlesPosition(newBounds);
}
private void ApplyUIElementBounds(UIElement element, Rect bounds)
{
InkCanvas.SetLeft(element, bounds.X);
InkCanvas.SetTop(element, bounds.Y);
if (element is FrameworkElement fe)
{
fe.Width = bounds.Width;
fe.Height = bounds.Height;
}
}
private void UIElement_MouseDown(object sender, MouseButtonEventArgs e)
{
if (inkCanvas.EditingMode == InkCanvasEditingMode.Select)
{
var element = sender as UIElement;
if (element != null)
{
// 切换到选择模式并选择这个元素
inkCanvas.Select(new[] { element });
SelectUIElement(element);
e.Handled = true;
}
}
}
#endregion
} }
} }
+40 -20
View File
@@ -1,19 +1,26 @@
using Ink_Canvas.Helpers;
using Newtonsoft.Json;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input; using System.Windows.Input;
using File = System.IO.File; using System.Windows.Interop;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Interop;
using Hardcodet.Wpf.TaskbarNotification; using Hardcodet.Wpf.TaskbarNotification;
using Ink_Canvas.Helpers;
using Newtonsoft.Json;
using OSVersionExtension; using OSVersionExtension;
using Microsoft.Win32; using Application = System.Windows.Application;
using System.IO; using CheckBox = System.Windows.Controls.CheckBox;
using ComboBox = System.Windows.Controls.ComboBox;
using File = System.IO.File;
using MessageBox = System.Windows.MessageBox;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
using OperatingSystem = OSVersionExtension.OperatingSystem;
using RadioButton = System.Windows.Controls.RadioButton;
namespace Ink_Canvas { namespace Ink_Canvas {
public partial class MainWindow : Window { public partial class MainWindow : Window {
@@ -312,7 +319,7 @@ namespace Ink_Canvas {
{ {
ComboBoxItem item = new ComboBoxItem(); ComboBoxItem item = new ComboBoxItem();
item.Content = customIcon.Name; item.Content = customIcon.Name;
item.FontFamily = new System.Windows.Media.FontFamily("Microsoft YaHei UI"); item.FontFamily = new FontFamily("Microsoft YaHei UI");
ComboBoxFloatingBarImg.Items.Add(item); ComboBoxFloatingBarImg.Items.Add(item);
} }
} }
@@ -834,7 +841,7 @@ namespace Ink_Canvas {
Settings.InkToShape.LineStraightenSensitivity = e.NewValue; Settings.InkToShape.LineStraightenSensitivity = e.NewValue;
// 输出调试信息,观察值变化 // 输出调试信息,观察值变化
System.Diagnostics.Debug.WriteLine($"LineStraightenSensitivity changed: {oldValue} -> {e.NewValue}"); Debug.WriteLine($"LineStraightenSensitivity changed: {oldValue} -> {e.NewValue}");
// 立即保存设置到文件,确保设置不会丢失 // 立即保存设置到文件,确保设置不会丢失
SaveSettingsToFile(); SaveSettingsToFile();
@@ -844,7 +851,7 @@ namespace Ink_Canvas {
if (!isLoaded) return; if (!isLoaded) return;
Settings.Canvas.HighPrecisionLineStraighten = ToggleSwitchHighPrecisionLineStraighten.IsOn; Settings.Canvas.HighPrecisionLineStraighten = ToggleSwitchHighPrecisionLineStraighten.IsOn;
System.Diagnostics.Debug.WriteLine($"HighPrecisionLineStraighten changed: {Settings.Canvas.HighPrecisionLineStraighten}"); Debug.WriteLine($"HighPrecisionLineStraighten changed: {Settings.Canvas.HighPrecisionLineStraighten}");
SaveSettingsToFile(); SaveSettingsToFile();
} }
@@ -1399,7 +1406,7 @@ namespace Ink_Canvas {
} }
private void AutoSavedStrokesLocationButton_Click(object sender, RoutedEventArgs e) { private void AutoSavedStrokesLocationButton_Click(object sender, RoutedEventArgs e) {
var folderBrowser = new System.Windows.Forms.FolderBrowserDialog(); var folderBrowser = new FolderBrowserDialog();
folderBrowser.ShowDialog(); folderBrowser.ShowDialog();
if (folderBrowser.SelectedPath.Length > 0) AutoSavedStrokesLocation.Text = folderBrowser.SelectedPath; if (folderBrowser.SelectedPath.Length > 0) AutoSavedStrokesLocation.Text = folderBrowser.SelectedPath;
SaveSettingsToFile(); SaveSettingsToFile();
@@ -1507,18 +1514,22 @@ namespace Ink_Canvas {
InkCanvasEditingMode currentEditingMode = inkCanvas.EditingMode; InkCanvasEditingMode currentEditingMode = inkCanvas.EditingMode;
int currentDrawingShapeMode = drawingShapeMode; int currentDrawingShapeMode = drawingShapeMode;
bool currentForceEraser = forceEraser; bool currentForceEraser = forceEraser;
inkCanvas.StylusDown -= MainWindow_StylusDown; inkCanvas.StylusDown -= MainWindow_StylusDown;
inkCanvas.StylusMove -= MainWindow_StylusMove; inkCanvas.StylusMove -= MainWindow_StylusMove;
inkCanvas.StylusUp -= MainWindow_StylusUp; inkCanvas.StylusUp -= MainWindow_StylusUp;
inkCanvas.TouchDown -= MainWindow_TouchDown; inkCanvas.TouchDown -= MainWindow_TouchDown;
inkCanvas.TouchDown += Main_Grid_TouchDown; inkCanvas.TouchDown += Main_Grid_TouchDown;
// 先设为None再设回原来的模式,避免可能的事件冲突 // 先设为None再设回原来的模式,避免可能的事件冲突
inkCanvas.EditingMode = InkCanvasEditingMode.None; inkCanvas.EditingMode = InkCanvasEditingMode.None;
// 保存非笔画元素(如图片)
var preservedElements = PreserveNonStrokeElements();
inkCanvas.Children.Clear(); inkCanvas.Children.Clear();
// 恢复非笔画元素
RestoreNonStrokeElements(preservedElements);
isInMultiTouchMode = false; isInMultiTouchMode = false;
// 恢复到之前的编辑状态 // 恢复到之前的编辑状态
inkCanvas.EditingMode = currentEditingMode; inkCanvas.EditingMode = currentEditingMode;
drawingShapeMode = currentDrawingShapeMode; drawingShapeMode = currentDrawingShapeMode;
@@ -1817,7 +1828,7 @@ namespace Ink_Canvas {
private void ToggleSwitchIsEnableEdgeGestureUtil_Toggled(object sender, RoutedEventArgs e) { private void ToggleSwitchIsEnableEdgeGestureUtil_Toggled(object sender, RoutedEventArgs e) {
if (!isLoaded) return; if (!isLoaded) return;
Settings.Advanced.IsEnableEdgeGestureUtil = ToggleSwitchIsEnableEdgeGestureUtil.IsOn; Settings.Advanced.IsEnableEdgeGestureUtil = ToggleSwitchIsEnableEdgeGestureUtil.IsOn;
if (OSVersion.GetOperatingSystem() >= OSVersionExtension.OperatingSystem.Windows10) EdgeGestureUtil.DisableEdgeGestures(new WindowInteropHelper(this).Handle, ToggleSwitchIsEnableEdgeGestureUtil.IsOn); if (OSVersion.GetOperatingSystem() >= OperatingSystem.Windows10) EdgeGestureUtil.DisableEdgeGestures(new WindowInteropHelper(this).Handle, ToggleSwitchIsEnableEdgeGestureUtil.IsOn);
SaveSettingsToFile(); SaveSettingsToFile();
} }
@@ -1909,7 +1920,7 @@ namespace Ink_Canvas {
string backupDir = Path.Combine(App.RootPath, "Backups"); string backupDir = Path.Combine(App.RootPath, "Backups");
if (!Directory.Exists(backupDir)) { if (!Directory.Exists(backupDir)) {
Directory.CreateDirectory(backupDir); Directory.CreateDirectory(backupDir);
LogHelper.WriteLogToFile($"创建备份目录: {backupDir}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"创建备份目录: {backupDir}");
} }
// 创建备份文件名(使用当前日期时间) // 创建备份文件名(使用当前日期时间)
@@ -1920,7 +1931,7 @@ namespace Ink_Canvas {
string settingsJson = JsonConvert.SerializeObject(Settings, Formatting.Indented); string settingsJson = JsonConvert.SerializeObject(Settings, Formatting.Indented);
File.WriteAllText(backupPath, settingsJson); File.WriteAllText(backupPath, settingsJson);
LogHelper.WriteLogToFile($"成功创建设置备份: {backupPath}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"成功创建设置备份: {backupPath}");
MessageBox.Show($"设置已成功备份到:\n{backupPath}", "备份成功", MessageBoxButton.OK, MessageBoxImage.Information); MessageBox.Show($"设置已成功备份到:\n{backupPath}", "备份成功", MessageBoxButton.OK, MessageBoxImage.Information);
} }
catch (Exception ex) { catch (Exception ex) {
@@ -1937,7 +1948,7 @@ namespace Ink_Canvas {
string backupDir = Path.Combine(App.RootPath, "Backups"); string backupDir = Path.Combine(App.RootPath, "Backups");
if (!Directory.Exists(backupDir)) { if (!Directory.Exists(backupDir)) {
Directory.CreateDirectory(backupDir); Directory.CreateDirectory(backupDir);
LogHelper.WriteLogToFile($"创建备份目录: {backupDir}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"创建备份目录: {backupDir}");
MessageBox.Show("没有找到备份文件,请先创建备份", "还原失败", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("没有找到备份文件,请先创建备份", "还原失败", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;
} }
@@ -1974,7 +1985,7 @@ namespace Ink_Canvas {
// 重新加载设置到UI // 重新加载设置到UI
LoadSettings(); LoadSettings();
LogHelper.WriteLogToFile($"成功从备份还原设置: {dlg.FileName}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"成功从备份还原设置: {dlg.FileName}");
MessageBox.Show("设置已成功还原,部分设置可能需要重启软件后生效。", "还原成功", MessageBoxButton.OK, MessageBoxImage.Information); MessageBox.Show("设置已成功还原,部分设置可能需要重启软件后生效。", "还原成功", MessageBoxButton.OK, MessageBoxImage.Information);
} }
} }
@@ -2069,7 +2080,7 @@ namespace Ink_Canvas {
private async void UpdateChannelSelector_Checked(object sender, RoutedEventArgs e) { private async void UpdateChannelSelector_Checked(object sender, RoutedEventArgs e) {
if (!isLoaded) return; if (!isLoaded) return;
var radioButton = sender as System.Windows.Controls.RadioButton; var radioButton = sender as RadioButton;
if (radioButton != null) { if (radioButton != null) {
string channel = radioButton.Tag.ToString(); string channel = radioButton.Tag.ToString();
UpdateChannel newChannel = channel == "Beta" ? UpdateChannel.Beta : UpdateChannel.Release; UpdateChannel newChannel = channel == "Beta" ? UpdateChannel.Beta : UpdateChannel.Release;
@@ -2168,7 +2179,7 @@ namespace Ink_Canvas {
{ {
ComboBoxItem item = new ComboBoxItem(); ComboBoxItem item = new ComboBoxItem();
item.Content = background.Name; item.Content = background.Name;
item.FontFamily = new System.Windows.Media.FontFamily("Microsoft YaHei UI"); item.FontFamily = new FontFamily("Microsoft YaHei UI");
ComboBoxPickNameBackground.Items.Add(item); ComboBoxPickNameBackground.Items.Add(item);
} }
} }
@@ -2217,6 +2228,13 @@ namespace Ink_Canvas {
SaveSettingsToFile(); SaveSettingsToFile();
} }
private void ToggleSwitchClearCanvasAlsoClearImages_Toggled(object sender, RoutedEventArgs e)
{
if (!isLoaded) return;
Settings.Canvas.ClearCanvasAlsoClearImages = ToggleSwitchClearCanvasAlsoClearImages.IsOn;
SaveSettingsToFile();
}
private void ToggleSwitchCompressPicturesUploaded_Toggled(object sender, RoutedEventArgs e) private void ToggleSwitchCompressPicturesUploaded_Toggled(object sender, RoutedEventArgs e)
{ {
if (!isLoaded) return; if (!isLoaded) return;
@@ -2247,5 +2265,7 @@ namespace Ink_Canvas {
Settings.Canvas.EnablePalmEraser = ToggleSwitchEnablePalmEraser.IsOn; Settings.Canvas.EnablePalmEraser = ToggleSwitchEnablePalmEraser.IsOn;
SaveSettingsToFile(); SaveSettingsToFile();
} }
} }
} }
@@ -1,8 +1,4 @@
using Hardcodet.Wpf.TaskbarNotification; using System;
using Ink_Canvas.Helpers;
using Newtonsoft.Json;
using OSVersionExtension;
using System;
using System.Reflection; using System.Reflection;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
@@ -10,11 +6,15 @@ using System.Windows.Ink;
using System.Windows.Interop; using System.Windows.Interop;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using Hardcodet.Wpf.TaskbarNotification;
using Ink_Canvas.Helpers;
using Newtonsoft.Json;
using OSVersionExtension;
using File = System.IO.File; using File = System.IO.File;
using OperatingSystem = OSVersionExtension.OperatingSystem; using OperatingSystem = OSVersionExtension.OperatingSystem;
namespace Ink_Canvas { namespace Ink_Canvas {
public partial class MainWindow : System.Windows.Window { public partial class MainWindow : Window {
private void LoadSettings(bool isStartup = false) { private void LoadSettings(bool isStartup = false) {
AppVersionTextBlock.Text = Assembly.GetExecutingAssembly().GetName().Version.ToString(); AppVersionTextBlock.Text = Assembly.GetExecutingAssembly().GetName().Version.ToString();
try { try {
@@ -92,7 +92,7 @@ namespace Ink_Canvas {
// 初始化更新通道选择 // 初始化更新通道选择
foreach (var radioButton in UpdateChannelSelector.Items) { foreach (var radioButton in UpdateChannelSelector.Items) {
if (radioButton is System.Windows.Controls.RadioButton rb) { if (radioButton is RadioButton rb) {
if (rb.Tag.ToString() == Settings.Startup.UpdateChannel.ToString()) { if (rb.Tag.ToString() == Settings.Startup.UpdateChannel.ToString()) {
rb.IsChecked = true; rb.IsChecked = true;
break; break;
@@ -465,7 +465,8 @@ namespace Ink_Canvas {
BoardComboBoxEraserSize.SelectedIndex = Settings.Canvas.EraserSize; BoardComboBoxEraserSize.SelectedIndex = Settings.Canvas.EraserSize;
ToggleSwitchClearCanvasAndClearTimeMachine.IsOn = ToggleSwitchClearCanvasAndClearTimeMachine.IsOn =
Settings.Canvas.ClearCanvasAndClearTimeMachine == true; Settings.Canvas.ClearCanvasAndClearTimeMachine;
ToggleSwitchClearCanvasAlsoClearImages.IsOn = Settings.Canvas.ClearCanvasAlsoClearImages;
switch (Settings.Canvas.EraserShapeType) { switch (Settings.Canvas.EraserShapeType) {
case 0: { case 0: {
+21 -21
View File
@@ -1,5 +1,4 @@
using Ink_Canvas.Helpers; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -9,6 +8,8 @@ using System.Windows.Ink;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Animation; using System.Windows.Media.Animation;
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern.Controls;
using MessageBox = System.Windows.MessageBox; using MessageBox = System.Windows.MessageBox;
using Point = System.Windows.Point; using Point = System.Windows.Point;
@@ -55,8 +56,8 @@ namespace Ink_Canvas {
#endregion Floating Bar Control #endregion Floating Bar Control
private int drawingShapeMode = 0; private int drawingShapeMode;
private bool isLongPressSelected = false; // 用于存是否是"选中"状态,便于后期抬笔后不做切换到笔的处理 private bool isLongPressSelected; // 用于存是否是"选中"状态,便于后期抬笔后不做切换到笔的处理
#region Buttons #region Buttons
@@ -66,12 +67,12 @@ namespace Ink_Canvas {
ToggleSwitchDrawShapeBorderAutoHide.IsOn = !ToggleSwitchDrawShapeBorderAutoHide.IsOn; ToggleSwitchDrawShapeBorderAutoHide.IsOn = !ToggleSwitchDrawShapeBorderAutoHide.IsOn;
if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) if (ToggleSwitchDrawShapeBorderAutoHide.IsOn)
((iNKORE.UI.WPF.Modern.Controls.SymbolIcon)sender).Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.Pin; ((SymbolIcon)sender).Symbol = Symbol.Pin;
else else
((iNKORE.UI.WPF.Modern.Controls.SymbolIcon)sender).Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.UnPin; ((SymbolIcon)sender).Symbol = Symbol.UnPin;
} }
private object lastMouseDownSender = null; private object lastMouseDownSender;
private DateTime lastMouseDownTime = DateTime.MinValue; private DateTime lastMouseDownTime = DateTime.MinValue;
private async void Image_MouseDown(object sender, MouseButtonEventArgs e) { private async void Image_MouseDown(object sender, MouseButtonEventArgs e) {
@@ -402,23 +403,22 @@ namespace Ink_Canvas {
inkCanvas.EditingMode == InkCanvasEditingMode.Select || inkCanvas.EditingMode == InkCanvasEditingMode.Select ||
inkCanvas.EditingMode == InkCanvasEditingMode.Ink) { inkCanvas.EditingMode == InkCanvasEditingMode.Ink) {
// 允许正常橡皮、套索、批注 // 允许正常橡皮、套索、批注
return;
} }
} }
private int drawMultiStepShapeCurrentStep = 0; //多笔完成的图形 当前所处在的笔画 private int drawMultiStepShapeCurrentStep; //多笔完成的图形 当前所处在的笔画
private StrokeCollection drawMultiStepShapeSpecialStrokeCollection = new StrokeCollection(); //多笔完成的图形 当前所处在的笔画 private StrokeCollection drawMultiStepShapeSpecialStrokeCollection = new StrokeCollection(); //多笔完成的图形 当前所处在的笔画
//double drawMultiStepShapeSpecialParameter1 = 0.0; //多笔完成的图形 特殊参数 通常用于表示a //double drawMultiStepShapeSpecialParameter1 = 0.0; //多笔完成的图形 特殊参数 通常用于表示a
//double drawMultiStepShapeSpecialParameter2 = 0.0; //多笔完成的图形 特殊参数 通常用于表示b //double drawMultiStepShapeSpecialParameter2 = 0.0; //多笔完成的图形 特殊参数 通常用于表示b
private double drawMultiStepShapeSpecialParameter3 = 0.0; //多笔完成的图形 特殊参数 通常用于表示k private double drawMultiStepShapeSpecialParameter3; //多笔完成的图形 特殊参数 通常用于表示k
#region #region
private void MouseTouchMove(Point endP) { private void MouseTouchMove(Point endP) {
// 禁用原有的FitToCurve,使用新的高级贝塞尔曲线平滑 // 禁用原有的FitToCurve,使用新的高级贝塞尔曲线平滑
if (Settings.Canvas.FitToCurve == true) drawingAttributes.FitToCurve = false; if (Settings.Canvas.FitToCurve) drawingAttributes.FitToCurve = false;
ViewboxFloatingBar.IsHitTestVisible = false; ViewboxFloatingBar.IsHitTestVisible = false;
BlackboardUIGridForInkReplay.IsHitTestVisible = false; BlackboardUIGridForInkReplay.IsHitTestVisible = false;
List<Point> pointList; List<Point> pointList;
@@ -1041,7 +1041,7 @@ namespace Ink_Canvas {
strokes.Add(stroke.Clone()); strokes.Add(stroke.Clone());
//底部椭圆 //底部椭圆
pointList = GenerateEllipseGeometry(new Point(newIniP.X, endP.Y - topB / 2), pointList = GenerateEllipseGeometry(new Point(newIniP.X, endP.Y - topB / 2),
new Point(endP.X, endP.Y + topB / 2), false, true); new Point(endP.X, endP.Y + topB / 2), false);
point = new StylusPointCollection(pointList); point = new StylusPointCollection(pointList);
stroke = new Stroke(point) { stroke = new Stroke(point) {
DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
@@ -1090,7 +1090,7 @@ namespace Ink_Canvas {
var bottomB = bottomA / 2.646; var bottomB = bottomA / 2.646;
//底部椭圆 //底部椭圆
pointList = GenerateEllipseGeometry(new Point(newIniP.X, endP.Y - bottomB / 2), pointList = GenerateEllipseGeometry(new Point(newIniP.X, endP.Y - bottomB / 2),
new Point(endP.X, endP.Y + bottomB / 2), false, true); new Point(endP.X, endP.Y + bottomB / 2), false);
point = new StylusPointCollection(pointList); point = new StylusPointCollection(pointList);
stroke = new Stroke(point) { stroke = new Stroke(point) {
DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
@@ -1221,13 +1221,13 @@ namespace Ink_Canvas {
#endregion #endregion
private bool isFirstTouchCuboid = true; private bool isFirstTouchCuboid = true;
private Point CuboidFrontRectIniP = new Point(); private Point CuboidFrontRectIniP;
private Point CuboidFrontRectEndP = new Point(); private Point CuboidFrontRectEndP;
private Stroke lastTempStroke = null; private Stroke lastTempStroke;
private StrokeCollection lastTempStrokeCollection = new StrokeCollection(); private StrokeCollection lastTempStrokeCollection = new StrokeCollection();
private bool isWaitUntilNextTouchDown = false; private bool isWaitUntilNextTouchDown;
private List<Point> GenerateEllipseGeometry(Point st, Point ed, bool isDrawTop = true, private List<Point> GenerateEllipseGeometry(Point st, Point ed, bool isDrawTop = true,
bool isDrawBottom = true) { bool isDrawBottom = true) {
@@ -1377,7 +1377,7 @@ namespace Ink_Canvas {
return strokes; return strokes;
} }
private bool isMouseDown = false; private bool isMouseDown;
private void inkCanvas_MouseDown(object sender, MouseButtonEventArgs e) { private void inkCanvas_MouseDown(object sender, MouseButtonEventArgs e) {
inkCanvas.CaptureMouse(); inkCanvas.CaptureMouse();
@@ -1547,7 +1547,7 @@ namespace Ink_Canvas {
StrokeCollection collection = null; StrokeCollection collection = null;
if (lastTempStrokeCollection != null && lastTempStrokeCollection.Count > 0) if (lastTempStrokeCollection != null && lastTempStrokeCollection.Count > 0)
collection = lastTempStrokeCollection; collection = lastTempStrokeCollection;
else if (lastTempStroke != null) collection = new StrokeCollection() { lastTempStroke }; else if (lastTempStroke != null) collection = new StrokeCollection { lastTempStroke };
if (collection != null) timeMachine.CommitStrokeUserInputHistory(collection); if (collection != null) timeMachine.CommitStrokeUserInputHistory(collection);
} }
@@ -1593,10 +1593,10 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
System.Diagnostics.Debug.WriteLine($"形状绘制高级贝塞尔曲线平滑失败: {ex.Message}"); Debug.WriteLine($"形状绘制高级贝塞尔曲线平滑失败: {ex.Message}");
} }
} }
else if (Settings.Canvas.FitToCurve == true) else if (Settings.Canvas.FitToCurve)
{ {
drawingAttributes.FitToCurve = true; drawingAttributes.FitToCurve = true;
} }
@@ -1,6 +1,6 @@
using Ink_Canvas.Helpers; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
@@ -8,6 +8,7 @@ using System.Windows.Controls;
using System.Windows.Ink; using System.Windows.Ink;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using Ink_Canvas.Helpers;
using Point = System.Windows.Point; using Point = System.Windows.Point;
namespace Ink_Canvas { namespace Ink_Canvas {
@@ -21,7 +22,7 @@ namespace Ink_Canvas {
bool wasStraightened = false; bool wasStraightened = false;
// 禁用原有的FitToCurve,使用新的高级贝塞尔曲线平滑 // 禁用原有的FitToCurve,使用新的高级贝塞尔曲线平滑
if (Settings.Canvas.FitToCurve == true) drawingAttributes.FitToCurve = false; if (Settings.Canvas.FitToCurve) drawingAttributes.FitToCurve = false;
try { try {
inkCanvas.Opacity = 1; inkCanvas.Opacity = 1;
@@ -134,13 +135,13 @@ namespace Ink_Canvas {
// 先完成所有直线判定,再考虑端点吸附 // 先完成所有直线判定,再考虑端点吸附
// 读取实际的灵敏度设置值 // 读取实际的灵敏度设置值
double sensitivity = Settings.InkToShape.LineStraightenSensitivity; double sensitivity = Settings.InkToShape.LineStraightenSensitivity;
System.Diagnostics.Debug.WriteLine($"当前灵敏度值: {sensitivity}"); Debug.WriteLine($"当前灵敏度值: {sensitivity}");
// 判断是否应该拉直线条 // 判断是否应该拉直线条
bool shouldStraighten = ShouldStraightenLine(e.Stroke); bool shouldStraighten = ShouldStraightenLine(e.Stroke);
// 输出一些调试信息,帮助理解灵敏度设置的效果 // 输出一些调试信息,帮助理解灵敏度设置的效果
System.Diagnostics.Debug.WriteLine($"LineStraightenSensitivity: {Settings.InkToShape.LineStraightenSensitivity}, ShouldStraighten: {shouldStraighten}"); Debug.WriteLine($"LineStraightenSensitivity: {Settings.InkToShape.LineStraightenSensitivity}, ShouldStraighten: {shouldStraighten}");
// 只有当确定要拉直线条时,才检查端点吸附 // 只有当确定要拉直线条时,才检查端点吸附
if (shouldStraighten && Settings.Canvas.LineEndpointSnapping) { if (shouldStraighten && Settings.Canvas.LineEndpointSnapping) {
@@ -208,7 +209,7 @@ namespace Ink_Canvas {
} }
if (result.InkDrawingNode.GetShapeName() == "Circle" && if (result.InkDrawingNode.GetShapeName() == "Circle" &&
Settings.InkToShape.IsInkToShapeRounded == true) { Settings.InkToShape.IsInkToShapeRounded) {
var shape = result.InkDrawingNode.GetShape(); var shape = result.InkDrawingNode.GetShape();
if (shape.Width > 75) { if (shape.Width > 75) {
foreach (var circle in circles) foreach (var circle in circles)
@@ -264,7 +265,7 @@ namespace Ink_Canvas {
} }
} }
else if (result.InkDrawingNode.GetShapeName().Contains("Ellipse") && else if (result.InkDrawingNode.GetShapeName().Contains("Ellipse") &&
Settings.InkToShape.IsInkToShapeRounded == true) { Settings.InkToShape.IsInkToShapeRounded) {
var shape = result.InkDrawingNode.GetShape(); var shape = result.InkDrawingNode.GetShape();
//var shape1 = result.InkDrawingNode.GetShape(); //var shape1 = result.InkDrawingNode.GetShape();
//shape1.Fill = Brushes.Gray; //shape1.Fill = Brushes.Gray;
@@ -334,14 +335,14 @@ namespace Ink_Canvas {
inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes); inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes);
newStrokes = new StrokeCollection(); newStrokes = new StrokeCollection();
var _pointList = GenerateEllipseGeometry(iniP, endP, false, true); var _pointList = GenerateEllipseGeometry(iniP, endP, false);
var _point = new StylusPointCollection(_pointList); var _point = new StylusPointCollection(_pointList);
var _stroke = new Stroke(_point) { var _stroke = new Stroke(_point) {
DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
}; };
var _dashedLineStroke = var _dashedLineStroke =
GenerateDashedLineEllipseStrokeCollection(iniP, endP, true, false); GenerateDashedLineEllipseStrokeCollection(iniP, endP, true, false);
var strokes = new StrokeCollection() { var strokes = new StrokeCollection {
_stroke, _stroke,
_dashedLineStroke _dashedLineStroke
}; };
@@ -398,7 +399,7 @@ namespace Ink_Canvas {
} }
} }
else if (result.InkDrawingNode.GetShapeName().Contains("Triangle") && else if (result.InkDrawingNode.GetShapeName().Contains("Triangle") &&
Settings.InkToShape.IsInkToShapeTriangle == true) { Settings.InkToShape.IsInkToShapeTriangle) {
var shape = result.InkDrawingNode.GetShape(); var shape = result.InkDrawingNode.GetShape();
var p = result.InkDrawingNode.HotPoints; var p = result.InkDrawingNode.HotPoints;
if ((Math.Max(Math.Max(p[0].X, p[1].X), p[2].X) - if ((Math.Max(Math.Max(p[0].X, p[1].X), p[2].X) -
@@ -437,7 +438,7 @@ namespace Ink_Canvas {
result.InkDrawingNode.GetShapeName().Contains("Parallelogram") || result.InkDrawingNode.GetShapeName().Contains("Parallelogram") ||
result.InkDrawingNode.GetShapeName().Contains("Square") || result.InkDrawingNode.GetShapeName().Contains("Square") ||
result.InkDrawingNode.GetShapeName().Contains("Trapezoid")) && result.InkDrawingNode.GetShapeName().Contains("Trapezoid")) &&
Settings.InkToShape.IsInkToShapeRectangle == true) { Settings.InkToShape.IsInkToShapeRectangle) {
var shape = result.InkDrawingNode.GetShape(); var shape = result.InkDrawingNode.GetShape();
var p = result.InkDrawingNode.HotPoints; var p = result.InkDrawingNode.HotPoints;
if ((Math.Max(Math.Max(Math.Max(p[0].X, p[1].X), p[2].X), p[3].X) - if ((Math.Max(Math.Max(Math.Max(p[0].X, p[1].X), p[2].X), p[3].X) -
@@ -514,7 +515,7 @@ namespace Ink_Canvas {
var speed = GetPointSpeed(e.Stroke.StylusPoints[Math.Max(i - 1, 0)].ToPoint(), var speed = GetPointSpeed(e.Stroke.StylusPoints[Math.Max(i - 1, 0)].ToPoint(),
e.Stroke.StylusPoints[i].ToPoint(), e.Stroke.StylusPoints[i].ToPoint(),
e.Stroke.StylusPoints[Math.Min(i + 1, n)].ToPoint()); e.Stroke.StylusPoints[Math.Min(i + 1, n)].ToPoint());
s += speed.ToString() + "\t"; s += speed + "\t";
var point = new StylusPoint(); var point = new StylusPoint();
if (speed >= 0.25) if (speed >= 0.25)
point.PressureFactor = (float)(0.5 - 0.3 * (Math.Min(speed, 1.5) - 0.3) / 1.2); point.PressureFactor = (float)(0.5 - 0.3 * (Math.Min(speed, 1.5) - 0.3) / 1.2);
@@ -614,10 +615,10 @@ namespace Ink_Canvas {
catch (Exception ex) catch (Exception ex)
{ {
// 如果高级平滑失败,回退到原始笔画 // 如果高级平滑失败,回退到原始笔画
System.Diagnostics.Debug.WriteLine($"高级贝塞尔曲线平滑失败: {ex.Message}"); Debug.WriteLine($"高级贝塞尔曲线平滑失败: {ex.Message}");
} }
} }
else if (Settings.Canvas.FitToCurve == true && !wasStraightened) else if (Settings.Canvas.FitToCurve && !wasStraightened)
{ {
drawingAttributes.FitToCurve = true; drawingAttributes.FitToCurve = true;
} }
@@ -645,7 +646,7 @@ namespace Ink_Canvas {
} }
catch (Exception ex) catch (Exception ex)
{ {
System.Diagnostics.Debug.WriteLine($"异步墨迹平滑失败: {ex.Message}"); Debug.WriteLine($"异步墨迹平滑失败: {ex.Message}");
} }
} }
@@ -668,7 +669,7 @@ namespace Ink_Canvas {
double sensitivity = Settings.InkToShape.LineStraightenSensitivity; double sensitivity = Settings.InkToShape.LineStraightenSensitivity;
// 输出当前灵敏度值(调试用) // 输出当前灵敏度值(调试用)
System.Diagnostics.Debug.WriteLine($"IsPotentialStraightLine - sensitivity: {sensitivity}, length: {lineLength}"); Debug.WriteLine($"IsPotentialStraightLine - sensitivity: {sensitivity}, length: {lineLength}");
// 根据灵敏度调整快速检查阈值 // 根据灵敏度调整快速检查阈值
double quickThreshold; double quickThreshold;
@@ -682,7 +683,7 @@ namespace Ink_Canvas {
quickThreshold = Math.Min(sensitivity * 1.5, 0.20); quickThreshold = Math.Min(sensitivity * 1.5, 0.20);
} }
System.Diagnostics.Debug.WriteLine($"使用快速检查阈值: {quickThreshold}"); Debug.WriteLine($"使用快速检查阈值: {quickThreshold}");
// 快速检查:计算几个关键点与直线的距离 // 快速检查:计算几个关键点与直线的距离
if (stroke.StylusPoints.Count >= 10) { if (stroke.StylusPoints.Count >= 10) {
@@ -703,7 +704,7 @@ namespace Ink_Canvas {
double quickRelativeThreshold = lineLength * quickThreshold; double quickRelativeThreshold = lineLength * quickThreshold;
// 记录检测到的偏差(调试用) // 记录检测到的偏差(调试用)
System.Diagnostics.Debug.WriteLine($"Deviations: q={quarterDeviation}, m={midDeviation}, tq={threeQuarterDeviation}, threshold={quickRelativeThreshold}"); Debug.WriteLine($"Deviations: q={quarterDeviation}, m={midDeviation}, tq={threeQuarterDeviation}, threshold={quickRelativeThreshold}");
// 如果灵敏度超过1.5,则即使有一个点满足条件也认为可能是直线 // 如果灵敏度超过1.5,则即使有一个点满足条件也认为可能是直线
if (sensitivity > 1.5) { if (sensitivity > 1.5) {
@@ -745,7 +746,7 @@ namespace Ink_Canvas {
double sensitivity = Settings.InkToShape.LineStraightenSensitivity; double sensitivity = Settings.InkToShape.LineStraightenSensitivity;
// 输出详细的调试信息 // 输出详细的调试信息
System.Diagnostics.Debug.WriteLine($"ShouldStraightenLine - sensitivity: {sensitivity}, length: {lineLength}"); Debug.WriteLine($"ShouldStraightenLine - sensitivity: {sensitivity}, length: {lineLength}");
// 临时:显示调试消息框 // 临时:显示调试消息框
// MessageBox.Show($"灵敏度值: {sensitivity}", "调试信息"); // MessageBox.Show($"灵敏度值: {sensitivity}", "调试信息");
@@ -758,7 +759,7 @@ namespace Ink_Canvas {
bool useHighPrecision = Settings.Canvas.HighPrecisionLineStraighten; bool useHighPrecision = Settings.Canvas.HighPrecisionLineStraighten;
if (useHighPrecision) { if (useHighPrecision) {
System.Diagnostics.Debug.WriteLine("使用高精度直线拉直模式"); Debug.WriteLine("使用高精度直线拉直模式");
// 高精度模式:每隔10像素取一个计数点 // 高精度模式:每隔10像素取一个计数点
double strokeLength = 0; double strokeLength = 0;
@@ -844,7 +845,7 @@ namespace Ink_Canvas {
double avgDeviation = totalDeviation / pointCount; double avgDeviation = totalDeviation / pointCount;
// 更详细的调试信息 // 更详细的调试信息
System.Diagnostics.Debug.WriteLine($"Max deviation: {maxDeviation}, Avg: {avgDeviation}, Threshold: {sensitivity * lineLength}, Points: {pointCount}"); Debug.WriteLine($"Max deviation: {maxDeviation}, Avg: {avgDeviation}, Threshold: {sensitivity * lineLength}, Points: {pointCount}");
// 支持更广泛的灵敏度范围 (0.05-2.0) // 支持更广泛的灵敏度范围 (0.05-2.0)
@@ -855,129 +856,128 @@ namespace Ink_Canvas {
// 只判断平均偏差和相对偏差 // 只判断平均偏差和相对偏差
if (maxDeviation / lineLength < adjustedSensitivity && avgDeviation < lineLength * 0.1 * adjustedSensitivity) { if (maxDeviation / lineLength < adjustedSensitivity && avgDeviation < lineLength * 0.1 * adjustedSensitivity) {
System.Diagnostics.Debug.WriteLine("接受拉直 (高灵敏度模式)"); Debug.WriteLine("接受拉直 (高灵敏度模式)");
return true; return true;
} }
System.Diagnostics.Debug.WriteLine("拒绝拉直 (高灵敏度模式)"); Debug.WriteLine("拒绝拉直 (高灵敏度模式)");
return false; return false;
} }
// 否则使用常规判断标准 // 否则使用常规判断标准
else {
// 检查点分布的一致性 - 如果有些点偏离很大而其他点很接近直线,表明线条有明显弯曲 // 检查点分布的一致性 - 如果有些点偏离很大而其他点很接近直线,表明线条有明显弯曲
double deviationVariance = 0; double deviationVariance = 0;
// 使用相同的高精度/原始模式来计算方差 // 使用相同的高精度/原始模式来计算方差
if (useHighPrecision) { if (useHighPrecision) {
// 高精度模式:重新采样计算方差 // 高精度模式:重新采样计算方差
double strokeLength = 0; double strokeLength = 0;
double sampleInterval = 10.0; // 10像素间隔 double sampleInterval = 10.0; // 10像素间隔
// 计算笔画的总长度,用于后续采样 // 计算笔画的总长度,用于后续采样
for (int i = 1; i < stroke.StylusPoints.Count; i++) { for (int i = 1; i < stroke.StylusPoints.Count; i++) {
Point p1 = stroke.StylusPoints[i-1].ToPoint(); Point p1 = stroke.StylusPoints[i-1].ToPoint();
Point p2 = stroke.StylusPoints[i].ToPoint(); Point p2 = stroke.StylusPoints[i].ToPoint();
strokeLength += GetDistance(p1, p2); strokeLength += GetDistance(p1, p2);
} }
// 如果笔画太短,直接使用所有点 // 如果笔画太短,直接使用所有点
if (strokeLength < sampleInterval * 5) { if (strokeLength < sampleInterval * 5) {
foreach (StylusPoint sp in stroke.StylusPoints) {
Point p = sp.ToPoint();
double deviation = DistanceFromLineToPoint(start, end, p);
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
}
} else {
// 使用等距采样点
double currentLength = 0;
double nextSampleAt = 0;
Point lastPoint = start;
// 起点方差
double deviation = DistanceFromLineToPoint(start, end, lastPoint);
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
// 采样中间点
for (int i = 1; i < stroke.StylusPoints.Count; i++) {
Point currentPoint = stroke.StylusPoints[i].ToPoint();
double segmentLength = GetDistance(lastPoint, currentPoint);
// 如果这段线段跨越了下一个采样点
while (currentLength + segmentLength >= nextSampleAt) {
// 计算采样点在线段上的位置
double t = (nextSampleAt - currentLength) / segmentLength;
Point samplePoint = new Point(
lastPoint.X + t * (currentPoint.X - lastPoint.X),
lastPoint.Y + t * (currentPoint.Y - lastPoint.Y)
);
// 计算采样点的方差
deviation = DistanceFromLineToPoint(start, end, samplePoint);
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
// 设置下一个采样点位置
nextSampleAt += sampleInterval;
// 防止无限循环
if (nextSampleAt > strokeLength) break;
}
currentLength += segmentLength;
lastPoint = currentPoint;
}
// 终点方差
deviation = DistanceFromLineToPoint(start, end, end);
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
}
} else {
// 原始模式:使用所有点计算方差
foreach (StylusPoint sp in stroke.StylusPoints) { foreach (StylusPoint sp in stroke.StylusPoints) {
Point p = sp.ToPoint(); Point p = sp.ToPoint();
double deviation = DistanceFromLineToPoint(start, end, p); double deviation = DistanceFromLineToPoint(start, end, p);
deviationVariance += Math.Pow(deviation - avgDeviation, 2); deviationVariance += Math.Pow(deviation - avgDeviation, 2);
} }
} } else {
// 使用等距采样点
deviationVariance /= pointCount; double currentLength = 0;
double nextSampleAt = 0;
// 输出更多调试信息 Point lastPoint = start;
System.Diagnostics.Debug.WriteLine($"Deviation variance: {deviationVariance}, Threshold: {sensitivity * lineLength * 0.05}");
// 起点方差
// 如果最大偏差超过线长的阈值比例,或者偏差方差较大(表示不均匀弯曲),则不拉直 double deviation = DistanceFromLineToPoint(start, end, lastPoint);
// 灵敏度越大,容许的偏差越大,更容易将线条识别为直线 deviationVariance += Math.Pow(deviation - avgDeviation, 2);
if ((maxDeviation / lineLength) > sensitivity) {
System.Diagnostics.Debug.WriteLine("拒绝拉直:最大偏差过大"); // 采样中间点
return false; for (int i = 1; i < stroke.StylusPoints.Count; i++) {
} Point currentPoint = stroke.StylusPoints[i].ToPoint();
double segmentLength = GetDistance(lastPoint, currentPoint);
// 如果偏差方差大,说明线条弯曲不均匀
// 灵敏度越大,容许的偏差方差越大 // 如果这段线段跨越了下一个采样点
if (deviationVariance > (sensitivity * lineLength * 0.05)) { while (currentLength + segmentLength >= nextSampleAt) {
System.Diagnostics.Debug.WriteLine("拒绝拉直:偏差方差过大"); // 计算采样点在线段上的位置
return false; double t = (nextSampleAt - currentLength) / segmentLength;
} Point samplePoint = new Point(
lastPoint.X + t * (currentPoint.X - lastPoint.X),
// 检查中点偏离情况 - 针对弧形线条特别有效 lastPoint.Y + t * (currentPoint.Y - lastPoint.Y)
if (stroke.StylusPoints.Count > 10) { );
int midIndex = stroke.StylusPoints.Count / 2;
Point midPoint = stroke.StylusPoints[midIndex].ToPoint(); // 计算采样点的方差
double midDeviation = DistanceFromLineToPoint(start, end, midPoint); deviation = DistanceFromLineToPoint(start, end, samplePoint);
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
// 输出中点偏差信息
System.Diagnostics.Debug.WriteLine($"Mid deviation: {midDeviation}, Threshold: {lineLength * sensitivity * 0.8}"); // 设置下一个采样点位置
nextSampleAt += sampleInterval;
// 如果中点偏离过大,不拉直
// 使用灵敏度作为判断基准,灵敏度越大,容许的中点偏离越大 // 防止无限循环
if (midDeviation > (lineLength * sensitivity * 0.8)) { if (nextSampleAt > strokeLength) break;
System.Diagnostics.Debug.WriteLine("拒绝拉直:中点偏差过大"); }
return false;
currentLength += segmentLength;
lastPoint = currentPoint;
} }
// 终点方差
deviation = DistanceFromLineToPoint(start, end, end);
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
}
} else {
// 原始模式:使用所有点计算方差
foreach (StylusPoint sp in stroke.StylusPoints) {
Point p = sp.ToPoint();
double deviation = DistanceFromLineToPoint(start, end, p);
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
} }
System.Diagnostics.Debug.WriteLine("接受拉直");
return true;
} }
deviationVariance /= pointCount;
// 输出更多调试信息
Debug.WriteLine($"Deviation variance: {deviationVariance}, Threshold: {sensitivity * lineLength * 0.05}");
// 如果最大偏差超过线长的阈值比例,或者偏差方差较大(表示不均匀弯曲),则不拉直
// 灵敏度越大,容许的偏差越大,更容易将线条识别为直线
if ((maxDeviation / lineLength) > sensitivity) {
Debug.WriteLine("拒绝拉直:最大偏差过大");
return false;
}
// 如果偏差方差大,说明线条弯曲不均匀
// 灵敏度越大,容许的偏差方差越大
if (deviationVariance > (sensitivity * lineLength * 0.05)) {
Debug.WriteLine("拒绝拉直:偏差方差过大");
return false;
}
// 检查中点偏离情况 - 针对弧形线条特别有效
if (stroke.StylusPoints.Count > 10) {
int midIndex = stroke.StylusPoints.Count / 2;
Point midPoint = stroke.StylusPoints[midIndex].ToPoint();
double midDeviation = DistanceFromLineToPoint(start, end, midPoint);
// 输出中点偏差信息
Debug.WriteLine($"Mid deviation: {midDeviation}, Threshold: {lineLength * sensitivity * 0.8}");
// 如果中点偏离过大,不拉直
// 使用灵敏度作为判断基准,灵敏度越大,容许的中点偏离越大
if (midDeviation > (lineLength * sensitivity * 0.8)) {
Debug.WriteLine("拒绝拉直:中点偏差过大");
return false;
}
}
Debug.WriteLine("接受拉直");
return true;
} }
// New method: Creates a straight line stroke between two points // New method: Creates a straight line stroke between two points
@@ -987,7 +987,7 @@ namespace Ink_Canvas {
// 根据是否启用压感触屏模式决定如何设置压感 // 根据是否启用压感触屏模式决定如何设置压感
// 如果未启用压感触屏模式,则使用均匀粗细 // 如果未启用压感触屏模式,则使用均匀粗细
if (!Settings.Canvas.EnablePressureTouchMode || Settings.Canvas.DisablePressure || if (!Settings.Canvas.EnablePressureTouchMode || Settings.Canvas.DisablePressure ||
Settings.InkToShape.IsInkToShapeNoFakePressureRectangle == true || penType == 1) { Settings.InkToShape.IsInkToShapeNoFakePressureRectangle || penType == 1) {
// 使用均匀粗细(所有点压感值都是0.5f) // 使用均匀粗细(所有点压感值都是0.5f)
points.Add(new StylusPoint(start.X, start.Y, 0.5f)); points.Add(new StylusPoint(start.X, start.Y, 0.5f));
@@ -1083,7 +1083,7 @@ namespace Ink_Canvas {
// Return snapped points if any snapping occurred // Return snapped points if any snapping occurred
if (startSnapped || endSnapped) { if (startSnapped || endSnapped) {
return new Point[] { snappedStart, snappedEnd }; return new[] { snappedStart, snappedEnd };
} }
return null; return null;
@@ -1140,7 +1140,7 @@ namespace Ink_Canvas {
} }
public StylusPointCollection GenerateFakePressureTriangle(StylusPointCollection points) { public StylusPointCollection GenerateFakePressureTriangle(StylusPointCollection points) {
if (Settings.InkToShape.IsInkToShapeNoFakePressureTriangle == true || penType == 1) { if (Settings.InkToShape.IsInkToShapeNoFakePressureTriangle || penType == 1) {
var newPoint = new StylusPointCollection(); var newPoint = new StylusPointCollection();
newPoint.Add(new StylusPoint(points[0].X, points[0].Y)); newPoint.Add(new StylusPoint(points[0].X, points[0].Y));
var cPoint = GetCenterPoint(points[0], points[1]); var cPoint = GetCenterPoint(points[0], points[1]);
@@ -1174,30 +1174,30 @@ namespace Ink_Canvas {
} }
} }
public StylusPointCollection GenerateFakePressureRectangle(StylusPointCollection points) { public StylusPointCollection GenerateFakePressureRectangle(StylusPointCollection points)
if (Settings.InkToShape.IsInkToShapeNoFakePressureRectangle == true || penType == 1) { {
if (Settings.InkToShape.IsInkToShapeNoFakePressureRectangle || penType == 1) {
return points; return points;
} }
else {
var newPoint = new StylusPointCollection(); var newPoint = new StylusPointCollection();
newPoint.Add(new StylusPoint(points[0].X, points[0].Y, (float)0.4)); newPoint.Add(new StylusPoint(points[0].X, points[0].Y, (float)0.4));
var cPoint = GetCenterPoint(points[0], points[1]); var cPoint = GetCenterPoint(points[0], points[1]);
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8)); newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
newPoint.Add(new StylusPoint(points[1].X, points[1].Y, (float)0.4)); newPoint.Add(new StylusPoint(points[1].X, points[1].Y, (float)0.4));
newPoint.Add(new StylusPoint(points[1].X, points[1].Y, (float)0.4)); newPoint.Add(new StylusPoint(points[1].X, points[1].Y, (float)0.4));
cPoint = GetCenterPoint(points[1], points[2]); cPoint = GetCenterPoint(points[1], points[2]);
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8)); newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
newPoint.Add(new StylusPoint(points[2].X, points[2].Y, (float)0.4)); newPoint.Add(new StylusPoint(points[2].X, points[2].Y, (float)0.4));
newPoint.Add(new StylusPoint(points[2].X, points[2].Y, (float)0.4)); newPoint.Add(new StylusPoint(points[2].X, points[2].Y, (float)0.4));
cPoint = GetCenterPoint(points[2], points[3]); cPoint = GetCenterPoint(points[2], points[3]);
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8)); newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
newPoint.Add(new StylusPoint(points[3].X, points[3].Y, (float)0.4)); newPoint.Add(new StylusPoint(points[3].X, points[3].Y, (float)0.4));
newPoint.Add(new StylusPoint(points[3].X, points[3].Y, (float)0.4)); newPoint.Add(new StylusPoint(points[3].X, points[3].Y, (float)0.4));
cPoint = GetCenterPoint(points[3], points[0]); cPoint = GetCenterPoint(points[3], points[0]);
newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8)); newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
newPoint.Add(new StylusPoint(points[0].X, points[0].Y, (float)0.4)); newPoint.Add(new StylusPoint(points[0].X, points[0].Y, (float)0.4));
return newPoint; return newPoint;
}
} }
public Point GetCenterPoint(Point point1, Point point2) { public Point GetCenterPoint(Point point1, Point point2) {
+40 -17
View File
@@ -1,12 +1,12 @@
using Ink_Canvas.Helpers; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System; using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Ink; using System.Windows.Ink;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Diagnostics; using Ink_Canvas.Helpers;
namespace Ink_Canvas { namespace Ink_Canvas {
public partial class MainWindow : Window { public partial class MainWindow : Window {
@@ -32,7 +32,7 @@ namespace Ink_Canvas {
private Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>> DrawingAttributesHistory = private Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>> DrawingAttributesHistory =
new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>(); new Dictionary<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
private Dictionary<Guid, List<Stroke>> DrawingAttributesHistoryFlag = new Dictionary<Guid, List<Stroke>>() { private Dictionary<Guid, List<Stroke>> DrawingAttributesHistoryFlag = new Dictionary<Guid, List<Stroke>> {
{ DrawingAttributeIds.Color, new List<Stroke>() }, { DrawingAttributeIds.Color, new List<Stroke>() },
{ DrawingAttributeIds.DrawingFlags, new List<Stroke>() }, { DrawingAttributeIds.DrawingFlags, new List<Stroke>() },
{ DrawingAttributeIds.IsHighlighter, new List<Stroke>() }, { DrawingAttributeIds.IsHighlighter, new List<Stroke>() },
@@ -130,14 +130,17 @@ namespace Ink_Canvas {
canvas.Strokes.Remove(currentStroke); canvas.Strokes.Remove(currentStroke);
} }
} else if (item.CommitType == TimeMachineHistoryType.ElementInsert) { } else if (item.CommitType == TimeMachineHistoryType.ElementInsert) {
if (!item.StrokeHasBeenCleared) { // 使用传入的canvas参数,而不是总是使用inkCanvas
var targetCanvas = canvas ?? inkCanvas;
if (item.StrokeHasBeenCleared) {
// Undo: 移除元素 // Undo: 移除元素
if (item.InsertedElement != null && inkCanvas.Children.Contains(item.InsertedElement)) if (item.InsertedElement != null && targetCanvas.Children.Contains(item.InsertedElement))
inkCanvas.Children.Remove(item.InsertedElement); targetCanvas.Children.Remove(item.InsertedElement);
} else { } else {
// Redo: 添加元素 // Redo: 添加元素
if (item.InsertedElement != null && !inkCanvas.Children.Contains(item.InsertedElement)) if (item.InsertedElement != null && !targetCanvas.Children.Contains(item.InsertedElement))
inkCanvas.Children.Add(item.InsertedElement); targetCanvas.Children.Add(item.InsertedElement);
} }
} }
@@ -145,7 +148,7 @@ namespace Ink_Canvas {
} }
private StrokeCollection ApplyHistoriesToNewStrokeCollection(TimeMachineHistory[] items) { private StrokeCollection ApplyHistoriesToNewStrokeCollection(TimeMachineHistory[] items) {
InkCanvas fakeInkCanv = new InkCanvas() { InkCanvas fakeInkCanv = new InkCanvas {
Width = inkCanvas.ActualWidth, Width = inkCanvas.ActualWidth,
Height = inkCanvas.ActualHeight, Height = inkCanvas.ActualHeight,
EditingMode = InkCanvasEditingMode.None, EditingMode = InkCanvasEditingMode.None,
@@ -153,13 +156,34 @@ namespace Ink_Canvas {
if (items != null && items.Length > 0) { if (items != null && items.Length > 0) {
foreach (var timeMachineHistory in items) { foreach (var timeMachineHistory in items) {
ApplyHistoryToCanvas(timeMachineHistory, fakeInkCanv); // 只处理笔画历史,不处理图片元素历史
// 因为页面预览只需要显示笔画,图片元素会影响主画布
if (timeMachineHistory.CommitType != TimeMachineHistoryType.ElementInsert) {
ApplyHistoryToCanvas(timeMachineHistory, fakeInkCanv);
}
} }
} }
return fakeInkCanv.Strokes; return fakeInkCanv.Strokes;
} }
// 新增:获取页面的所有图片元素
private List<UIElement> GetPageImageElements(TimeMachineHistory[] items) {
var imageElements = new List<UIElement>();
if (items != null && items.Length > 0) {
foreach (var timeMachineHistory in items) {
if (timeMachineHistory.CommitType == TimeMachineHistoryType.ElementInsert &&
timeMachineHistory.InsertedElement != null &&
!timeMachineHistory.StrokeHasBeenCleared) {
imageElements.Add(timeMachineHistory.InsertedElement);
}
}
}
return imageElements;
}
private void TimeMachine_OnUndoStateChanged(bool status) { private void TimeMachine_OnUndoStateChanged(bool status) {
var result = status ? Visibility.Visible : Visibility.Collapsed; var result = status ? Visibility.Visible : Visibility.Collapsed;
BtnUndo.Visibility = result; BtnUndo.Visibility = result;
@@ -202,24 +226,23 @@ namespace Ink_Canvas {
return; return;
} }
if (e.Added.Count != 0) { if (e.Added.Count != 0)
{
if (_currentCommitType == CommitReason.ShapeRecognition) { if (_currentCommitType == CommitReason.ShapeRecognition) {
timeMachine.CommitStrokeShapeHistory(ReplacedStroke, e.Added); timeMachine.CommitStrokeShapeHistory(ReplacedStroke, e.Added);
ReplacedStroke = null; ReplacedStroke = null;
return; return;
} else {
timeMachine.CommitStrokeUserInputHistory(e.Added);
return;
} }
timeMachine.CommitStrokeUserInputHistory(e.Added);
return;
} }
if (e.Removed.Count != 0) { if (e.Removed.Count != 0) {
if (_currentCommitType == CommitReason.ShapeRecognition) { if (_currentCommitType == CommitReason.ShapeRecognition) {
ReplacedStroke = e.Removed; ReplacedStroke = e.Removed;
return;
} else if (!IsEraseByPoint || _currentCommitType == CommitReason.ClearingCanvas) { } else if (!IsEraseByPoint || _currentCommitType == CommitReason.ClearingCanvas) {
timeMachine.CommitStrokeEraseHistory(e.Removed); timeMachine.CommitStrokeEraseHistory(e.Removed);
return;
} }
} }
} }
+13 -13
View File
@@ -1,17 +1,17 @@
using Ink_Canvas.Helpers; using System;
using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Timers;
using System.Windows;
using System.IO; using System.IO;
using System.Reflection; using System.Linq;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Linq; using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using Ink_Canvas.Helpers;
namespace Ink_Canvas { namespace Ink_Canvas {
public class TimeViewModel : INotifyPropertyChanged { public class TimeViewModel : INotifyPropertyChanged {
@@ -49,9 +49,9 @@ namespace Ink_Canvas {
private Timer timerCheckPPT = new Timer(); private Timer timerCheckPPT = new Timer();
private Timer timerKillProcess = new Timer(); private Timer timerKillProcess = new Timer();
private Timer timerCheckAutoFold = new Timer(); private Timer timerCheckAutoFold = new Timer();
private string AvailableLatestVersion = null; private string AvailableLatestVersion;
private Timer timerCheckAutoUpdateWithSilence = new Timer(); private Timer timerCheckAutoUpdateWithSilence = new Timer();
private bool isHidingSubPanelsWhenInking = false; // 避免书写时触发二次关闭二级菜单导致动画不连续 private bool isHidingSubPanelsWhenInking; // 避免书写时触发二次关闭二级菜单导致动画不连续
private Timer timerDisplayTime = new Timer(); private Timer timerDisplayTime = new Timer();
private Timer timerDisplayDate = new Timer(); private Timer timerDisplayDate = new Timer();
@@ -232,8 +232,8 @@ namespace Ink_Canvas {
} }
private bool foldFloatingBarByUser = false, // 保持收纳操作不受自动收纳的控制 private bool foldFloatingBarByUser, // 保持收纳操作不受自动收纳的控制
unfoldFloatingBarByUser = false; // 允许用户在希沃软件内进行展开操作 unfoldFloatingBarByUser; // 允许用户在希沃软件内进行展开操作
private void timerCheckAutoFold_Elapsed(object sender, ElapsedEventArgs e) { private void timerCheckAutoFold_Elapsed(object sender, ElapsedEventArgs e) {
if (isFloatingBarChangingHideMode) return; if (isFloatingBarChangingHideMode) return;
+71 -11
View File
@@ -1,4 +1,3 @@
using Ink_Canvas.Helpers;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -8,19 +7,59 @@ using System.Windows.Controls;
using System.Windows.Ink; using System.Windows.Ink;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using Ink_Canvas.Helpers;
using Point = System.Windows.Point; using Point = System.Windows.Point;
using System.Diagnostics;
namespace Ink_Canvas { namespace Ink_Canvas {
public partial class MainWindow : Window { public partial class MainWindow : Window {
#region Multi-Touch #region Multi-Touch
private bool isInMultiTouchMode = false; private bool isInMultiTouchMode;
private List<int> dec = new List<int>(); private List<int> dec = new List<int>();
private bool isSingleFingerDragMode = false; private bool isSingleFingerDragMode;
private Point centerPoint = new Point(0, 0); private Point centerPoint = new Point(0, 0);
private InkCanvasEditingMode lastInkCanvasEditingMode = InkCanvasEditingMode.Ink; private InkCanvasEditingMode lastInkCanvasEditingMode = InkCanvasEditingMode.Ink;
/// <summary>
/// 保存画布上的非笔画元素(如图片、媒体元素等)
/// </summary>
private List<UIElement> PreserveNonStrokeElements()
{
var preservedElements = new List<UIElement>();
// 遍历inkCanvas的所有子元素
for (int i = inkCanvas.Children.Count - 1; i >= 0; i--)
{
var child = inkCanvas.Children[i];
// 保存图片、媒体元素等非笔画相关的UI元素
if (child is Image || child is MediaElement ||
(child is Border border && border.Name != "AdvancedEraserOverlay"))
{
preservedElements.Add(child);
}
}
return preservedElements;
}
/// <summary>
/// 恢复之前保存的非笔画元素到画布
/// </summary>
private void RestoreNonStrokeElements(List<UIElement> preservedElements)
{
if (preservedElements == null) return;
foreach (var element in preservedElements)
{
// 确保元素没有父容器再添加到inkCanvas
if (element is FrameworkElement fe && fe.Parent == null)
{
inkCanvas.Children.Add(element);
}
}
}
private void BorderMultiTouchMode_MouseUp(object sender, MouseButtonEventArgs e) { private void BorderMultiTouchMode_MouseUp(object sender, MouseButtonEventArgs e) {
if (isInMultiTouchMode) { if (isInMultiTouchMode) {
inkCanvas.StylusDown -= MainWindow_StylusDown; inkCanvas.StylusDown -= MainWindow_StylusDown;
@@ -31,12 +70,16 @@ namespace Ink_Canvas {
if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint) { if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint) {
inkCanvas.EditingMode = InkCanvasEditingMode.Ink; inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
} }
// 保存非笔画元素(如图片)
var preservedElements = PreserveNonStrokeElements();
inkCanvas.Children.Clear(); inkCanvas.Children.Clear();
// 恢复非笔画元素
RestoreNonStrokeElements(preservedElements);
isInMultiTouchMode = false; isInMultiTouchMode = false;
} }
else { else {
inkCanvas.StylusDown += MainWindow_StylusDown; inkCanvas.StylusDown += MainWindow_StylusDown;
inkCanvas.StylusMove += MainWindow_StylusMove; inkCanvas.StylusMove += MainWindow_StylusMove;
inkCanvas.StylusUp += MainWindow_StylusUp; inkCanvas.StylusUp += MainWindow_StylusUp;
@@ -45,7 +88,11 @@ namespace Ink_Canvas {
if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint) { if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint) {
inkCanvas.EditingMode = InkCanvasEditingMode.None; inkCanvas.EditingMode = InkCanvasEditingMode.None;
} }
// 保存非笔画元素(如图片)
var preservedElements = PreserveNonStrokeElements();
inkCanvas.Children.Clear(); inkCanvas.Children.Clear();
// 恢复非笔画元素
RestoreNonStrokeElements(preservedElements);
isInMultiTouchMode = true; isInMultiTouchMode = true;
} }
} }
@@ -118,7 +165,12 @@ namespace Ink_Canvas {
VisualCanvasList.Remove(e.StylusDevice.Id); VisualCanvasList.Remove(e.StylusDevice.Id);
TouchDownPointsList.Remove(e.StylusDevice.Id); TouchDownPointsList.Remove(e.StylusDevice.Id);
if (StrokeVisualList.Count == 0 || VisualCanvasList.Count == 0 || TouchDownPointsList.Count == 0) { if (StrokeVisualList.Count == 0 || VisualCanvasList.Count == 0 || TouchDownPointsList.Count == 0) {
inkCanvas.Children.Clear(); // 只清除手写笔预览相关的Canvas,不清除所有子元素
foreach (var canvas in VisualCanvasList.Values.ToList()) {
if (inkCanvas.Children.Contains(canvas)) {
inkCanvas.Children.Remove(canvas);
}
}
StrokeVisualList.Clear(); StrokeVisualList.Clear();
VisualCanvasList.Clear(); VisualCanvasList.Clear();
TouchDownPointsList.Clear(); TouchDownPointsList.Clear();
@@ -220,10 +272,10 @@ namespace Ink_Canvas {
} }
// 手掌擦相关变量 // 手掌擦相关变量
private bool isPalmEraserActive = false; private bool isPalmEraserActive;
private InkCanvasEditingMode palmEraserLastEditingMode = InkCanvasEditingMode.Ink; private InkCanvasEditingMode palmEraserLastEditingMode = InkCanvasEditingMode.Ink;
private bool palmEraserLastIsHighlighter = false; private bool palmEraserLastIsHighlighter;
private bool palmEraserWasEnabledBeforeMultiTouch = false; private bool palmEraserWasEnabledBeforeMultiTouch;
private void inkCanvas_PreviewTouchDown(object sender, TouchEventArgs e) { private void inkCanvas_PreviewTouchDown(object sender, TouchEventArgs e) {
// 橡皮状态下不做任何切换,直接return,保证橡皮可持续 // 橡皮状态下不做任何切换,直接return,保证橡皮可持续
@@ -305,7 +357,7 @@ namespace Ink_Canvas {
if (drawingShapeMode != 0) { if (drawingShapeMode != 0) {
var mouseArgs = new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left) var mouseArgs = new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left)
{ {
RoutedEvent = UIElement.MouseLeftButtonUpEvent, RoutedEvent = MouseLeftButtonUpEvent,
Source = inkCanvas Source = inkCanvas
}; };
inkCanvas_MouseUp(inkCanvas, mouseArgs); inkCanvas_MouseUp(inkCanvas, mouseArgs);
@@ -446,7 +498,11 @@ namespace Ink_Canvas {
{ {
inkCanvas.EditingMode = InkCanvasEditingMode.Ink; inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
} }
// 保存非笔画元素(如图片)
var preservedElements = PreserveNonStrokeElements();
inkCanvas.Children.Clear(); inkCanvas.Children.Clear();
// 恢复非笔画元素
RestoreNonStrokeElements(preservedElements);
isInMultiTouchMode = false; isInMultiTouchMode = false;
// 关闭多指书写时,恢复手掌擦开关 // 关闭多指书写时,恢复手掌擦开关
if (palmEraserWasEnabledBeforeMultiTouch) { if (palmEraserWasEnabledBeforeMultiTouch) {
@@ -471,7 +527,11 @@ namespace Ink_Canvas {
{ {
inkCanvas.EditingMode = InkCanvasEditingMode.None; inkCanvas.EditingMode = InkCanvasEditingMode.None;
} }
// 保存非笔画元素(如图片)
var preservedElements = PreserveNonStrokeElements();
inkCanvas.Children.Clear(); inkCanvas.Children.Clear();
// 恢复非笔画元素
RestoreNonStrokeElements(preservedElements);
isInMultiTouchMode = true; isInMultiTouchMode = true;
// 启用多指书写时,自动禁用手掌擦 // 启用多指书写时,自动禁用手掌擦
palmEraserWasEnabledBeforeMultiTouch = Settings.Canvas.EnablePalmEraser; palmEraserWasEnabledBeforeMultiTouch = Settings.Canvas.EnablePalmEraser;
+28 -23
View File
@@ -1,11 +1,15 @@
using Ink_Canvas.Helpers; using System;
using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Diagnostics; using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Interop; using System.Windows.Interop;
using Hardcodet.Wpf.TaskbarNotification; using Hardcodet.Wpf.TaskbarNotification;
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern.Controls;
using Application = System.Windows.Application;
using ContextMenu = System.Windows.Controls.ContextMenu;
using MenuItem = System.Windows.Controls.MenuItem;
namespace Ink_Canvas namespace Ink_Canvas
{ {
@@ -21,7 +25,7 @@ namespace Ink_Canvas
(TextBlock)((SimpleStackPanel)((MenuItem)s.Items[s.Items.Count - 5]).Header).Children[0]; (TextBlock)((SimpleStackPanel)((MenuItem)s.Items[s.Items.Count - 5]).Header).Children[0];
var ResetFloatingBarPositionTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 4]; var ResetFloatingBarPositionTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 4];
var HideICCMainWindowTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 9]; var HideICCMainWindowTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 9];
var mainWin = (MainWindow)Application.Current.MainWindow; var mainWin = (MainWindow)Current.MainWindow;
if (mainWin.IsLoaded) { if (mainWin.IsLoaded) {
// 判斷是否在收納模式中 // 判斷是否在收納模式中
if (mainWin.isFloatingBarFolded) { if (mainWin.isFloatingBarFolded) {
@@ -46,49 +50,50 @@ namespace Ink_Canvas
} }
private void CloseAppTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) { private void CloseAppTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) {
var mainWin = (MainWindow)Application.Current.MainWindow; var mainWin = (MainWindow)Current.MainWindow;
if (mainWin.IsLoaded) { if (mainWin.IsLoaded) {
App.IsAppExitByUser = true; IsAppExitByUser = true;
Application.Current.Shutdown(); Current.Shutdown();
// mainWin.BtnExit_Click(null,null); // mainWin.BtnExit_Click(null,null);
} }
} }
private void RestartAppTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) { private void RestartAppTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) {
var mainWin = (MainWindow)Application.Current.MainWindow; var mainWin = (MainWindow)Current.MainWindow;
if (mainWin.IsLoaded) { if (mainWin.IsLoaded) {
App.IsAppExitByUser = true; IsAppExitByUser = true;
try { try {
// 启动新实例 // 启动新实例,添加 -m 参数允许多实例启动
string exePath = Process.GetCurrentProcess().MainModule.FileName; string exePath = Process.GetCurrentProcess().MainModule.FileName;
ProcessStartInfo startInfo = new ProcessStartInfo(); ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = exePath; startInfo.FileName = exePath;
startInfo.Arguments = "-m";
startInfo.UseShellExecute = true; startInfo.UseShellExecute = true;
// 启动进程但不等待 // 启动进程但不等待
Process.Start(startInfo); Process.Start(startInfo);
} catch (Exception ex) { } catch (Exception ex) {
LogHelper.NewLog($"重启程序时出错: {ex.Message}"); LogHelper.NewLog($"重启程序时出错: {ex.Message}");
} }
// 退出当前实例 // 退出当前实例
Application.Current.Shutdown(); Current.Shutdown();
} }
} }
private void ForceFullScreenTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) { private void ForceFullScreenTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) {
var mainWin = (MainWindow)Application.Current.MainWindow; var mainWin = (MainWindow)Current.MainWindow;
if (mainWin.IsLoaded) { if (mainWin.IsLoaded) {
Ink_Canvas.MainWindow.MoveWindow(new WindowInteropHelper(mainWin).Handle, 0, 0, Ink_Canvas.MainWindow.MoveWindow(new WindowInteropHelper(mainWin).Handle, 0, 0,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, true); Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, true);
Ink_Canvas.MainWindow.ShowNewMessage($"已强制全屏化:{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}"); Ink_Canvas.MainWindow.ShowNewMessage($"已强制全屏化:{Screen.PrimaryScreen.Bounds.Width}x{Screen.PrimaryScreen.Bounds.Height}(缩放比例为{Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth}x{Screen.PrimaryScreen.Bounds.Height / SystemParameters.PrimaryScreenHeight}");
} }
} }
private void FoldFloatingBarTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) private void FoldFloatingBarTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e)
{ {
var mainWin = (MainWindow)Application.Current.MainWindow; var mainWin = (MainWindow)Current.MainWindow;
if (mainWin.IsLoaded) if (mainWin.IsLoaded)
if (mainWin.isFloatingBarFolded) mainWin.UnFoldFloatingBar_MouseUp(new object(),null); if (mainWin.isFloatingBarFolded) mainWin.UnFoldFloatingBar_MouseUp(new object(),null);
else mainWin.FoldFloatingBar_MouseUp(new object(),null); else mainWin.FoldFloatingBar_MouseUp(new object(),null);
@@ -96,7 +101,7 @@ namespace Ink_Canvas
private void ResetFloatingBarPositionTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) private void ResetFloatingBarPositionTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e)
{ {
var mainWin = (MainWindow)Application.Current.MainWindow; var mainWin = (MainWindow)Current.MainWindow;
if (mainWin.IsLoaded) { if (mainWin.IsLoaded) {
var isInPPTPresentationMode = false; var isInPPTPresentationMode = false;
Dispatcher.Invoke(() => { Dispatcher.Invoke(() => {
@@ -111,10 +116,10 @@ namespace Ink_Canvas
private void HideICCMainWindowTrayIconMenuItem_Checked(object sender, RoutedEventArgs e) { private void HideICCMainWindowTrayIconMenuItem_Checked(object sender, RoutedEventArgs e) {
var mi = (MenuItem)sender; var mi = (MenuItem)sender;
var mainWin = (MainWindow)Application.Current.MainWindow; var mainWin = (MainWindow)Current.MainWindow;
if (mainWin.IsLoaded) { if (mainWin.IsLoaded) {
mainWin.Hide(); mainWin.Hide();
var s = ((TaskbarIcon)Application.Current.Resources["TaskbarTrayIcon"]).ContextMenu; var s = ((TaskbarIcon)Current.Resources["TaskbarTrayIcon"]).ContextMenu;
var ResetFloatingBarPositionTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 4]; var ResetFloatingBarPositionTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 4];
var FoldFloatingBarTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 5]; var FoldFloatingBarTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 5];
var ForceFullScreenTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 6]; var ForceFullScreenTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 6];
@@ -132,10 +137,10 @@ namespace Ink_Canvas
private void HideICCMainWindowTrayIconMenuItem_UnChecked(object sender, RoutedEventArgs e) { private void HideICCMainWindowTrayIconMenuItem_UnChecked(object sender, RoutedEventArgs e) {
var mi = (MenuItem)sender; var mi = (MenuItem)sender;
var mainWin = (MainWindow)Application.Current.MainWindow; var mainWin = (MainWindow)Current.MainWindow;
if (mainWin.IsLoaded) { if (mainWin.IsLoaded) {
mainWin.Show(); mainWin.Show();
var s = ((TaskbarIcon)Application.Current.Resources["TaskbarTrayIcon"]).ContextMenu; var s = ((TaskbarIcon)Current.Resources["TaskbarTrayIcon"]).ContextMenu;
var ResetFloatingBarPositionTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 4]; var ResetFloatingBarPositionTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 4];
var FoldFloatingBarTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 5]; var FoldFloatingBarTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 5];
var ForceFullScreenTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 6]; var ForceFullScreenTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 6];
+2 -2
View File
@@ -49,5 +49,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.7.4.0")] [assembly: AssemblyVersion("1.7.5.0")]
[assembly: AssemblyFileVersion("1.7.4.0")] [assembly: AssemblyFileVersion("1.7.5.0")]
+22 -16
View File
@@ -8,10 +8,16 @@
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Resources;
using System.Runtime.CompilerServices;
namespace Ink_Canvas.Properties { namespace Ink_Canvas.Properties {
using System;
/// <summary> /// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc. /// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary> /// </summary>
@@ -19,27 +25,27 @@ namespace Ink_Canvas.Properties {
// class via a tool like ResGen or Visual Studio. // class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project. // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [DebuggerNonUserCode()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [CompilerGenerated()]
internal class Resources { internal class Resources {
private static global::System.Resources.ResourceManager resourceMan; private static ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture; private static CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() { internal Resources() {
} }
/// <summary> /// <summary>
/// Returns the cached ResourceManager instance used by this class. /// Returns the cached ResourceManager instance used by this class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [EditorBrowsable(EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager { internal static ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Ink_Canvas.Properties.Resources", typeof(Resources).Assembly); ResourceManager temp = new ResourceManager("Ink_Canvas.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;
@@ -50,8 +56,8 @@ namespace Ink_Canvas.Properties {
/// Overrides the current thread's CurrentUICulture property for all /// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class. /// resource lookups using this strongly typed resource class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [EditorBrowsable(EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture { internal static CultureInfo Culture {
get { get {
return resourceCulture; return resourceCulture;
} }
@@ -63,7 +69,7 @@ namespace Ink_Canvas.Properties {
/// <summary> /// <summary>
/// Looks up a localized resource of type System.IO.UnmanagedMemoryStream similar to System.IO.MemoryStream. /// Looks up a localized resource of type System.IO.UnmanagedMemoryStream similar to System.IO.MemoryStream.
/// </summary> /// </summary>
internal static System.IO.UnmanagedMemoryStream TimerDownNotice { internal static UnmanagedMemoryStream TimerDownNotice {
get { get {
return ResourceManager.GetStream("TimerDownNotice", resourceCulture); return ResourceManager.GetStream("TimerDownNotice", resourceCulture);
} }
+8 -4
View File
@@ -8,14 +8,18 @@
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
using System.CodeDom.Compiler;
using System.Configuration;
using System.Runtime.CompilerServices;
namespace Ink_Canvas.Properties { namespace Ink_Canvas.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [CompilerGenerated()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")] [GeneratedCode("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Settings : ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(Synchronized(new Settings())));
public static Settings Default { public static Settings Default {
get { get {
+3 -3
View File
@@ -1,7 +1,7 @@
namespace Ink_Canvas namespace Ink_Canvas
{ {
public static class ChickenSoup { public static class ChickenSoup {
public static string[] OSUPlayerYuLu = new string[] { public static string[] OSUPlayerYuLu = {
"澳洲原神,启动!", "澳洲原神,启动!",
"一眼丁真,鉴定为玩osu!玩的", "一眼丁真,鉴定为玩osu!玩的",
"喊MimosaM给我炒两菜", "喊MimosaM给我炒两菜",
@@ -32,7 +32,7 @@
"又有人2000了" "又有人2000了"
}; };
public static string[] MingYanJingJu = new string[] { public static string[] MingYanJingJu = {
"老骥伏枥,志在千里;烈士暮年,壮心不已", "老骥伏枥,志在千里;烈士暮年,壮心不已",
"有志者,事竟成", "有志者,事竟成",
"有志者自有千方百计,无志者只感千难万难", "有志者自有千方百计,无志者只感千难万难",
@@ -98,7 +98,7 @@
"有志不在年高,无志空活百岁", "有志不在年高,无志空活百岁",
}; };
public static string[] GaoKaoPhrases = new string[] { public static string[] GaoKaoPhrases = {
"以梦为马,不负韶华。祝你高考顺利,未来可期!", "以梦为马,不负韶华。祝你高考顺利,未来可期!",
"高考顺利,愿你乘风破浪,前程似锦!", "高考顺利,愿你乘风破浪,前程似锦!",
"愿你高考顺利,不负韶华,梦想成真!", "愿你高考顺利,不负韶华,梦想成真!",
Binary file not shown.
Binary file not shown.
Binary file not shown.
+91 -88
View File
@@ -1,6 +1,7 @@
using Newtonsoft.Json; using System;
using System.IO;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
namespace Ink_Canvas namespace Ink_Canvas
{ {
@@ -35,19 +36,19 @@ namespace Ink_Canvas
[JsonProperty("inkAlpha")] [JsonProperty("inkAlpha")]
public double InkAlpha { get; set; } = 255; public double InkAlpha { get; set; } = 255;
[JsonProperty("isShowCursor")] [JsonProperty("isShowCursor")]
public bool IsShowCursor { get; set; } = false; public bool IsShowCursor { get; set; }
[JsonProperty("inkStyle")] [JsonProperty("inkStyle")]
public int InkStyle { get; set; } = 0; public int InkStyle { get; set; }
[JsonProperty("eraserSize")] [JsonProperty("eraserSize")]
public int EraserSize { get; set; } = 2; public int EraserSize { get; set; } = 2;
[JsonProperty("eraserType")] [JsonProperty("eraserType")]
public int EraserType { get; set; } = 0; // 0 - 图标切换模式 1 - 面积擦 2 - 线条擦 public int EraserType { get; set; } // 0 - 图标切换模式 1 - 面积擦 2 - 线条擦
[JsonProperty("eraserShapeType")] [JsonProperty("eraserShapeType")]
public int EraserShapeType { get; set; } = 0; // 0 - 圆形擦 1 - 黑板擦 public int EraserShapeType { get; set; } // 0 - 圆形擦 1 - 黑板擦
[JsonProperty("hideStrokeWhenSelecting")] [JsonProperty("hideStrokeWhenSelecting")]
public bool HideStrokeWhenSelecting { get; set; } = true; public bool HideStrokeWhenSelecting { get; set; } = true;
[JsonProperty("fitToCurve")] [JsonProperty("fitToCurve")]
public bool FitToCurve { get; set; } = false; // 默认关闭原来的贝塞尔平滑 public bool FitToCurve { get; set; } // 默认关闭原来的贝塞尔平滑
[JsonProperty("useAdvancedBezierSmoothing")] [JsonProperty("useAdvancedBezierSmoothing")]
public bool UseAdvancedBezierSmoothing { get; set; } = true; // 默认启用高级贝塞尔曲线平滑 public bool UseAdvancedBezierSmoothing { get; set; } = true; // 默认启用高级贝塞尔曲线平滑
[JsonProperty("useAsyncInkSmoothing")] [JsonProperty("useAsyncInkSmoothing")]
@@ -57,13 +58,13 @@ namespace Ink_Canvas
[JsonProperty("inkSmoothingQuality")] [JsonProperty("inkSmoothingQuality")]
public int InkSmoothingQuality { get; set; } = 1; // 0-低质量高性能, 1-平衡, 2-高质量低性能 public int InkSmoothingQuality { get; set; } = 1; // 0-低质量高性能, 1-平衡, 2-高质量低性能
[JsonProperty("maxConcurrentSmoothingTasks")] [JsonProperty("maxConcurrentSmoothingTasks")]
public int MaxConcurrentSmoothingTasks { get; set; } = 0; // 0表示自动检测CPU核心数 public int MaxConcurrentSmoothingTasks { get; set; } // 0表示自动检测CPU核心数
[JsonProperty("clearCanvasAndClearTimeMachine")] [JsonProperty("clearCanvasAndClearTimeMachine")]
public bool ClearCanvasAndClearTimeMachine { get; set; } = false; public bool ClearCanvasAndClearTimeMachine { get; set; }
[JsonProperty("enablePressureTouchMode")] [JsonProperty("enablePressureTouchMode")]
public bool EnablePressureTouchMode { get; set; } = false; // 是否启用压感触屏模式 public bool EnablePressureTouchMode { get; set; } // 是否启用压感触屏模式
[JsonProperty("disablePressure")] [JsonProperty("disablePressure")]
public bool DisablePressure { get; set; } = false; // 是否屏蔽压感 public bool DisablePressure { get; set; } // 是否屏蔽压感
[JsonProperty("autoStraightenLine")] [JsonProperty("autoStraightenLine")]
public bool AutoStraightenLine { get; set; } = true; // 是否启用直线自动拉直 public bool AutoStraightenLine { get; set; } = true; // 是否启用直线自动拉直
[JsonProperty("autoStraightenLineThreshold")] [JsonProperty("autoStraightenLineThreshold")]
@@ -76,7 +77,7 @@ namespace Ink_Canvas
public int LineEndpointSnappingThreshold { get; set; } = 15; // 直线端点吸附的距离阈值(像素) public int LineEndpointSnappingThreshold { get; set; } = 15; // 直线端点吸附的距离阈值(像素)
[JsonProperty("usingWhiteboard")] [JsonProperty("usingWhiteboard")]
public bool UsingWhiteboard { get; set; } = false; public bool UsingWhiteboard { get; set; }
[JsonProperty("customBackgroundColor")] [JsonProperty("customBackgroundColor")]
public string CustomBackgroundColor { get; set; } = "#162924"; public string CustomBackgroundColor { get; set; } = "#162924";
@@ -84,9 +85,11 @@ namespace Ink_Canvas
[JsonProperty("hyperbolaAsymptoteOption")] [JsonProperty("hyperbolaAsymptoteOption")]
public OptionalOperation HyperbolaAsymptoteOption { get; set; } = OptionalOperation.Ask; public OptionalOperation HyperbolaAsymptoteOption { get; set; } = OptionalOperation.Ask;
[JsonProperty("isCompressPicturesUploaded")] [JsonProperty("isCompressPicturesUploaded")]
public bool IsCompressPicturesUploaded { get; set; } = false; public bool IsCompressPicturesUploaded { get; set; }
[JsonProperty("enablePalmEraser")] [JsonProperty("enablePalmEraser")]
public bool EnablePalmEraser { get; set; } = true; public bool EnablePalmEraser { get; set; } = true;
[JsonProperty("clearCanvasAlsoClearImages")]
public bool ClearCanvasAlsoClearImages { get; set; } = true;
} }
public enum OptionalOperation public enum OptionalOperation
@@ -111,9 +114,9 @@ namespace Ink_Canvas
[JsonProperty("AutoSwitchTwoFingerGesture")] [JsonProperty("AutoSwitchTwoFingerGesture")]
public bool AutoSwitchTwoFingerGesture { get; set; } = true; public bool AutoSwitchTwoFingerGesture { get; set; } = true;
[JsonProperty("isEnableTwoFingerRotation")] [JsonProperty("isEnableTwoFingerRotation")]
public bool IsEnableTwoFingerRotation { get; set; } = false; public bool IsEnableTwoFingerRotation { get; set; }
[JsonProperty("isEnableTwoFingerRotationOnSelection")] [JsonProperty("isEnableTwoFingerRotationOnSelection")]
public bool IsEnableTwoFingerRotationOnSelection { get; set; } = false; public bool IsEnableTwoFingerRotationOnSelection { get; set; }
} }
// 更新通道枚举 // 更新通道枚举
@@ -128,7 +131,7 @@ namespace Ink_Canvas
[JsonProperty("isAutoUpdate")] [JsonProperty("isAutoUpdate")]
public bool IsAutoUpdate { get; set; } = true; public bool IsAutoUpdate { get; set; } = true;
[JsonProperty("isAutoUpdateWithSilence")] [JsonProperty("isAutoUpdateWithSilence")]
public bool IsAutoUpdateWithSilence { get; set; } = false; public bool IsAutoUpdateWithSilence { get; set; }
[JsonProperty("isAutoUpdateWithSilenceStartTime")] [JsonProperty("isAutoUpdateWithSilenceStartTime")]
public string AutoUpdateWithSilenceStartTime { get; set; } = "06:00"; public string AutoUpdateWithSilenceStartTime { get; set; } = "06:00";
[JsonProperty("isAutoUpdateWithSilenceEndTime")] [JsonProperty("isAutoUpdateWithSilenceEndTime")]
@@ -138,11 +141,11 @@ namespace Ink_Canvas
[JsonProperty("skippedVersion")] [JsonProperty("skippedVersion")]
public string SkippedVersion { get; set; } = ""; public string SkippedVersion { get; set; } = "";
[JsonProperty("isEnableNibMode")] [JsonProperty("isEnableNibMode")]
public bool IsEnableNibMode { get; set; } = false; public bool IsEnableNibMode { get; set; }
[JsonProperty("isFoldAtStartup")] [JsonProperty("isFoldAtStartup")]
public bool IsFoldAtStartup { get; set; } = false; public bool IsFoldAtStartup { get; set; }
[JsonProperty("crashAction")] [JsonProperty("crashAction")]
public int CrashAction { get; set; } = 0; public int CrashAction { get; set; }
} }
public class Appearance public class Appearance
@@ -150,13 +153,13 @@ namespace Ink_Canvas
[JsonProperty("isEnableDisPlayNibModeToggler")] [JsonProperty("isEnableDisPlayNibModeToggler")]
public bool IsEnableDisPlayNibModeToggler { get; set; } = true; public bool IsEnableDisPlayNibModeToggler { get; set; } = true;
[JsonProperty("isColorfulViewboxFloatingBar")] [JsonProperty("isColorfulViewboxFloatingBar")]
public bool IsColorfulViewboxFloatingBar { get; set; } = false; public bool IsColorfulViewboxFloatingBar { get; set; }
// [JsonProperty("enableViewboxFloatingBarScaleTransform")] // [JsonProperty("enableViewboxFloatingBarScaleTransform")]
// public bool EnableViewboxFloatingBarScaleTransform { get; set; } = false; // public bool EnableViewboxFloatingBarScaleTransform { get; set; } = false;
[JsonProperty("viewboxFloatingBarScaleTransformValue")] [JsonProperty("viewboxFloatingBarScaleTransformValue")]
public double ViewboxFloatingBarScaleTransformValue { get; set; } = 1.0; public double ViewboxFloatingBarScaleTransformValue { get; set; } = 1.0;
[JsonProperty("floatingBarImg")] [JsonProperty("floatingBarImg")]
public int FloatingBarImg { get; set; } = 0; public int FloatingBarImg { get; set; }
[JsonProperty("customFloatingBarImgs")] [JsonProperty("customFloatingBarImgs")]
public List<CustomFloatingBarIcon> CustomFloatingBarImgs { get; set; } = new List<CustomFloatingBarIcon>(); public List<CustomFloatingBarIcon> CustomFloatingBarImgs { get; set; } = new List<CustomFloatingBarIcon>();
[JsonProperty("viewboxFloatingBarOpacityValue")] [JsonProperty("viewboxFloatingBarOpacityValue")]
@@ -166,7 +169,7 @@ namespace Ink_Canvas
[JsonProperty("viewboxFloatingBarOpacityInPPTValue")] [JsonProperty("viewboxFloatingBarOpacityInPPTValue")]
public double ViewboxFloatingBarOpacityInPPTValue { get; set; } = 0.5; public double ViewboxFloatingBarOpacityInPPTValue { get; set; } = 0.5;
[JsonProperty("enableViewboxBlackBoardScaleTransform")] [JsonProperty("enableViewboxBlackBoardScaleTransform")]
public bool EnableViewboxBlackBoardScaleTransform { get; set; } = false; public bool EnableViewboxBlackBoardScaleTransform { get; set; }
[JsonProperty("isTransparentButtonBackground")] [JsonProperty("isTransparentButtonBackground")]
public bool IsTransparentButtonBackground { get; set; } = true; public bool IsTransparentButtonBackground { get; set; } = true;
[JsonProperty("isShowExitButton")] [JsonProperty("isShowExitButton")]
@@ -178,11 +181,11 @@ namespace Ink_Canvas
[JsonProperty("enableChickenSoupInWhiteboardMode")] [JsonProperty("enableChickenSoupInWhiteboardMode")]
public bool EnableChickenSoupInWhiteboardMode { get; set; } = true; public bool EnableChickenSoupInWhiteboardMode { get; set; } = true;
[JsonProperty("isShowHideControlButton")] [JsonProperty("isShowHideControlButton")]
public bool IsShowHideControlButton { get; set; } = false; public bool IsShowHideControlButton { get; set; }
[JsonProperty("unFoldButtonImageType")] [JsonProperty("unFoldButtonImageType")]
public int UnFoldButtonImageType { get; set; } = 0; public int UnFoldButtonImageType { get; set; }
[JsonProperty("isShowLRSwitchButton")] [JsonProperty("isShowLRSwitchButton")]
public bool IsShowLRSwitchButton { get; set; } = false; public bool IsShowLRSwitchButton { get; set; }
[JsonProperty("isShowQuickPanel")] [JsonProperty("isShowQuickPanel")]
public bool IsShowQuickPanel { get; set; } = true; public bool IsShowQuickPanel { get; set; } = true;
[JsonProperty("chickenSoupSource")] [JsonProperty("chickenSoupSource")]
@@ -190,7 +193,7 @@ namespace Ink_Canvas
[JsonProperty("isShowModeFingerToggleSwitch")] [JsonProperty("isShowModeFingerToggleSwitch")]
public bool IsShowModeFingerToggleSwitch { get; set; } = true; public bool IsShowModeFingerToggleSwitch { get; set; } = true;
[JsonProperty("theme")] [JsonProperty("theme")]
public int Theme { get; set; } = 0; public int Theme { get; set; }
} }
public class PowerPointSettings public class PowerPointSettings
@@ -206,11 +209,11 @@ namespace Ink_Canvas
// 0居中,+就是往上,-就是往下 // 0居中,+就是往上,-就是往下
[JsonProperty("pptLSButtonPosition")] [JsonProperty("pptLSButtonPosition")]
public int PPTLSButtonPosition { get; set; } = 0; public int PPTLSButtonPosition { get; set; }
// 0居中,+就是往上,-就是往下 // 0居中,+就是往上,-就是往下
[JsonProperty("pptRSButtonPosition")] [JsonProperty("pptRSButtonPosition")]
public int PPTRSButtonPosition { get; set; } = 0; public int PPTRSButtonPosition { get; set; }
[JsonProperty("pptSButtonsOption")] [JsonProperty("pptSButtonsOption")]
public int PPTSButtonsOption { get; set; } = 221; public int PPTSButtonsOption { get; set; } = 221;
@@ -230,27 +233,27 @@ namespace Ink_Canvas
[JsonProperty("isNoClearStrokeOnSelectWhenInPowerPoint")] [JsonProperty("isNoClearStrokeOnSelectWhenInPowerPoint")]
public bool IsNoClearStrokeOnSelectWhenInPowerPoint { get; set; } = true; public bool IsNoClearStrokeOnSelectWhenInPowerPoint { get; set; } = true;
[JsonProperty("isShowStrokeOnSelectInPowerPoint")] [JsonProperty("isShowStrokeOnSelectInPowerPoint")]
public bool IsShowStrokeOnSelectInPowerPoint { get; set; } = false; public bool IsShowStrokeOnSelectInPowerPoint { get; set; }
[JsonProperty("isAutoSaveStrokesInPowerPoint")] [JsonProperty("isAutoSaveStrokesInPowerPoint")]
public bool IsAutoSaveStrokesInPowerPoint { get; set; } = true; public bool IsAutoSaveStrokesInPowerPoint { get; set; } = true;
[JsonProperty("isAutoSaveScreenShotInPowerPoint")] [JsonProperty("isAutoSaveScreenShotInPowerPoint")]
public bool IsAutoSaveScreenShotInPowerPoint { get; set; } = false; public bool IsAutoSaveScreenShotInPowerPoint { get; set; }
[JsonProperty("isNotifyPreviousPage")] [JsonProperty("isNotifyPreviousPage")]
public bool IsNotifyPreviousPage { get; set; } = false; public bool IsNotifyPreviousPage { get; set; }
[JsonProperty("isNotifyHiddenPage")] [JsonProperty("isNotifyHiddenPage")]
public bool IsNotifyHiddenPage { get; set; } = true; public bool IsNotifyHiddenPage { get; set; } = true;
[JsonProperty("isNotifyAutoPlayPresentation")] [JsonProperty("isNotifyAutoPlayPresentation")]
public bool IsNotifyAutoPlayPresentation { get; set; } = true; public bool IsNotifyAutoPlayPresentation { get; set; } = true;
[JsonProperty("isEnableTwoFingerGestureInPresentationMode")] [JsonProperty("isEnableTwoFingerGestureInPresentationMode")]
public bool IsEnableTwoFingerGestureInPresentationMode { get; set; } = false; public bool IsEnableTwoFingerGestureInPresentationMode { get; set; }
[JsonProperty("isEnableFingerGestureSlideShowControl")] [JsonProperty("isEnableFingerGestureSlideShowControl")]
public bool IsEnableFingerGestureSlideShowControl { get; set; } = true; public bool IsEnableFingerGestureSlideShowControl { get; set; } = true;
[JsonProperty("isSupportWPS")] [JsonProperty("isSupportWPS")]
public bool IsSupportWPS { get; set; } = false; public bool IsSupportWPS { get; set; }
[JsonProperty("enableWppProcessKill")] [JsonProperty("enableWppProcessKill")]
public bool EnableWppProcessKill { get; set; } = true; public bool EnableWppProcessKill { get; set; } = true;
[JsonProperty("isAlwaysGoToFirstPageOnReenter")] [JsonProperty("isAlwaysGoToFirstPageOnReenter")]
public bool IsAlwaysGoToFirstPageOnReenter { get; set; } = false; public bool IsAlwaysGoToFirstPageOnReenter { get; set; }
} }
public class Automation public class Automation
@@ -275,131 +278,131 @@ namespace Ink_Canvas
|| IsAutoFoldInMaxHubWhiteboard; || IsAutoFoldInMaxHubWhiteboard;
[JsonProperty("isAutoEnterAnnotationModeWhenExitFoldMode")] [JsonProperty("isAutoEnterAnnotationModeWhenExitFoldMode")]
public bool IsAutoEnterAnnotationModeWhenExitFoldMode { get; set; } = false; public bool IsAutoEnterAnnotationModeWhenExitFoldMode { get; set; }
[JsonProperty("isAutoFoldInEasiNote")] [JsonProperty("isAutoFoldInEasiNote")]
public bool IsAutoFoldInEasiNote { get; set; } = false; public bool IsAutoFoldInEasiNote { get; set; }
[JsonProperty("isAutoFoldInEasiNoteIgnoreDesktopAnno")] [JsonProperty("isAutoFoldInEasiNoteIgnoreDesktopAnno")]
public bool IsAutoFoldInEasiNoteIgnoreDesktopAnno { get; set; } = false; public bool IsAutoFoldInEasiNoteIgnoreDesktopAnno { get; set; }
[JsonProperty("isAutoFoldInEasiCamera")] [JsonProperty("isAutoFoldInEasiCamera")]
public bool IsAutoFoldInEasiCamera { get; set; } = false; public bool IsAutoFoldInEasiCamera { get; set; }
[JsonProperty("isAutoFoldInEasiNote3")] [JsonProperty("isAutoFoldInEasiNote3")]
public bool IsAutoFoldInEasiNote3 { get; set; } = false; public bool IsAutoFoldInEasiNote3 { get; set; }
[JsonProperty("isAutoFoldInEasiNote3C")] [JsonProperty("isAutoFoldInEasiNote3C")]
public bool IsAutoFoldInEasiNote3C { get; set; } = false; public bool IsAutoFoldInEasiNote3C { get; set; }
[JsonProperty("isAutoFoldInEasiNote5C")] [JsonProperty("isAutoFoldInEasiNote5C")]
public bool IsAutoFoldInEasiNote5C { get; set; } = false; public bool IsAutoFoldInEasiNote5C { get; set; }
[JsonProperty("isAutoFoldInSeewoPincoTeacher")] [JsonProperty("isAutoFoldInSeewoPincoTeacher")]
public bool IsAutoFoldInSeewoPincoTeacher { get; set; } = false; public bool IsAutoFoldInSeewoPincoTeacher { get; set; }
[JsonProperty("isAutoFoldInHiteTouchPro")] [JsonProperty("isAutoFoldInHiteTouchPro")]
public bool IsAutoFoldInHiteTouchPro { get; set; } = false; public bool IsAutoFoldInHiteTouchPro { get; set; }
[JsonProperty("isAutoFoldInHiteLightBoard")] [JsonProperty("isAutoFoldInHiteLightBoard")]
public bool IsAutoFoldInHiteLightBoard { get; set; } = false; public bool IsAutoFoldInHiteLightBoard { get; set; }
[JsonProperty("isAutoFoldInHiteCamera")] [JsonProperty("isAutoFoldInHiteCamera")]
public bool IsAutoFoldInHiteCamera { get; set; } = false; public bool IsAutoFoldInHiteCamera { get; set; }
[JsonProperty("isAutoFoldInWxBoardMain")] [JsonProperty("isAutoFoldInWxBoardMain")]
public bool IsAutoFoldInWxBoardMain { get; set; } = false; public bool IsAutoFoldInWxBoardMain { get; set; }
/* /*
[JsonProperty("isAutoFoldInZySmartBoard")] [JsonProperty("isAutoFoldInZySmartBoard")]
public bool IsAutoFoldInZySmartBoard { get; set; } = false; public bool IsAutoFoldInZySmartBoard { get; set; } = false;
*/ */
[JsonProperty("isAutoFoldInOldZyBoard")] [JsonProperty("isAutoFoldInOldZyBoard")]
public bool IsAutoFoldInOldZyBoard { get; set; } = false; public bool IsAutoFoldInOldZyBoard { get; set; }
[JsonProperty("isAutoFoldInMSWhiteboard")] [JsonProperty("isAutoFoldInMSWhiteboard")]
public bool IsAutoFoldInMSWhiteboard { get; set; } = false; public bool IsAutoFoldInMSWhiteboard { get; set; }
[JsonProperty("isAutoFoldInAdmoxWhiteboard")] [JsonProperty("isAutoFoldInAdmoxWhiteboard")]
public bool IsAutoFoldInAdmoxWhiteboard { get; set; } = false; public bool IsAutoFoldInAdmoxWhiteboard { get; set; }
[JsonProperty("isAutoFoldInAdmoxBooth")] [JsonProperty("isAutoFoldInAdmoxBooth")]
public bool IsAutoFoldInAdmoxBooth { get; set; } = false; public bool IsAutoFoldInAdmoxBooth { get; set; }
[JsonProperty("isAutoFoldInQPoint")] [JsonProperty("isAutoFoldInQPoint")]
public bool IsAutoFoldInQPoint { get; set; } = false; public bool IsAutoFoldInQPoint { get; set; }
[JsonProperty("isAutoFoldInYiYunVisualPresenter")] [JsonProperty("isAutoFoldInYiYunVisualPresenter")]
public bool IsAutoFoldInYiYunVisualPresenter { get; set; } = false; public bool IsAutoFoldInYiYunVisualPresenter { get; set; }
[JsonProperty("isAutoFoldInMaxHubWhiteboard")] [JsonProperty("isAutoFoldInMaxHubWhiteboard")]
public bool IsAutoFoldInMaxHubWhiteboard { get; set; } = false; public bool IsAutoFoldInMaxHubWhiteboard { get; set; }
[JsonProperty("isAutoFoldInPPTSlideShow")] [JsonProperty("isAutoFoldInPPTSlideShow")]
public bool IsAutoFoldInPPTSlideShow { get; set; } = false; public bool IsAutoFoldInPPTSlideShow { get; set; }
[JsonProperty("isAutoFoldAfterPPTSlideShow")] [JsonProperty("isAutoFoldAfterPPTSlideShow")]
public bool IsAutoFoldAfterPPTSlideShow { get; set; } = false; public bool IsAutoFoldAfterPPTSlideShow { get; set; }
[JsonProperty("isAutoKillPptService")] [JsonProperty("isAutoKillPptService")]
public bool IsAutoKillPptService { get; set; } = false; public bool IsAutoKillPptService { get; set; }
[JsonProperty("isAutoKillEasiNote")] [JsonProperty("isAutoKillEasiNote")]
public bool IsAutoKillEasiNote { get; set; } = false; public bool IsAutoKillEasiNote { get; set; }
[JsonProperty("isAutoKillHiteAnnotation")] [JsonProperty("isAutoKillHiteAnnotation")]
public bool IsAutoKillHiteAnnotation { get; set; } = false; public bool IsAutoKillHiteAnnotation { get; set; }
[JsonProperty("isAutoKillVComYouJiao")] [JsonProperty("isAutoKillVComYouJiao")]
public bool IsAutoKillVComYouJiao { get; set; } = false; public bool IsAutoKillVComYouJiao { get; set; }
[JsonProperty("isAutoKillSeewoLauncher2DesktopAnnotation")] [JsonProperty("isAutoKillSeewoLauncher2DesktopAnnotation")]
public bool IsAutoKillSeewoLauncher2DesktopAnnotation { get; set; } = false; public bool IsAutoKillSeewoLauncher2DesktopAnnotation { get; set; }
[JsonProperty("isAutoKillInkCanvas")] [JsonProperty("isAutoKillInkCanvas")]
public bool IsAutoKillInkCanvas { get; set; } = false; public bool IsAutoKillInkCanvas { get; set; }
[JsonProperty("isAutoKillICA")] [JsonProperty("isAutoKillICA")]
public bool IsAutoKillICA { get; set; } = false; public bool IsAutoKillICA { get; set; }
[JsonProperty("isAutoKillIDT")] [JsonProperty("isAutoKillIDT")]
public bool IsAutoKillIDT { get; set; } = false; public bool IsAutoKillIDT { get; set; }
[JsonProperty("isSaveScreenshotsInDateFolders")] [JsonProperty("isSaveScreenshotsInDateFolders")]
public bool IsSaveScreenshotsInDateFolders { get; set; } = false; public bool IsSaveScreenshotsInDateFolders { get; set; }
[JsonProperty("isAutoSaveStrokesAtScreenshot")] [JsonProperty("isAutoSaveStrokesAtScreenshot")]
public bool IsAutoSaveStrokesAtScreenshot { get; set; } = false; public bool IsAutoSaveStrokesAtScreenshot { get; set; }
[JsonProperty("isAutoSaveStrokesAtClear")] [JsonProperty("isAutoSaveStrokesAtClear")]
public bool IsAutoSaveStrokesAtClear { get; set; } = false; public bool IsAutoSaveStrokesAtClear { get; set; }
[JsonProperty("isAutoClearWhenExitingWritingMode")] [JsonProperty("isAutoClearWhenExitingWritingMode")]
public bool IsAutoClearWhenExitingWritingMode { get; set; } = false; public bool IsAutoClearWhenExitingWritingMode { get; set; }
[JsonProperty("minimumAutomationStrokeNumber")] [JsonProperty("minimumAutomationStrokeNumber")]
public int MinimumAutomationStrokeNumber { get; set; } = 0; public int MinimumAutomationStrokeNumber { get; set; }
[JsonProperty("autoSavedStrokesLocation")] [JsonProperty("autoSavedStrokesLocation")]
public string AutoSavedStrokesLocation = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "saves"); public string AutoSavedStrokesLocation = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "saves");
[JsonProperty("autoDelSavedFiles")] [JsonProperty("autoDelSavedFiles")]
public bool AutoDelSavedFiles = false; public bool AutoDelSavedFiles;
[JsonProperty("autoDelSavedFilesDaysThreshold")] [JsonProperty("autoDelSavedFilesDaysThreshold")]
public int AutoDelSavedFilesDaysThreshold = 15; public int AutoDelSavedFilesDaysThreshold = 15;
[JsonProperty("isSaveFullPageStrokes")] [JsonProperty("isSaveFullPageStrokes")]
public bool IsSaveFullPageStrokes = false; public bool IsSaveFullPageStrokes;
[JsonProperty("isAutoEnterAnnotationAfterKillHite")] [JsonProperty("isAutoEnterAnnotationAfterKillHite")]
public bool IsAutoEnterAnnotationAfterKillHite { get; set; } = false; public bool IsAutoEnterAnnotationAfterKillHite { get; set; }
} }
public class Advanced public class Advanced
{ {
[JsonProperty("isSpecialScreen")] [JsonProperty("isSpecialScreen")]
public bool IsSpecialScreen { get; set; } = false; public bool IsSpecialScreen { get; set; }
[JsonProperty("isQuadIR")] [JsonProperty("isQuadIR")]
public bool IsQuadIR { get; set; } = false; public bool IsQuadIR { get; set; }
[JsonProperty("touchMultiplier")] [JsonProperty("touchMultiplier")]
public double TouchMultiplier { get; set; } = 0.25; public double TouchMultiplier { get; set; } = 0.25;
@@ -411,7 +414,7 @@ namespace Ink_Canvas
public int FingerModeBoundsWidth { get; set; } = 30; public int FingerModeBoundsWidth { get; set; } = 30;
[JsonProperty("eraserBindTouchMultiplier")] [JsonProperty("eraserBindTouchMultiplier")]
public bool EraserBindTouchMultiplier { get; set; } = false; public bool EraserBindTouchMultiplier { get; set; }
[JsonProperty("isLogEnabled")] [JsonProperty("isLogEnabled")]
public bool IsLogEnabled { get; set; } = true; public bool IsLogEnabled { get; set; } = true;
@@ -420,28 +423,28 @@ namespace Ink_Canvas
public bool IsSaveLogByDate { get; set; } = true; public bool IsSaveLogByDate { get; set; } = true;
[JsonProperty("isEnableFullScreenHelper")] [JsonProperty("isEnableFullScreenHelper")]
public bool IsEnableFullScreenHelper { get; set; } = false; public bool IsEnableFullScreenHelper { get; set; }
[JsonProperty("isEnableEdgeGestureUtil")] [JsonProperty("isEnableEdgeGestureUtil")]
public bool IsEnableEdgeGestureUtil { get; set; } = false; public bool IsEnableEdgeGestureUtil { get; set; }
[JsonProperty("edgeGestureUtilOnlyAffectBlackboardMode")] [JsonProperty("edgeGestureUtilOnlyAffectBlackboardMode")]
public bool EdgeGestureUtilOnlyAffectBlackboardMode { get; set; } = false; public bool EdgeGestureUtilOnlyAffectBlackboardMode { get; set; }
[JsonProperty("isEnableForceFullScreen")] [JsonProperty("isEnableForceFullScreen")]
public bool IsEnableForceFullScreen { get; set; } = false; public bool IsEnableForceFullScreen { get; set; }
[JsonProperty("isEnableResolutionChangeDetection")] [JsonProperty("isEnableResolutionChangeDetection")]
public bool IsEnableResolutionChangeDetection { get; set; } = false; public bool IsEnableResolutionChangeDetection { get; set; }
[JsonProperty("isEnableDPIChangeDetection")] [JsonProperty("isEnableDPIChangeDetection")]
public bool IsEnableDPIChangeDetection { get; set; } = false; public bool IsEnableDPIChangeDetection { get; set; }
[JsonProperty("isSecondConfirmWhenShutdownApp")] [JsonProperty("isSecondConfirmWhenShutdownApp")]
public bool IsSecondConfirmWhenShutdownApp { get; set; } = false; public bool IsSecondConfirmWhenShutdownApp { get; set; }
[JsonProperty("isEnableAvoidFullScreenHelper")] [JsonProperty("isEnableAvoidFullScreenHelper")]
public bool IsEnableAvoidFullScreenHelper { get; set; } = false; public bool IsEnableAvoidFullScreenHelper { get; set; }
[JsonProperty("isAutoBackupBeforeUpdate")] [JsonProperty("isAutoBackupBeforeUpdate")]
public bool IsAutoBackupBeforeUpdate { get; set; } = true; public bool IsAutoBackupBeforeUpdate { get; set; } = true;
@@ -455,9 +458,9 @@ namespace Ink_Canvas
[JsonProperty("isInkToShapeEnabled")] [JsonProperty("isInkToShapeEnabled")]
public bool IsInkToShapeEnabled { get; set; } = true; public bool IsInkToShapeEnabled { get; set; } = true;
[JsonProperty("isInkToShapeNoFakePressureRectangle")] [JsonProperty("isInkToShapeNoFakePressureRectangle")]
public bool IsInkToShapeNoFakePressureRectangle { get; set; } = false; public bool IsInkToShapeNoFakePressureRectangle { get; set; }
[JsonProperty("isInkToShapeNoFakePressureTriangle")] [JsonProperty("isInkToShapeNoFakePressureTriangle")]
public bool IsInkToShapeNoFakePressureTriangle { get; set; } = false; public bool IsInkToShapeNoFakePressureTriangle { get; set; }
[JsonProperty("isInkToShapeTriangle")] [JsonProperty("isInkToShapeTriangle")]
public bool IsInkToShapeTriangle { get; set; } = true; public bool IsInkToShapeTriangle { get; set; } = true;
[JsonProperty("isInkToShapeRectangle")] [JsonProperty("isInkToShapeRectangle")]
@@ -470,7 +473,7 @@ namespace Ink_Canvas
public class RandSettings { public class RandSettings {
[JsonProperty("displayRandWindowNamesInputBtn")] [JsonProperty("displayRandWindowNamesInputBtn")]
public bool DisplayRandWindowNamesInputBtn { get; set; } = false; public bool DisplayRandWindowNamesInputBtn { get; set; }
[JsonProperty("randWindowOnceCloseLatency")] [JsonProperty("randWindowOnceCloseLatency")]
public double RandWindowOnceCloseLatency { get; set; } = 2.5; public double RandWindowOnceCloseLatency { get; set; } = 2.5;
[JsonProperty("randWindowOnceMaxStudents")] [JsonProperty("randWindowOnceMaxStudents")]
@@ -478,9 +481,9 @@ namespace Ink_Canvas
[JsonProperty("showRandomAndSingleDraw")] [JsonProperty("showRandomAndSingleDraw")]
public bool ShowRandomAndSingleDraw { get; set; } = true; public bool ShowRandomAndSingleDraw { get; set; } = true;
[JsonProperty("directCallCiRand")] [JsonProperty("directCallCiRand")]
public bool DirectCallCiRand { get; set; } = false; public bool DirectCallCiRand { get; set; }
[JsonProperty("selectedBackgroundIndex")] [JsonProperty("selectedBackgroundIndex")]
public int SelectedBackgroundIndex { get; set; } = 0; public int SelectedBackgroundIndex { get; set; }
[JsonProperty("customPickNameBackgrounds")] [JsonProperty("customPickNameBackgrounds")]
public List<CustomPickNameBackground> CustomPickNameBackgrounds { get; set; } = new List<CustomPickNameBackground>(); public List<CustomPickNameBackground> CustomPickNameBackgrounds { get; set; } = new List<CustomPickNameBackground>();
} }
@@ -67,7 +67,7 @@ namespace Ink_Canvas
private void CancelButton_Click(object sender, RoutedEventArgs e) private void CancelButton_Click(object sender, RoutedEventArgs e)
{ {
this.Close(); Close();
} }
private void SaveButton_Click(object sender, RoutedEventArgs e) private void SaveButton_Click(object sender, RoutedEventArgs e)
@@ -109,7 +109,7 @@ namespace Ink_Canvas
MainWindow.SaveSettingsToFile(); MainWindow.SaveSettingsToFile();
IsSuccess = true; IsSuccess = true;
this.Close(); Close();
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -68,7 +68,7 @@ namespace Ink_Canvas
private void CancelButton_Click(object sender, RoutedEventArgs e) private void CancelButton_Click(object sender, RoutedEventArgs e)
{ {
this.Close(); Close();
} }
private void SaveButton_Click(object sender, RoutedEventArgs e) private void SaveButton_Click(object sender, RoutedEventArgs e)
@@ -110,7 +110,7 @@ namespace Ink_Canvas
MainWindow.SaveSettingsToFile(); MainWindow.SaveSettingsToFile();
IsSuccess = true; IsSuccess = true;
this.Close(); Close();
} }
catch (Exception ex) catch (Exception ex)
{ {
+22 -17
View File
@@ -1,11 +1,17 @@
using Ink_Canvas.Helpers; using System;
using System; using System.ComponentModel;
using System.Media; using System.Media;
using System.Timers; using System.Timers;
using System.Windows; using System.Windows;
using System.Windows.Forms;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Interop; using System.Windows.Interop;
using System.Windows.Media; using System.Windows.Media;
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern.Controls;
using Application = System.Windows.Application;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using Timer = System.Timers.Timer;
namespace Ink_Canvas namespace Ink_Canvas
{ {
@@ -51,7 +57,7 @@ namespace Ink_Canvas
TextBlockSecond.Text = "00"; TextBlockSecond.Text = "00";
timer.Stop(); timer.Stop();
isTimerRunning = false; isTimerRunning = false;
SymbolIconStart.Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.Play; SymbolIconStart.Symbol = Symbol.Play;
BtnStartCover.Visibility = Visibility.Visible; BtnStartCover.Visibility = Visibility.Visible;
TextBlockHour.Foreground = new SolidColorBrush(StringToColor("#FF5B5D5F")); TextBlockHour.Foreground = new SolidColorBrush(StringToColor("#FF5B5D5F"));
BorderStopTime.Visibility = Visibility.Collapsed; BorderStopTime.Visibility = Visibility.Collapsed;
@@ -70,16 +76,16 @@ namespace Ink_Canvas
SoundPlayer player = new SoundPlayer(); SoundPlayer player = new SoundPlayer();
int hour = 0; int hour;
int minute = 1; int minute = 1;
int second = 0; int second;
int totalSeconds = 60; int totalSeconds = 60;
DateTime startTime = DateTime.Now; DateTime startTime = DateTime.Now;
DateTime pauseTime = DateTime.Now; DateTime pauseTime = DateTime.Now;
bool isTimerRunning = false; bool isTimerRunning;
bool isPaused = false; bool isPaused;
Timer timer = new Timer(); Timer timer = new Timer();
@@ -202,12 +208,12 @@ namespace Ink_Canvas
if (WindowState == WindowState.Normal) if (WindowState == WindowState.Normal)
{ {
WindowState = WindowState.Maximized; WindowState = WindowState.Maximized;
SymbolIconFullscreen.Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.BackToWindow; SymbolIconFullscreen.Symbol = Symbol.BackToWindow;
} }
else else
{ {
WindowState = WindowState.Normal; WindowState = WindowState.Normal;
SymbolIconFullscreen.Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.FullScreen; SymbolIconFullscreen.Symbol = Symbol.FullScreen;
} }
} }
@@ -222,7 +228,6 @@ namespace Ink_Canvas
BtnStartCover.Visibility = Visibility.Collapsed; BtnStartCover.Visibility = Visibility.Collapsed;
BorderStopTime.Visibility = Visibility.Collapsed; BorderStopTime.Visibility = Visibility.Collapsed;
TextBlockHour.Foreground = new SolidColorBrush(StringToColor("#FF5B5D5F")); TextBlockHour.Foreground = new SolidColorBrush(StringToColor("#FF5B5D5F"));
return;
} }
else if (isTimerRunning && isPaused) else if (isTimerRunning && isPaused)
{ {
@@ -233,7 +238,7 @@ namespace Ink_Canvas
BtnStartCover.Visibility = Visibility.Collapsed; BtnStartCover.Visibility = Visibility.Collapsed;
BorderStopTime.Visibility = Visibility.Collapsed; BorderStopTime.Visibility = Visibility.Collapsed;
TextBlockHour.Foreground = new SolidColorBrush(StringToColor("#FF5B5D5F")); TextBlockHour.Foreground = new SolidColorBrush(StringToColor("#FF5B5D5F"));
SymbolIconStart.Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.Play; SymbolIconStart.Symbol = Symbol.Play;
isTimerRunning = false; isTimerRunning = false;
timer.Stop(); timer.Stop();
isPaused = false; isPaused = false;
@@ -283,7 +288,7 @@ namespace Ink_Canvas
startTime += DateTime.Now - pauseTime; startTime += DateTime.Now - pauseTime;
ProcessBarTime.IsPaused = false; ProcessBarTime.IsPaused = false;
TextBlockHour.Foreground = Brushes.Black; TextBlockHour.Foreground = Brushes.Black;
SymbolIconStart.Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.Pause; SymbolIconStart.Symbol = Symbol.Pause;
isPaused = false; isPaused = false;
timer.Start(); timer.Start();
UpdateStopTime(); UpdateStopTime();
@@ -295,7 +300,7 @@ namespace Ink_Canvas
pauseTime = DateTime.Now; pauseTime = DateTime.Now;
ProcessBarTime.IsPaused = true; ProcessBarTime.IsPaused = true;
TextBlockHour.Foreground = new SolidColorBrush(StringToColor("#FF5B5D5F")); TextBlockHour.Foreground = new SolidColorBrush(StringToColor("#FF5B5D5F"));
SymbolIconStart.Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.Play; SymbolIconStart.Symbol = Symbol.Play;
BorderStopTime.Visibility = Visibility.Collapsed; BorderStopTime.Visibility = Visibility.Collapsed;
isPaused = true; isPaused = true;
timer.Stop(); timer.Stop();
@@ -307,7 +312,7 @@ namespace Ink_Canvas
totalSeconds = ((hour * 60) + minute) * 60 + second; totalSeconds = ((hour * 60) + minute) * 60 + second;
ProcessBarTime.IsPaused = false; ProcessBarTime.IsPaused = false;
TextBlockHour.Foreground = Brushes.Black; TextBlockHour.Foreground = Brushes.Black;
SymbolIconStart.Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.Pause; SymbolIconStart.Symbol = Symbol.Pause;
BtnResetCover.Visibility = Visibility.Collapsed; BtnResetCover.Visibility = Visibility.Collapsed;
if (totalSeconds <= 10) if (totalSeconds <= 10)
@@ -335,7 +340,7 @@ namespace Ink_Canvas
} }
} }
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) private void Window_Closing(object sender, CancelEventArgs e)
{ {
isTimerRunning = false; isTimerRunning = false;
} }
@@ -345,7 +350,7 @@ namespace Ink_Canvas
Close(); Close();
} }
private bool _isInCompact = false; private bool _isInCompact;
private void BtnMinimal_OnMouseUp(object sender, MouseButtonEventArgs e) private void BtnMinimal_OnMouseUp(object sender, MouseButtonEventArgs e)
{ {
@@ -364,7 +369,7 @@ namespace Ink_Canvas
dpiScaleY = source.CompositionTarget.TransformToDevice.M22; dpiScaleY = source.CompositionTarget.TransformToDevice.M22;
} }
IntPtr windowHandle = new WindowInteropHelper(this).Handle; IntPtr windowHandle = new WindowInteropHelper(this).Handle;
System.Windows.Forms.Screen screen = System.Windows.Forms.Screen.FromHandle(windowHandle); Screen screen = Screen.FromHandle(windowHandle);
double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY; double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY;
Left = (screenWidth / 2) - (Width / 2); Left = (screenWidth / 2) - (Width / 2);
Top = (screenHeight / 2) - (Height / 2); Top = (screenHeight / 2) - (Height / 2);
+1 -1
View File
@@ -55,7 +55,7 @@ namespace Ink_Canvas
private void CloseButton_Click(object sender, RoutedEventArgs e) private void CloseButton_Click(object sender, RoutedEventArgs e)
{ {
this.Close(); Close();
} }
} }
} }
+1 -1
View File
@@ -197,7 +197,7 @@ namespace Ink_Canvas.ProcessBars
//达到100%则闭合整个 //达到100%则闭合整个
if (angel == 360) if (angel == 360)
{ {
myCycleProcessBar.Data = Geometry.Parse(myCycleProcessBar.Data.ToString() + " z"); myCycleProcessBar.Data = Geometry.Parse(myCycleProcessBar.Data + " z");
} }
} }
} }
+28 -25
View File
@@ -1,15 +1,18 @@
using Ink_Canvas.Helpers; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Interop; using System.Windows.Interop;
using System.Windows.Media; using System.Windows.Media;
using System.Threading.Tasks; using Ink_Canvas.Helpers;
using System.IO; using iNKORE.UI.WPF.Modern.Controls;
using System.Threading; using MdXaml;
namespace Ink_Canvas namespace Ink_Canvas
{ {
@@ -98,7 +101,7 @@ namespace Ink_Canvas
UseImmersiveDarkMode(new WindowInteropHelper(this).Handle, true); UseImmersiveDarkMode(new WindowInteropHelper(this).Handle, true);
// 窗口加载完成后再次确保按钮可见 // 窗口加载完成后再次确保按钮可见
this.Loaded += HasNewUpdateWindow_Loaded; Loaded += HasNewUpdateWindow_Loaded;
} }
private void HasNewUpdateWindow_Loaded(object sender, RoutedEventArgs e) private void HasNewUpdateWindow_Loaded(object sender, RoutedEventArgs e)
@@ -231,35 +234,35 @@ namespace Ink_Canvas
bool needsAdjustment = false; bool needsAdjustment = false;
// 如果窗口高度超过最大允许高度,调整窗口高度 // 如果窗口高度超过最大允许高度,调整窗口高度
if (this.Height > maxHeight) if (Height > maxHeight)
{ {
this.Height = maxHeight; Height = maxHeight;
needsAdjustment = true; needsAdjustment = true;
LogHelper.WriteLogToFile($"AutoUpdate | Adjusted window height to: {this.Height}"); LogHelper.WriteLogToFile($"AutoUpdate | Adjusted window height to: {Height}");
} }
// 如果窗口宽度超过最大允许宽度,调整窗口宽度 // 如果窗口宽度超过最大允许宽度,调整窗口宽度
if (this.Width > maxWidth) if (Width > maxWidth)
{ {
this.Width = maxWidth; Width = maxWidth;
needsAdjustment = true; needsAdjustment = true;
LogHelper.WriteLogToFile($"AutoUpdate | Adjusted window width to: {this.Width}"); LogHelper.WriteLogToFile($"AutoUpdate | Adjusted window width to: {Width}");
} }
// 如果屏幕分辨率较低,调整更多UI元素 // 如果屏幕分辨率较低,调整更多UI元素
if (screenHeight < 768 || screenWidth < 1024 || needsAdjustment) if (screenHeight < 768 || screenWidth < 1024 || needsAdjustment)
{ {
// 查找相关控件并调整大小 // 查找相关控件并调整大小
var markdownViewer = this.FindName("markdownContent") as MdXaml.MarkdownScrollViewer; var markdownViewer = FindName("markdownContent") as MarkdownScrollViewer;
var updateNowButton = this.FindName("UpdateNowButton") as Button; var updateNowButton = FindName("UpdateNowButton") as Button;
var updateLaterButton = this.FindName("UpdateLaterButton") as Button; var updateLaterButton = FindName("UpdateLaterButton") as Button;
var skipVersionButton = this.FindName("SkipVersionButton") as Button; var skipVersionButton = FindName("SkipVersionButton") as Button;
// 查找包含ScrollViewer的边框控件,减小其高度 // 查找包含ScrollViewer的边框控件,减小其高度
var contentBorders = this.FindVisualChildren<Border>().ToList(); var contentBorders = FindVisualChildren<Border>().ToList();
foreach (var border in contentBorders) foreach (var border in contentBorders)
{ {
if (border.Child is ScrollViewer || border.Child is iNKORE.UI.WPF.Modern.Controls.ScrollViewerEx) if (border.Child is ScrollViewer || border.Child is ScrollViewerEx)
{ {
// 减小内容显示区域的高度 // 减小内容显示区域的高度
if (border.Height > 180) if (border.Height > 180)
@@ -267,7 +270,7 @@ namespace Ink_Canvas
border.Height = 160; border.Height = 160;
LogHelper.WriteLogToFile("AutoUpdate | Reduced content area height"); LogHelper.WriteLogToFile("AutoUpdate | Reduced content area height");
} }
else if (border.Child is iNKORE.UI.WPF.Modern.Controls.ScrollViewerEx scrollViewer && scrollViewer.Height > 160) else if (border.Child is ScrollViewerEx scrollViewer && scrollViewer.Height > 160)
{ {
scrollViewer.Height = 160; scrollViewer.Height = 160;
LogHelper.WriteLogToFile("AutoUpdate | Reduced scroll viewer height"); LogHelper.WriteLogToFile("AutoUpdate | Reduced scroll viewer height");
@@ -289,12 +292,12 @@ namespace Ink_Canvas
} }
// 确保窗口在屏幕范围内 // 确保窗口在屏幕范围内
if (this.Left < 0) this.Left = 0; if (Left < 0) Left = 0;
if (this.Top < 0) this.Top = 0; if (Top < 0) Top = 0;
if (this.Left + this.Width > screenWidth) this.Left = screenWidth - this.Width; if (Left + Width > screenWidth) Left = screenWidth - Width;
if (this.Top + this.Height > screenHeight) this.Top = screenHeight - this.Height; if (Top + Height > screenHeight) Top = screenHeight - Height;
LogHelper.WriteLogToFile($"AutoUpdate | Final window size: {this.Width}x{this.Height}"); LogHelper.WriteLogToFile($"AutoUpdate | Final window size: {Width}x{Height}");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -332,7 +335,7 @@ namespace Ink_Canvas
if (string.IsNullOrEmpty(downloadUrl)) if (string.IsNullOrEmpty(downloadUrl))
{ {
// 自动更新场景下,downloadUrl为null,直接用主下载目录 // 自动更新场景下,downloadUrl为null,直接用主下载目录
string updatesFolderPath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "AutoUpdate"); string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
downloadUrl = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip"); downloadUrl = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip");
} }
LogHelper.WriteLogToFile($"AutoUpdate | 开始安装版本: {version}"); LogHelper.WriteLogToFile($"AutoUpdate | 开始安装版本: {version}");
@@ -1,14 +1,14 @@
using Ink_Canvas.Helpers;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Linq; // Added for OrderByDescending using Ink_Canvas.Helpers;
using System.ComponentModel; // Added for OrderByDescending
using System.Threading;
namespace Ink_Canvas namespace Ink_Canvas
{ {
@@ -22,7 +22,7 @@ namespace Ink_Canvas
} }
private List<VersionItem> versionList = new List<VersionItem>(); private List<VersionItem> versionList = new List<VersionItem>();
private VersionItem selectedItem = null; private VersionItem selectedItem;
private UpdateChannel channel = UpdateChannel.Release; private UpdateChannel channel = UpdateChannel.Release;
private CancellationTokenSource downloadCts = null; private CancellationTokenSource downloadCts = null;
@@ -60,7 +60,7 @@ namespace Ink_Canvas
else else
{ {
ReleaseNotesViewer.Markdown = "未获取到历史版本信息。"; ReleaseNotesViewer.Markdown = "未获取到历史版本信息。";
LogHelper.WriteLogToFile($"HistoryRollback | 未获取到历史版本信息", LogHelper.LogType.Warning); LogHelper.WriteLogToFile("HistoryRollback | 未获取到历史版本信息", LogHelper.LogType.Warning);
} }
} }
@@ -122,8 +122,8 @@ namespace Ink_Canvas
DownloadProgressBar.Value = 100; DownloadProgressBar.Value = 100;
DownloadProgressText.Text = "下载完成,准备安装..."; DownloadProgressText.Text = "下载完成,准备安装...";
await Task.Delay(800); await Task.Delay(800);
this.DialogResult = true; DialogResult = true;
this.Close(); Close();
} }
else else
{ {
@@ -92,7 +92,7 @@ namespace Ink_Canvas
private void CloseButton_Click(object sender, RoutedEventArgs e) private void CloseButton_Click(object sender, RoutedEventArgs e)
{ {
this.Close(); Close();
} }
} }
} }
+3 -2
View File
@@ -1,6 +1,7 @@
using Ink_Canvas.Helpers; using System.ComponentModel;
using System.IO; using System.IO;
using System.Windows; using System.Windows;
using Ink_Canvas.Helpers;
namespace Ink_Canvas namespace Ink_Canvas
{ {
@@ -26,7 +27,7 @@ namespace Ink_Canvas
} }
} }
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) private void Window_Closing(object sender, CancelEventArgs e)
{ {
if (originText != TextBoxNames.Text) if (originText != TextBoxNames.Text)
{ {
@@ -1,6 +1,7 @@
using Ink_Canvas.Helpers; using System.Windows;
using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern.Controls;
namespace Ink_Canvas namespace Ink_Canvas
{ {
@@ -28,10 +29,10 @@ namespace Ink_Canvas
private void BtnFullscreen_MouseUp(object sender, MouseButtonEventArgs e) { private void BtnFullscreen_MouseUp(object sender, MouseButtonEventArgs e) {
if (WindowState == WindowState.Normal) { if (WindowState == WindowState.Normal) {
WindowState = WindowState.Maximized; WindowState = WindowState.Maximized;
SymbolIconFullscreen.Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.BackToWindow; SymbolIconFullscreen.Symbol = Symbol.BackToWindow;
} else { } else {
WindowState = WindowState.Normal; WindowState = WindowState.Normal;
SymbolIconFullscreen.Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.FullScreen; SymbolIconFullscreen.Symbol = Symbol.FullScreen;
} }
} }
+37 -33
View File
@@ -1,13 +1,18 @@
using Ink_Canvas.Helpers.Plugins;
using Microsoft.Win32;
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.IO; using System.IO;
using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Threading;
using Ink_Canvas.Helpers; using Ink_Canvas.Helpers;
using System.Linq; using Ink_Canvas.Helpers.Plugins;
using Ink_Canvas.Helpers.Plugins.BuiltIn;
using Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher;
using iNKORE.UI.WPF.Modern.Controls;
using Microsoft.Win32;
using MessageBox = System.Windows.MessageBox;
namespace Ink_Canvas.Windows namespace Ink_Canvas.Windows
{ {
@@ -36,7 +41,7 @@ namespace Ink_Canvas.Windows
} }
OnPropertyChanged(nameof(SelectedPlugin)); OnPropertyChanged(nameof(SelectedPlugin));
LogHelper.WriteLogToFile("插件列表已刷新", LogHelper.LogType.Info); LogHelper.WriteLogToFile("插件列表已刷新");
} }
private IPlugin _selectedPlugin; private IPlugin _selectedPlugin;
@@ -90,20 +95,20 @@ namespace Ink_Canvas.Windows
LoadPlugins(); LoadPlugins();
// 注册窗口关闭事件 // 注册窗口关闭事件
this.Closing += PluginSettingsWindow_Closing; Closing += PluginSettingsWindow_Closing;
} }
/// <summary> /// <summary>
/// 窗口关闭事件处理 /// 窗口关闭事件处理
/// </summary> /// </summary>
private void PluginSettingsWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) private void PluginSettingsWindow_Closing(object sender, CancelEventArgs e)
{ {
try try
{ {
// 保存插件配置 // 保存插件配置
LogHelper.WriteLogToFile("插件管理窗口关闭,保存插件配置...", LogHelper.LogType.Info); LogHelper.WriteLogToFile("插件管理窗口关闭,保存插件配置...");
PluginManager.Instance.SaveConfig(); PluginManager.Instance.SaveConfig();
LogHelper.WriteLogToFile("插件配置已保存", LogHelper.LogType.Info); LogHelper.WriteLogToFile("插件配置已保存");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -118,7 +123,7 @@ namespace Ink_Canvas.Windows
{ {
Plugins.Clear(); Plugins.Clear();
LogHelper.WriteLogToFile($"开始加载插件列表到UI,插件总数: {PluginManager.Instance.Plugins.Count}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"开始加载插件列表到UI,插件总数: {PluginManager.Instance.Plugins.Count}");
// 添加所有已加载的插件 // 添加所有已加载的插件
foreach (var plugin in PluginManager.Instance.Plugins) foreach (var plugin in PluginManager.Instance.Plugins)
@@ -132,8 +137,7 @@ namespace Ink_Canvas.Windows
} }
// 记录插件详细信息 // 记录插件详细信息
LogHelper.WriteLogToFile($"正在加载插件到UI: 类型={plugin.GetType().FullName}, 名称={plugin.Name ?? ""}, 状态={isEnabled}", LogHelper.WriteLogToFile($"正在加载插件到UI: 类型={plugin.GetType().FullName}, 名称={plugin.Name ?? ""}, 状态={isEnabled}");
LogHelper.LogType.Info);
// 创建视图模型并添加到集合 // 创建视图模型并添加到集合
var viewModel = new PluginViewModel(plugin) var viewModel = new PluginViewModel(plugin)
@@ -142,17 +146,17 @@ namespace Ink_Canvas.Windows
}; };
Plugins.Add(viewModel); Plugins.Add(viewModel);
LogHelper.WriteLogToFile($"已加载插件到UI列表: {plugin.Name},状态: {(isEnabled ? "" : "")}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"已加载插件到UI列表: {plugin.Name},状态: {(isEnabled ? "" : "")}");
} }
// 绑定到ListView // 绑定到ListView
LogHelper.WriteLogToFile($"绑定 {Plugins.Count} 个插件到ListView", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"绑定 {Plugins.Count} 个插件到ListView");
PluginListView.ItemsSource = Plugins; PluginListView.ItemsSource = Plugins;
// 如果有插件,选择第一个 // 如果有插件,选择第一个
if (Plugins.Count > 0) if (Plugins.Count > 0)
{ {
LogHelper.WriteLogToFile($"选择第一个插件: {Plugins[0].Name}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"选择第一个插件: {Plugins[0].Name}");
PluginListView.SelectedIndex = 0; PluginListView.SelectedIndex = 0;
} }
else else
@@ -389,7 +393,7 @@ namespace Ink_Canvas.Windows
File.Copy(pluginPath, targetPath, true); File.Copy(pluginPath, targetPath, true);
} }
LogHelper.WriteLogToFile($"插件 {SelectedPlugin.Name} 已成功导出到: {targetPath}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {SelectedPlugin.Name} 已成功导出到: {targetPath}");
MessageBox.Show($"插件 {SelectedPlugin.Name} 已成功导出!", "成功", MessageBoxButton.OK, MessageBoxImage.Information); MessageBox.Show($"插件 {SelectedPlugin.Name} 已成功导出!", "成功", MessageBoxButton.OK, MessageBoxImage.Information);
} }
} }
@@ -407,7 +411,7 @@ namespace Ink_Canvas.Windows
{ {
try try
{ {
if (sender is iNKORE.UI.WPF.Modern.Controls.ToggleSwitch toggleSwitch && if (sender is ToggleSwitch toggleSwitch &&
toggleSwitch.Tag is IPlugin plugin) toggleSwitch.Tag is IPlugin plugin)
{ {
// 记录当前开关状态 // 记录当前开关状态
@@ -418,14 +422,14 @@ namespace Ink_Canvas.Windows
string pluginName = plugin.Name; string pluginName = plugin.Name;
bool wasBuiltIn = plugin.IsBuiltIn; bool wasBuiltIn = plugin.IsBuiltIn;
LogHelper.WriteLogToFile($"UI开关切换: {pluginName}, 目标状态: {(targetState ? "" : "")}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"UI开关切换: {pluginName}, 目标状态: {(targetState ? "" : "")}");
// 切换插件状态 // 切换插件状态
PluginManager.Instance.TogglePlugin(plugin, targetState); PluginManager.Instance.TogglePlugin(plugin, targetState);
// 立即同步保存配置到文件(确保状态被立即持久化) // 立即同步保存配置到文件(确保状态被立即持久化)
PluginManager.Instance.SaveConfig(); PluginManager.Instance.SaveConfig();
LogHelper.WriteLogToFile($"插件状态已立即保存到配置文件", LogHelper.LogType.Info); LogHelper.WriteLogToFile("插件状态已立即保存到配置文件");
// 延迟一下再检查状态,确保变更已应用 // 延迟一下再检查状态,确保变更已应用
Dispatcher.BeginInvoke(new Action(() => Dispatcher.BeginInvoke(new Action(() =>
@@ -451,7 +455,7 @@ namespace Ink_Canvas.Windows
// 检查实际状态 // 检查实际状态
bool actualState = currentPlugin is PluginBase pb && pb.IsEnabled; bool actualState = currentPlugin is PluginBase pb && pb.IsEnabled;
LogHelper.WriteLogToFile($"插件 {pluginName} 实际状态: {(actualState ? "" : "")}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {pluginName} 实际状态: {(actualState ? "" : "")}");
// 更新视图模型 // 更新视图模型
PluginViewModel viewModel = null; PluginViewModel viewModel = null;
@@ -469,14 +473,14 @@ namespace Ink_Canvas.Windows
// 确保视图模型状态与实际状态一致 // 确保视图模型状态与实际状态一致
if (viewModel.IsEnabled != actualState) if (viewModel.IsEnabled != actualState)
{ {
LogHelper.WriteLogToFile($"同步视图模型状态: {(actualState ? "" : "")}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"同步视图模型状态: {(actualState ? "" : "")}");
viewModel.IsEnabled = actualState; viewModel.IsEnabled = actualState;
} }
// 确保UI开关状态与实际状态一致 // 确保UI开关状态与实际状态一致
if (toggleSwitch.IsOn != actualState) if (toggleSwitch.IsOn != actualState)
{ {
LogHelper.WriteLogToFile($"同步UI开关状态: {(actualState ? "" : "")}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"同步UI开关状态: {(actualState ? "" : "")}");
toggleSwitch.IsOn = actualState; toggleSwitch.IsOn = actualState;
} }
} }
@@ -491,21 +495,21 @@ namespace Ink_Canvas.Windows
if (wasBuiltIn) if (wasBuiltIn)
{ {
// 特殊插件刷新逻辑,如果是超级启动台插件,立即刷新UI // 特殊插件刷新逻辑,如果是超级启动台插件,立即刷新UI
if (currentPlugin is Helpers.Plugins.BuiltIn.SuperLauncherPlugin && if (currentPlugin is SuperLauncherPlugin &&
PluginSettingsContainer.Content is Helpers.Plugins.BuiltIn.SuperLauncher.LauncherSettingsControl) PluginSettingsContainer.Content is LauncherSettingsControl)
{ {
// 重新获取设置界面 // 重新获取设置界面
PluginSettingsContainer.Content = currentPlugin.GetSettingsView(); PluginSettingsContainer.Content = currentPlugin.GetSettingsView();
} }
} }
LogHelper.WriteLogToFile($"插件 {pluginName} UI状态同步完成", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"插件 {pluginName} UI状态同步完成");
} }
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"同步UI状态时出错: {ex.Message}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"同步UI状态时出错: {ex.Message}", LogHelper.LogType.Error);
} }
}), System.Windows.Threading.DispatcherPriority.Background); }), DispatcherPriority.Background);
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -567,7 +571,7 @@ namespace Ink_Canvas.Windows
{ {
// 应用界面的状态到插件 // 应用界面的状态到插件
PluginManager.Instance.TogglePlugin(actualPlugin, uiState); PluginManager.Instance.TogglePlugin(actualPlugin, uiState);
LogHelper.WriteLogToFile($"手动保存:同步插件 {actualPlugin.Name} 状态 {pluginState} -> {uiState}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"手动保存:同步插件 {actualPlugin.Name} 状态 {pluginState} -> {uiState}");
syncCount++; syncCount++;
} }
@@ -575,7 +579,7 @@ namespace Ink_Canvas.Windows
if (PluginManager.Instance.PluginStates.TryGetValue(pluginTypeName, out bool configState) && configState != uiState) if (PluginManager.Instance.PluginStates.TryGetValue(pluginTypeName, out bool configState) && configState != uiState)
{ {
PluginManager.Instance.PluginStates[pluginTypeName] = uiState; PluginManager.Instance.PluginStates[pluginTypeName] = uiState;
LogHelper.WriteLogToFile($"手动保存:更新配置中插件 {actualPlugin.Name} 状态 {configState} -> {uiState}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"手动保存:更新配置中插件 {actualPlugin.Name} 状态 {configState} -> {uiState}");
syncCount++; syncCount++;
} }
} }
@@ -591,7 +595,7 @@ namespace Ink_Canvas.Windows
PluginManager.Instance.SaveConfig(); PluginManager.Instance.SaveConfig();
// 记录日志 // 记录日志
LogHelper.WriteLogToFile($"用户手动保存插件状态配置,同步了 {syncCount} 个状态变更", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"用户手动保存插件状态配置,同步了 {syncCount} 个状态变更");
// 刷新插件列表,确保UI与最新状态同步 // 刷新插件列表,确保UI与最新状态同步
RefreshPluginList(); RefreshPluginList();
@@ -642,7 +646,7 @@ namespace Ink_Canvas.Windows
get get
{ {
string name = Plugin?.Name ?? "未命名插件"; string name = Plugin?.Name ?? "未命名插件";
LogHelper.WriteLogToFile($"获取插件名称: {name},类型: {Plugin?.GetType().FullName ?? ""}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"获取插件名称: {name},类型: {Plugin?.GetType().FullName ?? ""}");
return name; return name;
} }
} }
@@ -672,7 +676,7 @@ namespace Ink_Canvas.Windows
_isEnabled = plugin is PluginBase pluginBase && pluginBase.IsEnabled; _isEnabled = plugin is PluginBase pluginBase && pluginBase.IsEnabled;
// 记录日志 // 记录日志
LogHelper.WriteLogToFile($"创建插件视图模型: {plugin?.GetType().FullName ?? ""}, 名称: {plugin?.Name ?? ""}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"创建插件视图模型: {plugin?.GetType().FullName ?? ""}, 名称: {plugin?.Name ?? ""}");
// 注册插件状态变更事件 // 注册插件状态变更事件
if (plugin is PluginBase pb) if (plugin is PluginBase pb)
@@ -694,9 +698,9 @@ namespace Ink_Canvas.Windows
// 确保配置立即保存 // 确保配置立即保存
if (sender is IPlugin plugin) if (sender is IPlugin plugin)
{ {
LogHelper.WriteLogToFile($"视图模型捕获到插件 {plugin.Name} 状态变更: {(isEnabled ? "" : "")}", LogHelper.LogType.Info); LogHelper.WriteLogToFile($"视图模型捕获到插件 {plugin.Name} 状态变更: {(isEnabled ? "" : "")}");
Helpers.Plugins.PluginManager.Instance.SaveConfig(); PluginManager.Instance.SaveConfig();
LogHelper.WriteLogToFile($"视图模型已触发配置保存", LogHelper.LogType.Info); LogHelper.WriteLogToFile("视图模型已触发配置保存");
} }
})); }));
} }
+29 -26
View File
@@ -1,13 +1,16 @@
using Ink_Canvas.Helpers; using System;
using Microsoft.VisualBasic;
using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern.Controls;
using Microsoft.VisualBasic;
using MessageBox = iNKORE.UI.WPF.Modern.Controls.MessageBox; using MessageBox = iNKORE.UI.WPF.Modern.Controls.MessageBox;
namespace Ink_Canvas { namespace Ink_Canvas {
@@ -35,7 +38,7 @@ namespace Ink_Canvas {
{ {
// 默认背景(无背景) // 默认背景(无背景)
BackgroundImage.ImageSource = null; BackgroundImage.ImageSource = null;
MainBorder.Background = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(240, 243, 249)); MainBorder.Background = new SolidColorBrush(Color.FromRgb(240, 243, 249));
} }
else if (selectedIndex <= settings.RandSettings.CustomPickNameBackgrounds.Count) else if (selectedIndex <= settings.RandSettings.CustomPickNameBackgrounds.Count)
{ {
@@ -43,7 +46,7 @@ namespace Ink_Canvas {
var customBackground = settings.RandSettings.CustomPickNameBackgrounds[selectedIndex - 1]; var customBackground = settings.RandSettings.CustomPickNameBackgrounds[selectedIndex - 1];
if (File.Exists(customBackground.FilePath)) if (File.Exists(customBackground.FilePath))
{ {
var bitmap = new System.Windows.Media.Imaging.BitmapImage(); var bitmap = new BitmapImage();
bitmap.BeginInit(); bitmap.BeginInit();
bitmap.UriSource = new Uri(customBackground.FilePath); bitmap.UriSource = new Uri(customBackground.FilePath);
bitmap.EndInit(); bitmap.EndInit();
@@ -69,16 +72,16 @@ namespace Ink_Canvas {
// 加载背景 // 加载背景
LoadBackground(settings); LoadBackground(settings);
new Thread(new ThreadStart(() => { new Thread(() => {
Thread.Sleep(100); Thread.Sleep(100);
Application.Current.Dispatcher.Invoke(() => { Application.Current.Dispatcher.Invoke(() => {
BorderBtnRand_MouseUp(BorderBtnRand, null); BorderBtnRand_MouseUp(BorderBtnRand, null);
}); });
})).Start(); }).Start();
} }
public static int randSeed = 0; public static int randSeed = 0;
public bool isAutoClose = false; public bool isAutoClose;
public bool isNotRepeatName = false; public bool isNotRepeatName = false;
public int TotalCount = 1; public int TotalCount = 1;
@@ -118,7 +121,7 @@ namespace Ink_Canvas {
LabelOutput2.Visibility = Visibility.Collapsed; LabelOutput2.Visibility = Visibility.Collapsed;
LabelOutput3.Visibility = Visibility.Collapsed; LabelOutput3.Visibility = Visibility.Collapsed;
new Thread(new ThreadStart(() => { new Thread(() => {
for (int i = 0; i < RandWaitingTimes; i++) { for (int i = 0; i < RandWaitingTimes; i++) {
int rand = random.Next(1, PeopleCount + 1); int rand = random.Next(1, PeopleCount + 1);
while (rands.Contains(rand)) { while (rands.Contains(rand)) {
@@ -152,55 +155,55 @@ namespace Ink_Canvas {
outputString += Names[rand - 1] + Environment.NewLine; outputString += Names[rand - 1] + Environment.NewLine;
} else { } else {
outputs.Add(rand.ToString()); outputs.Add(rand.ToString());
outputString += rand.ToString() + Environment.NewLine; outputString += rand + Environment.NewLine;
} }
} }
if (TotalCount <= 5) { if (TotalCount <= 5) {
LabelOutput.Content = outputString.ToString().Trim(); LabelOutput.Content = outputString.Trim();
} else if (TotalCount <= 10) { } else if (TotalCount <= 10) {
LabelOutput2.Visibility = Visibility.Visible; LabelOutput2.Visibility = Visibility.Visible;
outputString = ""; outputString = "";
for (int i = 0; i < (outputs.Count + 1) / 2; i++) { for (int i = 0; i < (outputs.Count + 1) / 2; i++) {
outputString += outputs[i].ToString() + Environment.NewLine; outputString += outputs[i] + Environment.NewLine;
} }
LabelOutput.Content = outputString.ToString().Trim(); LabelOutput.Content = outputString.Trim();
outputString = ""; outputString = "";
for (int i = (outputs.Count + 1) / 2; i < outputs.Count; i++) { for (int i = (outputs.Count + 1) / 2; i < outputs.Count; i++) {
outputString += outputs[i].ToString() + Environment.NewLine; outputString += outputs[i] + Environment.NewLine;
} }
LabelOutput2.Content = outputString.ToString().Trim(); LabelOutput2.Content = outputString.Trim();
} else { } else {
LabelOutput2.Visibility = Visibility.Visible; LabelOutput2.Visibility = Visibility.Visible;
LabelOutput3.Visibility = Visibility.Visible; LabelOutput3.Visibility = Visibility.Visible;
outputString = ""; outputString = "";
for (int i = 0; i < (outputs.Count + 1) / 3; i++) { for (int i = 0; i < (outputs.Count + 1) / 3; i++) {
outputString += outputs[i].ToString() + Environment.NewLine; outputString += outputs[i] + Environment.NewLine;
} }
LabelOutput.Content = outputString.ToString().Trim(); LabelOutput.Content = outputString.Trim();
outputString = ""; outputString = "";
for (int i = (outputs.Count + 1) / 3; i < (outputs.Count + 1) * 2 / 3; i++) { for (int i = (outputs.Count + 1) / 3; i < (outputs.Count + 1) * 2 / 3; i++) {
outputString += outputs[i].ToString() + Environment.NewLine; outputString += outputs[i] + Environment.NewLine;
} }
LabelOutput2.Content = outputString.ToString().Trim(); LabelOutput2.Content = outputString.Trim();
outputString = ""; outputString = "";
for (int i = (outputs.Count + 1) * 2 / 3; i < outputs.Count; i++) { for (int i = (outputs.Count + 1) * 2 / 3; i < outputs.Count; i++) {
outputString += outputs[i].ToString() + Environment.NewLine; outputString += outputs[i] + Environment.NewLine;
} }
LabelOutput3.Content = outputString.ToString().Trim(); LabelOutput3.Content = outputString.Trim();
} }
if (isAutoClose) { if (isAutoClose) {
new Thread(new ThreadStart(() => { new Thread(() => {
Thread.Sleep(RandDoneAutoCloseWaitTime); Thread.Sleep(RandDoneAutoCloseWaitTime);
Application.Current.Dispatcher.Invoke(() => { Application.Current.Dispatcher.Invoke(() => {
PeopleControlPane.Opacity = 1; PeopleControlPane.Opacity = 1;
PeopleControlPane.IsHitTestVisible = true; PeopleControlPane.IsHitTestVisible = true;
Close(); Close();
}); });
})).Start(); }).Start();
} }
}); });
})).Start(); }).Start();
} }
private void Window_Loaded(object sender, RoutedEventArgs e) { private void Window_Loaded(object sender, RoutedEventArgs e) {
@@ -261,7 +264,7 @@ namespace Ink_Canvas {
try try
{ {
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo Process.Start(new ProcessStartInfo
{ {
FileName = "classisland://plugins/IslandCaller/Run", FileName = "classisland://plugins/IslandCaller/Run",
UseShellExecute = true UseShellExecute = true
@@ -1,6 +1,5 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Controls;
namespace Ink_Canvas namespace Ink_Canvas
{ {
@@ -1,20 +0,0 @@
InkCanvasForClass
winexe
C#
.cs
E:\ICC CE\ICC CE main\community\Ink Canvas\obj\Debug\net472\
Ink_Canvas
none
false
TRACE;DEBUG;NETFRAMEWORK;NET472;;NET30_OR_GREATER;NET35_OR_GREATER;NET40_OR_GREATER;NET45_OR_GREATER;NET451_OR_GREATER;NET452_OR_GREATER;NET46_OR_GREATER;NET461_OR_GREATER;NET462_OR_GREATER;NET47_OR_GREATER;NET471_OR_GREATER;NET472_OR_GREATER
E:\ICC CE\ICC CE main\community\Ink Canvas\App.xaml
22-2143008179
79-461684434
471037513499
Helpers\Plugins\BuiltIn\SuperLauncher\LauncherSettingsControl.xaml;Helpers\Plugins\BuiltIn\SuperLauncher\LauncherWindow.xaml;MainWindow.xaml;MainWindow_cs\MW_Eraser.xaml;Resources\DrawShapeImageDictionary.xaml;Resources\IconImageDictionary.xaml;Resources\SeewoImageDictionary.xaml;Resources\Styles\Dark.xaml;Resources\Styles\Light.xaml;Windows\AddCustomIconWindow.xaml;Windows\AddPickNameBackgroundWindow.xaml;Windows\CountdownTimerWindow.xaml;Windows\CustomIconWindow.xaml;Windows\CycleProcessBar.xaml;Windows\HasNewUpdateWindow.xaml;Windows\HistoryRollbackWindow.xaml;Windows\ManagePickNameBackgroundsWindow.xaml;Windows\NamesInputWindow.xaml;Windows\OperatingGuideWindow.xaml;Windows\PluginSettingsWindow.xaml;Windows\RandWindow.xaml;Windows\YesOrNoNotificationWindow.xaml;
False
+4 -2
View File
@@ -85,13 +85,15 @@
<tbody> <tbody>
<tr> <tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CJKmkp"><img src="https://avatars.githubusercontent.com/u/113243675?v=4?s=100" width="100px;" alt="CJK_mkp"/><br /><sub><b>CJK_mkp</b></sub></a><br /><a href="#maintenance-CJKmkp" title="Maintenance">🚧</a> <a href="#doc-CJKmkp" title="Documentation">📖</a> <a href="#code-CJKmkp" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/CJKmkp"><img src="https://avatars.githubusercontent.com/u/113243675?v=4?s=100" width="100px;" alt="CJK_mkp"/><br /><sub><b>CJK_mkp</b></sub></a><br /><a href="#maintenance-CJKmkp" title="Maintenance">🚧</a> <a href="#doc-CJKmkp" title="Documentation">📖</a> <a href="#code-CJKmkp" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://hydro11451.qzz.io"><img src="https://avatars.githubusercontent.com/u/214308559?v=4?s=100" width="100px;" alt="Hydrogen"/><br /><sub><b>Hydrogen</b></sub></a><br /><a href="#code-Hydro11451" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CreeperAWA"><img src="https://avatars.githubusercontent.com/u/134939494?v=4?s=100" width="100px;" alt="CreeperAWA"/><br /><sub><b>CreeperAWA</b></sub></a><br /><a href="#code-CreeperAWA" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/CreeperAWA"><img src="https://avatars.githubusercontent.com/u/134939494?v=4?s=100" width="100px;" alt="CreeperAWA"/><br /><sub><b>CreeperAWA</b></sub></a><br /><a href="#code-CreeperAWA" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/2-2-3-trimethylpentane"><img src="https://avatars.githubusercontent.com/u/141403762?v=4?s=100" width="100px;" alt="2,2,3-三甲基戊烷"/><br /><sub><b>2,2,3-三甲基戊烷</b></sub></a><br /><a href="#blog-2-2-3-trimethylpentane" title="Blogposts">📝</a> <a href="#doc-2-2-3-trimethylpentane" title="Documentation">📖</a> <a href="#design-2-2-3-trimethylpentane" title="Design">🎨</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/2-2-3-trimethylpentane"><img src="https://avatars.githubusercontent.com/u/141403762?v=4?s=100" width="100px;" alt="2,2,3-三甲基戊烷"/><br /><sub><b>2,2,3-三甲基戊烷</b></sub></a><br /><a href="#blog-2-2-3-trimethylpentane" title="Blogposts">📝</a> <a href="#doc-2-2-3-trimethylpentane" title="Documentation">📖</a> <a href="#design-2-2-3-trimethylpentane" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Alan-CRL"><img src="https://avatars.githubusercontent.com/u/92425617?v=4?s=100" width="100px;" alt="Alan-CRL"/><br /><sub><b>Alan-CRL</b></sub></a><br /><a href="#code-Alan-CRL" title="Code">💻</a> <a href="#infra-Alan-CRL" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#doc-Alan-CRL" title="Documentation">📖</a> <a href="#financial-Alan-CRL" title="Financial">💵</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/Alan-CRL"><img src="https://avatars.githubusercontent.com/u/92425617?v=4?s=100" width="100px;" alt="Alan-CRL"/><br /><sub><b>Alan-CRL</b></sub></a><br /><a href="#code-Alan-CRL" title="Code">💻</a> <a href="#infra-Alan-CRL" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#doc-Alan-CRL" title="Documentation">📖</a> <a href="#financial-Alan-CRL" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MKStoler1024"><img src="https://avatars.githubusercontent.com/u/158786854?v=4?s=100" width="100px;" alt="MKStoler1024"/><br /><sub><b>MKStoler1024</b></sub></a><br /><a href="#doc-MKStoler1024" title="Documentation">📖</a> <a href="#code-MKStoler1024" title="Code">💻</a> <a href="#design-MKStoler1024" title="Design">🎨</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/MKStoler1024"><img src="https://avatars.githubusercontent.com/u/158786854?v=4?s=100" width="100px;" alt="MKStoler1024"/><br /><sub><b>MKStoler1024</b></sub></a><br /><a href="#doc-MKStoler1024" title="Documentation">📖</a> <a href="#code-MKStoler1024" title="Code">💻</a> <a href="#design-MKStoler1024" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/awesome-iwb"><img src="https://avatars.githubusercontent.com/u/184760810?v=4?s=100" width="100px;" alt="Awesome Iwb"/><br /><sub><b>Awesome Iwb</b></sub></a><br /><a href="#doc-awesome-iwb" title="Documentation">📖</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/awesome-iwb"><img src="https://avatars.githubusercontent.com/u/184760810?v=4?s=100" width="100px;" alt="Awesome Iwb"/><br /><sub><b>Awesome Iwb</b></sub></a><br /><a href="#doc-awesome-iwb" title="Documentation">📖</a></td>
</tr> </tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PrefacedCorg"><img src="https://avatars.githubusercontent.com/u/129855423?v=4?s=100" width="100px;" alt="PrefacedCorg"/><br /><sub><b>PrefacedCorg</b></sub></a><br /><a href="#code-PrefacedCorg" title="Code">💻</a></td>
</tr>
</tbody> </tbody>
</table> </table>
@@ -103,7 +105,7 @@
## 🤝 感谢 ## 🤝 感谢
感谢 [DotteringDoge471](https://github.com/DotteringDoge471) 创造了 `InkCanvasForClass` 感谢 [DotteringDoge471](https://github.com/DotteringDoge471) 创造了 `InkCanvasForClass`
感谢 [yuwenhui2020](https://github.com/yuwenhui2020) 为 `Ink Canvas 使用说明` 做出的贡献! 感谢 [yuwenhui2020](https://github.com/yuwenhui2020) 为 `Ink Canvas 使用说明` 做出的贡献!
感谢 [CN-Ironegg](https://github.com/CN-Ironegg)、[jiajiaxd](https://github.com/jiajiaxd)、[Kengwang](https://github.com/kengwang)、[Raspberry Kan](https://github.com/Raspberry-Monster)、[clover-yan](https://github.com/clover-yan)、[STBBRD](https://github.com/STBBRD)、[ChangSakura](https://github.com/WuChanging)、[DotteringDoge471](https://github.com/DotteringDoge471)、[Hydro11451](https://github.com/Hydro11451) 为本项目贡献代码! 感谢 [CN-Ironegg](https://github.com/CN-Ironegg)、[jiajiaxd](https://github.com/jiajiaxd)、[Kengwang](https://github.com/kengwang)、[Raspberry Kan](https://github.com/Raspberry-Monster)、[clover-yan](https://github.com/clover-yan)、[STBBRD](https://github.com/STBBRD)、[ChangSakura](https://github.com/WuChanging)、[DotteringDoge471](https://github.com/DotteringDoge471) 为本项目贡献代码!
## License ## License
GPLv3 GPLv3
+1
View File
@@ -32,3 +32,4 @@
32. 修复快速面板中的退出放映按钮 32. 修复快速面板中的退出放映按钮
33. 优化多墨迹卡顿问题 33. 优化多墨迹卡顿问题
34. 优化至单文件版本 34. 优化至单文件版本
35. 优化图片插入功能