Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 869c8ce31b | |||
| 0b7b55224f | |||
| 2a23be44f2 | |||
| fa0cbb4d3f | |||
| 38bc4decf6 | |||
| b5ec6e0d79 | |||
| 82486c707d | |||
| 5ff437bed5 | |||
| 2f7e0b85c0 | |||
| c9548af008 | |||
| b20e4a041f | |||
| 87f64ccc81 | |||
| 58028ea95c | |||
| 35fa062cc3 | |||
| 9de6555519 | |||
| a9baf47823 | |||
| a9b64d2899 |
+573
-4
@@ -1,16 +1,20 @@
|
|||||||
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;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using System.Security; // 添加SecurityException所需命名空间
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Threading;
|
||||||
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
|
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
|
||||||
using MessageBox = System.Windows.MessageBox;
|
using MessageBox = System.Windows.MessageBox;
|
||||||
using Window = System.Windows.Window;
|
using Window = System.Windows.Window;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ink_Canvas
|
namespace Ink_Canvas
|
||||||
{
|
{
|
||||||
@@ -49,12 +53,11 @@ namespace Ink_Canvas
|
|||||||
LogHelper.NewLog(e.Exception.ToString());
|
LogHelper.NewLog(e.Exception.ToString());
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|
||||||
// 新增:根据设置自动处理崩溃
|
// 修改:仅当非用户主动退出时才触发自动重启
|
||||||
if (CrashAction == CrashActionType.SilentRestart)
|
if (CrashAction == CrashActionType.SilentRestart && !IsAppExitByUser)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 静默重启:启动新进程并退出当前进程
|
|
||||||
string exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
|
string exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
|
||||||
System.Diagnostics.Process.Start(exePath);
|
System.Diagnostics.Process.Start(exePath);
|
||||||
}
|
}
|
||||||
@@ -87,6 +90,127 @@ namespace Ink_Canvas
|
|||||||
_taskbar = (TaskbarIcon)FindResource("TaskbarTrayIcon");
|
_taskbar = (TaskbarIcon)FindResource("TaskbarTrayIcon");
|
||||||
|
|
||||||
StartArgs = e.Args;
|
StartArgs = e.Args;
|
||||||
|
|
||||||
|
// 新增:Office注册表检测
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("开始Office注册表检测");
|
||||||
|
|
||||||
|
// 检查Office安装
|
||||||
|
if (!IsOfficeInstalled())
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("未检测到Office安装", LogHelper.LogType.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试获取所有可能的Office版本路径
|
||||||
|
var officeVersions = GetOfficeVersions();
|
||||||
|
if (officeVersions.Count == 0)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("未找到任何Office版本", LogHelper.LogType.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var version in officeVersions)
|
||||||
|
{
|
||||||
|
string regPath = $"Software\\Microsoft\\Office\\{version}\\Common\\Security";
|
||||||
|
LogHelper.WriteLogToFile($"正在处理Office版本 {version}, 注册表路径: {regPath}");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (Microsoft.Win32.RegistryKey baseKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(regPath))
|
||||||
|
{
|
||||||
|
if (baseKey == null)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"注册表路径不存在: {regPath}", LogHelper.LogType.Warning);
|
||||||
|
// 尝试创建路径
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (Microsoft.Win32.RegistryKey createKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(regPath, true))
|
||||||
|
{
|
||||||
|
if (createKey != null)
|
||||||
|
{
|
||||||
|
createKey.SetValue("DisableProtectedView", 1, Microsoft.Win32.RegistryValueKind.DWord);
|
||||||
|
LogHelper.WriteLogToFile($"创建并设置注册表路径: {regPath}", LogHelper.LogType.Info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception createEx)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"创建注册表路径失败: {createEx.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 备份路径更改为软件根目录下的saves/RegistryBackups文件夹
|
||||||
|
string backupPath = Path.Combine(RootPath, "saves", "RegistryBackups");
|
||||||
|
LogHelper.WriteLogToFile($"备份路径: {backupPath}");
|
||||||
|
|
||||||
|
if (!Directory.Exists(backupPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(backupPath);
|
||||||
|
LogHelper.WriteLogToFile($"创建备份目录: {backupPath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
string backupFile = Path.Combine(backupPath, $"SecurityBackup_{version}_{DateTime.Now:yyyyMMddHHmmss}.reg");
|
||||||
|
LogHelper.WriteLogToFile($"创建备份文件: {backupFile}");
|
||||||
|
|
||||||
|
// 使用UTF8编码写入注册表文件
|
||||||
|
using (StreamWriter sw = new StreamWriter(backupFile, false, System.Text.Encoding.UTF8))
|
||||||
|
{
|
||||||
|
sw.WriteLine("Windows Registry Editor Version 5.00\n");
|
||||||
|
sw.WriteLine();
|
||||||
|
sw.WriteLine($"[{Microsoft.Win32.Registry.CurrentUser.Name}\\{regPath}]");
|
||||||
|
|
||||||
|
foreach (string valueName in baseKey.GetValueNames())
|
||||||
|
{
|
||||||
|
object value = baseKey.GetValue(valueName);
|
||||||
|
sw.WriteLine($"\"{valueName}\"=dword:{((int)value):x8}");
|
||||||
|
LogHelper.WriteLogToFile($"备份注册表值: {valueName} = {value}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(regPath, true))
|
||||||
|
{
|
||||||
|
// 仅在值不存在或不等于1时更新
|
||||||
|
object currentValue = key.GetValue("DisableProtectedView");
|
||||||
|
if (currentValue == null || (int)currentValue != 1)
|
||||||
|
{
|
||||||
|
key.SetValue("DisableProtectedView", 1, Microsoft.Win32.RegistryValueKind.DWord);
|
||||||
|
LogHelper.WriteLogToFile($"Office {version} 注册表值已设置: DisableProtectedView = 1");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"Office {version} 注册表值已存在且无需更改: DisableProtectedView = 1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"处理Office版本 {version} 时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理Office 365的特殊路径
|
||||||
|
TryModifyOffice365Registry();
|
||||||
|
}
|
||||||
|
catch (SecurityException secEx)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"安全异常: {secEx.Message}", LogHelper.LogType.Error);
|
||||||
|
ShowPermissionError();
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException authEx)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"访问被拒绝: {authEx.Message}", LogHelper.LogType.Error);
|
||||||
|
ShowPermissionError();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"未知错误: {ex.GetType().FullName} - {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
LogHelper.WriteLogToFile(ex.StackTrace, LogHelper.LogType.Info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
|
private void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
|
||||||
@@ -208,5 +332,450 @@ namespace Ink_Canvas
|
|||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查Office是否安装
|
||||||
|
/// </summary>
|
||||||
|
private bool IsOfficeInstalled()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 检查多个可能的注册表路径
|
||||||
|
// 1. 检查传统的Office版本
|
||||||
|
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office"))
|
||||||
|
{
|
||||||
|
if (key != null && key.GetSubKeyNames().Any(name => name.Contains(".0")))
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("检测到传统Office安装", LogHelper.LogType.Info);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 检查64位注册表中的Office
|
||||||
|
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\Microsoft\\Office"))
|
||||||
|
{
|
||||||
|
if (key != null && key.GetSubKeyNames().Any(name => name.Contains(".0")))
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("检测到64位注册表中的Office安装", LogHelper.LogType.Info);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 检查Office 365/Click-to-Run安装
|
||||||
|
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("检测到Office 365 Click-to-Run", LogHelper.LogType.Info);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 检查Office 365部署配置
|
||||||
|
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\15.0\\ClickToRun"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("检测到Office 365 (15.0)", LogHelper.LogType.Info);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\16.0\\ClickToRun"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("检测到Office 365 (16.0)", LogHelper.LogType.Info);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 检查Office 365零售订阅信息
|
||||||
|
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun\\Configuration"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("检测到Office 365配置", LogHelper.LogType.Info);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogHelper.WriteLogToFile("未检测到任何Office安装", LogHelper.LogType.Warning);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"检查Office安装时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显示权限不足的错误提示
|
||||||
|
/// </summary>
|
||||||
|
private void ShowPermissionError()
|
||||||
|
{
|
||||||
|
const string message = "需要管理员权限才能完成此操作\n请以管理员身份重新启动应用程序";
|
||||||
|
LogHelper.WriteLogToFile(message, LogHelper.LogType.Error);
|
||||||
|
System.Windows.MessageBox.Show(message, "权限错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有已安装的Office版本
|
||||||
|
/// </summary>
|
||||||
|
private List<string> GetOfficeVersions()
|
||||||
|
{
|
||||||
|
var versions = new List<string>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 检查HKLM
|
||||||
|
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
{
|
||||||
|
foreach (var subKeyName in key.GetSubKeyNames())
|
||||||
|
{
|
||||||
|
if (subKeyName.Contains(".0"))
|
||||||
|
{
|
||||||
|
versions.Add(subKeyName);
|
||||||
|
LogHelper.WriteLogToFile($"在HKLM中找到Office版本: {subKeyName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查HKCU
|
||||||
|
using (var key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Office"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
{
|
||||||
|
foreach (var subKeyName in key.GetSubKeyNames())
|
||||||
|
{
|
||||||
|
if (subKeyName.Contains(".0") && !versions.Contains(subKeyName))
|
||||||
|
{
|
||||||
|
versions.Add(subKeyName);
|
||||||
|
LogHelper.WriteLogToFile($"在HKCU中找到Office版本: {subKeyName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查64位注册表
|
||||||
|
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\Microsoft\\Office"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
{
|
||||||
|
foreach (var subKeyName in key.GetSubKeyNames())
|
||||||
|
{
|
||||||
|
if (subKeyName.Contains(".0") && !versions.Contains(subKeyName))
|
||||||
|
{
|
||||||
|
versions.Add(subKeyName);
|
||||||
|
LogHelper.WriteLogToFile($"在64位注册表中找到Office版本: {subKeyName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查Office 365的特殊路径
|
||||||
|
CheckOffice365Versions(versions);
|
||||||
|
|
||||||
|
// 如果没有找到任何版本,添加默认的Office 365版本号
|
||||||
|
if (versions.Count == 0 && IsOffice365Installed())
|
||||||
|
{
|
||||||
|
versions.Add("16.0");
|
||||||
|
LogHelper.WriteLogToFile("未找到具体版本,添加默认Office 365版本: 16.0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"获取Office版本时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按版本号排序
|
||||||
|
versions.Sort((a, b) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
double va = double.Parse(a.Replace(".0", ""));
|
||||||
|
double vb = double.Parse(b.Replace(".0", ""));
|
||||||
|
return vb.CompareTo(va); // 降序排列,最新版本在前
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return versions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检测Office 365是否已安装
|
||||||
|
/// </summary>
|
||||||
|
private bool IsOffice365Installed()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 检查多个Office 365特定路径
|
||||||
|
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\15.0\\ClickToRun"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\16.0\\ClickToRun"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun\\Configuration"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查Office 365特有的版本信息
|
||||||
|
/// </summary>
|
||||||
|
private void CheckOffice365Versions(List<string> versions)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 检查Click-to-Run版本路径
|
||||||
|
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun\\Configuration"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
{
|
||||||
|
var platformVersion = key.GetValue("Platform") as string;
|
||||||
|
var clickToRunVersion = key.GetValue("VersionToReport") as string;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(platformVersion))
|
||||||
|
{
|
||||||
|
var majorVersion = platformVersion.Split('.').FirstOrDefault();
|
||||||
|
if (!string.IsNullOrEmpty(majorVersion) && !versions.Contains($"{majorVersion}.0"))
|
||||||
|
{
|
||||||
|
versions.Add($"{majorVersion}.0");
|
||||||
|
LogHelper.WriteLogToFile($"在Office 365配置中找到平台版本: {majorVersion}.0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(clickToRunVersion))
|
||||||
|
{
|
||||||
|
var majorVersion = clickToRunVersion.Split('.').FirstOrDefault();
|
||||||
|
if (!string.IsNullOrEmpty(majorVersion) && !versions.Contains($"{majorVersion}.0"))
|
||||||
|
{
|
||||||
|
versions.Add($"{majorVersion}.0");
|
||||||
|
LogHelper.WriteLogToFile($"在Office 365配置中找到报告版本: {majorVersion}.0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查安装路径来确认版本
|
||||||
|
var possibleVersions = new[] { "15.0", "16.0" }; // Office 2013 (15.0) 和 Office 2016/2019/365 (16.0)
|
||||||
|
foreach (var version in possibleVersions)
|
||||||
|
{
|
||||||
|
using (var key = Registry.LocalMachine.OpenSubKey($"Software\\Microsoft\\Office\\{version}\\Common\\InstallRoot"))
|
||||||
|
{
|
||||||
|
if (key != null && key.GetValue("Path") != null && !versions.Contains(version))
|
||||||
|
{
|
||||||
|
versions.Add(version);
|
||||||
|
LogHelper.WriteLogToFile($"在InstallRoot中找到Office版本: {version}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"检查Office 365版本时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 尝试修改Office 365的特殊注册表路径
|
||||||
|
/// </summary>
|
||||||
|
private void TryModifyOffice365Registry()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 准备备份目录
|
||||||
|
string backupPath = Path.Combine(RootPath, "saves", "RegistryBackups");
|
||||||
|
if (!Directory.Exists(backupPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(backupPath);
|
||||||
|
LogHelper.WriteLogToFile($"创建Office 365备份目录: {backupPath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查Office 365 Outlook和PowerPoint的特定路径
|
||||||
|
string[] apps = { "outlook", "powerpoint" };
|
||||||
|
|
||||||
|
foreach (var app in apps)
|
||||||
|
{
|
||||||
|
// 检查用户级别的注册表
|
||||||
|
string regPath = $"Software\\Microsoft\\Office\\16.0\\{app}\\Security";
|
||||||
|
LogHelper.WriteLogToFile($"检查Office 365特定应用注册表: {regPath}");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 先检查是否存在该路径
|
||||||
|
using (var baseKey = Registry.CurrentUser.OpenSubKey(regPath))
|
||||||
|
{
|
||||||
|
// 如果路径存在,先备份
|
||||||
|
if (baseKey != null)
|
||||||
|
{
|
||||||
|
string backupFile = Path.Combine(backupPath, $"SecurityBackup_365_{app}_{DateTime.Now:yyyyMMddHHmmss}.reg");
|
||||||
|
LogHelper.WriteLogToFile($"创建Office 365 {app}备份文件: {backupFile}");
|
||||||
|
|
||||||
|
// 使用UTF8编码写入注册表文件
|
||||||
|
using (StreamWriter sw = new StreamWriter(backupFile, false, System.Text.Encoding.UTF8))
|
||||||
|
{
|
||||||
|
sw.WriteLine("Windows Registry Editor Version 5.00\n");
|
||||||
|
sw.WriteLine();
|
||||||
|
sw.WriteLine($"[{Microsoft.Win32.Registry.CurrentUser.Name}\\{regPath}]");
|
||||||
|
|
||||||
|
foreach (string valueName in baseKey.GetValueNames())
|
||||||
|
{
|
||||||
|
object value = baseKey.GetValue(valueName);
|
||||||
|
sw.WriteLine($"\"{valueName}\"=dword:{((int)value):x8}");
|
||||||
|
LogHelper.WriteLogToFile($"备份Office 365 {app}注册表值: {valueName} = {value}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改或创建注册表项
|
||||||
|
using (var key = Registry.CurrentUser.CreateSubKey(regPath, true))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
{
|
||||||
|
object currentValue = key.GetValue("DisableProtectedView");
|
||||||
|
if (currentValue == null || (int)currentValue != 1)
|
||||||
|
{
|
||||||
|
key.SetValue("DisableProtectedView", 1, RegistryValueKind.DWord);
|
||||||
|
LogHelper.WriteLogToFile($"Office 365 {app} 注册表值已设置: DisableProtectedView = 1");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"Office 365 {app} 注册表值已存在且无需更改");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"修改 {app} 注册表时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试通过Office信任中心路径修改
|
||||||
|
string trustCenterPath = "Software\\Microsoft\\Office\\16.0\\Common\\Security\\FileValidation";
|
||||||
|
LogHelper.WriteLogToFile($"检查信任中心路径: {trustCenterPath}");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 先检查是否存在该路径
|
||||||
|
using (var baseKey = Registry.CurrentUser.OpenSubKey(trustCenterPath))
|
||||||
|
{
|
||||||
|
// 如果路径存在,先备份
|
||||||
|
if (baseKey != null)
|
||||||
|
{
|
||||||
|
string backupFile = Path.Combine(backupPath, $"SecurityBackup_365_TrustCenter_{DateTime.Now:yyyyMMddHHmmss}.reg");
|
||||||
|
LogHelper.WriteLogToFile($"创建信任中心备份文件: {backupFile}");
|
||||||
|
|
||||||
|
// 使用UTF8编码写入注册表文件
|
||||||
|
using (StreamWriter sw = new StreamWriter(backupFile, false, System.Text.Encoding.UTF8))
|
||||||
|
{
|
||||||
|
sw.WriteLine("Windows Registry Editor Version 5.00\n");
|
||||||
|
sw.WriteLine();
|
||||||
|
sw.WriteLine($"[{Microsoft.Win32.Registry.CurrentUser.Name}\\{trustCenterPath}]");
|
||||||
|
|
||||||
|
foreach (string valueName in baseKey.GetValueNames())
|
||||||
|
{
|
||||||
|
object value = baseKey.GetValue(valueName);
|
||||||
|
sw.WriteLine($"\"{valueName}\"=dword:{((int)value):x8}");
|
||||||
|
LogHelper.WriteLogToFile($"备份信任中心注册表值: {valueName} = {value}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var key = Registry.CurrentUser.CreateSubKey(trustCenterPath, true))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
{
|
||||||
|
key.SetValue("DisableEditFromPV", 1, RegistryValueKind.DWord);
|
||||||
|
LogHelper.WriteLogToFile("已禁用受保护视图中的编辑");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"修改信任中心路径时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试修改EnableEditWhileViewingPolicy
|
||||||
|
string policyPath = "Software\\Policies\\Microsoft\\Office\\16.0\\Common\\Security";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 先检查是否存在该路径
|
||||||
|
using (var baseKey = Registry.CurrentUser.OpenSubKey(policyPath))
|
||||||
|
{
|
||||||
|
// 如果路径存在,先备份
|
||||||
|
if (baseKey != null)
|
||||||
|
{
|
||||||
|
string backupFile = Path.Combine(backupPath, $"SecurityBackup_365_Policy_{DateTime.Now:yyyyMMddHHmmss}.reg");
|
||||||
|
LogHelper.WriteLogToFile($"创建策略备份文件: {backupFile}");
|
||||||
|
|
||||||
|
// 使用UTF8编码写入注册表文件
|
||||||
|
using (StreamWriter sw = new StreamWriter(backupFile, false, System.Text.Encoding.UTF8))
|
||||||
|
{
|
||||||
|
sw.WriteLine("Windows Registry Editor Version 5.00\n");
|
||||||
|
sw.WriteLine();
|
||||||
|
sw.WriteLine($"[{Microsoft.Win32.Registry.CurrentUser.Name}\\{policyPath}]");
|
||||||
|
|
||||||
|
foreach (string valueName in baseKey.GetValueNames())
|
||||||
|
{
|
||||||
|
object value = baseKey.GetValue(valueName);
|
||||||
|
sw.WriteLine($"\"{valueName}\"=dword:{((int)value):x8}");
|
||||||
|
LogHelper.WriteLogToFile($"备份策略注册表值: {valueName} = {value}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var key = Registry.CurrentUser.CreateSubKey(policyPath, true))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
{
|
||||||
|
key.SetValue("EnableEditWhileViewingPolicy", 1, RegistryValueKind.DWord);
|
||||||
|
LogHelper.WriteLogToFile("已启用查看时编辑策略");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"修改策略路径时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"修改Office 365注册表时发生未知错误: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,44 @@ namespace Ink_Canvas.Helpers
|
|||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
||||||
|
|
||||||
|
[DllImport("shell32.dll")]
|
||||||
|
private static extern IntPtr SHAppBarMessage(uint dwMessage, ref APPBARDATA pData);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern int SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);
|
||||||
|
|
||||||
|
private const uint ABM_GETTASKBARPOS = 0x00000005;
|
||||||
|
private const uint ABM_GETSTATE = 0x00000004;
|
||||||
|
private const int SPI_GETWORKAREA = 0x0030;
|
||||||
|
private const uint MONITOR_DEFAULTTOPRIMARY = 1;
|
||||||
|
private const int ABS_AUTOHIDE = 0x0000001;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct MONITORINFO
|
||||||
|
{
|
||||||
|
public int cbSize;
|
||||||
|
public RECT rcMonitor;
|
||||||
|
public RECT rcWork;
|
||||||
|
public uint dwFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct APPBARDATA
|
||||||
|
{
|
||||||
|
public int cbSize;
|
||||||
|
public IntPtr hWnd;
|
||||||
|
public uint uCallbackMessage;
|
||||||
|
public uint uEdge;
|
||||||
|
public RECT rc;
|
||||||
|
public IntPtr lParam;
|
||||||
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct RECT {
|
public struct RECT {
|
||||||
public int Left;
|
public int Left;
|
||||||
@@ -34,6 +72,72 @@ namespace Ink_Canvas.Helpers
|
|||||||
public int Height => Bottom - Top;
|
public int Height => Bottom - Top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取Windows任务栏的高度(仅计算任务栏,不包括其他应用的停靠栏)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="screen">当前屏幕</param>
|
||||||
|
/// <param name="dpiScaleY">DPI缩放Y值</param>
|
||||||
|
/// <returns>任务栏高度</returns>
|
||||||
|
public static double GetTaskbarHeight(System.Windows.Forms.Screen screen, double dpiScaleY)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 创建APPBARDATA结构
|
||||||
|
var abd = new APPBARDATA();
|
||||||
|
abd.cbSize = Marshal.SizeOf(abd);
|
||||||
|
|
||||||
|
// 获取任务栏状态
|
||||||
|
IntPtr state = SHAppBarMessage(ABM_GETSTATE, ref abd);
|
||||||
|
bool isAutoHide = (state.ToInt32() & ABS_AUTOHIDE) == ABS_AUTOHIDE;
|
||||||
|
|
||||||
|
// 如果任务栏是自动隐藏的,返回0
|
||||||
|
if (isAutoHide)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("任务栏处于自动隐藏状态", LogHelper.LogType.Info);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取任务栏信息
|
||||||
|
IntPtr result = SHAppBarMessage(ABM_GETTASKBARPOS, ref abd);
|
||||||
|
if (result != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
// 获取当前屏幕的工作区
|
||||||
|
RECT workArea = new RECT();
|
||||||
|
SystemParametersInfo(SPI_GETWORKAREA, 0, Marshal.AllocHGlobal(Marshal.SizeOf(workArea)), 0);
|
||||||
|
|
||||||
|
// 根据任务栏位置计算高度
|
||||||
|
int taskbarHeight = 0;
|
||||||
|
|
||||||
|
// 任务栏的uEdge: 0=左, 1=上, 2=右, 3=下
|
||||||
|
switch (abd.uEdge)
|
||||||
|
{
|
||||||
|
case 1: // 上
|
||||||
|
taskbarHeight = abd.rc.Height;
|
||||||
|
break;
|
||||||
|
case 3: // 下
|
||||||
|
taskbarHeight = abd.rc.Height;
|
||||||
|
break;
|
||||||
|
case 0: // 左
|
||||||
|
case 2: // 右
|
||||||
|
// 水平任务栏不影响高度
|
||||||
|
taskbarHeight = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 考虑DPI缩放
|
||||||
|
return taskbarHeight / dpiScaleY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"获取任务栏高度出错: {ex.Message}");
|
||||||
|
LogHelper.WriteLogToFile($"获取任务栏高度出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果获取失败,回退到通用方法
|
||||||
|
return (screen.Bounds.Height - screen.WorkingArea.Height) / dpiScaleY;
|
||||||
|
}
|
||||||
|
|
||||||
public static string WindowTitle() {
|
public static string WindowTitle() {
|
||||||
IntPtr foregroundWindowHandle = GetForegroundWindow();
|
IntPtr foregroundWindowHandle = GetForegroundWindow();
|
||||||
|
|
||||||
|
|||||||
@@ -226,7 +226,7 @@
|
|||||||
<ui:SimpleStackPanel VerticalAlignment="Center">
|
<ui:SimpleStackPanel VerticalAlignment="Center">
|
||||||
<TextBlock Foreground="#fafafa" HorizontalAlignment="Center"
|
<TextBlock Foreground="#fafafa" HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Center" FontSize="15" Margin="0,0,0,10"
|
VerticalAlignment="Center" FontSize="15" Margin="0,0,0,10"
|
||||||
Text="开发中..." />
|
Text="开发中...请不要点击,可能会导致ICC异常崩溃" />
|
||||||
<ui:SimpleStackPanel Spacing="5">
|
<ui:SimpleStackPanel Spacing="5">
|
||||||
<ui:SimpleStackPanel Spacing="5" Orientation="Horizontal"
|
<ui:SimpleStackPanel Spacing="5" Orientation="Horizontal"
|
||||||
HorizontalAlignment="Center">
|
HorizontalAlignment="Center">
|
||||||
@@ -377,6 +377,23 @@
|
|||||||
IsOn="True" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
IsOn="True" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
||||||
Toggled="ToggleSwitchShowCursor_Toggled" />
|
Toggled="ToggleSwitchShowCursor_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="ToggleSwitchEnablePressureTouchMode"
|
||||||
|
IsOn="True" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
||||||
|
Toggled="ToggleSwitchEnablePressureTouchMode_Toggled" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
|
<TextBlock Text="# 开启后,触屏设备也将支持压感效果,适用于部分支持压感但无法被系统识别的触屏设备。" TextWrapping="Wrap" Foreground="#a1a1aa" />
|
||||||
|
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||||
|
<TextBlock Foreground="#fafafa" Text="屏蔽压感" VerticalAlignment="Center"
|
||||||
|
FontSize="14" Margin="0,0,16,0" />
|
||||||
|
<ui:ToggleSwitch OnContent="" OffContent="" Name="ToggleSwitchDisablePressure"
|
||||||
|
IsOn="True" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
||||||
|
Toggled="ToggleSwitchDisablePressure_Toggled" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
|
<TextBlock Text="# 开启后,将忽略所有设备的压感信息,使所有笔画具有统一的粗细。与压感触屏模式互斥。" TextWrapping="Wrap" Foreground="#a1a1aa" />
|
||||||
|
|
||||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||||
<TextBlock Foreground="#fafafa" Text="橡皮大小" VerticalAlignment="Center"
|
<TextBlock Foreground="#fafafa" Text="橡皮大小" VerticalAlignment="Center"
|
||||||
FontSize="14" Margin="0,0,16,0" />
|
FontSize="14" Margin="0,0,16,0" />
|
||||||
@@ -553,7 +570,46 @@
|
|||||||
</CheckBox>
|
</CheckBox>
|
||||||
</ui:SimpleStackPanel>
|
</ui:SimpleStackPanel>
|
||||||
</ui:SimpleStackPanel>
|
</ui:SimpleStackPanel>
|
||||||
|
<Line HorizontalAlignment="Center" X1="0" Y1="0" X2="400" Y2="0"
|
||||||
|
Stroke="#3f3f46" StrokeThickness="1" Margin="0,4,0,4" />
|
||||||
|
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||||
|
<TextBlock Foreground="#fafafa" Text="直线自动拉直" VerticalAlignment="Center"
|
||||||
|
FontSize="14" Margin="0,0,16,0" />
|
||||||
|
<ui:ToggleSwitch OnContent="" OffContent="" Name="ToggleSwitchAutoStraightenLine"
|
||||||
|
IsOn="True" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
||||||
|
Toggled="ToggleSwitchAutoStraightenLine_Toggled" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
|
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left"
|
||||||
|
Visibility="{Binding ElementName=ToggleSwitchAutoStraightenLine, Path=IsOn, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||||
|
<TextBlock Foreground="#fafafa" Text="长度阈值" VerticalAlignment="Center"
|
||||||
|
FontSize="14" Margin="0,0,16,0" />
|
||||||
|
<Slider Name="AutoStraightenLineThresholdSlider" Width="150" Minimum="30" Maximum="300"
|
||||||
|
Value="30" TickFrequency="30" IsSnapToTickEnabled="True"
|
||||||
|
ValueChanged="AutoStraightenLineThresholdSlider_ValueChanged" />
|
||||||
|
<TextBlock Foreground="#fafafa" Text="{Binding ElementName=AutoStraightenLineThresholdSlider, Path=Value, StringFormat={}{0:0}}"
|
||||||
|
VerticalAlignment="Center" FontSize="14" Margin="16,0,0,0" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
|
<TextBlock Text="# 开启后,当绘制的直线超过设定长度阈值时,将自动调整为完美直线。" TextWrapping="Wrap" Foreground="#a1a1aa" />
|
||||||
|
<Line HorizontalAlignment="Center" X1="0" Y1="0" X2="400" Y2="0"
|
||||||
|
Stroke="#3f3f46" StrokeThickness="1" Margin="0,4,0,4" />
|
||||||
|
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||||
|
<TextBlock Foreground="#fafafa" Text="直线端点吸附" VerticalAlignment="Center"
|
||||||
|
FontSize="14" Margin="0,0,16,0" />
|
||||||
|
<ui:ToggleSwitch OnContent="" OffContent="" Name="ToggleSwitchLineEndpointSnapping"
|
||||||
|
IsOn="True" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
||||||
|
Toggled="ToggleSwitchLineEndpointSnapping_Toggled" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
|
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left"
|
||||||
|
Visibility="{Binding ElementName=ToggleSwitchLineEndpointSnapping, Path=IsOn, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||||
|
<TextBlock Foreground="#fafafa" Text="吸附距离" VerticalAlignment="Center"
|
||||||
|
FontSize="14" Margin="0,0,16,0" />
|
||||||
|
<Slider Name="LineEndpointSnappingThresholdSlider" Width="150" Minimum="5" Maximum="50"
|
||||||
|
Value="15" TickFrequency="5" IsSnapToTickEnabled="True"
|
||||||
|
ValueChanged="LineEndpointSnappingThresholdSlider_ValueChanged" />
|
||||||
|
<TextBlock Foreground="#fafafa" Text="{Binding ElementName=LineEndpointSnappingThresholdSlider, Path=Value, StringFormat={}{0:0}}"
|
||||||
|
VerticalAlignment="Center" FontSize="14" Margin="16,0,0,0" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
|
<TextBlock Text="# 开启后,当绘制的直线端点靠近其他直线端点时,将自动吸附连接。" TextWrapping="Wrap" Foreground="#a1a1aa" />
|
||||||
</ui:SimpleStackPanel>
|
</ui:SimpleStackPanel>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
<GroupBox Name="GroupBoxAppearanceNewUI">
|
<GroupBox Name="GroupBoxAppearanceNewUI">
|
||||||
@@ -1965,6 +2021,15 @@
|
|||||||
FontWeight="Bold"
|
FontWeight="Bold"
|
||||||
Toggled="ToggleSwitchDisplayRandWindowNamesInputBtn_OnToggled" />
|
Toggled="ToggleSwitchDisplayRandWindowNamesInputBtn_OnToggled" />
|
||||||
</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="ToggleSwitchShowRandomAndSingleDraw"
|
||||||
|
IsOn="True" FontFamily="Microsoft YaHei UI"
|
||||||
|
FontWeight="Bold"
|
||||||
|
Toggled="ToggleSwitchShowRandomAndSingleDraw_Toggled" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
<Line HorizontalAlignment="Center" X1="0" Y1="0" X2="400" Y2="0"
|
<Line HorizontalAlignment="Center" X1="0" Y1="0" X2="400" Y2="0"
|
||||||
Stroke="#3f3f46" StrokeThickness="1" Margin="0,4,0,4" />
|
Stroke="#3f3f46" StrokeThickness="1" Margin="0,4,0,4" />
|
||||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||||
@@ -2381,7 +2446,7 @@
|
|||||||
<Grid Name="GridTransparencyFakeBackground" Opacity="0" />
|
<Grid Name="GridTransparencyFakeBackground" Opacity="0" />
|
||||||
<Label Name="Label" Visibility="Collapsed" Foreground="Gray" Content="0" />
|
<Label Name="Label" Visibility="Collapsed" Foreground="Gray" Content="0" />
|
||||||
<Grid Name="InkCanvasGridForInkReplay">
|
<Grid Name="InkCanvasGridForInkReplay">
|
||||||
<InkCanvas x:Name="inkCanvas" ForceCursor="False"
|
<InkCanvas x:Name="inkCanvas" ForceCursor="True" UseCustomCursor="True"
|
||||||
TouchUp="Main_Grid_TouchUp" TouchDown="Main_Grid_TouchDown"
|
TouchUp="Main_Grid_TouchUp" TouchDown="Main_Grid_TouchDown"
|
||||||
TouchMove="inkCanvas_TouchMove"
|
TouchMove="inkCanvas_TouchMove"
|
||||||
ManipulationDelta="Main_Grid_ManipulationDelta"
|
ManipulationDelta="Main_Grid_ManipulationDelta"
|
||||||
@@ -4386,7 +4451,7 @@
|
|||||||
<Label Content="计时器" FontSize="8"
|
<Label Content="计时器" FontSize="8"
|
||||||
HorizontalAlignment="Center" />
|
HorizontalAlignment="Center" />
|
||||||
</ui:SimpleStackPanel>
|
</ui:SimpleStackPanel>
|
||||||
<ui:SimpleStackPanel MouseDown="Border_MouseDown"
|
<ui:SimpleStackPanel x:Name="RandomDrawPanel" Visibility="Collapsed" MouseDown="Border_MouseDown"
|
||||||
MouseUp="SymbolIconRand_MouseUp"
|
MouseUp="SymbolIconRand_MouseUp"
|
||||||
Margin="0,0,0,0" Height="38" Width="32"
|
Margin="0,0,0,0" Height="38" Width="32"
|
||||||
Orientation="Vertical">
|
Orientation="Vertical">
|
||||||
@@ -4406,7 +4471,7 @@
|
|||||||
<Label Content="随机抽" FontSize="8"
|
<Label Content="随机抽" FontSize="8"
|
||||||
HorizontalAlignment="Center" />
|
HorizontalAlignment="Center" />
|
||||||
</ui:SimpleStackPanel>
|
</ui:SimpleStackPanel>
|
||||||
<ui:SimpleStackPanel MouseDown="Border_MouseDown"
|
<ui:SimpleStackPanel x:Name="SingleDrawPanel" Visibility="Collapsed" MouseDown="Border_MouseDown"
|
||||||
MouseUp="SymbolIconRandOne_MouseUp"
|
MouseUp="SymbolIconRandOne_MouseUp"
|
||||||
Margin="0,0,0,0" Height="38" Width="32"
|
Margin="0,0,0,0" Height="38" Width="32"
|
||||||
Orientation="Vertical">
|
Orientation="Vertical">
|
||||||
|
|||||||
@@ -154,16 +154,24 @@ namespace Ink_Canvas {
|
|||||||
private void inkCanvas_EditingModeChanged(object sender, RoutedEventArgs e) {
|
private void inkCanvas_EditingModeChanged(object sender, RoutedEventArgs e) {
|
||||||
var inkCanvas1 = sender as InkCanvas;
|
var inkCanvas1 = sender as InkCanvas;
|
||||||
if (inkCanvas1 == null) return;
|
if (inkCanvas1 == null) return;
|
||||||
// 修复“显示画笔光标”选项不可用的问题
|
// 修复"显示画笔光标"选项不可用的问题
|
||||||
if (Settings.Canvas.IsShowCursor) {
|
if (Settings.Canvas.IsShowCursor) {
|
||||||
inkCanvas1.UseCustomCursor = true;
|
inkCanvas1.UseCustomCursor = true;
|
||||||
// 修复触屏和数位笔时光标不显示:只要有输入设备悬停、捕获,或有任何Stylus设备连接就显示
|
// 修复触屏和数位笔时光标不显示:强制显示光标,不再依赖鼠标或触控状态
|
||||||
if ((inkCanvas1.EditingMode == InkCanvasEditingMode.Ink || drawingShapeMode != 0)
|
inkCanvas1.ForceCursor = true;
|
||||||
&& (inkCanvas1.IsStylusDirectlyOver || inkCanvas1.IsMouseDirectlyOver || inkCanvas1.IsStylusCaptured || inkCanvas1.IsMouseCaptured
|
|
||||||
|| Stylus.CurrentStylusDevice != null))
|
// 根据编辑模式设置不同的光标
|
||||||
inkCanvas1.ForceCursor = true;
|
if (inkCanvas1.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||||
else
|
var sri = Application.GetResourceStream(new Uri("Resources/Cursors/Eraser.cur", UriKind.Relative));
|
||||||
inkCanvas1.ForceCursor = false;
|
if (sri != null)
|
||||||
|
inkCanvas1.Cursor = new Cursor(sri.Stream);
|
||||||
|
} else if (inkCanvas1.EditingMode == InkCanvasEditingMode.Ink) {
|
||||||
|
var sri = Application.GetResourceStream(new Uri("Resources/Cursors/Pen.cur", UriKind.Relative));
|
||||||
|
if (sri != null)
|
||||||
|
inkCanvas1.Cursor = new Cursor(sri.Stream);
|
||||||
|
} else if (inkCanvas1.EditingMode == InkCanvasEditingMode.Select) {
|
||||||
|
inkCanvas1.Cursor = Cursors.Cross;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
inkCanvas1.UseCustomCursor = false;
|
inkCanvas1.UseCustomCursor = false;
|
||||||
inkCanvas1.ForceCursor = false;
|
inkCanvas1.ForceCursor = false;
|
||||||
@@ -292,8 +300,8 @@ namespace Ink_Canvas {
|
|||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true)]
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
|
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
|
||||||
|
|
||||||
private void MainWindow_OnSizeChanged(object sender, SizeChangedEventArgs e) {
|
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})");
|
$"检测到窗口大小变化,已自动恢复到全屏:{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})");
|
||||||
@@ -361,16 +369,38 @@ namespace Ink_Canvas {
|
|||||||
inkCanvas.Cursor = new Cursor(sri.Stream);
|
inkCanvas.Cursor = new Cursor(sri.Stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 触摸输入,通常隐藏光标
|
// 触摸输入,不隐藏光标
|
||||||
private void inkCanvas_TouchDown(object sender, TouchEventArgs e)
|
private void inkCanvas_TouchDown(object sender, TouchEventArgs e)
|
||||||
{
|
{
|
||||||
System.Windows.Forms.Cursor.Show();
|
// 修改:根据用户设置决定是否强制显示自定义光标
|
||||||
|
if (Settings.Canvas.IsShowCursor)
|
||||||
|
{
|
||||||
|
inkCanvas.ForceCursor = true;
|
||||||
|
// 确保鼠标光标对触摸可见
|
||||||
|
System.Windows.Forms.Cursor.Show();
|
||||||
|
// 新增:当处于套索选择模式时保持光标可见
|
||||||
|
if (inkCanvas.EditingMode == InkCanvasEditingMode.Select)
|
||||||
|
inkCanvas.Cursor = Cursors.Cross;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inkCanvas.ForceCursor = false;
|
||||||
|
System.Windows.Forms.Cursor.Show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 触摸结束,恢复光标
|
// 触摸结束,恢复光标
|
||||||
private void inkCanvas_TouchUp(object sender, TouchEventArgs e)
|
private void inkCanvas_TouchUp(object sender, TouchEventArgs e)
|
||||||
{
|
{
|
||||||
System.Windows.Forms.Cursor.Show();
|
// 修改:根据当前模式和设置恢复光标状态
|
||||||
|
if (Settings.Canvas.IsShowCursor) {
|
||||||
|
inkCanvas.ForceCursor = true;
|
||||||
|
// 确保鼠标光标对触摸可见
|
||||||
|
System.Windows.Forms.Cursor.Show();
|
||||||
|
} else {
|
||||||
|
inkCanvas.ForceCursor = false;
|
||||||
|
System.Windows.Forms.Cursor.Show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Definations and Loading
|
#endregion Definations and Loading
|
||||||
|
|||||||
@@ -740,9 +740,11 @@ namespace Ink_Canvas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void SymbolIconRand_MouseUp(object sender, MouseButtonEventArgs e) {
|
private void SymbolIconRand_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||||
|
// 如果控件被隐藏,不处理事件
|
||||||
|
if (RandomDrawPanel.Visibility != Visibility.Visible) return;
|
||||||
|
|
||||||
LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
||||||
RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
||||||
//if (lastBorderMouseDownObject != sender) return;
|
|
||||||
|
|
||||||
AnimationsHelper.HideWithSlideAndFade(BorderTools);
|
AnimationsHelper.HideWithSlideAndFade(BorderTools);
|
||||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
|
AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
|
||||||
@@ -808,14 +810,16 @@ namespace Ink_Canvas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void SymbolIconRandOne_MouseUp(object sender, MouseButtonEventArgs e) {
|
private void SymbolIconRandOne_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||||
|
// 如果控件被隐藏,不处理事件
|
||||||
|
if (SingleDrawPanel.Visibility != Visibility.Visible) return;
|
||||||
|
|
||||||
LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
||||||
RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
||||||
//if (lastBorderMouseDownObject != sender) return;
|
|
||||||
|
|
||||||
AnimationsHelper.HideWithSlideAndFade(BorderTools);
|
AnimationsHelper.HideWithSlideAndFade(BorderTools);
|
||||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
|
AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
|
||||||
|
|
||||||
new RandWindow(Settings,true).ShowDialog();
|
new RandWindow(Settings, true).ShowDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GridInkReplayButton_MouseUp(object sender, MouseButtonEventArgs e) {
|
private void GridInkReplayButton_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||||
@@ -1074,15 +1078,38 @@ 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 = System.Windows.Forms.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;
|
||||||
var toolbarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.FullPrimaryScreenHeight -
|
// 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响
|
||||||
SystemParameters.WindowCaptionHeight;
|
var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY);
|
||||||
pos.X = (screenWidth - ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX) / 2;
|
pos.X = (screenWidth - ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX) / 2;
|
||||||
|
|
||||||
if (PosXCaculatedWithTaskbarHeight == false)
|
if (PosXCaculatedWithTaskbarHeight == false)
|
||||||
pos.Y = screenHeight - MarginFromEdge * ViewboxFloatingBarScaleTransform.ScaleY;
|
{
|
||||||
|
// 如果任务栏高度为0(隐藏状态),则使用固定边距
|
||||||
|
if (toolbarHeight == 0)
|
||||||
|
{
|
||||||
|
pos.Y = screenHeight - MarginFromEdge * ViewboxFloatingBarScaleTransform.ScaleY;
|
||||||
|
LogHelper.WriteLogToFile($"任务栏隐藏,使用固定边距: {MarginFromEdge}", LogHelper.LogType.Info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pos.Y = screenHeight - MarginFromEdge * ViewboxFloatingBarScaleTransform.ScaleY;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (PosXCaculatedWithTaskbarHeight == true)
|
else if (PosXCaculatedWithTaskbarHeight == true)
|
||||||
pos.Y = screenHeight - ViewboxFloatingBar.ActualHeight * ViewboxFloatingBarScaleTransform.ScaleY -
|
{
|
||||||
toolbarHeight - ViewboxFloatingBarScaleTransform.ScaleY * 3;
|
// 如果任务栏高度为0(隐藏状态),则使用固定高度
|
||||||
|
if (toolbarHeight == 0)
|
||||||
|
{
|
||||||
|
pos.Y = screenHeight - ViewboxFloatingBar.ActualHeight * ViewboxFloatingBarScaleTransform.ScaleY -
|
||||||
|
3 * ViewboxFloatingBarScaleTransform.ScaleY;
|
||||||
|
LogHelper.WriteLogToFile($"任务栏隐藏,使用固定高度: {ViewboxFloatingBar.ActualHeight}", LogHelper.LogType.Info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pos.Y = screenHeight - ViewboxFloatingBar.ActualHeight * ViewboxFloatingBarScaleTransform.ScaleY -
|
||||||
|
toolbarHeight - ViewboxFloatingBarScaleTransform.ScaleY * 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (MarginFromEdge != -60) {
|
if (MarginFromEdge != -60) {
|
||||||
if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) {
|
if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) {
|
||||||
@@ -1137,12 +1164,22 @@ 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 = System.Windows.Forms.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;
|
||||||
var toolbarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.FullPrimaryScreenHeight -
|
// 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响
|
||||||
SystemParameters.WindowCaptionHeight;
|
var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY);
|
||||||
pos.X = (screenWidth - ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX) / 2;
|
pos.X = (screenWidth - ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX) / 2;
|
||||||
|
|
||||||
pos.Y = screenHeight - ViewboxFloatingBar.ActualHeight * ViewboxFloatingBarScaleTransform.ScaleY -
|
// 如果任务栏高度为0(隐藏状态),则使用固定边距
|
||||||
toolbarHeight - ViewboxFloatingBarScaleTransform.ScaleY * 3;
|
if (toolbarHeight == 0)
|
||||||
|
{
|
||||||
|
pos.Y = screenHeight - ViewboxFloatingBar.ActualHeight * ViewboxFloatingBarScaleTransform.ScaleY -
|
||||||
|
3 * ViewboxFloatingBarScaleTransform.ScaleY;
|
||||||
|
LogHelper.WriteLogToFile($"任务栏隐藏,使用固定高度: {ViewboxFloatingBar.ActualHeight}", LogHelper.LogType.Info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pos.Y = screenHeight - ViewboxFloatingBar.ActualHeight * ViewboxFloatingBarScaleTransform.ScaleY -
|
||||||
|
toolbarHeight - ViewboxFloatingBarScaleTransform.ScaleY * 3;
|
||||||
|
}
|
||||||
|
|
||||||
if (pointDesktop.X != -1 || pointDesktop.Y != -1) pointDesktop = pos;
|
if (pointDesktop.X != -1 || pointDesktop.Y != -1) pointDesktop = pos;
|
||||||
|
|
||||||
@@ -1180,8 +1217,8 @@ 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 = System.Windows.Forms.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;
|
||||||
var toolbarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.FullPrimaryScreenHeight -
|
// 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响
|
||||||
SystemParameters.WindowCaptionHeight;
|
var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY);
|
||||||
pos.X = (screenWidth - ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX) / 2;
|
pos.X = (screenWidth - ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX) / 2;
|
||||||
|
|
||||||
pos.Y = screenHeight - 55 * ViewboxFloatingBarScaleTransform.ScaleY;
|
pos.Y = screenHeight - 55 * ViewboxFloatingBarScaleTransform.ScaleY;
|
||||||
@@ -1585,7 +1622,7 @@ 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");
|
Process.Start(System.Windows.Forms.Application.ExecutablePath, "-m");
|
||||||
|
App.IsAppExitByUser = true;
|
||||||
CloseIsFromButton = true;
|
CloseIsFromButton = true;
|
||||||
Application.Current.Shutdown();
|
Application.Current.Shutdown();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ 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 Microsoft.Win32;
|
||||||
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;
|
||||||
@@ -86,6 +87,61 @@ namespace Ink_Canvas {
|
|||||||
|
|
||||||
Settings.PowerPointSettings.IsSupportWPS = ToggleSwitchSupportWPS.IsOn;
|
Settings.PowerPointSettings.IsSupportWPS = ToggleSwitchSupportWPS.IsOn;
|
||||||
SaveSettingsToFile();
|
SaveSettingsToFile();
|
||||||
|
|
||||||
|
// 重置PowerPoint/WPS实例状态
|
||||||
|
ResetPresentationObjects();
|
||||||
|
isPowerPointInitialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重置所有演示相关的COM对象
|
||||||
|
/// </summary>
|
||||||
|
private void ResetPresentationObjects()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 清理对象引用
|
||||||
|
if (pptApplication != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 尝试解除事件绑定
|
||||||
|
pptApplication.PresentationOpen -= PptApplication_PresentationOpen;
|
||||||
|
pptApplication.PresentationClose -= PptApplication_PresentationClose;
|
||||||
|
pptApplication.SlideShowBegin -= PptApplication_SlideShowBegin;
|
||||||
|
pptApplication.SlideShowNextSlide -= PptApplication_SlideShowNextSlide;
|
||||||
|
pptApplication.SlideShowEnd -= PptApplication_SlideShowEnd;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
try { Marshal.ReleaseComObject(pptApplication); } catch { }
|
||||||
|
pptApplication = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (presentation != null)
|
||||||
|
{
|
||||||
|
try { Marshal.ReleaseComObject(presentation); } catch { }
|
||||||
|
presentation = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slides != null)
|
||||||
|
{
|
||||||
|
try { Marshal.ReleaseComObject(slides); } catch { }
|
||||||
|
slides = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
slide = null;
|
||||||
|
|
||||||
|
// 强制GC回收
|
||||||
|
GC.Collect();
|
||||||
|
GC.WaitForPendingFinalizers();
|
||||||
|
|
||||||
|
LogHelper.WriteLogToFile("成功重置所有演示对象", LogHelper.LogType.Info);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"重置演示对象时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool isWPSSupportOn => Settings.PowerPointSettings.IsSupportWPS;
|
private static bool isWPSSupportOn => Settings.PowerPointSettings.IsSupportWPS;
|
||||||
@@ -93,8 +149,34 @@ namespace Ink_Canvas {
|
|||||||
public static bool IsShowingRestoreHiddenSlidesWindow = false;
|
public static bool IsShowingRestoreHiddenSlidesWindow = false;
|
||||||
private static bool IsShowingAutoplaySlidesWindow = false;
|
private static bool IsShowingAutoplaySlidesWindow = false;
|
||||||
private bool isPowerPointInitialized = false;
|
private bool isPowerPointInitialized = false;
|
||||||
|
private bool isWPSMode = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有可能的WPS进程名
|
||||||
|
/// </summary>
|
||||||
|
private string[] GetPossibleWPSProcessNames()
|
||||||
|
{
|
||||||
|
return new[] { "wpp", "wppmain", "wps", "et" };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查WPS进程是否正在运行
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writeLog">是否记录日志,默认为true</param>
|
||||||
|
private bool IsWPSRunning(bool writeLog = true)
|
||||||
|
{
|
||||||
|
foreach (var processName in GetPossibleWPSProcessNames())
|
||||||
|
{
|
||||||
|
var processes = Process.GetProcessesByName(processName);
|
||||||
|
if (processes.Length > 0)
|
||||||
|
{
|
||||||
|
if (writeLog)
|
||||||
|
LogHelper.WriteLogToFile($"检测到WPS进程: {processName}", LogHelper.LogType.Info);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void TimerCheckPPT_Elapsed(object sender, ElapsedEventArgs e)
|
private void TimerCheckPPT_Elapsed(object sender, ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
@@ -107,19 +189,44 @@ namespace Ink_Canvas {
|
|||||||
// 检查是否已有初始化的 PowerPoint 实例
|
// 检查是否已有初始化的 PowerPoint 实例
|
||||||
if (!isPowerPointInitialized)
|
if (!isPowerPointInitialized)
|
||||||
{
|
{
|
||||||
// 优先检测WPS进程
|
// 检测WPS和PowerPoint进程
|
||||||
var wpsProcesses = Process.GetProcessesByName("wpp");
|
bool wpsRunning = IsWPSRunning(true);
|
||||||
var pptProcesses = Process.GetProcessesByName("POWERPNT");
|
var pptProcesses = Process.GetProcessesByName("POWERPNT");
|
||||||
|
|
||||||
|
// 根据设置和进程状态决定模式
|
||||||
|
isWPSMode = isWPSSupportOn && wpsRunning;
|
||||||
|
|
||||||
|
LogHelper.WriteLogToFile($"初始化模式: {(isWPSMode ? "WPS" : "PowerPoint")}", LogHelper.LogType.Info);
|
||||||
|
|
||||||
// 优先获取WPS实例
|
// 优先获取WPS实例
|
||||||
if (isWPSSupportOn && wpsProcesses.Length > 0)
|
if (isWPSMode)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pptApplication = (Microsoft.Office.Interop.PowerPoint.Application)Marshal.GetActiveObject("wpp.Application");
|
// 尝试多种可能的ProgID
|
||||||
|
string[] possibleProgIds = { "wpp.Application", "WPS.Application" };
|
||||||
|
|
||||||
|
foreach (var progId in possibleProgIds)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"尝试获取COM对象: {progId}", LogHelper.LogType.Info);
|
||||||
|
pptApplication = (Microsoft.Office.Interop.PowerPoint.Application)Marshal.GetActiveObject(progId);
|
||||||
|
if (pptApplication != null)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"成功连接到WPS: {progId}", LogHelper.LogType.Info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (COMException)
|
catch (COMException ex)
|
||||||
{
|
{
|
||||||
|
LogHelper.WriteLogToFile($"获取WPS实例失败: {ex.Message}", LogHelper.LogType.Error);
|
||||||
pptApplication = null;
|
pptApplication = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,74 +236,71 @@ namespace Ink_Canvas {
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
LogHelper.WriteLogToFile("尝试获取PowerPoint实例", LogHelper.LogType.Info);
|
||||||
pptApplication = (Microsoft.Office.Interop.PowerPoint.Application)Marshal.GetActiveObject("PowerPoint.Application");
|
pptApplication = (Microsoft.Office.Interop.PowerPoint.Application)Marshal.GetActiveObject("PowerPoint.Application");
|
||||||
|
if (pptApplication != null)
|
||||||
|
LogHelper.WriteLogToFile("成功连接到PowerPoint", LogHelper.LogType.Info);
|
||||||
}
|
}
|
||||||
catch (COMException)
|
catch (COMException ex)
|
||||||
{
|
{
|
||||||
|
LogHelper.WriteLogToFile($"获取PowerPoint实例失败: {ex.Message}", LogHelper.LogType.Error);
|
||||||
pptApplication = null;
|
pptApplication = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果都没有找到,且未启用WPS支持,则自动创建PowerPoint进程
|
// 如果都没有找到,且未启用WPS支持,则自动创建PowerPoint进程
|
||||||
if (pptApplication == null && !isWPSSupportOn)
|
if (pptApplication == null && !isWPSMode && pptProcesses.Length == 0)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
LogHelper.WriteLogToFile("尝试创建新的PowerPoint实例", LogHelper.LogType.Info);
|
||||||
pptApplication = (Microsoft.Office.Interop.PowerPoint.Application)Activator.CreateInstance(
|
pptApplication = (Microsoft.Office.Interop.PowerPoint.Application)Activator.CreateInstance(
|
||||||
Marshal.GetTypeFromCLSID(new Guid("91493441-5A91-11CF-8700-00AA0060263B")));
|
Marshal.GetTypeFromCLSID(new Guid("91493441-5A91-11CF-8700-00AA0060263B")));
|
||||||
|
if (pptApplication != null)
|
||||||
|
LogHelper.WriteLogToFile("成功创建PowerPoint实例", LogHelper.LogType.Info);
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
LogHelper.WriteLogToFile($"创建PowerPoint实例失败: {ex.Message}", LogHelper.LogType.Error);
|
||||||
pptApplication = null;
|
pptApplication = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isPowerPointInitialized = true;
|
isPowerPointInitialized = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查进程是否还在
|
// 检查进程是否还在
|
||||||
var pptProcessesCheck = Process.GetProcessesByName("POWERPNT");
|
bool currentWpsRunning = IsWPSRunning(false); // 定期检查不输出日志
|
||||||
var wpsProcessesCheck = Process.GetProcessesByName("wpp");
|
var currentPptProcesses = Process.GetProcessesByName("POWERPNT");
|
||||||
bool isWpsMode = isWPSSupportOn && wpsProcessesCheck.Length > 0;
|
|
||||||
bool isPptMode = !isWPSSupportOn && pptProcessesCheck.Length > 0;
|
// 检测应用程序是否关闭
|
||||||
|
bool applicationClosed = isWPSMode ? !currentWpsRunning : currentPptProcesses.Length == 0;
|
||||||
|
|
||||||
if ((isWpsMode && wpsProcessesCheck.Length == 0) || (!isWpsMode && pptProcessesCheck.Length == 0))
|
if (applicationClosed)
|
||||||
{
|
{
|
||||||
// 进程已关闭,清理对象
|
LogHelper.WriteLogToFile($"{(isWPSMode ? "WPS" : "PowerPoint")}进程已关闭,清理对象", LogHelper.LogType.Info);
|
||||||
if (pptApplication != null)
|
|
||||||
{
|
// 进程已关闭,调用重置方法清理对象
|
||||||
try { Marshal.ReleaseComObject(pptApplication); } catch { }
|
ResetPresentationObjects();
|
||||||
pptApplication = null;
|
|
||||||
}
|
|
||||||
if (presentation != null)
|
|
||||||
{
|
|
||||||
try { Marshal.ReleaseComObject(presentation); } catch { }
|
|
||||||
presentation = null;
|
|
||||||
}
|
|
||||||
if (slides != null)
|
|
||||||
{
|
|
||||||
try { Marshal.ReleaseComObject(slides); } catch { }
|
|
||||||
slides = null;
|
|
||||||
}
|
|
||||||
slide = null;
|
|
||||||
isPowerPointInitialized = false;
|
isPowerPointInitialized = false;
|
||||||
|
|
||||||
// PowerPoint进程守护:自动重启PowerPoint进程(仅在未启用WPS支持时)
|
// PowerPoint进程守护:自动重启PowerPoint进程(仅在未启用WPS支持时)
|
||||||
if (!isWPSSupportOn)
|
if (!isWPSSupportOn && !isWPSMode)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
LogHelper.WriteLogToFile("尝试重启PowerPoint进程", LogHelper.LogType.Info);
|
||||||
pptApplication = (Microsoft.Office.Interop.PowerPoint.Application)Activator.CreateInstance(
|
pptApplication = (Microsoft.Office.Interop.PowerPoint.Application)Activator.CreateInstance(
|
||||||
Marshal.GetTypeFromCLSID(new Guid("91493441-5A91-11CF-8700-00AA0060263B")));
|
Marshal.GetTypeFromCLSID(new Guid("91493441-5A91-11CF-8700-00AA0060263B")));
|
||||||
isPowerPointInitialized = true;
|
isPowerPointInitialized = true;
|
||||||
|
LogHelper.WriteLogToFile("PowerPoint进程重启成功", LogHelper.LogType.Info);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile("PowerPoint 守护重启失败: " + ex.ToString(), LogHelper.LogType.Error);
|
LogHelper.WriteLogToFile($"PowerPoint守护重启失败: {ex.Message}", LogHelper.LogType.Error);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// 启用WPS支持时不守护PowerPoint进程
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +377,7 @@ namespace Ink_Canvas {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
|
LogHelper.WriteLogToFile($"TimerCheckPPT_Elapsed 异常: {ex.Message}", LogHelper.LogType.Error);
|
||||||
Application.Current.Dispatcher.Invoke(() => {
|
Application.Current.Dispatcher.Invoke(() => {
|
||||||
BtnPPTSlideShow.Visibility = Visibility.Collapsed;
|
BtnPPTSlideShow.Visibility = Visibility.Collapsed;
|
||||||
timerCheckPPT.Start();
|
timerCheckPPT.Start();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using iNKORE.UI.WPF.Modern.Controls;
|
using iNKORE.UI.WPF.Modern.Controls;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
@@ -17,6 +17,13 @@ namespace Ink_Canvas {
|
|||||||
private object lastBorderMouseDownObject;
|
private object lastBorderMouseDownObject;
|
||||||
|
|
||||||
private void Border_MouseDown(object sender, MouseButtonEventArgs e) {
|
private void Border_MouseDown(object sender, MouseButtonEventArgs e) {
|
||||||
|
// 如果发送者是 RandomDrawPanel 或 SingleDrawPanel,且它们被隐藏,则不处理事件
|
||||||
|
if (sender is SimpleStackPanel panel) {
|
||||||
|
if ((panel == RandomDrawPanel || panel == SingleDrawPanel) &&
|
||||||
|
panel.Visibility != Visibility.Visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
lastBorderMouseDownObject = sender;
|
lastBorderMouseDownObject = sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,6 +387,11 @@ namespace Ink_Canvas {
|
|||||||
isProgramChangeStrokeSelection = false;
|
isProgramChangeStrokeSelection = false;
|
||||||
inkCanvas.Strokes.Add(StrokesSelectionClone);
|
inkCanvas.Strokes.Add(StrokesSelectionClone);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// 新增:启动套索选择模式
|
||||||
|
inkCanvas.EditingMode = InkCanvasEditingMode.Select;
|
||||||
|
inkCanvas.Select(new StrokeCollection());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -694,6 +694,62 @@ namespace Ink_Canvas {
|
|||||||
SaveSettingsToFile();
|
SaveSettingsToFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ToggleSwitchEnablePressureTouchMode_Toggled(object sender, RoutedEventArgs e) {
|
||||||
|
if (!isLoaded) return;
|
||||||
|
|
||||||
|
Settings.Canvas.EnablePressureTouchMode = ToggleSwitchEnablePressureTouchMode.IsOn;
|
||||||
|
|
||||||
|
// 如果启用了压感触屏模式,则自动关闭屏蔽压感
|
||||||
|
if (Settings.Canvas.EnablePressureTouchMode && Settings.Canvas.DisablePressure) {
|
||||||
|
Settings.Canvas.DisablePressure = false;
|
||||||
|
ToggleSwitchDisablePressure.IsOn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveSettingsToFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ToggleSwitchDisablePressure_Toggled(object sender, RoutedEventArgs e) {
|
||||||
|
if (!isLoaded) return;
|
||||||
|
|
||||||
|
Settings.Canvas.DisablePressure = ToggleSwitchDisablePressure.IsOn;
|
||||||
|
|
||||||
|
// 如果启用了屏蔽压感,则自动关闭压感触屏模式
|
||||||
|
if (Settings.Canvas.DisablePressure && Settings.Canvas.EnablePressureTouchMode) {
|
||||||
|
Settings.Canvas.EnablePressureTouchMode = false;
|
||||||
|
ToggleSwitchEnablePressureTouchMode.IsOn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveSettingsToFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ToggleSwitchAutoStraightenLine_Toggled(object sender, RoutedEventArgs e) {
|
||||||
|
if (!isLoaded) return;
|
||||||
|
|
||||||
|
Settings.Canvas.AutoStraightenLine = ToggleSwitchAutoStraightenLine.IsOn;
|
||||||
|
SaveSettingsToFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AutoStraightenLineThresholdSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) {
|
||||||
|
if (!isLoaded) return;
|
||||||
|
|
||||||
|
Settings.Canvas.AutoStraightenLineThreshold = (int)e.NewValue;
|
||||||
|
SaveSettingsToFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ToggleSwitchLineEndpointSnapping_Toggled(object sender, RoutedEventArgs e) {
|
||||||
|
if (!isLoaded) return;
|
||||||
|
|
||||||
|
Settings.Canvas.LineEndpointSnapping = ToggleSwitchLineEndpointSnapping.IsOn;
|
||||||
|
SaveSettingsToFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LineEndpointSnappingThresholdSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) {
|
||||||
|
if (!isLoaded) return;
|
||||||
|
|
||||||
|
Settings.Canvas.LineEndpointSnappingThreshold = (int)e.NewValue;
|
||||||
|
SaveSettingsToFile();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Canvas
|
#region Canvas
|
||||||
@@ -1412,7 +1468,7 @@ namespace Ink_Canvas {
|
|||||||
Settings.Automation.IsAutoKillVComYouJiao = false;
|
Settings.Automation.IsAutoKillVComYouJiao = false;
|
||||||
Settings.Automation.IsAutoKillInkCanvas = false;
|
Settings.Automation.IsAutoKillInkCanvas = false;
|
||||||
Settings.Automation.IsAutoKillICA = false;
|
Settings.Automation.IsAutoKillICA = false;
|
||||||
Settings.Automation.IsAutoKillIDT = true;
|
Settings.Automation.IsAutoKillIDT = false;
|
||||||
Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation = false;
|
Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation = false;
|
||||||
Settings.Automation.IsSaveScreenshotsInDateFolders = false;
|
Settings.Automation.IsSaveScreenshotsInDateFolders = false;
|
||||||
Settings.Automation.IsAutoSaveStrokesAtScreenshot = true;
|
Settings.Automation.IsAutoSaveStrokesAtScreenshot = true;
|
||||||
@@ -1447,6 +1503,12 @@ namespace Ink_Canvas {
|
|||||||
Settings.Canvas.HideStrokeWhenSelecting = false;
|
Settings.Canvas.HideStrokeWhenSelecting = false;
|
||||||
Settings.Canvas.ClearCanvasAndClearTimeMachine = false;
|
Settings.Canvas.ClearCanvasAndClearTimeMachine = false;
|
||||||
Settings.Canvas.FitToCurve = true;
|
Settings.Canvas.FitToCurve = true;
|
||||||
|
Settings.Canvas.EnablePressureTouchMode = false;
|
||||||
|
Settings.Canvas.DisablePressure = false;
|
||||||
|
Settings.Canvas.AutoStraightenLine = true;
|
||||||
|
Settings.Canvas.AutoStraightenLineThreshold = 30;
|
||||||
|
Settings.Canvas.LineEndpointSnapping = true;
|
||||||
|
Settings.Canvas.LineEndpointSnappingThreshold = 15;
|
||||||
Settings.Canvas.UsingWhiteboard = false;
|
Settings.Canvas.UsingWhiteboard = false;
|
||||||
Settings.Canvas.HyperbolaAsymptoteOption = 0;
|
Settings.Canvas.HyperbolaAsymptoteOption = 0;
|
||||||
|
|
||||||
@@ -1690,6 +1752,21 @@ namespace Ink_Canvas {
|
|||||||
SaveSettingsToFile();
|
SaveSettingsToFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ToggleSwitchShowRandomAndSingleDraw_Toggled(object sender, RoutedEventArgs e) {
|
||||||
|
if (!isLoaded) return;
|
||||||
|
|
||||||
|
// 获取开关状态并保存到设置中
|
||||||
|
bool isToggled = ToggleSwitchShowRandomAndSingleDraw.IsOn;
|
||||||
|
Settings.RandSettings.ShowRandomAndSingleDraw = isToggled;
|
||||||
|
|
||||||
|
// 更新UI显示
|
||||||
|
RandomDrawPanel.Visibility = isToggled ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
SingleDrawPanel.Visibility = isToggled ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
|
||||||
|
// 保存设置到文件
|
||||||
|
SaveSettingsToFile();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public static void SaveSettingsToFile() {
|
public static void SaveSettingsToFile() {
|
||||||
|
|||||||
@@ -434,6 +434,12 @@ namespace Ink_Canvas {
|
|||||||
inkCanvas.ForceCursor = false;
|
inkCanvas.ForceCursor = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化压感触屏模式开关状态
|
||||||
|
ToggleSwitchEnablePressureTouchMode.IsOn = Settings.Canvas.EnablePressureTouchMode;
|
||||||
|
|
||||||
|
// 初始化屏蔽压感开关状态
|
||||||
|
ToggleSwitchDisablePressure.IsOn = Settings.Canvas.DisablePressure;
|
||||||
|
|
||||||
ComboBoxPenStyle.SelectedIndex = Settings.Canvas.InkStyle;
|
ComboBoxPenStyle.SelectedIndex = Settings.Canvas.InkStyle;
|
||||||
BoardComboBoxPenStyle.SelectedIndex = Settings.Canvas.InkStyle;
|
BoardComboBoxPenStyle.SelectedIndex = Settings.Canvas.InkStyle;
|
||||||
|
|
||||||
@@ -500,6 +506,14 @@ namespace Ink_Canvas {
|
|||||||
ToggleSwitchFitToCurve.IsOn = false;
|
ToggleSwitchFitToCurve.IsOn = false;
|
||||||
drawingAttributes.FitToCurve = false;
|
drawingAttributes.FitToCurve = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化直线自动拉直相关设置
|
||||||
|
ToggleSwitchAutoStraightenLine.IsOn = Settings.Canvas.AutoStraightenLine;
|
||||||
|
AutoStraightenLineThresholdSlider.Value = Settings.Canvas.AutoStraightenLineThreshold;
|
||||||
|
|
||||||
|
// 初始化直线端点吸附相关设置
|
||||||
|
ToggleSwitchLineEndpointSnapping.IsOn = Settings.Canvas.LineEndpointSnapping;
|
||||||
|
LineEndpointSnappingThresholdSlider.Value = Settings.Canvas.LineEndpointSnappingThreshold;
|
||||||
} else {
|
} else {
|
||||||
Settings.Canvas = new Canvas();
|
Settings.Canvas = new Canvas();
|
||||||
}
|
}
|
||||||
@@ -569,7 +583,14 @@ namespace Ink_Canvas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RandSettings
|
// RandSettings
|
||||||
if (Settings.RandSettings != null) { } else {
|
if (Settings.RandSettings != null) {
|
||||||
|
ToggleSwitchDisplayRandWindowNamesInputBtn.IsOn = Settings.RandSettings.DisplayRandWindowNamesInputBtn;
|
||||||
|
RandWindowOnceCloseLatencySlider.Value = Settings.RandSettings.RandWindowOnceCloseLatency;
|
||||||
|
RandWindowOnceMaxStudentsSlider.Value = Settings.RandSettings.RandWindowOnceMaxStudents;
|
||||||
|
ToggleSwitchShowRandomAndSingleDraw.IsOn = Settings.RandSettings.ShowRandomAndSingleDraw;
|
||||||
|
RandomDrawPanel.Visibility = Settings.RandSettings.ShowRandomAndSingleDraw ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
SingleDrawPanel.Visibility = Settings.RandSettings.ShowRandomAndSingleDraw ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
} else {
|
||||||
Settings.RandSettings = new RandSettings();
|
Settings.RandSettings = new RandSettings();
|
||||||
ToggleSwitchDisplayRandWindowNamesInputBtn.IsOn = Settings.RandSettings.DisplayRandWindowNamesInputBtn;
|
ToggleSwitchDisplayRandWindowNamesInputBtn.IsOn = Settings.RandSettings.DisplayRandWindowNamesInputBtn;
|
||||||
RandWindowOnceCloseLatencySlider.Value = Settings.RandSettings.RandWindowOnceCloseLatency;
|
RandWindowOnceCloseLatencySlider.Value = Settings.RandSettings.RandWindowOnceCloseLatency;
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ namespace Ink_Canvas {
|
|||||||
#endregion Floating Bar Control
|
#endregion Floating Bar Control
|
||||||
|
|
||||||
private int drawingShapeMode = 0;
|
private int drawingShapeMode = 0;
|
||||||
private bool isLongPressSelected = false; // 用于存是否是“选中”状态,便于后期抬笔后不做切换到笔的处理
|
private bool isLongPressSelected = false; // 用于存是否是"选中"状态,便于后期抬笔后不做切换到笔的处理
|
||||||
|
|
||||||
#region Buttons
|
#region Buttons
|
||||||
|
|
||||||
@@ -429,6 +429,8 @@ namespace Ink_Canvas {
|
|||||||
|
|
||||||
private void inkCanvas_TouchMove(object sender, TouchEventArgs e) {
|
private void inkCanvas_TouchMove(object sender, TouchEventArgs e) {
|
||||||
if (isSingleFingerDragMode) return;
|
if (isSingleFingerDragMode) return;
|
||||||
|
|
||||||
|
// 处理形状绘制模式
|
||||||
if (drawingShapeMode != 0) {
|
if (drawingShapeMode != 0) {
|
||||||
if (isLastTouchEraser) return;
|
if (isLastTouchEraser) return;
|
||||||
//EraserContainer.Background = null;
|
//EraserContainer.Background = null;
|
||||||
@@ -443,15 +445,75 @@ namespace Ink_Canvas {
|
|||||||
catch {
|
catch {
|
||||||
Trace.WriteLine("lastTempStrokeCollection failed.");
|
Trace.WriteLine("lastTempStrokeCollection failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inkCanvas.EditingMode != InkCanvasEditingMode.None)
|
|
||||||
inkCanvas.EditingMode = InkCanvasEditingMode.None;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseTouchMove(e.GetTouchPoint(inkCanvas).Position);
|
// 触摸移动时保持自定义光标显示
|
||||||
|
if (Settings.Canvas.IsShowCursor) {
|
||||||
|
inkCanvas.ForceCursor = true;
|
||||||
|
System.Windows.Forms.Cursor.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NeedUpdateIniP()) iniP = e.GetTouchPoint(inkCanvas).Position;
|
||||||
|
if (drawingShapeMode == 9 && isFirstTouchCuboid == false) MouseTouchMove(iniP);
|
||||||
|
inkCanvas.Opacity = 1;
|
||||||
|
double boundsWidth = GetTouchBoundWidth(e), eraserMultiplier = 1.0;
|
||||||
|
if (!Settings.Advanced.EraserBindTouchMultiplier && Settings.Advanced.IsSpecialScreen)
|
||||||
|
eraserMultiplier = 1 / Settings.Advanced.TouchMultiplier;
|
||||||
|
if (boundsWidth > BoundsWidth) {
|
||||||
|
isLastTouchEraser = true;
|
||||||
|
if (drawingShapeMode == 0 && forceEraser) return;
|
||||||
|
if (boundsWidth > BoundsWidth * 2.5) {
|
||||||
|
double k = 1;
|
||||||
|
switch (Settings.Canvas.EraserSize) {
|
||||||
|
case 0:
|
||||||
|
k = 0.5;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
k = 0.8;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
k = 1.25;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
k = 1.8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
inkCanvas.EraserShape = new EllipseStylusShape(boundsWidth * k * eraserMultiplier,
|
||||||
|
boundsWidth * k * eraserMultiplier);
|
||||||
|
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (StackPanelPPTControls.Visibility == Visibility.Visible && inkCanvas.Strokes.Count == 0 &&
|
||||||
|
Settings.PowerPointSettings.IsEnableFingerGestureSlideShowControl) {
|
||||||
|
isLastTouchEraser = false;
|
||||||
|
inkCanvas.EditingMode = InkCanvasEditingMode.GestureOnly;
|
||||||
|
inkCanvas.Opacity = 0.1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
inkCanvas.EraserShape = new EllipseStylusShape(5, 5);
|
||||||
|
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isLastTouchEraser = false;
|
||||||
|
// 修复面积擦时不显示橡皮形状:无论 forcePointEraser 状态,均显示 50x50 橡皮
|
||||||
|
inkCanvas.EraserShape = new EllipseStylusShape(50, 50);
|
||||||
|
if (forceEraser) return;
|
||||||
|
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inkCanvas.EditingMode != InkCanvasEditingMode.None)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (e.TouchDevice == null) {
|
||||||
|
System.Windows.Forms.Cursor.Show();
|
||||||
|
} else {
|
||||||
|
System.Windows.Forms.Cursor.Hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int drawMultiStepShapeCurrentStep = 0; //多笔完成的图形 当前所处在的笔画
|
private int drawMultiStepShapeCurrentStep = 0; //多笔完成的图形 当前所处在的笔画
|
||||||
|
|||||||
@@ -19,7 +19,109 @@ namespace Ink_Canvas {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
inkCanvas.Opacity = 1;
|
inkCanvas.Opacity = 1;
|
||||||
if (Settings.InkToShape.IsInkToShapeEnabled && !Environment.Is64BitProcess) {
|
|
||||||
|
// 直线自动拉直功能
|
||||||
|
if (Settings.Canvas.AutoStraightenLine && e.Stroke.StylusPoints.Count > 1 && drawingShapeMode == 0 && penType == 0) {
|
||||||
|
// 获取起点和终点
|
||||||
|
StylusPoint startPoint = e.Stroke.StylusPoints[0];
|
||||||
|
StylusPoint endPoint = e.Stroke.StylusPoints[e.Stroke.StylusPoints.Count - 1];
|
||||||
|
|
||||||
|
// 计算直线长度
|
||||||
|
double length = Math.Sqrt(Math.Pow(endPoint.X - startPoint.X, 2) + Math.Pow(endPoint.Y - startPoint.Y, 2));
|
||||||
|
|
||||||
|
// 判断是否需要拉直
|
||||||
|
if (length >= Settings.Canvas.AutoStraightenLineThreshold) {
|
||||||
|
// 判断是否符合直线特征(计算点到直线的最大距离)
|
||||||
|
double maxDistance = 0;
|
||||||
|
for (int i = 1; i < e.Stroke.StylusPoints.Count - 1; i++) {
|
||||||
|
StylusPoint point = e.Stroke.StylusPoints[i];
|
||||||
|
double distance = DistanceFromPointToLine(point, startPoint, endPoint);
|
||||||
|
maxDistance = Math.Max(maxDistance, distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果最大距离小于线长的15%,认为是直线
|
||||||
|
if (maxDistance < length * 0.15) {
|
||||||
|
// 创建新的直线点集合
|
||||||
|
StylusPointCollection newPoints = new StylusPointCollection();
|
||||||
|
|
||||||
|
// 直线端点吸附功能
|
||||||
|
if (Settings.Canvas.LineEndpointSnapping) {
|
||||||
|
bool startPointSnapped = false;
|
||||||
|
bool endPointSnapped = false;
|
||||||
|
|
||||||
|
// 获取画布上的所有笔画
|
||||||
|
StrokeCollection allStrokes = inkCanvas.Strokes;
|
||||||
|
|
||||||
|
// 排除当前笔画
|
||||||
|
StrokeCollection otherStrokes = new StrokeCollection();
|
||||||
|
foreach (Stroke stroke in allStrokes) {
|
||||||
|
if (stroke != e.Stroke) {
|
||||||
|
otherStrokes.Add(stroke);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找最近的端点
|
||||||
|
double minStartDistance = Settings.Canvas.LineEndpointSnappingThreshold;
|
||||||
|
double minEndDistance = Settings.Canvas.LineEndpointSnappingThreshold;
|
||||||
|
StylusPoint nearestToStart = startPoint;
|
||||||
|
StylusPoint nearestToEnd = endPoint;
|
||||||
|
|
||||||
|
foreach (Stroke stroke in otherStrokes) {
|
||||||
|
// 只考虑直线(只有两个点的笔画)
|
||||||
|
if (stroke.StylusPoints.Count == 2) {
|
||||||
|
StylusPoint strokeStart = stroke.StylusPoints[0];
|
||||||
|
StylusPoint strokeEnd = stroke.StylusPoints[1];
|
||||||
|
|
||||||
|
// 计算当前笔画起点到其他笔画端点的距离
|
||||||
|
double distanceToStrokeStart = Distance(startPoint, strokeStart);
|
||||||
|
double distanceToStrokeEnd = Distance(startPoint, strokeEnd);
|
||||||
|
|
||||||
|
// 如果距离小于阈值且小于当前最小距离,更新最近点
|
||||||
|
if (distanceToStrokeStart < minStartDistance) {
|
||||||
|
minStartDistance = distanceToStrokeStart;
|
||||||
|
nearestToStart = strokeStart;
|
||||||
|
startPointSnapped = true;
|
||||||
|
}
|
||||||
|
if (distanceToStrokeEnd < minStartDistance) {
|
||||||
|
minStartDistance = distanceToStrokeEnd;
|
||||||
|
nearestToStart = strokeEnd;
|
||||||
|
startPointSnapped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算当前笔画终点到其他笔画端点的距离
|
||||||
|
double distanceEndToStrokeStart = Distance(endPoint, strokeStart);
|
||||||
|
double distanceEndToStrokeEnd = Distance(endPoint, strokeEnd);
|
||||||
|
|
||||||
|
// 如果距离小于阈值且小于当前最小距离,更新最近点
|
||||||
|
if (distanceEndToStrokeStart < minEndDistance) {
|
||||||
|
minEndDistance = distanceEndToStrokeStart;
|
||||||
|
nearestToEnd = strokeStart;
|
||||||
|
endPointSnapped = true;
|
||||||
|
}
|
||||||
|
if (distanceEndToStrokeEnd < minEndDistance) {
|
||||||
|
minEndDistance = distanceEndToStrokeEnd;
|
||||||
|
nearestToEnd = strokeEnd;
|
||||||
|
endPointSnapped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 应用吸附结果
|
||||||
|
newPoints.Add(startPointSnapped ? nearestToStart : startPoint);
|
||||||
|
newPoints.Add(endPointSnapped ? nearestToEnd : endPoint);
|
||||||
|
} else {
|
||||||
|
// 不启用吸附,直接使用原始端点
|
||||||
|
newPoints.Add(startPoint);
|
||||||
|
newPoints.Add(endPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 替换原有笔迹
|
||||||
|
e.Stroke.StylusPoints = newPoints;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Settings.InkToShape.IsInkToShapeEnabled && drawingShapeMode == 0 && !isInMultiTouchMode && penType == 0) {
|
||||||
void InkToShapeProcess() {
|
void InkToShapeProcess() {
|
||||||
try {
|
try {
|
||||||
newStrokes.Add(e.Stroke);
|
newStrokes.Add(e.Stroke);
|
||||||
@@ -320,13 +422,27 @@ namespace Ink_Canvas {
|
|||||||
InkToShapeProcess();
|
InkToShapeProcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var stylusPoint in e.Stroke.StylusPoints)
|
// 如果启用了屏蔽压感功能,强制所有点的压感值为0.5
|
||||||
//LogHelper.WriteLogToFile(stylusPoint.PressureFactor.ToString(), LogHelper.LogType.Info);
|
if (Settings.Canvas.DisablePressure) {
|
||||||
// 检查是否是压感笔书写
|
var stylusPoints = new StylusPointCollection();
|
||||||
//if (stylusPoint.PressureFactor != 0.5 && stylusPoint.PressureFactor != 0)
|
foreach (var point in e.Stroke.StylusPoints) {
|
||||||
if ((stylusPoint.PressureFactor > 0.501 || stylusPoint.PressureFactor < 0.5) &&
|
var newPoint = new StylusPoint(point.X, point.Y, 0.5f);
|
||||||
stylusPoint.PressureFactor != 0)
|
stylusPoints.Add(newPoint);
|
||||||
return;
|
}
|
||||||
|
e.Stroke.StylusPoints = stylusPoints;
|
||||||
|
return; // 跳过后续的压感处理
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否是压感笔书写,如果启用了压感触屏模式则跳过此检查
|
||||||
|
if (!Settings.Canvas.EnablePressureTouchMode) {
|
||||||
|
foreach (var stylusPoint in e.Stroke.StylusPoints)
|
||||||
|
//LogHelper.WriteLogToFile(stylusPoint.PressureFactor.ToString(), LogHelper.LogType.Info);
|
||||||
|
// 检查是否是压感笔书写
|
||||||
|
//if (stylusPoint.PressureFactor != 0.5 && stylusPoint.PressureFactor != 0)
|
||||||
|
if ((stylusPoint.PressureFactor > 0.501 || stylusPoint.PressureFactor < 0.5) &&
|
||||||
|
stylusPoint.PressureFactor != 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (e.Stroke.StylusPoints.Count > 3) {
|
if (e.Stroke.StylusPoints.Count > 3) {
|
||||||
@@ -540,5 +656,31 @@ namespace Ink_Canvas {
|
|||||||
public StylusPoint GetCenterPoint(StylusPoint point1, StylusPoint point2) {
|
public StylusPoint GetCenterPoint(StylusPoint point1, StylusPoint point2) {
|
||||||
return new StylusPoint((point1.X + point2.X) / 2, (point1.Y + point2.Y) / 2);
|
return new StylusPoint((point1.X + point2.X) / 2, (point1.Y + point2.Y) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计算点到直线的距离
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="point">点</param>
|
||||||
|
/// <param name="lineStart">直线起点</param>
|
||||||
|
/// <param name="lineEnd">直线终点</param>
|
||||||
|
/// <returns>距离</returns>
|
||||||
|
private double DistanceFromPointToLine(StylusPoint point, StylusPoint lineStart, StylusPoint lineEnd) {
|
||||||
|
double lineLength = Math.Sqrt(Math.Pow(lineEnd.X - lineStart.X, 2) + Math.Pow(lineEnd.Y - lineStart.Y, 2));
|
||||||
|
if (lineLength == 0) return 0;
|
||||||
|
|
||||||
|
double area = Math.Abs(
|
||||||
|
(lineEnd.X - lineStart.X) * (lineStart.Y - point.Y) -
|
||||||
|
(lineStart.X - point.X) * (lineEnd.Y - lineStart.Y)
|
||||||
|
);
|
||||||
|
|
||||||
|
return area / lineLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计算两点之间的距离
|
||||||
|
/// </summary>
|
||||||
|
private double Distance(StylusPoint p1, StylusPoint p2) {
|
||||||
|
return Math.Sqrt(Math.Pow(p2.X - p1.X, 2) + Math.Pow(p2.Y - p1.Y, 2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,6 +183,11 @@ namespace Ink_Canvas {
|
|||||||
private bool forcePointEraser = true;
|
private bool forcePointEraser = true;
|
||||||
|
|
||||||
private void Main_Grid_TouchDown(object sender, TouchEventArgs e) {
|
private void Main_Grid_TouchDown(object sender, TouchEventArgs e) {
|
||||||
|
// 确保触摸时显示自定义光标
|
||||||
|
if (Settings.Canvas.IsShowCursor) {
|
||||||
|
inkCanvas.ForceCursor = true;
|
||||||
|
System.Windows.Forms.Cursor.Show();
|
||||||
|
}
|
||||||
|
|
||||||
inkCanvas.CaptureTouch(e.TouchDevice);
|
inkCanvas.CaptureTouch(e.TouchDevice);
|
||||||
ViewboxFloatingBar.IsHitTestVisible = false;
|
ViewboxFloatingBar.IsHitTestVisible = false;
|
||||||
|
|||||||
@@ -63,7 +63,11 @@ namespace Ink_Canvas
|
|||||||
|
|
||||||
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)Application.Current.MainWindow;
|
||||||
if (mainWin.IsLoaded) mainWin.BtnRestart_Click(null,null);
|
if (mainWin.IsLoaded) {
|
||||||
|
App.IsAppExitByUser = true;
|
||||||
|
Application.Current.Shutdown();
|
||||||
|
// mainWin.BtnExit_Click(null,null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ForceFullScreenTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) {
|
private void ForceFullScreenTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) {
|
||||||
|
|||||||
@@ -48,6 +48,18 @@ namespace Ink_Canvas
|
|||||||
public bool FitToCurve { get; set; } = true;
|
public bool FitToCurve { get; set; } = true;
|
||||||
[JsonProperty("clearCanvasAndClearTimeMachine")]
|
[JsonProperty("clearCanvasAndClearTimeMachine")]
|
||||||
public bool ClearCanvasAndClearTimeMachine { get; set; } = false;
|
public bool ClearCanvasAndClearTimeMachine { get; set; } = false;
|
||||||
|
[JsonProperty("enablePressureTouchMode")]
|
||||||
|
public bool EnablePressureTouchMode { get; set; } = false; // 是否启用压感触屏模式
|
||||||
|
[JsonProperty("disablePressure")]
|
||||||
|
public bool DisablePressure { get; set; } = false; // 是否屏蔽压感
|
||||||
|
[JsonProperty("autoStraightenLine")]
|
||||||
|
public bool AutoStraightenLine { get; set; } = true; // 是否启用直线自动拉直
|
||||||
|
[JsonProperty("autoStraightenLineThreshold")]
|
||||||
|
public int AutoStraightenLineThreshold { get; set; } = 30; // 直线自动拉直的长度阈值(像素)
|
||||||
|
[JsonProperty("lineEndpointSnapping")]
|
||||||
|
public bool LineEndpointSnapping { get; set; } = true; // 是否启用直线端点吸附
|
||||||
|
[JsonProperty("lineEndpointSnappingThreshold")]
|
||||||
|
public int LineEndpointSnappingThreshold { get; set; } = 15; // 直线端点吸附的距离阈值(像素)
|
||||||
|
|
||||||
[JsonProperty("usingWhiteboard")]
|
[JsonProperty("usingWhiteboard")]
|
||||||
public bool UsingWhiteboard { get; set; }
|
public bool UsingWhiteboard { get; set; }
|
||||||
@@ -308,7 +320,7 @@ namespace Ink_Canvas
|
|||||||
public bool IsAutoKillICA { get; set; } = false;
|
public bool IsAutoKillICA { get; set; } = false;
|
||||||
|
|
||||||
[JsonProperty("isAutoKillIDT")]
|
[JsonProperty("isAutoKillIDT")]
|
||||||
public bool IsAutoKillIDT { get; set; } = true;
|
public bool IsAutoKillIDT { get; set; } = false;
|
||||||
|
|
||||||
[JsonProperty("isSaveScreenshotsInDateFolders")]
|
[JsonProperty("isSaveScreenshotsInDateFolders")]
|
||||||
public bool IsSaveScreenshotsInDateFolders { get; set; } = false;
|
public bool IsSaveScreenshotsInDateFolders { get; set; } = false;
|
||||||
@@ -406,5 +418,7 @@ namespace Ink_Canvas
|
|||||||
public double RandWindowOnceCloseLatency { get; set; } = 2.5;
|
public double RandWindowOnceCloseLatency { get; set; } = 2.5;
|
||||||
[JsonProperty("randWindowOnceMaxStudents")]
|
[JsonProperty("randWindowOnceMaxStudents")]
|
||||||
public int RandWindowOnceMaxStudents { get; set; } = 10;
|
public int RandWindowOnceMaxStudents { get; set; } = 10;
|
||||||
|
[JsonProperty("showRandomAndSingleDraw")]
|
||||||
|
public bool ShowRandomAndSingleDraw { get; set; } = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
+3200
-3063
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
|||||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
||||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\Administrator\.nuget\packages\;E:\Program Files\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
|
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\Administrator\.nuget\packages\;E:\Program Files\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
|
||||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.13.2</NuGetToolVersion>
|
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.14.0</NuGetToolVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||||
<SourceRoot Include="C:\Users\Administrator\.nuget\packages\" />
|
<SourceRoot Include="C:\Users\Administrator\.nuget\packages\" />
|
||||||
|
|||||||
Reference in New Issue
Block a user