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 iNKORE.UI.WPF.Modern.Controls;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using Microsoft.Win32;
|
||||
using System.Security; // 添加SecurityException所需命名空间
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
|
||||
using MessageBox = System.Windows.MessageBox;
|
||||
using Window = System.Windows.Window;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
@@ -49,12 +53,11 @@ namespace Ink_Canvas
|
||||
LogHelper.NewLog(e.Exception.ToString());
|
||||
e.Handled = true;
|
||||
|
||||
// 新增:根据设置自动处理崩溃
|
||||
if (CrashAction == CrashActionType.SilentRestart)
|
||||
// 修改:仅当非用户主动退出时才触发自动重启
|
||||
if (CrashAction == CrashActionType.SilentRestart && !IsAppExitByUser)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 静默重启:启动新进程并退出当前进程
|
||||
string exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
|
||||
System.Diagnostics.Process.Start(exePath);
|
||||
}
|
||||
@@ -87,6 +90,127 @@ namespace Ink_Canvas
|
||||
_taskbar = (TaskbarIcon)FindResource("TaskbarTrayIcon");
|
||||
|
||||
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)
|
||||
@@ -208,5 +332,450 @@ namespace Ink_Canvas
|
||||
}
|
||||
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")]
|
||||
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)]
|
||||
public struct RECT {
|
||||
public int Left;
|
||||
@@ -34,6 +72,72 @@ namespace Ink_Canvas.Helpers
|
||||
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() {
|
||||
IntPtr foregroundWindowHandle = GetForegroundWindow();
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
<ui:SimpleStackPanel VerticalAlignment="Center">
|
||||
<TextBlock Foreground="#fafafa" HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" FontSize="15" Margin="0,0,0,10"
|
||||
Text="开发中..." />
|
||||
Text="开发中...请不要点击,可能会导致ICC异常崩溃" />
|
||||
<ui:SimpleStackPanel Spacing="5">
|
||||
<ui:SimpleStackPanel Spacing="5" Orientation="Horizontal"
|
||||
HorizontalAlignment="Center">
|
||||
@@ -377,6 +377,23 @@
|
||||
IsOn="True" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
||||
Toggled="ToggleSwitchShowCursor_Toggled" />
|
||||
</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">
|
||||
<TextBlock Foreground="#fafafa" Text="橡皮大小" VerticalAlignment="Center"
|
||||
FontSize="14" Margin="0,0,16,0" />
|
||||
@@ -553,7 +570,46 @@
|
||||
</CheckBox>
|
||||
</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>
|
||||
</GroupBox>
|
||||
<GroupBox Name="GroupBoxAppearanceNewUI">
|
||||
@@ -1965,6 +2021,15 @@
|
||||
FontWeight="Bold"
|
||||
Toggled="ToggleSwitchDisplayRandWindowNamesInputBtn_OnToggled" />
|
||||
</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"
|
||||
Stroke="#3f3f46" StrokeThickness="1" Margin="0,4,0,4" />
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||
@@ -2381,7 +2446,7 @@
|
||||
<Grid Name="GridTransparencyFakeBackground" Opacity="0" />
|
||||
<Label Name="Label" Visibility="Collapsed" Foreground="Gray" Content="0" />
|
||||
<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"
|
||||
TouchMove="inkCanvas_TouchMove"
|
||||
ManipulationDelta="Main_Grid_ManipulationDelta"
|
||||
@@ -4386,7 +4451,7 @@
|
||||
<Label Content="计时器" FontSize="8"
|
||||
HorizontalAlignment="Center" />
|
||||
</ui:SimpleStackPanel>
|
||||
<ui:SimpleStackPanel MouseDown="Border_MouseDown"
|
||||
<ui:SimpleStackPanel x:Name="RandomDrawPanel" Visibility="Collapsed" MouseDown="Border_MouseDown"
|
||||
MouseUp="SymbolIconRand_MouseUp"
|
||||
Margin="0,0,0,0" Height="38" Width="32"
|
||||
Orientation="Vertical">
|
||||
@@ -4406,7 +4471,7 @@
|
||||
<Label Content="随机抽" FontSize="8"
|
||||
HorizontalAlignment="Center" />
|
||||
</ui:SimpleStackPanel>
|
||||
<ui:SimpleStackPanel MouseDown="Border_MouseDown"
|
||||
<ui:SimpleStackPanel x:Name="SingleDrawPanel" Visibility="Collapsed" MouseDown="Border_MouseDown"
|
||||
MouseUp="SymbolIconRandOne_MouseUp"
|
||||
Margin="0,0,0,0" Height="38" Width="32"
|
||||
Orientation="Vertical">
|
||||
|
||||
@@ -154,16 +154,24 @@ namespace Ink_Canvas {
|
||||
private void inkCanvas_EditingModeChanged(object sender, RoutedEventArgs e) {
|
||||
var inkCanvas1 = sender as InkCanvas;
|
||||
if (inkCanvas1 == null) return;
|
||||
// 修复“显示画笔光标”选项不可用的问题
|
||||
// 修复"显示画笔光标"选项不可用的问题
|
||||
if (Settings.Canvas.IsShowCursor) {
|
||||
inkCanvas1.UseCustomCursor = true;
|
||||
// 修复触屏和数位笔时光标不显示:只要有输入设备悬停、捕获,或有任何Stylus设备连接就显示
|
||||
if ((inkCanvas1.EditingMode == InkCanvasEditingMode.Ink || drawingShapeMode != 0)
|
||||
&& (inkCanvas1.IsStylusDirectlyOver || inkCanvas1.IsMouseDirectlyOver || inkCanvas1.IsStylusCaptured || inkCanvas1.IsMouseCaptured
|
||||
|| Stylus.CurrentStylusDevice != null))
|
||||
inkCanvas1.ForceCursor = true;
|
||||
else
|
||||
inkCanvas1.ForceCursor = false;
|
||||
// 修复触屏和数位笔时光标不显示:强制显示光标,不再依赖鼠标或触控状态
|
||||
inkCanvas1.ForceCursor = true;
|
||||
|
||||
// 根据编辑模式设置不同的光标
|
||||
if (inkCanvas1.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
var sri = Application.GetResourceStream(new Uri("Resources/Cursors/Eraser.cur", UriKind.Relative));
|
||||
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 {
|
||||
inkCanvas1.UseCustomCursor = false;
|
||||
inkCanvas1.ForceCursor = false;
|
||||
@@ -292,8 +300,8 @@ namespace Ink_Canvas {
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
|
||||
|
||||
private void MainWindow_OnSizeChanged(object sender, SizeChangedEventArgs e) {
|
||||
|
||||
private void MainWindow_OnSizeChanged(object sender, SizeChangedEventArgs e) {
|
||||
if (Settings.Advanced.IsEnableForceFullScreen) {
|
||||
if (isLoaded) ShowNotification(
|
||||
$"检测到窗口大小变化,已自动恢复到全屏:{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width}x{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height}(缩放比例为{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth}x{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height / SystemParameters.PrimaryScreenHeight})");
|
||||
@@ -361,16 +369,38 @@ namespace Ink_Canvas {
|
||||
inkCanvas.Cursor = new Cursor(sri.Stream);
|
||||
}
|
||||
|
||||
// 触摸输入,通常隐藏光标
|
||||
// 触摸输入,不隐藏光标
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
||||
@@ -740,9 +740,11 @@ namespace Ink_Canvas {
|
||||
}
|
||||
|
||||
private void SymbolIconRand_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
// 如果控件被隐藏,不处理事件
|
||||
if (RandomDrawPanel.Visibility != Visibility.Visible) return;
|
||||
|
||||
LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
||||
RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
||||
//if (lastBorderMouseDownObject != sender) return;
|
||||
|
||||
AnimationsHelper.HideWithSlideAndFade(BorderTools);
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
|
||||
@@ -808,14 +810,16 @@ namespace Ink_Canvas {
|
||||
}
|
||||
|
||||
private void SymbolIconRandOne_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
// 如果控件被隐藏,不处理事件
|
||||
if (SingleDrawPanel.Visibility != Visibility.Visible) return;
|
||||
|
||||
LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
||||
RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
|
||||
//if (lastBorderMouseDownObject != sender) return;
|
||||
|
||||
AnimationsHelper.HideWithSlideAndFade(BorderTools);
|
||||
AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
|
||||
|
||||
new RandWindow(Settings,true).ShowDialog();
|
||||
new RandWindow(Settings, true).ShowDialog();
|
||||
}
|
||||
|
||||
private void GridInkReplayButton_MouseUp(object sender, MouseButtonEventArgs e) {
|
||||
@@ -1074,15 +1078,38 @@ namespace Ink_Canvas {
|
||||
var windowHandle = new WindowInteropHelper(this).Handle;
|
||||
var screen = System.Windows.Forms.Screen.FromHandle(windowHandle);
|
||||
double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY;
|
||||
var toolbarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.FullPrimaryScreenHeight -
|
||||
SystemParameters.WindowCaptionHeight;
|
||||
// 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响
|
||||
var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY);
|
||||
pos.X = (screenWidth - ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX) / 2;
|
||||
|
||||
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)
|
||||
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 (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) {
|
||||
@@ -1137,12 +1164,22 @@ namespace Ink_Canvas {
|
||||
var windowHandle = new WindowInteropHelper(this).Handle;
|
||||
var screen = System.Windows.Forms.Screen.FromHandle(windowHandle);
|
||||
double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY;
|
||||
var toolbarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.FullPrimaryScreenHeight -
|
||||
SystemParameters.WindowCaptionHeight;
|
||||
// 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响
|
||||
var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY);
|
||||
pos.X = (screenWidth - ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX) / 2;
|
||||
|
||||
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 (pointDesktop.X != -1 || pointDesktop.Y != -1) pointDesktop = pos;
|
||||
|
||||
@@ -1180,8 +1217,8 @@ namespace Ink_Canvas {
|
||||
var windowHandle = new WindowInteropHelper(this).Handle;
|
||||
var screen = System.Windows.Forms.Screen.FromHandle(windowHandle);
|
||||
double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY;
|
||||
var toolbarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.FullPrimaryScreenHeight -
|
||||
SystemParameters.WindowCaptionHeight;
|
||||
// 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响
|
||||
var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY);
|
||||
pos.X = (screenWidth - ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX) / 2;
|
||||
|
||||
pos.Y = screenHeight - 55 * ViewboxFloatingBarScaleTransform.ScaleY;
|
||||
@@ -1585,7 +1622,7 @@ namespace Ink_Canvas {
|
||||
|
||||
public void BtnRestart_Click(object sender, RoutedEventArgs e) {
|
||||
Process.Start(System.Windows.Forms.Application.ExecutablePath, "-m");
|
||||
|
||||
App.IsAppExitByUser = true;
|
||||
CloseIsFromButton = true;
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using Microsoft.Win32;
|
||||
using Application = System.Windows.Application;
|
||||
using File = System.IO.File;
|
||||
using MessageBox = System.Windows.MessageBox;
|
||||
@@ -86,6 +87,61 @@ namespace Ink_Canvas {
|
||||
|
||||
Settings.PowerPointSettings.IsSupportWPS = ToggleSwitchSupportWPS.IsOn;
|
||||
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;
|
||||
@@ -93,8 +149,34 @@ namespace Ink_Canvas {
|
||||
public static bool IsShowingRestoreHiddenSlidesWindow = false;
|
||||
private static bool IsShowingAutoplaySlidesWindow = 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)
|
||||
{
|
||||
@@ -107,19 +189,44 @@ namespace Ink_Canvas {
|
||||
// 检查是否已有初始化的 PowerPoint 实例
|
||||
if (!isPowerPointInitialized)
|
||||
{
|
||||
// 优先检测WPS进程
|
||||
var wpsProcesses = Process.GetProcessesByName("wpp");
|
||||
// 检测WPS和PowerPoint进程
|
||||
bool wpsRunning = IsWPSRunning(true);
|
||||
var pptProcesses = Process.GetProcessesByName("POWERPNT");
|
||||
|
||||
// 根据设置和进程状态决定模式
|
||||
isWPSMode = isWPSSupportOn && wpsRunning;
|
||||
|
||||
LogHelper.WriteLogToFile($"初始化模式: {(isWPSMode ? "WPS" : "PowerPoint")}", LogHelper.LogType.Info);
|
||||
|
||||
// 优先获取WPS实例
|
||||
if (isWPSSupportOn && wpsProcesses.Length > 0)
|
||||
if (isWPSMode)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -129,74 +236,71 @@ namespace Ink_Canvas {
|
||||
{
|
||||
try
|
||||
{
|
||||
LogHelper.WriteLogToFile("尝试获取PowerPoint实例", LogHelper.LogType.Info);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果都没有找到,且未启用WPS支持,则自动创建PowerPoint进程
|
||||
if (pptApplication == null && !isWPSSupportOn)
|
||||
if (pptApplication == null && !isWPSMode && pptProcesses.Length == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogHelper.WriteLogToFile("尝试创建新的PowerPoint实例", LogHelper.LogType.Info);
|
||||
pptApplication = (Microsoft.Office.Interop.PowerPoint.Application)Activator.CreateInstance(
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
isPowerPointInitialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查进程是否还在
|
||||
var pptProcessesCheck = Process.GetProcessesByName("POWERPNT");
|
||||
var wpsProcessesCheck = Process.GetProcessesByName("wpp");
|
||||
bool isWpsMode = isWPSSupportOn && wpsProcessesCheck.Length > 0;
|
||||
bool isPptMode = !isWPSSupportOn && pptProcessesCheck.Length > 0;
|
||||
bool currentWpsRunning = IsWPSRunning(false); // 定期检查不输出日志
|
||||
var currentPptProcesses = Process.GetProcessesByName("POWERPNT");
|
||||
|
||||
// 检测应用程序是否关闭
|
||||
bool applicationClosed = isWPSMode ? !currentWpsRunning : currentPptProcesses.Length == 0;
|
||||
|
||||
if ((isWpsMode && wpsProcessesCheck.Length == 0) || (!isWpsMode && pptProcessesCheck.Length == 0))
|
||||
if (applicationClosed)
|
||||
{
|
||||
// 进程已关闭,清理对象
|
||||
if (pptApplication != null)
|
||||
{
|
||||
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;
|
||||
LogHelper.WriteLogToFile($"{(isWPSMode ? "WPS" : "PowerPoint")}进程已关闭,清理对象", LogHelper.LogType.Info);
|
||||
|
||||
// 进程已关闭,调用重置方法清理对象
|
||||
ResetPresentationObjects();
|
||||
isPowerPointInitialized = false;
|
||||
|
||||
// PowerPoint进程守护:自动重启PowerPoint进程(仅在未启用WPS支持时)
|
||||
if (!isWPSSupportOn)
|
||||
if (!isWPSSupportOn && !isWPSMode)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogHelper.WriteLogToFile("尝试重启PowerPoint进程", LogHelper.LogType.Info);
|
||||
pptApplication = (Microsoft.Office.Interop.PowerPoint.Application)Activator.CreateInstance(
|
||||
Marshal.GetTypeFromCLSID(new Guid("91493441-5A91-11CF-8700-00AA0060263B")));
|
||||
isPowerPointInitialized = true;
|
||||
LogHelper.WriteLogToFile("PowerPoint进程重启成功", LogHelper.LogType.Info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile("PowerPoint 守护重启失败: " + ex.ToString(), LogHelper.LogType.Error);
|
||||
LogHelper.WriteLogToFile($"PowerPoint守护重启失败: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 启用WPS支持时不守护PowerPoint进程
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -273,7 +377,7 @@ namespace Ink_Canvas {
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
|
||||
LogHelper.WriteLogToFile($"TimerCheckPPT_Elapsed 异常: {ex.Message}", LogHelper.LogType.Error);
|
||||
Application.Current.Dispatcher.Invoke(() => {
|
||||
BtnPPTSlideShow.Visibility = Visibility.Collapsed;
|
||||
timerCheckPPT.Start();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using iNKORE.UI.WPF.Modern.Controls;
|
||||
using iNKORE.UI.WPF.Modern.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
@@ -17,6 +17,13 @@ namespace Ink_Canvas {
|
||||
private object lastBorderMouseDownObject;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -380,6 +387,11 @@ namespace Ink_Canvas {
|
||||
isProgramChangeStrokeSelection = false;
|
||||
inkCanvas.Strokes.Add(StrokesSelectionClone);
|
||||
}
|
||||
else {
|
||||
// 新增:启动套索选择模式
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Select;
|
||||
inkCanvas.Select(new StrokeCollection());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -694,6 +694,62 @@ namespace Ink_Canvas {
|
||||
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
|
||||
|
||||
#region Canvas
|
||||
@@ -1412,7 +1468,7 @@ namespace Ink_Canvas {
|
||||
Settings.Automation.IsAutoKillVComYouJiao = false;
|
||||
Settings.Automation.IsAutoKillInkCanvas = false;
|
||||
Settings.Automation.IsAutoKillICA = false;
|
||||
Settings.Automation.IsAutoKillIDT = true;
|
||||
Settings.Automation.IsAutoKillIDT = false;
|
||||
Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation = false;
|
||||
Settings.Automation.IsSaveScreenshotsInDateFolders = false;
|
||||
Settings.Automation.IsAutoSaveStrokesAtScreenshot = true;
|
||||
@@ -1447,6 +1503,12 @@ namespace Ink_Canvas {
|
||||
Settings.Canvas.HideStrokeWhenSelecting = false;
|
||||
Settings.Canvas.ClearCanvasAndClearTimeMachine = false;
|
||||
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.HyperbolaAsymptoteOption = 0;
|
||||
|
||||
@@ -1690,6 +1752,21 @@ namespace Ink_Canvas {
|
||||
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
|
||||
|
||||
public static void SaveSettingsToFile() {
|
||||
|
||||
@@ -434,6 +434,12 @@ namespace Ink_Canvas {
|
||||
inkCanvas.ForceCursor = false;
|
||||
}
|
||||
|
||||
// 初始化压感触屏模式开关状态
|
||||
ToggleSwitchEnablePressureTouchMode.IsOn = Settings.Canvas.EnablePressureTouchMode;
|
||||
|
||||
// 初始化屏蔽压感开关状态
|
||||
ToggleSwitchDisablePressure.IsOn = Settings.Canvas.DisablePressure;
|
||||
|
||||
ComboBoxPenStyle.SelectedIndex = Settings.Canvas.InkStyle;
|
||||
BoardComboBoxPenStyle.SelectedIndex = Settings.Canvas.InkStyle;
|
||||
|
||||
@@ -500,6 +506,14 @@ namespace Ink_Canvas {
|
||||
ToggleSwitchFitToCurve.IsOn = 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 {
|
||||
Settings.Canvas = new Canvas();
|
||||
}
|
||||
@@ -569,7 +583,14 @@ namespace Ink_Canvas {
|
||||
}
|
||||
|
||||
// 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();
|
||||
ToggleSwitchDisplayRandWindowNamesInputBtn.IsOn = Settings.RandSettings.DisplayRandWindowNamesInputBtn;
|
||||
RandWindowOnceCloseLatencySlider.Value = Settings.RandSettings.RandWindowOnceCloseLatency;
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Ink_Canvas {
|
||||
#endregion Floating Bar Control
|
||||
|
||||
private int drawingShapeMode = 0;
|
||||
private bool isLongPressSelected = false; // 用于存是否是“选中”状态,便于后期抬笔后不做切换到笔的处理
|
||||
private bool isLongPressSelected = false; // 用于存是否是"选中"状态,便于后期抬笔后不做切换到笔的处理
|
||||
|
||||
#region Buttons
|
||||
|
||||
@@ -429,6 +429,8 @@ namespace Ink_Canvas {
|
||||
|
||||
private void inkCanvas_TouchMove(object sender, TouchEventArgs e) {
|
||||
if (isSingleFingerDragMode) return;
|
||||
|
||||
// 处理形状绘制模式
|
||||
if (drawingShapeMode != 0) {
|
||||
if (isLastTouchEraser) return;
|
||||
//EraserContainer.Background = null;
|
||||
@@ -443,15 +445,75 @@ namespace Ink_Canvas {
|
||||
catch {
|
||||
Trace.WriteLine("lastTempStrokeCollection failed.");
|
||||
}
|
||||
|
||||
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; //多笔完成的图形 当前所处在的笔画
|
||||
|
||||
@@ -19,7 +19,109 @@ namespace Ink_Canvas {
|
||||
|
||||
try {
|
||||
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() {
|
||||
try {
|
||||
newStrokes.Add(e.Stroke);
|
||||
@@ -320,13 +422,27 @@ namespace Ink_Canvas {
|
||||
InkToShapeProcess();
|
||||
}
|
||||
|
||||
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;
|
||||
// 如果启用了屏蔽压感功能,强制所有点的压感值为0.5
|
||||
if (Settings.Canvas.DisablePressure) {
|
||||
var stylusPoints = new StylusPointCollection();
|
||||
foreach (var point in e.Stroke.StylusPoints) {
|
||||
var newPoint = new StylusPoint(point.X, point.Y, 0.5f);
|
||||
stylusPoints.Add(newPoint);
|
||||
}
|
||||
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 {
|
||||
if (e.Stroke.StylusPoints.Count > 3) {
|
||||
@@ -540,5 +656,31 @@ namespace Ink_Canvas {
|
||||
public StylusPoint GetCenterPoint(StylusPoint point1, StylusPoint point2) {
|
||||
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 void Main_Grid_TouchDown(object sender, TouchEventArgs e) {
|
||||
// 确保触摸时显示自定义光标
|
||||
if (Settings.Canvas.IsShowCursor) {
|
||||
inkCanvas.ForceCursor = true;
|
||||
System.Windows.Forms.Cursor.Show();
|
||||
}
|
||||
|
||||
inkCanvas.CaptureTouch(e.TouchDevice);
|
||||
ViewboxFloatingBar.IsHitTestVisible = false;
|
||||
|
||||
@@ -63,7 +63,11 @@ namespace Ink_Canvas
|
||||
|
||||
private void RestartAppTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) {
|
||||
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) {
|
||||
|
||||
@@ -48,6 +48,18 @@ namespace Ink_Canvas
|
||||
public bool FitToCurve { get; set; } = true;
|
||||
[JsonProperty("clearCanvasAndClearTimeMachine")]
|
||||
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")]
|
||||
public bool UsingWhiteboard { get; set; }
|
||||
@@ -308,7 +320,7 @@ namespace Ink_Canvas
|
||||
public bool IsAutoKillICA { get; set; } = false;
|
||||
|
||||
[JsonProperty("isAutoKillIDT")]
|
||||
public bool IsAutoKillIDT { get; set; } = true;
|
||||
public bool IsAutoKillIDT { get; set; } = false;
|
||||
|
||||
[JsonProperty("isSaveScreenshotsInDateFolders")]
|
||||
public bool IsSaveScreenshotsInDateFolders { get; set; } = false;
|
||||
@@ -406,5 +418,7 @@ namespace Ink_Canvas
|
||||
public double RandWindowOnceCloseLatency { get; set; } = 2.5;
|
||||
[JsonProperty("randWindowOnceMaxStudents")]
|
||||
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>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\Administrator\.nuget\packages\;E:\Program Files\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.13.2</NuGetToolVersion>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.14.0</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="C:\Users\Administrator\.nuget\packages\" />
|
||||
|
||||
Reference in New Issue
Block a user