Compare commits

...

27 Commits

Author SHA1 Message Date
CJK_mkp ab67ea48f0 Merge pull request #36 from awesome-iwb/beta
ICC CE 1.6.6 (ICC CE Beta 1.6.13)
2025-06-19 12:00:20 +08:00
CJK_mkp 912c1b91e4 更新版本号 2025-06-19 11:56:36 +08:00
CJK_mkp d4f1d21634 improve:静默更新 2025-06-19 11:47:16 +08:00
CJK_mkp 6c0e7c2e64 fix:触屏类问题及设置内点击问题 2025-06-19 11:25:15 +08:00
CJK_mkp e054a50b55 Merge pull request #35 from awesome-iwb/beta
Update AutomaticUpdateVersionControl.txt
2025-06-18 23:09:27 +08:00
CJK_mkp ff005e6398 Update AutomaticUpdateVersionControl.txt 2025-06-18 23:08:47 +08:00
CJK_mkp 74cc8e7dda Merge pull request #34 from awesome-iwb/beta
修改版本号
2025-06-18 22:59:52 +08:00
CJK_mkp 254d70a787 修改版本号 2025-06-18 22:58:18 +08:00
CJK_mkp 28b728822c Merge pull request #33 from awesome-iwb/beta
ICC CE 1.6.4(ICC CE Beta1.6.8)
2025-06-18 22:44:30 +08:00
CJK_mkp 5a53471bcd improve:自动更新 2025-06-18 22:42:21 +08:00
CJK_mkp a3fee5d77c improve:自动更新 2025-06-18 22:40:48 +08:00
CJK_mkp 6f961225d7 更新版本号 2025-06-18 22:29:28 +08:00
CJK_mkp 1b0b4f7505 去除了miku 2025-06-18 22:19:34 +08:00
CJK_mkp fac66fafbd fix:墨迹压感问题 2025-06-18 18:31:03 +08:00
CJK_mkp b9d6ac3047 Merge pull request #32 from awesome-iwb/beta
ICC CE 1.6.4(ICC CE Beta1.6.7)
2025-06-18 18:20:56 +08:00
CJK_mkp e7c723de46 fix:进程崩溃判定错误 improve:重新配置了自动更新 2025-06-18 18:16:48 +08:00
CJK_mkp 10629b253c 修复自动更新 2025-06-18 16:12:47 +08:00
CJK_mkp dace6ad486 修改自动更新 2025-06-18 16:08:26 +08:00
CJK_mkp 4c70f35714 Merge pull request #31 from awesome-iwb/beta
ICC CE 1.6.3 (ICC CE Beta1.6.6)
2025-06-18 15:44:17 +08:00
CJK_mkp 7b4d13c16f update:自动更新服务 2025-06-18 15:40:07 +08:00
CJK_mkp 0e561ad24e 修改版本 2025-06-18 15:32:45 +08:00
CJK_mkp d09d8223c9 更新版本号 2025-06-18 15:12:44 +08:00
CJK_mkp 6dafde9735 improve:直线拉直灵敏度设置 2025-06-18 15:10:33 +08:00
CJK_mkp a0f84bf017 Merge pull request #30 from awesome-iwb/beta
ICC CE 1.6.2 (ICC CE Beta  1.6.4)
2025-06-18 13:42:52 +08:00
CJK_mkp 7049c53889 fix:墨迹纠正 2025-06-18 13:37:52 +08:00
CJK_mkp 7750fa799d fix:墨迹纠正 2025-06-18 13:24:50 +08:00
CJK_mkp 5f828736de fix:issue #13 #23 add:设置页面侧边栏 2025-06-18 09:08:38 +08:00
28 changed files with 10096 additions and 7598 deletions
+1 -1
View File
@@ -1 +1 @@
1.4.7
1.6.6
+2 -2
View File
@@ -49,5 +49,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("5.0.2.0")]
[assembly: AssemblyFileVersion("5.0.2.0")]
[assembly: AssemblyVersion("1.6.6")]
[assembly: AssemblyFileVersion("1.6.6")]
+593 -40
View File
@@ -8,6 +8,8 @@ using System.Windows;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Controls;
using System.IO.Compression;
using System.Text;
namespace Ink_Canvas.Helpers
{
@@ -18,30 +20,48 @@ namespace Ink_Canvas.Helpers
try
{
string localVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
LogHelper.WriteLogToFile($"AutoUpdate | Local version: {localVersion}");
string remoteAddress = proxy;
remoteAddress += "https://github.com/CJKmkp/ICC-CE/blob/main/AutomaticUpdateVersionControl.txt";
string primaryUrl = "https://raw.githubusercontent.com/awesome-iwb/icc-ce/refs/heads/main/AutomaticUpdateVersionControl.txt";
string fallbackUrl = "https://raw.bgithub.xyz/awesome-iwb/icc-ce/refs/heads/main/AutomaticUpdateVersionControl.txt";
// 先尝试主地址
remoteAddress += primaryUrl;
string remoteVersion = await GetRemoteVersion(remoteAddress);
// 如果主地址失败,尝试备用地址
if (remoteVersion == null)
{
LogHelper.WriteLogToFile($"AutoUpdate | Primary URL failed, trying fallback URL");
remoteVersion = await GetRemoteVersion(proxy + fallbackUrl);
}
if (remoteVersion != null)
{
LogHelper.WriteLogToFile($"AutoUpdate | Remote version: {remoteVersion}");
Version local = new Version(localVersion);
Version remote = new Version(remoteVersion);
if (remote > local)
{
LogHelper.WriteLogToFile("AutoUpdate | New version Availble: " + remoteVersion);
LogHelper.WriteLogToFile($"AutoUpdate | New version available: {remoteVersion}");
return remoteVersion;
}
else return null;
else
{
LogHelper.WriteLogToFile($"AutoUpdate | Current version is up to date");
return null;
}
}
else
{
LogHelper.WriteLogToFile("Failed to retrieve remote version.", LogHelper.LogType.Error);
LogHelper.WriteLogToFile("AutoUpdate | Failed to retrieve remote version from both URLs.", LogHelper.LogType.Error);
return null;
}
}
catch (Exception ex)
{
Console.WriteLine($"AutoUpdate | Error: {ex.Message}");
LogHelper.WriteLogToFile($"AutoUpdate | Error in CheckForUpdates: {ex.Message}", LogHelper.LogType.Error);
return null;
}
}
@@ -52,15 +72,72 @@ namespace Ink_Canvas.Helpers
{
try
{
HttpResponseMessage response = await client.GetAsync(fileUrl);
// Set a reasonable timeout
client.Timeout = TimeSpan.FromSeconds(10); // 减少超时时间以便更快切换到备用地址
LogHelper.WriteLogToFile($"AutoUpdate | Sending HTTP request to: {fileUrl}");
// 使用带超时的Task.WhenAny来确保请求不会无限期等待
var downloadTask = client.GetAsync(fileUrl);
var timeoutTask = Task.Delay(client.Timeout);
var completedTask = await Task.WhenAny(downloadTask, timeoutTask);
if (completedTask == timeoutTask)
{
LogHelper.WriteLogToFile($"AutoUpdate | Request timed out after {client.Timeout.TotalSeconds} seconds", LogHelper.LogType.Error);
return null;
}
// 请求完成,检查结果
HttpResponseMessage response = await downloadTask;
LogHelper.WriteLogToFile($"AutoUpdate | HTTP response status: {response.StatusCode}");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
string content = await response.Content.ReadAsStringAsync();
// Trim any whitespace, newlines, etc.
content = content.Trim();
// If the content contains HTML (likely the GitHub view page instead of raw content),
// try to extract the version number
if (content.Contains("<html") || content.Contains("<!DOCTYPE"))
{
LogHelper.WriteLogToFile($"AutoUpdate | Received HTML content instead of raw version number - trying to extract version");
// Try to extract version from GitHub page - look for text content in the file
int startPos = content.IndexOf("<table");
if (startPos > 0)
{
int endPos = content.IndexOf("</table>", startPos);
if (endPos > startPos)
{
string tableContent = content.Substring(startPos, endPos - startPos);
// Look for the version number pattern (like 1.2.3 or 1.2.3.4)
var match = System.Text.RegularExpressions.Regex.Match(tableContent, @"(\d+\.\d+\.\d+(\.\d+)?)");
if (match.Success)
{
content = match.Groups[1].Value;
LogHelper.WriteLogToFile($"AutoUpdate | Extracted version from HTML: {content}");
}
else
{
LogHelper.WriteLogToFile($"AutoUpdate | Could not extract version from HTML content");
return null;
}
}
}
}
LogHelper.WriteLogToFile($"AutoUpdate | Response content: {content}");
return content;
}
catch (HttpRequestException ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | HTTP request error: {ex.Message}", LogHelper.LogType.Error);
}
catch (TaskCanceledException ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | Request timed out: {ex.Message}", LogHelper.LogType.Error);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | Error: {ex.Message}", LogHelper.LogType.Error);
@@ -70,7 +147,7 @@ namespace Ink_Canvas.Helpers
}
}
private static string updatesFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Ink Canvas Annotation", "AutoUpdate");
private static string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
private static string statusFilePath = null;
public static async Task<bool> DownloadSetupFileAndSaveStatus(string version, string proxy = "")
@@ -85,49 +162,203 @@ namespace Ink_Canvas.Helpers
return true;
}
string downloadUrl = $"{proxy}https://github.com/ChangSakura/Ink-Canvas/releases/download/v{version}/Ink.Canvas.Annotation.V{version}.Setup.exe";
// Ensure update directory exists
if (!Directory.Exists(updatesFolderPath))
{
Directory.CreateDirectory(updatesFolderPath);
LogHelper.WriteLogToFile($"AutoUpdate | Created updates directory: {updatesFolderPath}");
}
// 主下载地址
string primaryUrl = $"{proxy}https://github.com/awesome-iwb/icc-ce/releases/download/{version}/InkCanvasForClass.CE.{version}.zip";
// 备用下载地址
string fallbackUrl = $"{proxy}https://bgithub.xyz/awesome-iwb/icc-ce/releases/download/{version}/InkCanvasForClass.CE.{version}.zip";
LogHelper.WriteLogToFile($"AutoUpdate | Primary download URL: {primaryUrl}");
SaveDownloadStatus(false);
await DownloadFile(downloadUrl, $"{updatesFolderPath}\\Ink.Canvas.Annotation.V{version}.Setup.exe");
SaveDownloadStatus(true);
LogHelper.WriteLogToFile("AutoUpdate | Setup file successfully downloaded.");
return true;
string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip");
LogHelper.WriteLogToFile($"AutoUpdate | Target file path: {zipFilePath}");
// 先尝试主地址下载
bool downloadSuccess = await DownloadFile(primaryUrl, zipFilePath);
// 如果主地址下载失败,尝试备用地址
if (!downloadSuccess)
{
LogHelper.WriteLogToFile($"AutoUpdate | Primary download failed, trying fallback URL: {fallbackUrl}");
downloadSuccess = await DownloadFile(fallbackUrl, zipFilePath);
}
if (downloadSuccess)
{
SaveDownloadStatus(true);
LogHelper.WriteLogToFile("AutoUpdate | Setup file successfully downloaded.");
return true;
}
else
{
LogHelper.WriteLogToFile("AutoUpdate | Failed to download the update file from both URLs.", LogHelper.LogType.Error);
return false;
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | Error downloading and installing update: {ex.Message}", LogHelper.LogType.Error);
LogHelper.WriteLogToFile($"AutoUpdate | Error downloading update: {ex.Message}", LogHelper.LogType.Error);
if (ex.InnerException != null)
{
LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error);
}
SaveDownloadStatus(false);
return false;
}
}
private static async Task DownloadFile(string fileUrl, string destinationPath)
private static async Task<bool> DownloadFile(string fileUrl, string destinationPath)
{
using (HttpClient client = new HttpClient())
{
try
{
HttpResponseMessage response = await client.GetAsync(fileUrl);
response.EnsureSuccessStatusCode();
using (FileStream fileStream = File.Create(destinationPath))
// Configure client
client.Timeout = TimeSpan.FromMinutes(5); // Longer timeout for downloading larger files
client.DefaultRequestHeaders.Add("User-Agent", "ICC-CE Auto Updater");
LogHelper.WriteLogToFile($"AutoUpdate | Downloading from: {fileUrl}");
// 创建临时文件路径
string tempFilePath = destinationPath + ".tmp";
// 确保目标目录存在
string directory = Path.GetDirectoryName(destinationPath);
if (!Directory.Exists(directory))
{
await response.Content.CopyToAsync(fileStream);
fileStream.Close();
Directory.CreateDirectory(directory);
}
// 使用带超时的Task.WhenAny来确保请求不会无限期等待
var downloadTask = client.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead);
var initialTimeoutTask = Task.Delay(TimeSpan.FromSeconds(30)); // 30秒内必须有响应
var completedTask = await Task.WhenAny(downloadTask, initialTimeoutTask);
if (completedTask == initialTimeoutTask)
{
LogHelper.WriteLogToFile($"AutoUpdate | Initial connection timed out after 30 seconds", LogHelper.LogType.Error);
return false;
}
// 请求完成,检查结果
HttpResponseMessage response = await downloadTask;
LogHelper.WriteLogToFile($"AutoUpdate | HTTP response status: {response.StatusCode}");
response.EnsureSuccessStatusCode();
// 获取文件总大小
long? totalBytes = response.Content.Headers.ContentLength;
LogHelper.WriteLogToFile($"AutoUpdate | File size: {(totalBytes.HasValue ? (totalBytes.Value / 1024.0 / 1024.0).ToString("F2") + " MB" : "Unknown")}");
// 创建临时文件流
using (var fileStream = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
// 获取下载流
using (var downloadStream = await response.Content.ReadAsStreamAsync())
{
byte[] buffer = new byte[8192]; // 8KB buffer
long totalBytesRead = 0;
int bytesRead;
DateTime lastProgressUpdate = DateTime.Now;
// 设置下载超时 - 如果60秒内没有数据传输,则认为下载超时
var downloadTimeoutTask = Task.Delay(TimeSpan.FromSeconds(60));
var readTask = Task.Run(async () => {
while ((bytesRead = await downloadStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await fileStream.WriteAsync(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
// 每5秒更新一次进度
if ((DateTime.Now - lastProgressUpdate).TotalSeconds >= 5)
{
if (totalBytes.HasValue)
{
double percentage = (double)totalBytesRead / totalBytes.Value * 100;
LogHelper.WriteLogToFile($"AutoUpdate | Download progress: {percentage:F1}% ({(totalBytesRead / 1024.0 / 1024.0):F2} MB / {(totalBytes.Value / 1024.0 / 1024.0):F2} MB)");
}
else
{
LogHelper.WriteLogToFile($"AutoUpdate | Downloaded: {(totalBytesRead / 1024.0 / 1024.0):F2} MB");
}
lastProgressUpdate = DateTime.Now;
// 重置下载超时
downloadTimeoutTask = Task.Delay(TimeSpan.FromSeconds(60));
}
}
return true;
});
// 等待下载完成或超时
if (await Task.WhenAny(readTask, downloadTimeoutTask) == downloadTimeoutTask)
{
LogHelper.WriteLogToFile($"AutoUpdate | Download timed out after 60 seconds of inactivity", LogHelper.LogType.Error);
return false;
}
// 确保下载任务完成
bool downloadCompleted = await readTask;
if (downloadCompleted)
{
LogHelper.WriteLogToFile($"AutoUpdate | Download completed: {(totalBytesRead / 1024.0 / 1024.0):F2} MB");
}
}
}
// 如果临时文件存在,则将其移动到目标位置
if (File.Exists(tempFilePath))
{
// 如果目标文件已存在,先删除
if (File.Exists(destinationPath))
{
File.Delete(destinationPath);
}
File.Move(tempFilePath, destinationPath);
LogHelper.WriteLogToFile($"AutoUpdate | File saved to: {destinationPath}");
return true;
}
return false;
}
catch (HttpRequestException ex)
{
Console.WriteLine($"AutoUpdate | HTTP request error: {ex.Message}");
throw;
LogHelper.WriteLogToFile($"AutoUpdate | HTTP request error: {ex.Message}", LogHelper.LogType.Error);
}
catch (TaskCanceledException ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | Download timed out: {ex.Message}", LogHelper.LogType.Error);
}
catch (Exception ex)
{
Console.WriteLine($"AutoUpdate | Error: {ex.Message}");
throw;
LogHelper.WriteLogToFile($"AutoUpdate | Error downloading file: {ex.Message}", LogHelper.LogType.Error);
if (ex.InnerException != null)
{
LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error);
}
}
// 清理临时文件
try
{
string tempFilePath = destinationPath + ".tmp";
if (File.Exists(tempFilePath))
{
File.Delete(tempFilePath);
}
}
catch { }
return false;
}
}
@@ -155,17 +386,263 @@ namespace Ink_Canvas.Helpers
{
try
{
string setupFilePath = Path.Combine(updatesFolderPath, $"Ink.Canvas.Annotation.V{version}.Setup.exe");
string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip");
LogHelper.WriteLogToFile($"AutoUpdate | Checking for ZIP file: {zipFilePath}");
if (!File.Exists(setupFilePath))
if (!File.Exists(zipFilePath))
{
LogHelper.WriteLogToFile($"AutoUpdate | Setup file not found: {setupFilePath}", LogHelper.LogType.Error);
LogHelper.WriteLogToFile($"AutoUpdate | ZIP file not found: {zipFilePath}", LogHelper.LogType.Error);
return;
}
string InstallCommand = $"\"{setupFilePath}\" /SILENT";
if (isInSilence) InstallCommand += " /VERYSILENT";
ExecuteCommandLine(InstallCommand);
// Verify ZIP file size and validity
FileInfo fileInfo = new FileInfo(zipFilePath);
if (fileInfo.Length == 0)
{
LogHelper.WriteLogToFile($"AutoUpdate | ZIP file is empty, cannot continue", LogHelper.LogType.Error);
return;
}
LogHelper.WriteLogToFile($"AutoUpdate | ZIP file size: {fileInfo.Length} bytes");
// 获取当前应用程序路径和进程ID
string currentAppDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
int currentProcessId = Process.GetCurrentProcess().Id;
string appPath = Assembly.GetExecutingAssembly().Location;
LogHelper.WriteLogToFile($"AutoUpdate | Current application directory: {currentAppDir}");
LogHelper.WriteLogToFile($"AutoUpdate | Current process ID: {currentProcessId}");
LogHelper.WriteLogToFile($"AutoUpdate | Silent update mode: {isInSilence}");
// 创建批处理文件来执行更新操作
string batchFilePath = Path.Combine(Path.GetTempPath(), "UpdateICC_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat");
LogHelper.WriteLogToFile($"AutoUpdate | Creating update batch file: {batchFilePath}");
// 构建批处理文件内容
StringBuilder batchContent = new StringBuilder();
batchContent.AppendLine("@echo off");
// 使窗口隐藏(使用VBS脚本运行隐藏窗口)
batchContent.AppendLine("echo Set objShell = CreateObject(\"WScript.Shell\") > \"%temp%\\hideme.vbs\"");
batchContent.AppendLine("echo objShell.Run \"cmd /c \"\"\" ^& WScript.Arguments(0) ^& \"\"\"\", 0, True >> \"%temp%\\hideme.vbs\"");
batchContent.AppendLine($"echo Wscript.Sleep 100 >> \"%temp%\\hideme.vbs\"");
// 创建真正的更新批处理文件
string updateBatPath = Path.Combine(Path.GetTempPath(), "ICCUpdate_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat");
batchContent.AppendLine($"echo @echo off > \"{updateBatPath}\"");
// 写入等待进程退出的代码到更新批处理文件
batchContent.AppendLine($"echo set PROC_ID={currentProcessId} >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo :CHECK_PROCESS >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo tasklist /fi \"PID eq %PROC_ID%\" ^| find \"%PROC_ID%\" ^> nul >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo if %%ERRORLEVEL%% == 0 ( >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo timeout /t 1 /nobreak ^> nul >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo goto CHECK_PROCESS >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo ) >> \"{updateBatPath}\"");
// 应用程序已关闭,开始更新操作
batchContent.AppendLine($"echo echo Application closed, starting update process... >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo timeout /t 2 /nobreak ^> nul >> \"{updateBatPath}\"");
// 创建临时解压目录
string extractPath = Path.Combine(updatesFolderPath, $"Extract_{version}");
batchContent.AppendLine($"echo echo Extracting update files... >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo if exist \"{extractPath}\" rd /s /q \"{extractPath}\" >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo mkdir \"{extractPath}\" >> \"{updateBatPath}\"");
// PowerShell解压ZIP文件(因为批处理不直接支持ZIP解压)
batchContent.AppendLine($"echo powershell -command \"Expand-Archive -Path '{zipFilePath.Replace("'", "''")}' -DestinationPath '{extractPath.Replace("'", "''")}' -Force\" >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo goto ERROR_EXIT >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo ) >> \"{updateBatPath}\"");
// 复制文件到应用程序目录
batchContent.AppendLine($"echo echo Copying updated files to application directory... >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo xcopy /s /y /e \"{extractPath}\\*\" \"{currentAppDir}\\\" >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo goto ERROR_EXIT >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo ) >> \"{updateBatPath}\"");
// 清理临时文件
batchContent.AppendLine($"echo echo Cleaning up temporary files... >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo if exist \"{extractPath}\" rd /s /q \"{extractPath}\" >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo if exist \"{zipFilePath}\" del /f /q \"{zipFilePath}\" >> \"{updateBatPath}\"");
// 启动更新后的应用程序
batchContent.AppendLine($"echo echo Update completed successfully! >> \"{updateBatPath}\"");
// 根据是否为静默更新模式决定是否自动启动应用程序
if (isInSilence)
{
// 静默更新模式下,自动启动应用程序
batchContent.AppendLine($"echo echo 自动启动应用程序... >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo start \"\" \"{appPath}\" >> \"{updateBatPath}\"");
}
else
{
// 非静默模式下,检查应用程序是否已经在运行
batchContent.AppendLine($"echo :: 检查应用程序是否已经在运行 >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo tasklist /FI \"IMAGENAME eq Ink Canvas.exe\" | find /i \"Ink Canvas.exe\" > nul >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo echo 启动应用程序... >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo start \"\" \"{appPath}\" >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo ) else ( >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo echo 应用程序已经在运行,不再重复启动 >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo ) >> \"{updateBatPath}\"");
}
batchContent.AppendLine($"echo exit /b 0 >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo goto EXIT >> \"{updateBatPath}\"");
// 错误退出处理
if (isInSilence)
{
// 静默模式下,不显示错误提示
batchContent.AppendLine($"echo :ERROR_EXIT >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo echo Update failed! >> \"%temp%\\icc_update_error.log\" >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo exit /b 1 >> \"{updateBatPath}\"");
}
else
{
// 非静默模式下,显示错误提示
batchContent.AppendLine($"echo :ERROR_EXIT >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo start \"\" cmd /c \"echo Update failed! ^& pause\" >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo exit /b 1 >> \"{updateBatPath}\"");
}
// 删除批处理文件自身
batchContent.AppendLine($"echo :EXIT >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo del \"{updateBatPath}\" >> \"{updateBatPath}\"");
batchContent.AppendLine($"echo exit >> \"{updateBatPath}\"");
// 使用VBS脚本执行更新批处理文件(隐藏窗口)
batchContent.AppendLine($"wscript \"%temp%\\hideme.vbs\" \"{updateBatPath}\"");
batchContent.AppendLine("del \"%temp%\\hideme.vbs\"");
batchContent.AppendLine("exit");
// 写入批处理文件
File.WriteAllText(batchFilePath, batchContent.ToString());
LogHelper.WriteLogToFile($"AutoUpdate | Created update batch file");
// 启动批处理文件(隐藏窗口)
Process.Start(new ProcessStartInfo
{
FileName = batchFilePath,
CreateNoWindow = true,
UseShellExecute = true,
WindowStyle = ProcessWindowStyle.Hidden
});
LogHelper.WriteLogToFile($"AutoUpdate | Started update batch process with hidden window");
// 应用程序将由用户手动关闭或由MainWindow中的代码关闭
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | Error preparing update installation: {ex.Message}", LogHelper.LogType.Error);
if (ex.InnerException != null)
{
LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error);
}
}
}
private static bool CopyDirectory(string sourceDir, string destinationDir)
{
bool allCopiesSuccessful = true;
try
{
// 创建目标目录(如果不存在)
Directory.CreateDirectory(destinationDir);
LogHelper.WriteLogToFile($"AutoUpdate | Created/verified destination directory: {destinationDir}");
// 复制所有文件
foreach (string filePath in Directory.GetFiles(sourceDir))
{
string fileName = Path.GetFileName(filePath);
string destPath = Path.Combine(destinationDir, fileName);
try
{
LogHelper.WriteLogToFile($"AutoUpdate | Copying file: {fileName}");
// 如果目标文件存在,先删除
if (File.Exists(destPath))
{
File.Delete(destPath);
}
File.Copy(filePath, destPath);
}
catch (Exception ex)
{
allCopiesSuccessful = false;
LogHelper.WriteLogToFile($"AutoUpdate | Error copying file {fileName}: {ex.Message}", LogHelper.LogType.Error);
}
}
// 递归复制所有子目录
foreach (string subDirPath in Directory.GetDirectories(sourceDir))
{
string subDirName = Path.GetFileName(subDirPath);
string destSubDir = Path.Combine(destinationDir, subDirName);
bool subDirCopyResult = CopyDirectory(subDirPath, destSubDir);
if (!subDirCopyResult)
{
allCopiesSuccessful = false;
}
}
return allCopiesSuccessful;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | Error copying directory {sourceDir}: {ex.Message}", LogHelper.LogType.Error);
return false;
}
}
private static void RestartApplication()
{
try
{
string appPath = Assembly.GetExecutingAssembly().Location;
LogHelper.WriteLogToFile($"AutoUpdate | Restarting application: {appPath}");
// Create a batch file to wait briefly and then start the application
// This allows the current process to fully exit before starting the new instance
string batchFilePath = Path.Combine(Path.GetTempPath(), "RestartICC_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat");
string batchContent =
"@echo off\r\n" +
"timeout /t 2 /nobreak >nul\r\n" +
":: 检查应用程序是否已经在运行\r\n" +
"tasklist /FI \"IMAGENAME eq Ink Canvas.exe\" | find /i \"Ink Canvas.exe\" > nul\r\n" +
"if %ERRORLEVEL% neq 0 (\r\n" +
" echo 启动应用程序...\r\n" +
$" start \"\" \"{appPath}\"\r\n" +
") else (\r\n" +
" echo 应用程序已经在运行,不再重复启动\r\n" +
")\r\n" +
"timeout /t 1 /nobreak >nul\r\n" +
"del \"%~f0\"\r\n" +
"exit\r\n"; // 确保批处理进程结束
File.WriteAllText(batchFilePath, batchContent);
// Start the batch file
Process.Start(new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/c start \"\" \"{batchFilePath}\"",
CreateNoWindow = true,
UseShellExecute = false
});
LogHelper.WriteLogToFile($"AutoUpdate | Created restart script at {batchFilePath}");
// Shutdown the application
LogHelper.WriteLogToFile($"AutoUpdate | Shutting down application for restart");
Application.Current.Dispatcher.Invoke(() =>
{
Application.Current.Shutdown();
@@ -173,11 +650,37 @@ namespace Ink_Canvas.Helpers
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | Error installing update: {ex.Message}", LogHelper.LogType.Error);
LogHelper.WriteLogToFile($"AutoUpdate | Error restarting application: {ex.Message}", LogHelper.LogType.Error);
// Fallback direct restart approach
try
{
string appPath = Assembly.GetExecutingAssembly().Location;
LogHelper.WriteLogToFile($"AutoUpdate | Attempting direct restart: {appPath}");
// 检查是否已有实例运行
Process[] processes = Process.GetProcessesByName("Ink Canvas");
if (processes.Length <= 1) // 只有当前进程
{
Process.Start(appPath);
}
else
{
LogHelper.WriteLogToFile($"AutoUpdate | Application already running, not starting a new instance");
}
Application.Current.Dispatcher.Invoke(() =>
{
Application.Current.Shutdown();
});
}
catch (Exception fallbackEx)
{
LogHelper.WriteLogToFile($"AutoUpdate | Fallback restart also failed: {fallbackEx.Message}", LogHelper.LogType.Error);
}
}
}
private static void ExecuteCommandLine(string command)
{
try
@@ -185,7 +688,7 @@ namespace Ink_Canvas.Helpers
ProcessStartInfo processStartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/c {command}",
Arguments = $"/c {command} & exit", // 添加exit确保cmd进程退出
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
@@ -195,12 +698,20 @@ namespace Ink_Canvas.Helpers
using (Process process = new Process { StartInfo = processStartInfo })
{
process.Start();
// 设置一个超时时间
bool exited = process.WaitForExit(500); // 等待500毫秒
if (!exited)
{
// 不等待进程完成,让它在后台运行
LogHelper.WriteLogToFile($"AutoUpdate | Command is running in background");
}
Application.Current.Shutdown();
/*process.WaitForExit();
int exitCode = process.ExitCode;*/
}
}
catch { }
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | Error executing command: {ex.Message}", LogHelper.LogType.Error);
}
}
public static void DeleteUpdatesFolder()
@@ -209,12 +720,53 @@ namespace Ink_Canvas.Helpers
{
if (Directory.Exists(updatesFolderPath))
{
Directory.Delete(updatesFolderPath, true);
// Try to delete all files first in case of locking issues
foreach (string file in Directory.GetFiles(updatesFolderPath, "*", SearchOption.AllDirectories))
{
try
{
File.Delete(file);
LogHelper.WriteLogToFile($"AutoUpdate | Deleted file: {file}");
}
catch (Exception fileEx)
{
LogHelper.WriteLogToFile($"AutoUpdate | Could not delete file {file}: {fileEx.Message}", LogHelper.LogType.Warning);
}
}
// Then try to delete subdirectories
foreach (string dir in Directory.GetDirectories(updatesFolderPath))
{
try
{
Directory.Delete(dir, true);
LogHelper.WriteLogToFile($"AutoUpdate | Deleted directory: {dir}");
}
catch (Exception dirEx)
{
LogHelper.WriteLogToFile($"AutoUpdate | Could not delete directory {dir}: {dirEx.Message}", LogHelper.LogType.Warning);
}
}
// Finally try to delete the main directory
try
{
Directory.Delete(updatesFolderPath, true);
LogHelper.WriteLogToFile($"AutoUpdate | Deleted updates folder: {updatesFolderPath}");
}
catch (Exception mainDirEx)
{
LogHelper.WriteLogToFile($"AutoUpdate | Could not completely delete updates folder: {mainDirEx.Message}", LogHelper.LogType.Warning);
}
}
else
{
LogHelper.WriteLogToFile($"AutoUpdate | Updates folder does not exist: {updatesFolderPath}");
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate clearing| Error deleting updates folder: {ex.Message}", LogHelper.LogType.Error);
LogHelper.WriteLogToFile($"AutoUpdate | Error deleting updates folder: {ex.Message}", LogHelper.LogType.Error);
}
}
}
@@ -256,3 +808,4 @@ namespace Ink_Canvas.Helpers
}
}
}
+401 -54
View File
@@ -53,9 +53,72 @@
<RoutedUICommand x:Key="HotKey_ChangeToPen3" Text=" " />
<RoutedUICommand x:Key="HotKey_ChangeToPen4" Text=" " />
<RoutedUICommand x:Key="HotKey_ChangeToPen5" Text=" " />
<RoutedUICommand x:Key="HotKey_DrawLine" Text=" " />
<RoutedUICommand x:Key="NothingWillHappened" Text=" " />
</Window.Resources>
<RoutedUICommand x:Key="HotKey_DrawLine" Text=" " />
<RoutedUICommand x:Key="NothingWillHappened" Text=" " />
<!-- Navigation Button Style -->
<Style x:Key="NavButton" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="border" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="4">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#27272a"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="#3b82f6"/>
</Trigger>
<!-- 使用多个DataTrigger替代动态绑定 -->
<DataTrigger Binding="{Binding Tag}" Value="startup">
<Setter Property="Background" Value="#3b82f6"/>
</DataTrigger>
<DataTrigger Binding="{Binding Tag}" Value="canvas">
<Setter Property="Background" Value="#3b82f6"/>
</DataTrigger>
<DataTrigger Binding="{Binding Tag}" Value="gesture">
<Setter Property="Background" Value="#3b82f6"/>
</DataTrigger>
<DataTrigger Binding="{Binding Tag}" Value="inkrecognition">
<Setter Property="Background" Value="#3b82f6"/>
</DataTrigger>
<DataTrigger Binding="{Binding Tag}" Value="crashaction">
<Setter Property="Background" Value="#3b82f6"/>
</DataTrigger>
<DataTrigger Binding="{Binding Tag}" Value="ppt">
<Setter Property="Background" Value="#3b82f6"/>
</DataTrigger>
<DataTrigger Binding="{Binding Tag}" Value="advanced">
<Setter Property="Background" Value="#3b82f6"/>
</DataTrigger>
<DataTrigger Binding="{Binding Tag}" Value="automation">
<Setter Property="Background" Value="#3b82f6"/>
</DataTrigger>
<DataTrigger Binding="{Binding Tag}" Value="randomwindow">
<Setter Property="Background" Value="#3b82f6"/>
</DataTrigger>
<DataTrigger Binding="{Binding Tag}" Value="theme">
<Setter Property="Background" Value="#3b82f6"/>
</DataTrigger>
<DataTrigger Binding="{Binding Tag}" Value="shortcuts">
<Setter Property="Background" Value="#3b82f6"/>
</DataTrigger>
<DataTrigger Binding="{Binding Tag}" Value="about">
<Setter Property="Background" Value="#3b82f6"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<!--输入命令绑定-->
<Window.InputBindings>
<KeyBinding Gesture="Escape" Command="{StaticResource KeyExit}" />
@@ -107,15 +170,303 @@
<Grid x:Name="Main_Grid">
<!--// 设置界面 //-->
<Grid Panel.ZIndex="999" x:Name="BorderSettingsMask" MouseDown="SettingsOverlayClick" IsHitTestVisible="False"
<Grid Panel.ZIndex="999" x:Name="BorderSettingsMask" MouseDown="SettingsOverlayClick" IsHitTestVisible="True"
Margin="0,0,0,0">
<Border Name="BorderSettings" Background="#ee18181b" ui:ThemeManager.RequestedTheme="Dark" Width="440"
<Border Name="BorderSettings" Background="#ee18181b" ui:ThemeManager.RequestedTheme="Dark" Width="490"
HorizontalAlignment="Left" Margin="300,150,0,350" Visibility="Visible">
<Grid>
<ui:ScrollViewerEx Margin="0,80,0,50" VerticalScrollBarVisibility="Auto"
PanningMode="VerticalOnly" ui:ThemeManager.RequestedTheme="Dark"
ManipulationBoundaryFeedback="SCManipulationBoundaryFeedback"
Name="SettingsPanelScrollViewer">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Navigation Sidebar -->
<Border Grid.Column="0" Background="#1e1e1e" BorderBrush="#27272a" BorderThickness="0,0,1,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 顶部Logo区域 -->
<Border Grid.Row="0" Height="50" Background="#2d2d30" BorderBrush="#3f3f46" BorderThickness="0,0,0,1">
<Image Width="30" Height="30" Source="/Resources/icc.ico" RenderOptions.BitmapScalingMode="HighQuality"/>
</Border>
<!-- 主要导航按钮 -->
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<StackPanel>
<!-- Startup -->
<Button Width="40" Height="40" Margin="0,10,0,0" Style="{StaticResource NavButton}"
Click="NavStartup_Click" Tag="startup" ToolTip="启动设置">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M2.81,14.12L5.64,11.29L8.17,10.79C11.39,6.41 17.55,4.22 19.78,4.22C19.78,6.45 17.59,12.61 13.21,15.83L12.71,18.36L9.88,21.19L9.17,17.66C7.76,17.66 7.76,17.66 7.05,16.95C6.34,16.24 6.34,16.24 6.34,14.83L2.81,14.12M5.64,16.95L7.05,18.36L4.39,21.03H2.97V19.61L5.64,16.95M4.22,15.54L5.46,15.71L3,18.16V16.74L4.22,15.54M8.29,18.54L8.46,19.78L7.26,21H5.84L8.29,18.54M13,9.5A1.5,1.5 0 0,0 11.5,11A1.5,1.5 0 0,0 13,12.5A1.5,1.5 0 0,0 14.5,11A1.5,1.5 0 0,0 13,9.5Z"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
<!-- Canvas -->
<Button Width="40" Height="40" Margin="0,5,0,0" Style="{StaticResource NavButton}"
Click="NavCanvas_Click" Tag="canvas" ToolTip="画布设置">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M19,1L17.74,3.75L15,5L17.74,6.26L19,9L20.25,6.26L23,5L20.25,3.75M9,4L6.5,9.5L1,12L6.5,14.5L9,20L11.5,14.5L17,12L11.5,9.5"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
<!-- Gesture -->
<Button Width="40" Height="40" Margin="0,5,0,0" Style="{StaticResource NavButton}"
Click="NavGesture_Click" Tag="gesture" ToolTip="手势设置">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M13,6V11H18V7.75L22.25,12L18,16.25V13H13V18H16.25L12,22.25L7.75,18H11V13H6V16.25L1.75,12L6,7.75V11H11V6H7.75L12,1.75L16.25,6H13Z"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
<!-- Ink Recognition -->
<Button Width="40" Height="40" Margin="0,5,0,0" Style="{StaticResource NavButton}"
Click="NavInkRecognition_Click" Tag="inkrecognition" ToolTip="墨迹识别">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L15.12,5.12L18.87,8.87M3,17.25V21H6.75L17.81,9.93L14.06,6.18L3,17.25Z"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
<!-- Crash Action -->
<Button Width="40" Height="40" Margin="0,5,0,0" Style="{StaticResource NavButton}"
Click="NavCrashAction_Click" Tag="crashaction" ToolTip="崩溃处理">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M13 14H11V9H13M13 18H11V16H13M1 21H23L12 2L1 21Z"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
<!-- PPT -->
<Button Width="40" Height="40" Margin="0,5,0,0" Style="{StaticResource NavButton}"
Click="NavPPT_Click" Tag="ppt" ToolTip="PPT设置">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M2 2H22V4H2V2M2 8H22V10H2V8M2 14H22V16H2V14M2 20H22V22H2V20Z"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
<!-- Advanced -->
<Button Width="40" Height="40" Margin="0,5,0,0" Style="{StaticResource NavButton}"
Click="NavAdvanced_Click" Tag="advanced" ToolTip="高级设置">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
<!-- Automation -->
<Button Width="40" Height="40" Margin="0,5,0,0" Style="{StaticResource NavButton}"
Click="NavAutomation_Click" Tag="automation" ToolTip="自动化设置">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M12,0C8.96,0 6.21,1.23 4.22,3.22L5.63,4.63C7.24,3.01 9.5,2 12,2C14.5,2 16.76,3.01 18.36,4.63L19.77,3.22C17.79,1.23 15.04,0 12,0M7.05,6.05L8.46,7.46C9.37,6.56 10.62,6 12,6C13.38,6 14.63,6.56 15.54,7.46L16.95,6.05C15.68,4.78 13.93,4 12,4C10.07,4 8.32,4.78 7.05,6.05M12,15A2,2 0 0,1 10,13A2,2 0 0,1 12,11A2,2 0 0,1 14,13A2,2 0 0,1 12,15M15,9H9A1,1 0 0,0 8,10V22A1,1 0 0,0 9,23H15A1,1 0 0,0 16,22V10A1,1 0 0,0 15,9Z"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
<!-- Random Window -->
<Button Width="40" Height="40" Margin="0,5,0,0" Style="{StaticResource NavButton}"
Click="NavRandomWindow_Click" Tag="randomwindow" ToolTip="随机窗口设置">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M4,2H20A2,2 0 0,1 22,4V16A2,2 0 0,1 20,18H16L12,22L8,18H4A2,2 0 0,1 2,16V4A2,2 0 0,1 4,2M4,4V16H8.83L12,19.17L15.17,16H20V4H4M6,7H18V9H6V7M6,11H16V13H6V11Z"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
<!-- 新增:个性化设置 -->
<Button Width="40" Height="40" Margin="0,5,0,0" Style="{StaticResource NavButton}"
Click="NavTheme_Click" Tag="theme" ToolTip="个性化设置">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M12,18V6A6,6 0 0,1 18,12A6,6 0 0,1 12,18M20,15.31L23.31,12L20,8.69V4H15.31L12,0.69L8.69,4H4V8.69L0.69,12L4,15.31V20H8.69L12,23.31L15.31,20H20V15.31Z"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
<!-- 新增:快捷键设置 -->
<Button Width="40" Height="40" Margin="0,5,0,0" Style="{StaticResource NavButton}"
Click="NavShortcuts_Click" Tag="shortcuts" ToolTip="快捷键设置">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M20,5H4A2,2 0 0,0 2,7V17A2,2 0 0,0 4,19H20A2,2 0 0,0 22,17V7A2,2 0 0,0 20,5M20,17H4V7H20V17M5,8H7V10H5V8M8,8H10V10H8V8M11,8H13V10H11V8M14,8H16V10H14V8M17,8H19V10H17V8M5,11H7V13H5V11M8,11H10V13H8V11M11,11H13V13H11V11M14,11H16V13H14V11M17,11H19V13H17V11M8,14H16V16H8V14Z"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
<!-- About -->
<Button Width="40" Height="40" Margin="0,5,0,0" Style="{StaticResource NavButton}"
Click="NavAbout_Click" Tag="about" ToolTip="关于">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
</StackPanel>
</ScrollViewer>
<!-- 底部操作按钮 -->
<StackPanel Grid.Row="2" Margin="0,5,0,10">
<Separator Background="#3f3f46" Margin="5,0,5,10"/>
<!-- 折叠侧边栏按钮 -->
<Button Width="40" Height="40" Style="{StaticResource NavButton}"
Click="CollapseNavSidebar_Click" ToolTip="折叠侧边栏">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M20,11V13H8L13.5,18.5L12.08,19.92L4.16,12L12.08,4.08L13.5,5.5L8,11H20Z"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
</StackPanel>
</Grid>
</Border>
<!-- Content Area -->
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="80"/>
<RowDefinition Height="*"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<!-- 标题栏 -->
<Grid ClipToBounds="True" Grid.Row="0" Margin="0,0,0,0" Height="80" VerticalAlignment="Top">
<Border Background="#18181b" CornerRadius="0" Margin="-1,-1,-1,0">
<ui:SimpleStackPanel Orientation="Horizontal" VerticalAlignment="Center">
<!-- 显示侧边栏按钮 -->
<Button Width="40" Height="40" Margin="10,0,0,0" Style="{StaticResource NavButton}"
Click="ShowNavSidebar_Click" ToolTip="显示侧边栏">
<Image Width="24" Height="24">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="White"
Geometry="M4,11V13H16L10.5,18.5L11.92,19.92L19.84,12L11.92,4.08L10.5,5.5L16,11H4Z"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
<TextBlock Foreground="White" Margin="15,-2,0,0" Text="设置" FontWeight="Bold"
FontSize="32" />
</ui:SimpleStackPanel>
</Border>
<Canvas>
<Image Canvas.Top="12" Canvas.Right="-16" Width="98" Height="98" Opacity="0.4">
<Image.RenderTransform>
<!-- giving the transform a name tells the framework not to freeze it -->
<RotateTransform CenterX="49" CenterY="49" />
</Image.RenderTransform>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V257 H257 V0 H0 Z">
<GeometryDrawing Brush="GhostWhite"
Geometry="F0 M257,257z M0,0z M93.339,256.594L88.2444,215.634C85.4849,214.567 82.8846,213.287 80.4434,211.794 78.0023,210.301 75.6142,208.701 73.2793,206.994L35.3887,222.994 0.363831,162.194 33.1598,137.234C32.9476,135.741,32.8414,134.301,32.8414,132.914L32.8414,124.274C32.8414,122.887,32.9476,121.447,33.1598,119.954L0.363831,94.9941 35.3887,34.1941 73.2793,50.1941C75.6142,48.4874 78.0554,46.8874 80.6026,45.3941 83.1499,43.9007 85.6972,42.6207 88.2444,41.5541L93.339,0.594055 163.389,0.594055 168.483,41.5541C171.243,42.6207 173.843,43.9007 176.284,45.3941 178.725,46.8874 181.113,48.4874 183.448,50.1941L221.339,34.1941 256.364,94.9941 223.568,119.954C223.78,121.447,223.886,122.887,223.886,124.274L223.886,132.914C223.886,134.301,223.674,135.741,223.249,137.234L256.045,162.194 221.021,222.994 183.448,206.994C181.113,208.701 178.672,210.301 176.125,211.794 173.578,213.287 171.031,214.567 168.483,215.634L163.389,256.594 93.339,256.594z M160.523,160.274C151.82,169.021 141.312,173.394 129.001,173.394 116.477,173.394 105.916,169.021 97.3191,160.274 88.722,151.527 84.4235,140.967 84.4235,128.594 84.4235,116.221 88.722,105.661 97.3191,96.9141 105.916,88.1674 116.477,83.7941 129.001,83.7941 141.312,83.7941 151.82,88.1674 160.523,96.9141 169.226,105.661 173.578,116.221 173.578,128.594 173.578,140.967 169.226,151.527 160.523,160.274z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
<Image.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="(Image.RenderTransform).(RotateTransform.Angle)"
To="-360" Duration="0:0:3" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
</Canvas>
</Grid>
<!-- 内容区域 -->
<ui:ScrollViewerEx Grid.Row="1" Margin="0,0,0,0" VerticalScrollBarVisibility="Auto"
PanningMode="VerticalOnly" ui:ThemeManager.RequestedTheme="Dark"
ManipulationBoundaryFeedback="SCManipulationBoundaryFeedback"
Name="SettingsPanelScrollViewer">
<StackPanel Margin="20,20,20,20">
<Border Margin="0,0,0,10" Height="100" CornerRadius="5" BorderBrush="#a1a1aa"
@@ -589,7 +940,17 @@
<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" />
<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="LineStraightenSensitivitySlider" Width="150" Minimum="0.05" Maximum="0.75"
Value="0.10" TickFrequency="0.05" IsSnapToTickEnabled="True"
ValueChanged="LineStraightenSensitivitySlider_ValueChanged" />
<TextBlock Foreground="#fafafa" Text="{Binding ElementName=LineStraightenSensitivitySlider, Path=Value, StringFormat={}{0:F2}}"
VerticalAlignment="Center" FontSize="14" Margin="16,0,0,0" />
</ui:SimpleStackPanel>
<TextBlock Text="# 开启后,当绘制的直线超过设定长度阈值时,将自动调整为完美直线。灵敏度范围0.05-0.75,越小要求越严格,弯曲的线条越不容易被拉直;值越大越容易识别为直线。" 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">
@@ -2071,7 +2432,7 @@
<ui:SimpleStackPanel Orientation="Horizontal">
<TextBlock FontSize="18" FontWeight="Bold" Text="Version" />
<TextBlock x:Name="AppVersionTextBlock" FontSize="18" FontWeight="Bold"
Text="5.X.X.X" />
Text="1.X.X" />
</ui:SimpleStackPanel>
<TextBlock
Text="# 使用和分发本软件前,请您应当且务必知晓相关开源协议,且您应当知晓本软件基于 https://github.com/WXRIW/Ink-Canvas 修改而成。"
@@ -2385,55 +2746,41 @@
</GroupBox>
</StackPanel>
</ui:ScrollViewerEx>
<Grid ClipToBounds="True" Margin="0,0,0,0" Height="80" VerticalAlignment="Top">
<Border Background="#18181b" CornerRadius="0" Margin="-1,-1,-1,0">
<ui:SimpleStackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Foreground="White" Margin="25,-2,0,0" Text="设置" FontWeight="Bold"
FontSize="32" />
</ui:SimpleStackPanel>
</Border>
<Canvas>
<Image Canvas.Top="12" Canvas.Right="-16" Width="98" Height="98" Opacity="0.4">
<Image.RenderTransform>
<!-- giving the transform a name tells the framework not to freeze it -->
<RotateTransform CenterX="49" CenterY="49" />
</Image.RenderTransform>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V257 H257 V0 H0 Z">
<GeometryDrawing Brush="GhostWhite"
Geometry="F0 M257,257z M0,0z M93.339,256.594L88.2444,215.634C85.4849,214.567 82.8846,213.287 80.4434,211.794 78.0023,210.301 75.6142,208.701 73.2793,206.994L35.3887,222.994 0.363831,162.194 33.1598,137.234C32.9476,135.741,32.8414,134.301,32.8414,132.914L32.8414,124.274C32.8414,122.887,32.9476,121.447,33.1598,119.954L0.363831,94.9941 35.3887,34.1941 73.2793,50.1941C75.6142,48.4874 78.0554,46.8874 80.6026,45.3941 83.1499,43.9007 85.6972,42.6207 88.2444,41.5541L93.339,0.594055 163.389,0.594055 168.483,41.5541C171.243,42.6207 173.843,43.9007 176.284,45.3941 178.725,46.8874 181.113,48.4874 183.448,50.1941L221.339,34.1941 256.364,94.9941 223.568,119.954C223.78,121.447,223.886,122.887,223.886,124.274L223.886,132.914C223.886,134.301,223.674,135.741,223.249,137.234L256.045,162.194 221.021,222.994 183.448,206.994C181.113,208.701 178.672,210.301 176.125,211.794 173.578,213.287 171.031,214.567 168.483,215.634L163.389,256.594 93.339,256.594z M160.523,160.274C151.82,169.021 141.312,173.394 129.001,173.394 116.477,173.394 105.916,169.021 97.3191,160.274 88.722,151.527 84.4235,140.967 84.4235,128.594 84.4235,116.221 88.722,105.661 97.3191,96.9141 105.916,88.1674 116.477,83.7941 129.001,83.7941 141.312,83.7941 151.82,88.1674 160.523,96.9141 169.226,105.661 173.578,116.221 173.578,128.594 173.578,140.967 169.226,151.527 160.523,160.274z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
<Image.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="(Image.RenderTransform).(RotateTransform.Angle)"
To="-360" Duration="0:0:3" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
</Canvas>
</Grid>
<Grid VerticalAlignment="Bottom" Height="50">
<Button FontFamily="Microsoft YaHei UI"
<!-- 底部按钮区域 -->
<Grid Grid.Row="2" VerticalAlignment="Bottom" Height="50">
<Button FontFamily="Microsoft YaHei UI"
Width="120" Margin="10"
HorizontalAlignment="Right"
Content="关闭"
Click="BtnSettings_Click" />
</Grid>
</Grid>
Click="BtnCloseSettings_Click">
<ui:SimpleStackPanel Orientation="Horizontal" VerticalAlignment="Center"
HorizontalAlignment="Center" Spacing="0">
<Image RenderOptions.BitmapScalingMode="HighQuality"
Margin="0,0,6,0" Height="20" Width="20">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
<GeometryDrawing Brush="White"
Geometry="M19,6.41 L17.59,5 L12,10.59 L6.41,5 L5,6.41 L10.59,12 L5,17.59 L6.41,19 L12,13.41 L17.59,19 L19,17.59 L13.41,12 Z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
<Label FontSize="16" Foreground="#fafafa" VerticalAlignment="Center"
FontFamily="Microsoft YaHei UI" FontWeight="Bold">
关闭
</Label>
</ui:SimpleStackPanel>
</Button>
</Grid>
</Grid></Grid>
</Border>
</Grid>
<!--// 黑/白 板幕布 //-->
<Grid Name="GridBackgroundCoverHolder">
<Grid Name="GridBackgroundCover" Visibility="Collapsed" Background="#1F1F1F">
+434 -56
View File
@@ -18,6 +18,10 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.Win32;
using System.Windows.Input;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media.Animation;
using System.Reflection;
namespace Ink_Canvas {
public partial class MainWindow : Window {
@@ -154,28 +158,9 @@ 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;
// 修复触屏和数位笔时光标不显示:强制显示光标,不再依赖鼠标或触控状态
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;
}
// 使用辅助方法设置光标
SetCursorBasedOnEditingMode(inkCanvas1);
if (inkCanvas1.EditingMode == InkCanvasEditingMode.Ink) forcePointEraser = !forcePointEraser;
}
@@ -317,24 +302,169 @@ namespace Ink_Canvas {
SystemEvents.DisplaySettingsChanged -= SystemEventsOnDisplaySettingsChanged;
LogHelper.WriteLogToFile("Ink Canvas closed", LogHelper.LogType.Event);
// 检查是否有待安装的更新
CheckPendingUpdates();
}
private void CheckPendingUpdates()
{
try
{
// 如果有可用的更新版本且启用了自动更新
if (AvailableLatestVersion != null && Settings.Startup.IsAutoUpdate)
{
// 检查更新文件是否已下载
string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
string statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{AvailableLatestVersion}Status.txt");
if (File.Exists(statusFilePath) && File.ReadAllText(statusFilePath).Trim().ToLower() == "true")
{
LogHelper.WriteLogToFile($"AutoUpdate | Installing pending update v{AvailableLatestVersion} on application close");
// 设置为用户主动退出,避免被看门狗判定为崩溃
App.IsAppExitByUser = true;
// 创建批处理脚本并启动,软件关闭后会执行更新操作
AutoUpdateHelper.InstallNewVersionApp(AvailableLatestVersion, true);
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | Error checking pending updates: {ex.Message}", LogHelper.LogType.Error);
}
}
private async void AutoUpdate() {
AvailableLatestVersion = await AutoUpdateHelper.CheckForUpdates();
if (AvailableLatestVersion != null) {
var IsDownloadSuccessful = false;
IsDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFileAndSaveStatus(AvailableLatestVersion);
// 打开更新提示窗口
LogHelper.WriteLogToFile($"AutoUpdate | New version available: {AvailableLatestVersion}");
// 获取当前版本和发布日期
string currentVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
string releaseDate = DateTime.Now.ToString("yyyy年MM月dd日");
// 创建更新说明内容(可以从服务器获取或直接在此处设置)
string releaseNotes = $@"# InkCanvasForClass v{AvailableLatestVersion}更新
你好,此次更新包含了一系列新功能和改进:
if (IsDownloadSuccessful) {
if (!Settings.Startup.IsAutoUpdateWithSilence) {
if (MessageBox.Show("InkCanvasForClass 新版本安装包已下载完成,是否立即更新?",
"InkCanvasForClass New Version Available", MessageBoxButton.YesNo,
MessageBoxImage.Question) ==
MessageBoxResult.Yes) AutoUpdateHelper.InstallNewVersionApp(AvailableLatestVersion, false);
} else {
timerCheckAutoUpdateWithSilence.Start();
1. 修复了一些已知的bug
2. 优化了程序性能
3. 改进了用户界面
4. 添加了新的功能
感谢您使用InkCanvasForClass CE";
// 创建并显示更新窗口
HasNewUpdateWindow updateWindow = new HasNewUpdateWindow(currentVersion, AvailableLatestVersion, releaseDate, releaseNotes);
bool? dialogResult = updateWindow.ShowDialog();
// 声明下载结果变量
bool isDownloadSuccessful;
// 如果窗口被关闭但没有点击按钮,视为"稍后更新"
if (dialogResult != true) {
LogHelper.WriteLogToFile("AutoUpdate | Update dialog closed without selection");
// 更新自动更新设置并保存
Settings.Startup.IsAutoUpdate = updateWindow.IsAutoUpdateEnabled;
Settings.Startup.IsAutoUpdateWithSilence = updateWindow.IsSilentUpdateEnabled;
SaveSettingsToFile();
// 如果启用了静默更新,则自动下载更新
if (Settings.Startup.IsAutoUpdateWithSilence) {
LogHelper.WriteLogToFile("AutoUpdate | Silent update enabled, downloading update automatically");
// 静默下载更新
isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFileAndSaveStatus(AvailableLatestVersion);
if (isDownloadSuccessful) {
LogHelper.WriteLogToFile("AutoUpdate | Update downloaded successfully, will install when application closes");
// 启动检查定时器
timerCheckAutoUpdateWithSilence.Start();
} else {
LogHelper.WriteLogToFile("AutoUpdate | Silent update download failed", LogHelper.LogType.Error);
}
}
return;
}
// 更新自动更新设置并保存
Settings.Startup.IsAutoUpdate = updateWindow.IsAutoUpdateEnabled;
Settings.Startup.IsAutoUpdateWithSilence = updateWindow.IsSilentUpdateEnabled;
SaveSettingsToFile();
// 根据用户选择处理更新
switch (updateWindow.Result) {
case HasNewUpdateWindow.UpdateResult.UpdateNow:
// 立即更新:显示下载进度,下载完成后立即安装
LogHelper.WriteLogToFile("AutoUpdate | User chose to update now");
// 显示下载进度提示
MessageBox.Show("开始下载更新,请稍候...", "正在更新", MessageBoxButton.OK, MessageBoxImage.Information);
// 下载更新文件
isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFileAndSaveStatus(AvailableLatestVersion);
if (isDownloadSuccessful) {
// 下载成功,提示用户准备安装
MessageBoxResult result = MessageBox.Show("更新已下载完成,点击确定后将关闭软件并安装新版本!", "安装更新", MessageBoxButton.OKCancel, MessageBoxImage.Information);
// 只有当用户点击确定按钮后才关闭软件
if (result == MessageBoxResult.OK) {
// 设置为用户主动退出,避免被看门狗判定为崩溃
App.IsAppExitByUser = true;
// 准备批处理脚本
AutoUpdateHelper.InstallNewVersionApp(AvailableLatestVersion, false);
// 关闭软件,让安装程序接管
Application.Current.Shutdown();
} else {
LogHelper.WriteLogToFile("AutoUpdate | User cancelled update installation");
}
} else {
// 下载失败
MessageBox.Show("更新下载失败,请检查网络连接后重试。", "下载失败", MessageBoxButton.OK, MessageBoxImage.Error);
}
break;
case HasNewUpdateWindow.UpdateResult.UpdateLater:
// 稍后更新:静默下载,在软件关闭时自动安装
LogHelper.WriteLogToFile("AutoUpdate | User chose to update later");
// 不管设置如何,都进行下载
isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFileAndSaveStatus(AvailableLatestVersion);
if (isDownloadSuccessful) {
LogHelper.WriteLogToFile("AutoUpdate | Update downloaded successfully, will install when application closes");
// 设置标志,在应用程序关闭时安装
Settings.Startup.IsAutoUpdate = true;
Settings.Startup.IsAutoUpdateWithSilence = true;
// 启动检查定时器
timerCheckAutoUpdateWithSilence.Start();
// 通知用户
MessageBox.Show("更新已下载完成,将在软件关闭时自动安装。", "更新已准备就绪", MessageBoxButton.OK, MessageBoxImage.Information);
} else {
LogHelper.WriteLogToFile("AutoUpdate | Update download failed", LogHelper.LogType.Error);
MessageBox.Show("更新下载失败,请检查网络连接后重试。", "下载失败", MessageBoxButton.OK, MessageBoxImage.Error);
}
break;
case HasNewUpdateWindow.UpdateResult.SkipVersion:
// 跳过该版本:记录到设置中
LogHelper.WriteLogToFile($"AutoUpdate | User chose to skip version {AvailableLatestVersion}");
// 可以在设置中添加"已跳过的版本"列表
break;
}
} else {
AutoUpdateHelper.DeleteUpdatesFolder();
@@ -355,54 +485,302 @@ namespace Ink_Canvas {
SaveSettingsToFile();
}
// 添加一个辅助方法,根据当前编辑模式设置光标
private void SetCursorBasedOnEditingMode(InkCanvas canvas)
{
if (Settings.Canvas.IsShowCursor) {
canvas.UseCustomCursor = true;
canvas.ForceCursor = true;
// 根据编辑模式设置不同的光标
if (canvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
canvas.Cursor = Cursors.Cross;
} else if (canvas.EditingMode == InkCanvasEditingMode.Ink) {
var sri = Application.GetResourceStream(new Uri("Resources/Cursors/Pen.cur", UriKind.Relative));
if (sri != null)
canvas.Cursor = new Cursor(sri.Stream);
} else if (canvas.EditingMode == InkCanvasEditingMode.Select) {
canvas.Cursor = Cursors.Cross;
}
// 确保光标可见,无论是鼠标、触控还是手写笔
System.Windows.Forms.Cursor.Show();
// 强制应用光标设置
canvas.ForceCursor = true;
// 确保手写笔模式下也能显示光标
if (Tablet.TabletDevices.Count > 0) {
foreach (TabletDevice device in Tablet.TabletDevices) {
if (device.Type == TabletDeviceType.Stylus) {
// 手写笔设备存在,强制显示光标
System.Windows.Forms.Cursor.Show();
break;
}
}
}
} else {
canvas.UseCustomCursor = false;
canvas.ForceCursor = false;
System.Windows.Forms.Cursor.Show();
}
}
// 鼠标输入
private void inkCanvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
inkCanvas.Cursor = Cursors.Arrow;
// 使用辅助方法设置光标
SetCursorBasedOnEditingMode(inkCanvas);
}
// 手写笔输入
private void inkCanvas_StylusDown(object sender, StylusDownEventArgs e)
{
var sri = Application.GetResourceStream(new Uri("Resources/Cursors/Pen.cur", UriKind.Relative));
if (sri != null)
inkCanvas.Cursor = new Cursor(sri.Stream);
// 使用辅助方法设置光标
SetCursorBasedOnEditingMode(inkCanvas);
}
// 触摸输入,不隐藏光标
private void inkCanvas_TouchDown(object sender, TouchEventArgs e)
{
// 修改:根据用户设置决定是否强制显示自定义光标
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();
}
// 使用辅助方法设置光标
SetCursorBasedOnEditingMode(inkCanvas);
}
// 触摸结束,恢复光标
private void inkCanvas_TouchUp(object sender, TouchEventArgs e)
{
// 修改:根据当前模式和设置恢复光标状态
// 使用辅助方法设置光标
SetCursorBasedOnEditingMode(inkCanvas);
// 确保光标可见
if (Settings.Canvas.IsShowCursor) {
inkCanvas.ForceCursor = true;
// 确保鼠标光标对触摸可见
System.Windows.Forms.Cursor.Show();
} else {
inkCanvas.ForceCursor = false;
inkCanvas.UseCustomCursor = true;
System.Windows.Forms.Cursor.Show();
}
}
#endregion Definations and Loading
#region Navigation Sidebar Methods
// 侧边栏导航按钮事件处理
private void NavStartup_Click(object sender, RoutedEventArgs e)
{
// 切换到启动设置页面
ShowSettingsSection("startup");
}
private void NavCanvas_Click(object sender, RoutedEventArgs e)
{
// 切换到画布设置页面
ShowSettingsSection("canvas");
}
private void NavGesture_Click(object sender, RoutedEventArgs e)
{
// 切换到手势设置页面
ShowSettingsSection("gesture");
}
private void NavInkRecognition_Click(object sender, RoutedEventArgs e)
{
// 切换到墨迹识别设置页面
ShowSettingsSection("inkrecognition");
}
private void NavCrashAction_Click(object sender, RoutedEventArgs e)
{
// 切换到崩溃处理设置页面
ShowSettingsSection("crashaction");
}
private void NavPPT_Click(object sender, RoutedEventArgs e)
{
// 切换到PPT设置页面
ShowSettingsSection("ppt");
}
private void NavAdvanced_Click(object sender, RoutedEventArgs e)
{
// 切换到高级设置页面
ShowSettingsSection("advanced");
}
private void NavAutomation_Click(object sender, RoutedEventArgs e)
{
// 切换到自动化设置页面
ShowSettingsSection("automation");
}
private void NavRandomWindow_Click(object sender, RoutedEventArgs e)
{
// 切换到随机窗口设置页面
ShowSettingsSection("randomwindow");
}
private void NavAbout_Click(object sender, RoutedEventArgs e)
{
// 切换到关于页面
ShowSettingsSection("about");
}
// 新增:个性化设置
private void NavTheme_Click(object sender, RoutedEventArgs e)
{
// 切换到个性化设置页面
ShowSettingsSection("theme");
}
// 新增:快捷键设置
private void NavShortcuts_Click(object sender, RoutedEventArgs e)
{
// 切换到快捷键设置页面
ShowSettingsSection("shortcuts");
// 如果设置部分尚未快捷键
MessageBox.Show("设置功能正在开发中", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}
private void BtnCloseSettings_Click(object sender, RoutedEventArgs e)
{
// 关闭设置面板
BorderSettings.Visibility = Visibility.Collapsed;
BorderSettingsMask.IsHitTestVisible = false;
}
// 新增:折叠侧边栏
private void CollapseNavSidebar_Click(object sender, RoutedEventArgs e)
{
// 折叠/展开侧边栏
var columnDefinitions = ((Grid)BorderSettings.Child).ColumnDefinitions;
if (columnDefinitions[0].Width.Value == 50)
{
// 折叠侧边栏
columnDefinitions[0].Width = new GridLength(0);
}
else
{
// 展开侧边栏
columnDefinitions[0].Width = new GridLength(50);
}
}
// 新增:显示侧边栏
private void ShowNavSidebar_Click(object sender, RoutedEventArgs e)
{
// 确保侧边栏展开
var columnDefinitions = ((Grid)BorderSettings.Child).ColumnDefinitions;
columnDefinitions[0].Width = new GridLength(50);
}
// 辅助方法:显示指定的设置部分
private void ShowSettingsSection(string sectionTag)
{
// 显示设置面板
BorderSettings.Visibility = Visibility.Visible;
BorderSettingsMask.IsHitTestVisible = true;
// 获取SettingsPanelScrollViewer中的所有GroupBox
var stackPanel = SettingsPanelScrollViewer.Content as StackPanel;
if (stackPanel == null) return;
// 首先隐藏所有GroupBox
foreach (var child in stackPanel.Children)
{
if (child is GroupBox groupBox)
{
groupBox.Visibility = Visibility.Collapsed;
}
}
// 根据传入的sectionTag显示相应的设置部分
switch (sectionTag.ToLower())
{
case "startup":
// 显示启动设置
ShowGroupBoxByHeader(stackPanel, "启动");
break;
case "canvas":
// 显示画板和墨迹设置
ShowGroupBoxByHeader(stackPanel, "画板和墨迹");
break;
case "gesture":
// 显示手势设置
ShowGroupBoxByHeader(stackPanel, "手势");
break;
case "inkrecognition":
// 显示墨迹纠正设置
ShowGroupBoxByHeader(stackPanel, "墨迹纠正");
if (GroupBoxInkRecognition != null)
GroupBoxInkRecognition.Visibility = Visibility.Visible;
break;
case "crashaction":
// 显示崩溃后操作设置
ShowGroupBoxByHeader(stackPanel, "崩溃后操作");
break;
case "ppt":
// 显示PPT联动设置
ShowGroupBoxByHeader(stackPanel, "PPT联动");
break;
case "advanced":
// 显示高级设置
// 这里可能需要根据实际情况调整
break;
case "automation":
// 显示自动化设置
// 这里可能需要根据实际情况调整
break;
case "randomwindow":
// 显示随机窗口设置
if (GroupBoxRandWindow != null)
GroupBoxRandWindow.Visibility = Visibility.Visible;
break;
case "theme":
// 显示主题设置
if (GroupBoxAppearanceNewUI != null)
GroupBoxAppearanceNewUI.Visibility = Visibility.Visible;
break;
case "shortcuts":
// 显示快捷键设置
// 快捷键设置部分可能尚未实现
break;
case "about":
// 显示关于页面
ShowGroupBoxByHeader(stackPanel, "关于");
break;
default:
// 默认显示第一个GroupBox
if (stackPanel.Children.Count > 0 && stackPanel.Children[0] is GroupBox firstGroupBox)
{
firstGroupBox.Visibility = Visibility.Visible;
}
break;
}
// 滚动到顶部
SettingsPanelScrollViewer.ScrollToTop();
}
// 根据Header文本查找并显示GroupBox
private void ShowGroupBoxByHeader(StackPanel parent, string headerText)
{
foreach (var child in parent.Children)
{
if (child is GroupBox groupBox)
{
// 查找GroupBox的Header
if (groupBox.Header is TextBlock headerTextBlock &&
headerTextBlock.Text != null &&
headerTextBlock.Text.Contains(headerText))
{
groupBox.Visibility = Visibility.Visible;
return;
}
}
}
}
#endregion Navigation Sidebar Methods
}
}
+4 -36
View File
@@ -36,42 +36,10 @@ namespace Ink_Canvas {
} else {
forceEraser = true;
forcePointEraser = true;
double k = 1;
if (Settings.Canvas.EraserShapeType == 0) {
switch (BoardComboBoxEraserSize.SelectedIndex)
{
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(k * 90, k * 90);
} else if (Settings.Canvas.EraserShapeType == 1) {
switch (BoardComboBoxEraserSize.SelectedIndex)
{
case 0:
k = 0.7;
break;
case 1:
k = 0.9;
break;
case 3:
k = 1.2;
break;
case 4:
k = 1.6;
break;
}
inkCanvas.EraserShape = new RectangleStylusShape(k * 90 * 0.6, k * 90);
}
// 使用统一的方法应用橡皮擦形状,确保一致性
ApplyCurrentEraserShape();
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
drawingShapeMode = 0;
+56 -40
View File
@@ -282,6 +282,7 @@ namespace Ink_Canvas {
AnimationsHelper.HideWithSlideAndFade(BoardBorderRightPageListView);
if (BorderSettings.Visibility == Visibility.Visible) {
// 设置蒙版为不可点击,并移除背景
BorderSettingsMask.IsHitTestVisible = false;
BorderSettingsMask.Background = null;
var sb = new Storyboard();
@@ -403,6 +404,11 @@ namespace Ink_Canvas {
System.Windows.Controls.Canvas.SetLeft(FloatingbarSelectionBG, 28 * 5);
break;
}
case "shape": {
// 对图形模式进行特殊处理,不修改按钮UI状态
// 只隐藏相关面板,但保持图形绘制模式
break;
}
}
@@ -1422,44 +1428,9 @@ namespace Ink_Canvas {
forceEraser = true;
forcePointEraser = true;
if (Settings.Canvas.EraserShapeType == 0) {
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(k * 90, k * 90);
}
else if (Settings.Canvas.EraserShapeType == 1) {
double k = 1;
switch (Settings.Canvas.EraserSize) {
case 0:
k = 0.7;
break;
case 1:
k = 0.9;
break;
case 3:
k = 1.2;
break;
case 4:
k = 1.6;
break;
}
inkCanvas.EraserShape = new RectangleStylusShape(k * 90 * 0.6, k * 90);
}
// 即使手掌触发过面积擦,也强制应用当前的EraserShapeType设置
ApplyCurrentEraserShape();
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
if (EraserSizePanel.Visibility == Visibility.Collapsed) {
@@ -1498,6 +1469,33 @@ namespace Ink_Canvas {
inkCanvas_EditingModeChanged(inkCanvas, null);
CancelSingleFingerDragMode();
}
// 新增方法,根据当前设置应用橡皮擦形状
public void ApplyCurrentEraserShape() {
double k = 1;
switch (Settings.Canvas.EraserSize) {
case 0:
k = Settings.Canvas.EraserShapeType == 0 ? 0.5 : 0.7;
break;
case 1:
k = Settings.Canvas.EraserShapeType == 0 ? 0.8 : 0.9;
break;
case 3:
k = Settings.Canvas.EraserShapeType == 0 ? 1.25 : 1.2;
break;
case 4:
k = Settings.Canvas.EraserShapeType == 0 ? 1.8 : 1.6;
break;
}
if (Settings.Canvas.EraserShapeType == 0) {
// 圆形擦
inkCanvas.EraserShape = new EllipseStylusShape(k * 90, k * 90);
} else if (Settings.Canvas.EraserShapeType == 1) {
// 矩形黑板擦
inkCanvas.EraserShape = new RectangleStylusShape(k * 90 * 0.6, k * 90);
}
}
private void EraserIconByStrokes_Click(object sender, RoutedEventArgs e) {
@@ -1549,7 +1547,8 @@ namespace Ink_Canvas {
private void DrawShapePromptToPen() {
if (isLongPressSelected == true) {
HideSubPanels("pen");
// 如果是长按选中的状态,只隐藏面板,不切换到笔模式
HideSubPanels("shape");
}
else {
if (StackPanelCanvasControls.Visibility == Visibility.Visible)
@@ -1629,7 +1628,23 @@ namespace Ink_Canvas {
private void SettingsOverlayClick(object sender, MouseButtonEventArgs e) {
if (isOpeningOrHidingSettingsPane == true) return;
BtnSettings_Click(null, null);
// 获取点击的位置
Point clickPoint = e.GetPosition(BorderSettingsMask);
// 获取BorderSettings的位置和大小
Point settingsPosition = BorderSettings.TranslatePoint(new Point(0, 0), BorderSettingsMask);
Rect settingsRect = new Rect(
settingsPosition.X,
settingsPosition.Y,
BorderSettings.ActualWidth,
BorderSettings.ActualHeight
);
// 如果点击位置不在设置界面内部,才关闭设置界面
if (!settingsRect.Contains(clickPoint)) {
BtnSettings_Click(null, null);
}
}
private bool isOpeningOrHidingSettingsPane = false;
@@ -1639,6 +1654,7 @@ namespace Ink_Canvas {
HideSubPanels();
}
else {
// 设置蒙版为可点击,并添加半透明背景
BorderSettingsMask.IsHitTestVisible = true;
BorderSettingsMask.Background = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0));
SettingsPanelScrollViewer.ScrollToTop();
+52 -75
View File
@@ -749,6 +749,13 @@ namespace Ink_Canvas {
Settings.Canvas.LineEndpointSnappingThreshold = (int)e.NewValue;
SaveSettingsToFile();
}
private void LineStraightenSensitivitySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) {
if (!isLoaded) return;
Settings.InkToShape.LineStraightenSensitivity = e.NewValue;
SaveSettingsToFile();
}
#endregion
@@ -785,46 +792,17 @@ namespace Ink_Canvas {
ComboBoxEraserSizeFloatingBar.SelectedIndex = s.SelectedIndex;
ComboBoxEraserSize.SelectedIndex = s.SelectedIndex;
}
if (Settings.Canvas.EraserShapeType == 0) {
double k = 1;
switch (s.SelectedIndex) {
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(k * 90, k * 90);
} else if (Settings.Canvas.EraserShapeType == 1) {
double k = 1;
switch (s.SelectedIndex) {
case 0:
k = 0.7;
break;
case 1:
k = 0.9;
break;
case 3:
k = 1.2;
break;
case 4:
k = 1.6;
break;
}
inkCanvas.EraserShape = new RectangleStylusShape(k * 90 * 0.6, k * 90);
// 使用统一的方法应用橡皮擦形状
ApplyCurrentEraserShape();
// 确保当前处于橡皮擦模式时能立即看到效果
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
// 先切换一下模式,再切回来,确保橡皮擦形状得到刷新
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
}
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
SaveSettingsToFile();
}
@@ -833,23 +811,11 @@ namespace Ink_Canvas {
Settings.Canvas.EraserShapeType = 0;
SaveSettingsToFile();
CheckEraserTypeTab();
double k = 1;
switch (ComboBoxEraserSizeFloatingBar.SelectedIndex) {
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(k * 90, k * 90);
// 使用统一的方法应用橡皮擦形状
ApplyCurrentEraserShape();
// 确保当前处于橡皮擦模式时能立即看到效果
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
}
@@ -859,23 +825,11 @@ namespace Ink_Canvas {
Settings.Canvas.EraserShapeType = 1;
SaveSettingsToFile();
CheckEraserTypeTab();
double k = 1;
switch (ComboBoxEraserSizeFloatingBar.SelectedIndex) {
case 0:
k = 0.7;
break;
case 1:
k = 0.9;
break;
case 3:
k = 1.2;
break;
case 4:
k = 1.6;
break;
}
inkCanvas.EraserShape = new RectangleStylusShape(k * 90 * 0.6, k * 90);
// 使用统一的方法应用橡皮擦形状
ApplyCurrentEraserShape();
// 确保当前处于橡皮擦模式时能立即看到效果
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
}
@@ -1340,29 +1294,52 @@ namespace Ink_Canvas {
BoardToggleSwitchEnableMultiTouchMode.IsOn = ToggleSwitchEnableMultiTouchMode.IsOn;
else
ToggleSwitchEnableMultiTouchMode.IsOn = BoardToggleSwitchEnableMultiTouchMode.IsOn;
if (ToggleSwitchEnableMultiTouchMode.IsOn) {
if (!isInMultiTouchMode) {
// 保存当前编辑模式和绘图工具状态
InkCanvasEditingMode currentEditingMode = inkCanvas.EditingMode;
int currentDrawingShapeMode = drawingShapeMode;
bool currentForceEraser = forceEraser;
inkCanvas.StylusDown += MainWindow_StylusDown;
inkCanvas.StylusMove += MainWindow_StylusMove;
inkCanvas.StylusUp += MainWindow_StylusUp;
inkCanvas.TouchDown += MainWindow_TouchDown;
inkCanvas.TouchDown -= Main_Grid_TouchDown;
// 先设为None再设回原来的模式,避免可能的事件冲突
inkCanvas.EditingMode = InkCanvasEditingMode.None;
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
inkCanvas.Children.Clear();
isInMultiTouchMode = true;
// 恢复到之前的编辑状态
inkCanvas.EditingMode = currentEditingMode;
drawingShapeMode = currentDrawingShapeMode;
forceEraser = currentForceEraser;
}
} else {
if (isInMultiTouchMode) {
// 保存当前编辑模式和绘图工具状态
InkCanvasEditingMode currentEditingMode = inkCanvas.EditingMode;
int currentDrawingShapeMode = drawingShapeMode;
bool currentForceEraser = forceEraser;
inkCanvas.StylusDown -= MainWindow_StylusDown;
inkCanvas.StylusMove -= MainWindow_StylusMove;
inkCanvas.StylusUp -= MainWindow_StylusUp;
inkCanvas.TouchDown -= MainWindow_TouchDown;
inkCanvas.TouchDown += Main_Grid_TouchDown;
// 先设为None再设回原来的模式,避免可能的事件冲突
inkCanvas.EditingMode = InkCanvasEditingMode.None;
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
inkCanvas.Children.Clear();
isInMultiTouchMode = false;
// 恢复到之前的编辑状态
inkCanvas.EditingMode = currentEditingMode;
drawingShapeMode = currentDrawingShapeMode;
forceEraser = currentForceEraser;
}
}
+14 -2
View File
@@ -70,8 +70,17 @@ namespace Ink_Canvas {
BoundsWidth = Settings.Advanced.FingerModeBoundsWidth;
}
if (Settings.Startup.IsAutoUpdate) {
ToggleSwitchIsAutoUpdate.IsOn = true;
// Always show update setting in UI based on stored preference
ToggleSwitchIsAutoUpdate.IsOn = Settings.Startup.IsAutoUpdate;
// Always check for updates at startup, regardless of the setting
if (isStartup) {
LogHelper.WriteLogToFile("AutoUpdate | Running auto-update check at startup");
AutoUpdate();
}
// Call auto-update when setting is changed (not at startup)
else if (Settings.Startup.IsAutoUpdate) {
LogHelper.WriteLogToFile("AutoUpdate | Running auto-update check after settings change");
AutoUpdate();
}
@@ -578,6 +587,9 @@ namespace Ink_Canvas {
ToggleCheckboxEnableInkToShapeRectangle.IsChecked = Settings.InkToShape.IsInkToShapeRectangle;
ToggleCheckboxEnableInkToShapeRounded.IsChecked = Settings.InkToShape.IsInkToShapeRounded;
// 初始化直线拉直灵敏度
LineStraightenSensitivitySlider.Value = Settings.InkToShape.LineStraightenSensitivity;
} else {
Settings.InkToShape = new InkToShape();
}
+129 -9
View File
@@ -113,7 +113,16 @@ namespace Ink_Canvas {
private Task<bool> CheckIsDrawingShapesInMultiTouchMode() {
if (isInMultiTouchMode) {
ToggleSwitchEnableMultiTouchMode.IsOn = false;
// 不关闭多指书写模式,而是保存状态,暂时禁用多指书写相关的事件处理
// 不再调用 ToggleSwitchEnableMultiTouchMode.IsOn = false;
// 暂时禁用多指书写事件处理,以避免冲突
inkCanvas.StylusDown -= MainWindow_StylusDown;
inkCanvas.StylusMove -= MainWindow_StylusMove;
inkCanvas.StylusUp -= MainWindow_StylusUp;
inkCanvas.TouchDown -= MainWindow_TouchDown;
// 记录已暂时禁用多指书写模式,但实际上多指书写开关仍然为打开状态
lastIsInMultiTouchMode = true;
}
@@ -129,6 +138,14 @@ namespace Ink_Canvas {
inkCanvas.IsManipulationEnabled = true;
CancelSingleFingerDragMode();
}
else {
// 即使不是长按,也设置必要的绘图状态
forceEraser = true;
drawingShapeMode = 1;
inkCanvas.EditingMode = InkCanvasEditingMode.None;
inkCanvas.IsManipulationEnabled = true;
isLongPressSelected = true; // 设置为选中状态,避免抬笔后切换回笔模式
}
lastMouseDownSender = null;
if (isLongPressSelected) {
@@ -189,6 +206,14 @@ namespace Ink_Canvas {
inkCanvas.IsManipulationEnabled = true;
CancelSingleFingerDragMode();
}
else {
// 即使不是长按,也设置必要的绘图状态
forceEraser = true;
drawingShapeMode = 2;
inkCanvas.EditingMode = InkCanvasEditingMode.None;
inkCanvas.IsManipulationEnabled = true;
isLongPressSelected = true; // 设置为选中状态,避免抬笔后切换回笔模式
}
lastMouseDownSender = null;
if (isLongPressSelected) {
@@ -276,6 +301,7 @@ namespace Ink_Canvas {
drawingShapeMode = 3;
inkCanvas.EditingMode = InkCanvasEditingMode.None;
inkCanvas.IsManipulationEnabled = true;
isLongPressSelected = true; // 设置为选中状态,避免抬笔后切换回笔模式
CancelSingleFingerDragMode();
DrawShapePromptToPen();
}
@@ -435,7 +461,12 @@ namespace Ink_Canvas {
if (isLastTouchEraser) return;
//EraserContainer.Background = null;
//ImageEraser.Visibility = Visibility.Visible;
if (isWaitUntilNextTouchDown) return;
// 修复触屏状态下几何绘制功能不可用的问题
// 在几何绘制模式下,即使isWaitUntilNextTouchDown为true,也应该处理触摸移动事件
// 只有当多点触控时才需要等待下一次触摸
if (isWaitUntilNextTouchDown && dec.Count > 1) return;
if (dec.Count > 1) {
isWaitUntilNextTouchDown = true;
try {
@@ -447,11 +478,17 @@ namespace Ink_Canvas {
}
return;
}
// 在几何绘制模式下,确保处理单点触控的移动事件
Point touchPoint = e.GetTouchPoint(inkCanvas).Position;
MouseTouchMove(touchPoint);
return; // 处理完几何绘制后直接返回,不执行后面的代码
}
// 触摸移动时保持自定义光标显示
if (Settings.Canvas.IsShowCursor) {
inkCanvas.ForceCursor = true;
inkCanvas.UseCustomCursor = true; // 确保使用自定义光标
System.Windows.Forms.Cursor.Show();
}
@@ -484,6 +521,12 @@ namespace Ink_Canvas {
inkCanvas.EraserShape = new EllipseStylusShape(boundsWidth * k * eraserMultiplier,
boundsWidth * k * eraserMultiplier);
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
// 立即应用光标设置
if (Settings.Canvas.IsShowCursor) {
inkCanvas.Cursor = Cursors.Cross;
System.Windows.Forms.Cursor.Show();
}
}
else {
if (StackPanelPPTControls.Visibility == Visibility.Visible && inkCanvas.Strokes.Count == 0 &&
@@ -1339,8 +1382,34 @@ namespace Ink_Canvas {
ViewboxFloatingBar.IsHitTestVisible = true;
BlackboardUIGridForInkReplay.IsHitTestVisible = true;
// 在几何绘制模式下,确保正确处理触摸抬起事件
if (drawingShapeMode != 0) {
// 如果是几何绘制模式,确保将临时绘制的图形添加到永久图形中
if (lastTempStroke != null) {
// 将临时笔画添加到历史记录中
var strokes = new StrokeCollection();
strokes.Add(lastTempStroke);
timeMachine.CommitStrokeUserInputHistory(strokes);
// 清除临时笔画引用,以便下次绘制
lastTempStroke = null;
}
if (lastTempStrokeCollection != null && lastTempStrokeCollection.Count > 0) {
// 将临时笔画集合添加到历史记录中
timeMachine.CommitStrokeUserInputHistory(lastTempStrokeCollection);
// 清除临时笔画集合引用,以便下次绘制
lastTempStrokeCollection = new StrokeCollection();
}
// 如果不是长按选中的状态,则需要在抬起手指后重置isWaitUntilNextTouchDown
if (!isLongPressSelected && dec.Count == 0) {
isWaitUntilNextTouchDown = false;
}
}
inkCanvas_MouseUp(sender, null);
if (dec.Count == 0) isWaitUntilNextTouchDown = false;
// 修改此处逻辑,在长按选择图形模式下保持isWaitUntilNextTouchDown
if (dec.Count == 0 && !isLongPressSelected) isWaitUntilNextTouchDown = false;
}
private Stroke lastTempStroke = null;
@@ -1530,17 +1599,37 @@ namespace Ink_Canvas {
}
if (lastIsInMultiTouchMode) {
ToggleSwitchEnableMultiTouchMode.IsOn = true;
// 不再重新启用开关,而是恢复多指书写相关的事件处理
// ToggleSwitchEnableMultiTouchMode.IsOn = true;
// 恢复多指书写事件处理
inkCanvas.StylusDown += MainWindow_StylusDown;
inkCanvas.StylusMove += MainWindow_StylusMove;
inkCanvas.StylusUp += MainWindow_StylusUp;
inkCanvas.TouchDown += MainWindow_TouchDown;
lastIsInMultiTouchMode = false;
}
}
// 修改此处逻辑,确保在正确的情况下才切换回笔模式
if (drawingShapeMode != 9 && drawingShapeMode != 0 && drawingShapeMode != 24 && drawingShapeMode != 25) {
if (isLongPressSelected) { }
if (isLongPressSelected) {
// 如果是长按选中的情况,保持图形模式,不做任何切换
isWaitUntilNextTouchDown = true; // 保持当前绘图模式直到下一次触摸
}
else {
BtnPen_Click(null, null); //画完一次还原到笔模式
if (lastIsInMultiTouchMode) {
ToggleSwitchEnableMultiTouchMode.IsOn = true;
// 不再重新启用开关,而是恢复多指书写相关的事件处理
// ToggleSwitchEnableMultiTouchMode.IsOn = true;
// 恢复多指书写事件处理
inkCanvas.StylusDown += MainWindow_StylusDown;
inkCanvas.StylusMove += MainWindow_StylusMove;
inkCanvas.StylusUp += MainWindow_StylusUp;
inkCanvas.TouchDown += MainWindow_TouchDown;
lastIsInMultiTouchMode = false;
}
}
@@ -1566,7 +1655,15 @@ namespace Ink_Canvas {
else {
BtnPen_Click(null, null); //画完还原到笔模式
if (lastIsInMultiTouchMode) {
ToggleSwitchEnableMultiTouchMode.IsOn = true;
// 不再重新启用开关,而是恢复多指书写相关的事件处理
// ToggleSwitchEnableMultiTouchMode.IsOn = true;
// 恢复多指书写事件处理
inkCanvas.StylusDown += MainWindow_StylusDown;
inkCanvas.StylusMove += MainWindow_StylusMove;
inkCanvas.StylusUp += MainWindow_StylusUp;
inkCanvas.TouchDown += MainWindow_TouchDown;
lastIsInMultiTouchMode = false;
}
@@ -1612,7 +1709,15 @@ namespace Ink_Canvas {
BtnPen_Click(null, null); //画完还原到笔模式
if (lastIsInMultiTouchMode) {
ToggleSwitchEnableMultiTouchMode.IsOn = true;
// 不再重新启用开关,而是恢复多指书写相关的事件处理
// ToggleSwitchEnableMultiTouchMode.IsOn = true;
// 恢复多指书写事件处理
inkCanvas.StylusDown += MainWindow_StylusDown;
inkCanvas.StylusMove += MainWindow_StylusMove;
inkCanvas.StylusUp += MainWindow_StylusUp;
inkCanvas.TouchDown += MainWindow_TouchDown;
lastIsInMultiTouchMode = false;
}
}
@@ -1669,9 +1774,24 @@ namespace Ink_Canvas {
private void MainWindow_OnMouseMove(object sender, MouseEventArgs e) {
if (e.StylusDevice == null) {
// 鼠标移动时保持光标可见
System.Windows.Forms.Cursor.Show();
// 如果用户设置了显示光标,则确保光标显示正确
if (Settings.Canvas.IsShowCursor && inkCanvas != null) {
inkCanvas.ForceCursor = true;
inkCanvas.UseCustomCursor = true;
}
} else {
System.Windows.Forms.Cursor.Hide();
// 只有当用户未设置显示光标时才隐藏
if (!Settings.Canvas.IsShowCursor) {
System.Windows.Forms.Cursor.Hide();
} else if (inkCanvas != null) {
// 如果用户设置了显示光标,则确保光标显示正确
inkCanvas.ForceCursor = true;
inkCanvas.UseCustomCursor = true;
System.Windows.Forms.Cursor.Show();
}
}
}
}
@@ -13,6 +13,8 @@ namespace Ink_Canvas {
public partial class MainWindow : Window {
private StrokeCollection newStrokes = new StrokeCollection();
private List<Circle> circles = new List<Circle>();
private const double SNAP_THRESHOLD = 15.0; // Distance threshold for endpoint snapping
private const double LINE_STRAIGHTEN_THRESHOLD = 0.10; // 降低阈值,让直线检测更严格
private void inkCanvas_StrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e) {
if (Settings.Canvas.FitToCurve == true) drawingAttributes.FitToCurve = false;
@@ -20,108 +22,146 @@ namespace Ink_Canvas {
try {
inkCanvas.Opacity = 1;
// 直线自动拉直功能
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);
// 应用屏蔽压感功能 - 如果启用,所有笔画都使用统一粗细
if (Settings.Canvas.DisablePressure) {
var uniformPoints = new StylusPointCollection();
foreach (StylusPoint point in e.Stroke.StylusPoints) {
StylusPoint newPoint = new StylusPoint(point.X, point.Y, 0.5f); // 统一压感值为0.5
uniformPoints.Add(newPoint);
}
e.Stroke.StylusPoints = uniformPoints;
}
// 应用压感触屏模式 - 如果启用并且检测到触屏输入
else if (Settings.Canvas.EnablePressureTouchMode) {
bool isTouchInput = true;
foreach (StylusPoint point in e.Stroke.StylusPoints) {
// 检测是否为压感笔输入(压感笔的PressureFactor不等于0.5或0
if ((point.PressureFactor > 0.501 || point.PressureFactor < 0.5) && point.PressureFactor != 0) {
isTouchInput = false;
break;
}
// 如果最大距离小于线长的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);
}
// 如果是触屏输入,则应用模拟压感
if (isTouchInput) {
switch (Settings.Canvas.InkStyle) {
case 1:
if (penType == 0)
try {
var stylusPoints = new StylusPointCollection();
var n = e.Stroke.StylusPoints.Count - 1;
for (var i = 0; i <= n; i++) {
var speed = GetPointSpeed(e.Stroke.StylusPoints[Math.Max(i - 1, 0)].ToPoint(),
e.Stroke.StylusPoints[i].ToPoint(),
e.Stroke.StylusPoints[Math.Min(i + 1, n)].ToPoint());
var point = new StylusPoint();
if (speed >= 0.25)
point.PressureFactor = (float)(0.5 - 0.3 * (Math.Min(speed, 1.5) - 0.3) / 1.2);
else if (speed >= 0.05)
point.PressureFactor = (float)0.5;
else
point.PressureFactor = (float)(0.5 + 0.4 * (0.05 - speed) / 0.05);
point.X = e.Stroke.StylusPoints[i].X;
point.Y = e.Stroke.StylusPoints[i].Y;
stylusPoints.Add(point);
}
e.Stroke.StylusPoints = stylusPoints;
}
}
// 查找最近的端点
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;
catch { }
break;
case 0:
if (penType == 0)
try {
var stylusPoints = new StylusPointCollection();
var n = e.Stroke.StylusPoints.Count - 1;
var pressure = 0.1;
var x = 10;
if (n == 1) return;
if (n >= x) {
for (var i = 0; i < n - x; i++) {
var point = new StylusPoint();
point.PressureFactor = (float)0.5;
point.X = e.Stroke.StylusPoints[i].X;
point.Y = e.Stroke.StylusPoints[i].Y;
stylusPoints.Add(point);
}
for (var i = n - x; i <= n; i++) {
var point = new StylusPoint();
point.PressureFactor = (float)((0.5 - pressure) * (n - i) / x + pressure);
point.X = e.Stroke.StylusPoints[i].X;
point.Y = e.Stroke.StylusPoints[i].Y;
stylusPoints.Add(point);
}
}
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;
else {
for (var i = 0; i <= n; i++) {
var point = new StylusPoint();
point.PressureFactor = (float)(0.4 * (n - i) / n + pressure);
point.X = e.Stroke.StylusPoints[i].X;
point.Y = e.Stroke.StylusPoints[i].Y;
stylusPoints.Add(point);
}
}
e.Stroke.StylusPoints = stylusPoints;
}
}
// 应用吸附结果
newPoints.Add(startPointSnapped ? nearestToStart : startPoint);
newPoints.Add(endPointSnapped ? nearestToEnd : endPoint);
} else {
// 不启用吸附,直接使用原始端点
newPoints.Add(startPoint);
newPoints.Add(endPoint);
}
// 替换原有笔迹
e.Stroke.StylusPoints = newPoints;
catch { }
break;
}
}
}
if (Settings.InkToShape.IsInkToShapeEnabled && drawingShapeMode == 0 && !isInMultiTouchMode && penType == 0) {
// Apply line straightening and endpoint snapping if ink-to-shape is enabled
if (Settings.InkToShape.IsInkToShapeEnabled) {
// Check if this stroke could be a straight line
if (IsPotentialStraightLine(e.Stroke)) {
// Get start and end points of the stroke
Point startPoint = e.Stroke.StylusPoints[0].ToPoint();
Point endPoint = e.Stroke.StylusPoints[e.Stroke.StylusPoints.Count - 1].ToPoint();
// Try to snap endpoints to existing strokes
bool snapped = false;
if (Settings.InkToShape.IsInkToShapeRectangle || Settings.InkToShape.IsInkToShapeTriangle) {
Point[] snappedPoints = GetSnappedEndpoints(startPoint, endPoint);
if (snappedPoints != null) {
startPoint = snappedPoints[0];
endPoint = snappedPoints[1];
snapped = true;
}
}
// Create straight line stroke
if (snapped || ShouldStraightenLine(e.Stroke)) {
StylusPointCollection straightLinePoints = CreateStraightLine(startPoint, endPoint);
Stroke straightStroke = new Stroke(straightLinePoints) {
DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
};
// Replace the original stroke with the straightened one
SetNewBackupOfStroke();
_currentCommitType = CommitReason.ShapeRecognition;
inkCanvas.Strokes.Remove(e.Stroke);
inkCanvas.Strokes.Add(straightStroke);
_currentCommitType = CommitReason.UserInput;
// We can't modify e.Stroke directly, but we need to update newStrokes
// to ensure proper shape recognition for the straightened line
if (newStrokes.Contains(e.Stroke)) {
newStrokes.Remove(e.Stroke);
newStrokes.Add(straightStroke);
}
}
}
}
if (Settings.InkToShape.IsInkToShapeEnabled && !Environment.Is64BitProcess) {
void InkToShapeProcess() {
try {
newStrokes.Add(e.Stroke);
@@ -422,27 +462,13 @@ namespace Ink_Canvas {
InkToShapeProcess();
}
// 如果启用了屏蔽压感功能,强制所有点的压感值为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;
}
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) {
@@ -538,6 +564,221 @@ namespace Ink_Canvas {
if (Settings.Canvas.FitToCurve == true) drawingAttributes.FitToCurve = true;
}
// New method: Checks if a stroke is potentially a straight line
private bool IsPotentialStraightLine(Stroke stroke) {
// 确保有足够的点来进行线条分析
if (stroke.StylusPoints.Count < 5)
return false;
Point start = stroke.StylusPoints.First().ToPoint();
Point end = stroke.StylusPoints.Last().ToPoint();
double lineLength = GetDistance(start, end);
// 线条必须足够长才考虑拉直,至少30像素
if (lineLength < 30)
return false;
// 获取用户设置的灵敏度值
double sensitivity = Settings.InkToShape.LineStraightenSensitivity;
// 快速检查使用略宽松的阈值
double quickThreshold = Math.Min(sensitivity * 1.5, 0.20);
// 快速检查:计算几个关键点与直线的距离
if (stroke.StylusPoints.Count >= 10) {
// 取中点和1/4、3/4位置的点,快速检查偏差
int quarterIdx = stroke.StylusPoints.Count / 4;
int midIdx = stroke.StylusPoints.Count / 2;
int threeQuarterIdx = quarterIdx * 3;
Point quarterPoint = stroke.StylusPoints[quarterIdx].ToPoint();
Point midPoint = stroke.StylusPoints[midIdx].ToPoint();
Point threeQuarterPoint = stroke.StylusPoints[threeQuarterIdx].ToPoint();
double quarterDeviation = DistanceFromLineToPoint(start, end, quarterPoint);
double midDeviation = DistanceFromLineToPoint(start, end, midPoint);
double threeQuarterDeviation = DistanceFromLineToPoint(start, end, threeQuarterPoint);
// 如果任一点偏离太大,直接排除
double quickRelativeThreshold = lineLength * quickThreshold;
if (quarterDeviation > quickRelativeThreshold ||
midDeviation > quickRelativeThreshold ||
threeQuarterDeviation > quickRelativeThreshold) {
return false;
}
}
return true;
}
// New method: Determines if a stroke should be straightened into a line
private bool ShouldStraightenLine(Stroke stroke) {
// Basic implementation: check if points roughly follow a straight line
Point start = stroke.StylusPoints.First().ToPoint();
Point end = stroke.StylusPoints.Last().ToPoint();
// Calculate max deviation from the straight line between start and end
double maxDeviation = 0;
double lineLength = GetDistance(start, end);
// 如果线条太短,不进行拉直处理
if (lineLength < 50) {
return false;
}
// 获取用户设置的灵敏度值
double sensitivity = Settings.InkToShape.LineStraightenSensitivity;
// 计算点与直线的偏差
double totalDeviation = 0;
int pointCount = 0;
// Calculate deviation for each point
foreach (StylusPoint sp in stroke.StylusPoints) {
Point p = sp.ToPoint();
double deviation = DistanceFromLineToPoint(start, end, p);
maxDeviation = Math.Max(maxDeviation, deviation);
totalDeviation += deviation;
pointCount++;
}
// 计算平均偏差
double avgDeviation = totalDeviation / pointCount;
// 检查点分布的一致性 - 如果有些点偏离很大而其他点很接近直线,表明线条有明显弯曲
double deviationVariance = 0;
foreach (StylusPoint sp in stroke.StylusPoints) {
Point p = sp.ToPoint();
double deviation = DistanceFromLineToPoint(start, end, p);
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
}
deviationVariance /= pointCount;
// 如果最大偏差超过线长的阈值比例,或者偏差方差较大(表示不均匀弯曲),则不拉直
if ((maxDeviation / lineLength) > sensitivity) {
return false;
}
// 如果偏差方差大,说明线条弯曲不均匀
if (deviationVariance > (sensitivity * lineLength * 0.05)) {
return false;
}
// 检查中点偏离情况 - 针对弧形线条特别有效
if (stroke.StylusPoints.Count > 10) {
int midIndex = stroke.StylusPoints.Count / 2;
Point midPoint = stroke.StylusPoints[midIndex].ToPoint();
double midDeviation = DistanceFromLineToPoint(start, end, midPoint);
// 如果中点偏离过大,不拉直
if (midDeviation > (lineLength * sensitivity * 0.8)) {
return false;
}
}
return true;
}
// New method: Creates a straight line stroke between two points
private StylusPointCollection CreateStraightLine(Point start, Point end) {
StylusPointCollection points = new StylusPointCollection();
// 根据是否启用压感触屏模式决定如何设置压感
// 如果未启用压感触屏模式,则使用均匀粗细
if (!Settings.Canvas.EnablePressureTouchMode || Settings.Canvas.DisablePressure ||
Settings.InkToShape.IsInkToShapeNoFakePressureRectangle == true || penType == 1) {
// 使用均匀粗细(所有点压感值都是0.5f)
points.Add(new StylusPoint(start.X, start.Y, 0.5f));
// 可以添加一些额外的中间点使线条更平滑(均匀粗细)
double distance = GetDistance(start, end);
if (distance > 100) {
// 对于较长的线条,添加几个中间点
for (int i = 1; i < 3; i++) {
double ratio = i / 3.0;
Point midPoint = new Point(
start.X + (end.X - start.X) * ratio,
start.Y + (end.Y - start.Y) * ratio);
points.Add(new StylusPoint(midPoint.X, midPoint.Y, 0.5f));
}
}
points.Add(new StylusPoint(end.X, end.Y, 0.5f));
} else {
// 启用了压感触屏模式,使用变化的粗细(原有行为)
points.Add(new StylusPoint(start.X, start.Y, 0.4f));
// 添加中点,压感值较高,使线条中间较粗
Point midPoint = new Point((start.X + end.X) / 2, (start.Y + end.Y) / 2);
points.Add(new StylusPoint(midPoint.X, midPoint.Y, 0.8f));
points.Add(new StylusPoint(end.X, end.Y, 0.4f));
}
return points;
}
// New method: Gets distance from point to a line defined by two points
private double DistanceFromLineToPoint(Point lineStart, Point lineEnd, Point point) {
// Calculate distance from point to line defined by lineStart and lineEnd
double lineLength = GetDistance(lineStart, lineEnd);
if (lineLength == 0) return GetDistance(point, lineStart);
// Calculate the cross product to get the perpendicular distance
double distance = Math.Abs((lineEnd.Y - lineStart.Y) * point.X -
(lineEnd.X - lineStart.X) * point.Y +
lineEnd.X * lineStart.Y - lineEnd.Y * lineStart.X) / lineLength;
return distance;
}
// New method: Attempts to snap endpoints to existing stroke endpoints
private Point[] GetSnappedEndpoints(Point start, Point end) {
bool startSnapped = false;
bool endSnapped = false;
Point snappedStart = start;
Point snappedEnd = end;
// Check all strokes in canvas for potential snap points
foreach (Stroke stroke in inkCanvas.Strokes) {
if (stroke.StylusPoints.Count == 0) continue;
// Get stroke endpoints
Point strokeStart = stroke.StylusPoints.First().ToPoint();
Point strokeEnd = stroke.StylusPoints.Last().ToPoint();
// Check if start point should snap to an endpoint
if (!startSnapped) {
if (GetDistance(start, strokeStart) < SNAP_THRESHOLD) {
snappedStart = strokeStart;
startSnapped = true;
} else if (GetDistance(start, strokeEnd) < SNAP_THRESHOLD) {
snappedStart = strokeEnd;
startSnapped = true;
}
}
// Check if end point should snap to an endpoint
if (!endSnapped) {
if (GetDistance(end, strokeStart) < SNAP_THRESHOLD) {
snappedEnd = strokeStart;
endSnapped = true;
} else if (GetDistance(end, strokeEnd) < SNAP_THRESHOLD) {
snappedEnd = strokeEnd;
endSnapped = true;
}
}
// If both endpoints are snapped, we're done
if (startSnapped && endSnapped) break;
}
// Return snapped points if any snapping occurred
if (startSnapped || endSnapped) {
return new Point[] { snappedStart, snappedEnd };
}
return null;
}
private void SetNewBackupOfStroke() {
lastTouchDownStrokeCollection = inkCanvas.Strokes.Clone();
var whiteboardIndex = CurrentWhiteboardIndex;
@@ -656,31 +897,5 @@ 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));
}
}
}
+94 -13
View File
@@ -6,6 +6,9 @@ using System.Runtime.CompilerServices;
using System.Timers;
using System.Windows;
using MessageBox = System.Windows.MessageBox;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
namespace Ink_Canvas {
public class TimeViewModel : INotifyPropertyChanged {
@@ -302,24 +305,102 @@ namespace Ink_Canvas {
}
private void timerCheckAutoUpdateWithSilence_Elapsed(object sender, ElapsedEventArgs e) {
Dispatcher.Invoke(() => {
try {
if (!Topmost || inkCanvas.Strokes.Count > 0) return;
}
catch (Exception ex) {
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
}
});
// 停止计时器,避免重复触发
timerCheckAutoUpdateWithSilence.Stop();
try {
if (AutoUpdateWithSilenceTimeComboBox.CheckIsInSilencePeriod(
Settings.Startup.AutoUpdateWithSilenceStartTime,
Settings.Startup.AutoUpdateWithSilenceEndTime)) {
// 检查是否有可用的更新
if (string.IsNullOrEmpty(AvailableLatestVersion)) {
LogHelper.WriteLogToFile("AutoUpdate | No available update version found");
return;
}
// 检查是否启用了静默更新
if (!Settings.Startup.IsAutoUpdateWithSilence) {
LogHelper.WriteLogToFile("AutoUpdate | Silent update is disabled");
return;
}
// 检查更新文件是否已下载
string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
string statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{AvailableLatestVersion}Status.txt");
if (!File.Exists(statusFilePath) || File.ReadAllText(statusFilePath).Trim().ToLower() != "true") {
LogHelper.WriteLogToFile("AutoUpdate | Update file not downloaded yet");
// 尝试下载更新文件
Task.Run(async () => {
bool isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFileAndSaveStatus(AvailableLatestVersion);
if (isDownloadSuccessful) {
LogHelper.WriteLogToFile("AutoUpdate | Update downloaded successfully, will check again for installation");
// 重新启动计时器,下次检查时安装
timerCheckAutoUpdateWithSilence.Start();
} else {
LogHelper.WriteLogToFile("AutoUpdate | Failed to download update", LogHelper.LogType.Error);
}
});
return;
}
// 检查是否在静默更新时间段内
bool isInSilencePeriod = AutoUpdateWithSilenceTimeComboBox.CheckIsInSilencePeriod(
Settings.Startup.AutoUpdateWithSilenceStartTime,
Settings.Startup.AutoUpdateWithSilenceEndTime);
if (!isInSilencePeriod) {
LogHelper.WriteLogToFile("AutoUpdate | Not in silence update time period");
// 重新启动计时器,稍后再检查
timerCheckAutoUpdateWithSilence.Start();
return;
}
// 检查应用程序状态,确保可以安全更新
bool canSafelyUpdate = false;
Dispatcher.Invoke(() => {
try {
// 检查是否处于桌面模式(Topmost为true)且没有墨迹内容
if (Topmost && inkCanvas.Strokes.Count == 0) {
// 检查是否有未保存的内容或正在进行的操作
if (!isHidingSubPanelsWhenInking) {
canSafelyUpdate = true;
LogHelper.WriteLogToFile("AutoUpdate | Application is in a safe state for update");
} else {
LogHelper.WriteLogToFile("AutoUpdate | Application is currently performing operations");
}
} else {
LogHelper.WriteLogToFile("AutoUpdate | Application has unsaved content or is not in desktop mode");
}
}
catch (Exception ex) {
LogHelper.WriteLogToFile($"AutoUpdate | Error checking application state: {ex.Message}", LogHelper.LogType.Error);
}
});
if (canSafelyUpdate) {
LogHelper.WriteLogToFile("AutoUpdate | Installing update now");
// 设置为用户主动退出,避免被看门狗判定为崩溃
App.IsAppExitByUser = true;
// 执行更新安装
AutoUpdateHelper.InstallNewVersionApp(AvailableLatestVersion, true);
timerCheckAutoUpdateWithSilence.Stop();
// 关闭应用程序
Dispatcher.Invoke(() => {
Application.Current.Shutdown();
});
} else {
LogHelper.WriteLogToFile("AutoUpdate | Cannot safely update now, will try again later");
// 重新启动计时器,稍后再检查
timerCheckAutoUpdateWithSilence.Start();
}
}
catch (Exception ex) {
LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
LogHelper.WriteLogToFile($"AutoUpdate | Error in silent update check: {ex.Message}", LogHelper.LogType.Error);
// 出错时重新启动计时器,稍后再检查
timerCheckAutoUpdateWithSilence.Start();
}
}
}
+48 -3
View File
@@ -91,6 +91,24 @@ namespace Ink_Canvas {
ViewboxFloatingBar.IsHitTestVisible = false;
BlackboardUIGridForInkReplay.IsHitTestVisible = false;
// 确保手写笔模式下显示光标
if (Settings.Canvas.IsShowCursor) {
inkCanvas.ForceCursor = true;
inkCanvas.UseCustomCursor = true;
// 根据当前编辑模式设置不同的光标
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
inkCanvas.Cursor = Cursors.Cross;
} else if (inkCanvas.EditingMode == InkCanvasEditingMode.Ink) {
var sri = Application.GetResourceStream(new Uri("Resources/Cursors/Pen.cur", UriKind.Relative));
if (sri != null)
inkCanvas.Cursor = new Cursor(sri.Stream);
}
// 强制显示光标
System.Windows.Forms.Cursor.Show();
}
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint
|| inkCanvas.EditingMode == InkCanvasEditingMode.EraseByStroke
|| inkCanvas.EditingMode == InkCanvasEditingMode.Select) return;
@@ -137,6 +155,13 @@ namespace Ink_Canvas {
}
catch { }
// 确保手写笔移动时光标保持可见
if (Settings.Canvas.IsShowCursor) {
inkCanvas.ForceCursor = true;
inkCanvas.UseCustomCursor = true;
System.Windows.Forms.Cursor.Show();
}
var strokeVisual = GetStrokeVisual(e.StylusDevice.Id);
var stylusPointCollection = e.GetStylusPoints(this);
foreach (var stylusPoint in stylusPointCollection)
@@ -224,8 +249,17 @@ namespace Ink_Canvas {
break;
}
inkCanvas.EraserShape = new EllipseStylusShape(boundsWidth * k * eraserMultiplier,
boundsWidth * k * eraserMultiplier);
// 根据EraserShapeType设置合适的橡皮擦形状
if (Settings.Canvas.EraserShapeType == 0) {
// 圆形擦
inkCanvas.EraserShape = new EllipseStylusShape(boundsWidth * k * eraserMultiplier,
boundsWidth * k * eraserMultiplier);
} else if (Settings.Canvas.EraserShapeType == 1) {
// 矩形黑板擦
inkCanvas.EraserShape = new RectangleStylusShape(boundsWidth * k * eraserMultiplier * 0.6,
boundsWidth * k * eraserMultiplier);
}
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
}
else {
@@ -245,7 +279,8 @@ namespace Ink_Canvas {
isLastTouchEraser = false;
// 修复面积擦时不显示橡皮形状:无论 forcePointEraser 状态,均显示 50x50 橡皮
inkCanvas.EraserShape = new EllipseStylusShape(50, 50);
if (forceEraser) return;
// 修复触屏状态下几何绘制功能不可用的问题:在几何绘制模式下不应该因为forceEraser而直接返回
if (forceEraser && drawingShapeMode == 0) return;
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
}
}
@@ -304,6 +339,16 @@ namespace Ink_Canvas {
inkCanvas.EditingMode = lastInkCanvasEditingMode;
dec.Remove(e.TouchDevice.Id);
inkCanvas.Opacity = 1;
// 如果是手掌触发的面积擦抬起,需要确保橡皮擦形状被正确重置
if (isLastTouchEraser && dec.Count == 0) {
isLastTouchEraser = false;
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint && forcePointEraser) {
// 重新应用当前设置的橡皮擦形状
ApplyCurrentEraserShape();
}
}
if (dec.Count == 0)
if (lastTouchDownStrokeCollection.Count() != inkCanvas.Strokes.Count() &&
!(drawingShapeMode == 9 && !isFirstTouchCuboid)) {
+15 -1
View File
@@ -65,8 +65,22 @@ namespace Ink_Canvas
var mainWin = (MainWindow)Application.Current.MainWindow;
if (mainWin.IsLoaded) {
App.IsAppExitByUser = true;
try {
// 启动新实例
string exePath = Process.GetCurrentProcess().MainModule.FileName;
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = exePath;
startInfo.UseShellExecute = true;
// 启动进程但不等待
Process.Start(startInfo);
} catch (Exception ex) {
LogHelper.NewLog($"重启程序时出错: {ex.Message}");
}
// 退出当前实例
Application.Current.Shutdown();
// mainWin.BtnExit_Click(null,null);
}
}
+2 -2
View File
@@ -49,5 +49,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("5.0.5.1")]
[assembly: AssemblyFileVersion("5.0.5.1")]
[assembly: AssemblyVersion("1.6.6")]
[assembly: AssemblyFileVersion("1.6.6")]
+2
View File
@@ -409,6 +409,8 @@ namespace Ink_Canvas
public bool IsInkToShapeRectangle { get; set; } = true;
[JsonProperty("isInkToShapeRounded")]
public bool IsInkToShapeRounded { get; set; } = true;
[JsonProperty("lineStraightenSensitivity")]
public double LineStraightenSensitivity { get; set; } = 0.10; // 直线检测灵敏度,值越小越严格(0.05-0.75)
}
public class RandSettings {
+69 -23
View File
@@ -10,20 +10,24 @@
ui:WindowHelper.UseModernWindowStyle = "True"
ui:WindowHelper.SystemBackdropType="Mica"
ui:TitleBar.Height="36"
Title="InkCanvasForClass有新版本可用" Height="475" Width="800" ResizeMode="NoResize">
<Grid Background="#fafafa">
<ui:SimpleStackPanel VerticalAlignment="Stretch" Spacing="0">
Title="InkCanvasForClass CE有新版本可用" Height="680" Width="850" ResizeMode="NoResize"
WindowStartupLocation="CenterScreen">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<Grid Background="#fafafa" Margin="0,0,0,30">
<ui:SimpleStackPanel VerticalAlignment="Stretch" Spacing="0">
<!-- 标题栏 -->
<ui:SimpleStackPanel Orientation="Horizontal" Background="#2563eb" Margin="0,0,0,0">
<ui:SimpleStackPanel Orientation="Vertical" Width="685" Margin="24,18,0,12" Spacing="2">
<TextBlock Text="InkCanvasForClass 新版本来了!" FontSize="24" FontWeight="Bold" Foreground="White" TextAlignment="Left"/>
<ui:SimpleStackPanel Orientation="Vertical" Width="735" Margin="24,18,0,12" Spacing="2">
<TextBlock Text="InkCanvasForClass CE新版本来了!" FontSize="24" FontWeight="Bold" Foreground="White" TextAlignment="Left"/>
<TextBlock Text="希望您能喜欢我们的新版本 :-)" FontSize="20" TextAlignment="Left" Foreground="White"/>
</ui:SimpleStackPanel>
<Image Source="/Resources/Icons-fluent/party.png" Width="72" Height="72"/>
</ui:SimpleStackPanel>
<Border BorderBrush="#3f3f46" Background="White" BorderThickness="1" CornerRadius="4" Margin="24,12,24,0">
<ui:ScrollViewerEx Margin="0" VerticalScrollBarVisibility="Auto" Height="256" PanningMode="VerticalOnly">
<mdxam:MarkdownScrollViewer xml:space="preserve" Foreground="Black" MarkdownStyleName="GithubLike">
<!-- 更新内容 -->
<Border BorderBrush="#3f3f46" Background="White" BorderThickness="1" CornerRadius="4" Margin="24,16,24,0">
<ui:ScrollViewerEx Margin="0" VerticalScrollBarVisibility="Auto" Height="180" PanningMode="VerticalOnly">
<mdxam:MarkdownScrollViewer x:Name="markdownContent" xml:space="preserve" Foreground="Black" MarkdownStyleName="GithubLike">
# InkCanvasForClass v5.0.2更新
你好,旅行者们,本次InkCanvasForClass更新带来了如下新功能供您探索:
@@ -39,21 +43,63 @@
</mdxam:MarkdownScrollViewer>
</ui:ScrollViewerEx>
</Border>
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="12" Margin="0,8,0,0">
<TextBlock Text="本次更新: 4.9.1 -> 5.9.1" FontWeight="Bold" FontSize="14" TextAlignment="Center"/>
<TextBlock Text="2024年8月4日发布更新" FontSize="14" TextAlignment="Center"/>
<!-- 版本信息 -->
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="16" Margin="0,16,0,0">
<TextBlock x:Name="updateVersionInfo" Text="本次更新: 4.9.1 -> 5.9.1" FontWeight="Bold" FontSize="15" TextAlignment="Center"/>
<TextBlock x:Name="updateDateInfo" Text="2024年8月4日发布更新" FontSize="15" TextAlignment="Center"/>
</ui:SimpleStackPanel>
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="12">
<Button Content="立刻更新" Foreground="White" HorizontalAlignment="Center" Margin="0,10,0,0">
<Button.Resources>
<SolidColorBrush x:Key="{x:Static ui:ThemeKeys.ButtonBackgroundKey}" Color="#15803d"/>
<SolidColorBrush x:Key="{x:Static ui:ThemeKeys.ButtonBackgroundPointerOverKey}" Color="#15803d"/>
<SolidColorBrush x:Key="{x:Static ui:ThemeKeys.ButtonBackgroundPressedKey}" Color="#166534"/>
</Button.Resources>
</Button>
<Button Content="下次更新" Foreground="Black" HorizontalAlignment="Center" Margin="0,10,0,0"/>
<Button Content="跳过该版本" HorizontalAlignment="Center" Foreground="#71717a" Margin="0,10,0,0"/>
<!-- 自动更新选项 -->
<Border Background="White" BorderBrush="#e2e8f0" BorderThickness="1" CornerRadius="4" Margin="24,16,24,0">
<ui:SimpleStackPanel Orientation="Vertical" HorizontalAlignment="Center" Margin="0,16,0,16" Spacing="10">
<TextBlock Text="更新设置" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center" Margin="0,0,0,6"/>
<!-- 水平排列两个ToggleSwitch -->
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="20">
<ui:SimpleStackPanel Orientation="Vertical" Spacing="4">
<ui:ToggleSwitch x:Name="EnableAutoUpdateToggle" Header="启用自动更新" OnContent="开启" OffContent="关闭" IsOn="True" Width="170" Foreground="Black"/>
</ui:SimpleStackPanel>
<ui:SimpleStackPanel Orientation="Vertical" Spacing="4">
<ui:ToggleSwitch x:Name="EnableSilentUpdateToggle" Header="启用静默更新" OnContent="开启" OffContent="关闭" Width="170" Foreground="Black"/>
</ui:SimpleStackPanel>
</ui:SimpleStackPanel>
<TextBlock Text="静默更新将在软件不使用时自动安装,无需手动操作" FontSize="13" Foreground="#71717a" HorizontalAlignment="Center"
Margin="4,0,0,0" Width="360" TextWrapping="Wrap"/>
</ui:SimpleStackPanel>
</Border>
<!-- 更新按钮组 -->
<Border Background="#f1f5f9" BorderBrush="#e2e8f0" BorderThickness="1" CornerRadius="4" Margin="24,16,24,20">
<ui:SimpleStackPanel Orientation="Vertical" HorizontalAlignment="Center" Spacing="14" Margin="0,16,0,16">
<TextBlock Text="请选择更新方式" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center" Margin="0,0,0,6"/>
<!-- 立即更新按钮 -->
<Button x:Name="UpdateNowButton" Content="立刻下载并安装" Foreground="White" FontSize="15" FontWeight="SemiBold"
Padding="20,10" Width="360" Height="48" HorizontalAlignment="Center"
Click="UpdateNowButton_Click" ToolTip="立即下载更新并在完成后安装" Visibility="Visible" IsEnabled="True">
<Button.Resources>
<SolidColorBrush x:Key="{x:Static ui:ThemeKeys.ButtonBackgroundKey}" Color="#15803d"/>
<SolidColorBrush x:Key="{x:Static ui:ThemeKeys.ButtonBackgroundPointerOverKey}" Color="#15803d"/>
<SolidColorBrush x:Key="{x:Static ui:ThemeKeys.ButtonBackgroundPressedKey}" Color="#166534"/>
</Button.Resources>
</Button>
<!-- 稍后更新按钮 -->
<Button x:Name="UpdateLaterButton" Content="下载并在软件关闭时安装" Foreground="Black" FontSize="15"
Padding="20,10" Width="360" Height="48" HorizontalAlignment="Center"
Click="UpdateLaterButton_Click" Background="#e2e8f0" BorderBrush="#cbd5e1"
ToolTip="后台下载更新,在软件关闭时自动安装" Visibility="Visible" IsEnabled="True"/>
<!-- 跳过版本按钮 -->
<Button x:Name="SkipVersionButton" Content="跳过该版本" HorizontalAlignment="Center" Foreground="#71717a"
FontSize="15" Padding="20,10" Width="360" Height="48" Click="SkipVersionButton_Click"
Background="#f8fafc" BorderBrush="#cbd5e1" ToolTip="跳过此版本更新" Visibility="Visible" IsEnabled="True"/>
</ui:SimpleStackPanel>
</Border>
</ui:SimpleStackPanel>
</ui:SimpleStackPanel>
</Grid>
</Grid>
</ScrollViewer>
</Window>
+252 -3
View File
@@ -45,7 +45,7 @@ namespace Ink_Canvas
}
int useImmersiveDarkMode = enabled ? 1 : 0;
return DwmSetWindowAttribute(handle, (int)attribute, ref useImmersiveDarkMode, sizeof(int)) == 0;
return DwmSetWindowAttribute(handle, attribute, ref useImmersiveDarkMode, sizeof(int)) == 0;
}
return false;
@@ -55,12 +55,261 @@ namespace Ink_Canvas
{
return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build >= build;
}
public HasNewUpdateWindow()
// 存储更新版本信息
public string CurrentVersion { get; set; }
public string NewVersion { get; set; }
public string ReleaseDate { get; set; }
public string ReleaseNotes { get; set; }
// 更新按钮结果
public enum UpdateResult
{
UpdateNow,
UpdateLater,
SkipVersion
}
public UpdateResult Result { get; private set; } = UpdateResult.UpdateLater;
// 更新设置
public bool IsAutoUpdateEnabled => EnableAutoUpdateToggle.IsOn;
public bool IsSilentUpdateEnabled => EnableSilentUpdateToggle.IsOn;
public HasNewUpdateWindow(string currentVersion, string newVersion, string releaseDate, string releaseNotes = null)
{
InitializeComponent();
// 设置版本信息
CurrentVersion = currentVersion;
NewVersion = newVersion;
ReleaseDate = releaseDate;
ReleaseNotes = releaseNotes;
// 更新UI
updateVersionInfo.Text = $"本次更新: {CurrentVersion} -> {NewVersion}";
updateDateInfo.Text = $"{ReleaseDate}发布更新";
// 如果有发布说明,设置到Markdown内容中
if (!string.IsNullOrEmpty(ReleaseNotes))
{
markdownContent.Markdown = ReleaseNotes;
}
// 初始化自动更新设置
EnableAutoUpdateToggle.IsOn = MainWindow.Settings.Startup.IsAutoUpdate;
EnableSilentUpdateToggle.IsOn = MainWindow.Settings.Startup.IsAutoUpdateWithSilence;
// 确保按钮可见且可用
EnsureButtonsVisibility();
// 显示窗口动画
AnimationsHelper.ShowWithFadeIn(this, 0.25);
Trace.WriteLine(new WindowInteropHelper(this).Handle);
// 设置深色模式
UseImmersiveDarkMode(new WindowInteropHelper(this).Handle, true);
// 窗口加载完成后再次确保按钮可见
this.Loaded += HasNewUpdateWindow_Loaded;
}
private void HasNewUpdateWindow_Loaded(object sender, RoutedEventArgs e)
{
// 窗口加载完成后再次确保按钮可见
EnsureButtonsVisibility();
// 调整窗口大小以适应屏幕分辨率
AdjustWindowSizeForScreenResolution();
}
// 确保按钮可见并启用
private void EnsureButtonsVisibility()
{
// 确保立即更新按钮可见
UpdateNowButton.Visibility = Visibility.Visible;
UpdateNowButton.IsEnabled = true;
// 确保稍后更新按钮可见
UpdateLaterButton.Visibility = Visibility.Visible;
UpdateLaterButton.IsEnabled = true;
// 确保跳过版本按钮可见
SkipVersionButton.Visibility = Visibility.Visible;
SkipVersionButton.IsEnabled = true;
// 强制刷新UI
UpdateLayout();
// 记录日志
LogHelper.WriteLogToFile("AutoUpdate | Update dialog buttons visibility ensured");
}
private void UpdateNowButton_Click(object sender, RoutedEventArgs e)
{
LogHelper.WriteLogToFile("AutoUpdate | Update Now button clicked");
// 保存自动更新设置
SaveUpdateSettings();
// 设置结果为立即更新
Result = UpdateResult.UpdateNow;
// 关闭窗口,返回到MainWindow处理后续下载和安装流程
DialogResult = true;
Close();
}
private void UpdateLaterButton_Click(object sender, RoutedEventArgs e)
{
LogHelper.WriteLogToFile("AutoUpdate | Update Later button clicked");
// 保存自动更新设置
SaveUpdateSettings();
// 设置结果为稍后更新
Result = UpdateResult.UpdateLater;
// 关闭窗口
DialogResult = true;
Close();
}
private void SkipVersionButton_Click(object sender, RoutedEventArgs e)
{
LogHelper.WriteLogToFile("AutoUpdate | Skip Version button clicked");
// 保存自动更新设置
SaveUpdateSettings();
// 设置结果为跳过该版本
Result = UpdateResult.SkipVersion;
// 关闭窗口
DialogResult = true;
Close();
}
private void SaveUpdateSettings()
{
// 保存自动更新设置
MainWindow.Settings.Startup.IsAutoUpdate = EnableAutoUpdateToggle.IsOn;
MainWindow.Settings.Startup.IsAutoUpdateWithSilence = EnableSilentUpdateToggle.IsOn;
// 记录到日志
LogHelper.WriteLogToFile($"AutoUpdate | User settings changed: AutoUpdate={EnableAutoUpdateToggle.IsOn}, SilentUpdate={EnableSilentUpdateToggle.IsOn}");
}
// 根据屏幕分辨率调整窗口大小
private void AdjustWindowSizeForScreenResolution()
{
try
{
// 获取主屏幕分辨率
double screenWidth = SystemParameters.PrimaryScreenWidth;
double screenHeight = SystemParameters.PrimaryScreenHeight;
LogHelper.WriteLogToFile($"AutoUpdate | Screen resolution: {screenWidth}x{screenHeight}");
// 始终确保窗口不超过屏幕大小的85%
double maxHeight = screenHeight * 0.85;
double maxWidth = screenWidth * 0.85;
bool needsAdjustment = false;
// 如果窗口高度超过最大允许高度,调整窗口高度
if (this.Height > maxHeight)
{
this.Height = maxHeight;
needsAdjustment = true;
LogHelper.WriteLogToFile($"AutoUpdate | Adjusted window height to: {this.Height}");
}
// 如果窗口宽度超过最大允许宽度,调整窗口宽度
if (this.Width > maxWidth)
{
this.Width = maxWidth;
needsAdjustment = true;
LogHelper.WriteLogToFile($"AutoUpdate | Adjusted window width to: {this.Width}");
}
// 如果屏幕分辨率较低,调整更多UI元素
if (screenHeight < 768 || screenWidth < 1024 || needsAdjustment)
{
// 查找相关控件并调整大小
var markdownViewer = this.FindName("markdownContent") as MdXaml.MarkdownScrollViewer;
var updateNowButton = this.FindName("UpdateNowButton") as Button;
var updateLaterButton = this.FindName("UpdateLaterButton") as Button;
var skipVersionButton = this.FindName("SkipVersionButton") as Button;
// 查找包含ScrollViewer的边框控件,减小其高度
var contentBorders = this.FindVisualChildren<Border>().ToList();
foreach (var border in contentBorders)
{
if (border.Child is ScrollViewer || border.Child is iNKORE.UI.WPF.Modern.Controls.ScrollViewerEx)
{
// 减小内容显示区域的高度
if (border.Height > 180)
{
border.Height = 160;
LogHelper.WriteLogToFile("AutoUpdate | Reduced content area height");
}
else if (border.Child is iNKORE.UI.WPF.Modern.Controls.ScrollViewerEx scrollViewer && scrollViewer.Height > 160)
{
scrollViewer.Height = 160;
LogHelper.WriteLogToFile("AutoUpdate | Reduced scroll viewer height");
}
}
}
// 调整按钮大小
if (updateNowButton != null && updateLaterButton != null && skipVersionButton != null)
{
updateNowButton.Height = 42;
updateLaterButton.Height = 42;
skipVersionButton.Height = 42;
updateNowButton.Padding = new Thickness(15, 8, 15, 8);
updateLaterButton.Padding = new Thickness(15, 8, 15, 8);
skipVersionButton.Padding = new Thickness(15, 8, 15, 8);
LogHelper.WriteLogToFile("AutoUpdate | Reduced button sizes for small screen");
}
}
// 确保窗口在屏幕范围内
if (this.Left < 0) this.Left = 0;
if (this.Top < 0) this.Top = 0;
if (this.Left + this.Width > screenWidth) this.Left = screenWidth - this.Width;
if (this.Top + this.Height > screenHeight) this.Top = screenHeight - this.Height;
LogHelper.WriteLogToFile($"AutoUpdate | Final window size: {this.Width}x{this.Height}");
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | Error adjusting window size: {ex.Message}", LogHelper.LogType.Error);
}
}
// 递归查找指定类型的所有子控件
private IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj = null) where T : DependencyObject
{
if (depObj == null)
depObj = this;
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
}
}
-1
View File
@@ -11,7 +11,6 @@
Title="Ink Canvas 抽奖" Height="500" Width="900">
<Border Background="#F0F3F9" CornerRadius="10" BorderThickness="1" BorderBrush="#0066BF" Margin="0" ClipToBounds="True">
<Canvas>
<Image Source="/Resources/hatsune-miku1.png" Width="300" Canvas.Bottom="-140" Canvas.Left="-48" Canvas.Top="304"></Image>
<Grid Canvas.Left="0" Canvas.Right="0" Canvas.Top="0" Canvas.Bottom="0" Width="900" Height="309" HorizontalAlignment="Center" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1.8*"/>
@@ -373,15 +373,6 @@ E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\App.g.cs
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\GeneratedInternalTypeHelper.g.cs
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\InkCanvasForClass_MarkupCompile.cache
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\InkCanvasForClass_MarkupCompile.lref
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\App.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\MainWindow.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\CountdownTimerWindow.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\CycleProcessBar.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\HasNewUpdateWindow.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\NamesInputWindow.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\OperatingGuideWindow.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\RandWindow.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\YesOrNoNotificationWindow.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\InkCanvasForClass.g.resources
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Ink_Canvas.Properties.Resources.resources
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\InkCanvasForClass.csproj.GenerateResource.cache
@@ -391,3 +382,12 @@ E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\InkCanvasForClass.sourc
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\InkCanva.0F57E7D5.Up2Date
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\InkCanvasForClass.exe
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\InkCanvasForClass.exe.config
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\App.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\MainWindow.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\CountdownTimerWindow.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\CycleProcessBar.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\HasNewUpdateWindow.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\NamesInputWindow.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\OperatingGuideWindow.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\RandWindow.baml
E:\ICC CE\ICC CE main\ICC-CE\Ink Canvas\obj\Debug\net472\Windows\YesOrNoNotificationWindow.baml
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,4 +1,4 @@
#pragma checksum "..\..\..\..\Windows\HasNewUpdateWindow.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "237DE391CCBF9084C9908BFD5D5B61E01AF3B610"
#pragma checksum "..\..\..\..\Windows\HasNewUpdateWindow.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "53772E3067D35407A4B75166FFCE460ECF45D1E7"
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
@@ -59,6 +59,70 @@ namespace Ink_Canvas {
/// </summary>
public partial class HasNewUpdateWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector {
#line 30 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal MdXaml.MarkdownScrollViewer markdownContent;
#line default
#line hidden
#line 49 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock updateVersionInfo;
#line default
#line hidden
#line 50 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock updateDateInfo;
#line default
#line hidden
#line 61 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal iNKORE.UI.WPF.Modern.Controls.ToggleSwitch EnableAutoUpdateToggle;
#line default
#line hidden
#line 65 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal iNKORE.UI.WPF.Modern.Controls.ToggleSwitch EnableSilentUpdateToggle;
#line default
#line hidden
#line 80 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button UpdateNowButton;
#line default
#line hidden
#line 91 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button UpdateLaterButton;
#line default
#line hidden
#line 97 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button SkipVersionButton;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
@@ -87,6 +151,51 @@ namespace Ink_Canvas {
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.markdownContent = ((MdXaml.MarkdownScrollViewer)(target));
return;
case 2:
this.updateVersionInfo = ((System.Windows.Controls.TextBlock)(target));
return;
case 3:
this.updateDateInfo = ((System.Windows.Controls.TextBlock)(target));
return;
case 4:
this.EnableAutoUpdateToggle = ((iNKORE.UI.WPF.Modern.Controls.ToggleSwitch)(target));
return;
case 5:
this.EnableSilentUpdateToggle = ((iNKORE.UI.WPF.Modern.Controls.ToggleSwitch)(target));
return;
case 6:
this.UpdateNowButton = ((System.Windows.Controls.Button)(target));
#line 82 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
this.UpdateNowButton.Click += new System.Windows.RoutedEventHandler(this.UpdateNowButton_Click);
#line default
#line hidden
return;
case 7:
this.UpdateLaterButton = ((System.Windows.Controls.Button)(target));
#line 93 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
this.UpdateLaterButton.Click += new System.Windows.RoutedEventHandler(this.UpdateLaterButton_Click);
#line default
#line hidden
return;
case 8:
this.SkipVersionButton = ((System.Windows.Controls.Button)(target));
#line 98 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
this.SkipVersionButton.Click += new System.Windows.RoutedEventHandler(this.SkipVersionButton_Click);
#line default
#line hidden
return;
}
this._contentLoaded = true;
}
}
@@ -1,4 +1,4 @@
#pragma checksum "..\..\..\..\Windows\HasNewUpdateWindow.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "237DE391CCBF9084C9908BFD5D5B61E01AF3B610"
#pragma checksum "..\..\..\..\Windows\HasNewUpdateWindow.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "53772E3067D35407A4B75166FFCE460ECF45D1E7"
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
@@ -59,6 +59,70 @@ namespace Ink_Canvas {
/// </summary>
public partial class HasNewUpdateWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector {
#line 30 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal MdXaml.MarkdownScrollViewer markdownContent;
#line default
#line hidden
#line 49 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock updateVersionInfo;
#line default
#line hidden
#line 50 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock updateDateInfo;
#line default
#line hidden
#line 61 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal iNKORE.UI.WPF.Modern.Controls.ToggleSwitch EnableAutoUpdateToggle;
#line default
#line hidden
#line 65 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal iNKORE.UI.WPF.Modern.Controls.ToggleSwitch EnableSilentUpdateToggle;
#line default
#line hidden
#line 80 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button UpdateNowButton;
#line default
#line hidden
#line 91 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button UpdateLaterButton;
#line default
#line hidden
#line 97 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button SkipVersionButton;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
@@ -87,6 +151,51 @@ namespace Ink_Canvas {
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.markdownContent = ((MdXaml.MarkdownScrollViewer)(target));
return;
case 2:
this.updateVersionInfo = ((System.Windows.Controls.TextBlock)(target));
return;
case 3:
this.updateDateInfo = ((System.Windows.Controls.TextBlock)(target));
return;
case 4:
this.EnableAutoUpdateToggle = ((iNKORE.UI.WPF.Modern.Controls.ToggleSwitch)(target));
return;
case 5:
this.EnableSilentUpdateToggle = ((iNKORE.UI.WPF.Modern.Controls.ToggleSwitch)(target));
return;
case 6:
this.UpdateNowButton = ((System.Windows.Controls.Button)(target));
#line 82 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
this.UpdateNowButton.Click += new System.Windows.RoutedEventHandler(this.UpdateNowButton_Click);
#line default
#line hidden
return;
case 7:
this.UpdateLaterButton = ((System.Windows.Controls.Button)(target));
#line 93 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
this.UpdateLaterButton.Click += new System.Windows.RoutedEventHandler(this.UpdateLaterButton_Click);
#line default
#line hidden
return;
case 8:
this.SkipVersionButton = ((System.Windows.Controls.Button)(target));
#line 98 "..\..\..\..\Windows\HasNewUpdateWindow.xaml"
this.SkipVersionButton.Click += new System.Windows.RoutedEventHandler(this.SkipVersionButton_Click);
#line default
#line hidden
return;
}
this._contentLoaded = true;
}
}
@@ -1,4 +1,4 @@
#pragma checksum "..\..\..\..\Windows\RandWindow.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "A29F1514A9DC6332F074303F230464CD5C24A898"
#pragma checksum "..\..\..\..\Windows\RandWindow.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "4254CE0F9A30960C1D574123EA132E6F47F23758"
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
@@ -59,7 +59,7 @@ namespace Ink_Canvas {
public partial class RandWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector {
#line 22 "..\..\..\..\Windows\RandWindow.xaml"
#line 21 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Label LabelOutput;
@@ -67,7 +67,7 @@ namespace Ink_Canvas {
#line hidden
#line 23 "..\..\..\..\Windows\RandWindow.xaml"
#line 22 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Label LabelOutput2;
@@ -75,7 +75,7 @@ namespace Ink_Canvas {
#line hidden
#line 24 "..\..\..\..\Windows\RandWindow.xaml"
#line 23 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Label LabelOutput3;
@@ -83,7 +83,7 @@ namespace Ink_Canvas {
#line hidden
#line 27 "..\..\..\..\Windows\RandWindow.xaml"
#line 26 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal iNKORE.UI.WPF.Modern.Controls.SimpleStackPanel PeopleControlPane;
@@ -91,7 +91,7 @@ namespace Ink_Canvas {
#line hidden
#line 29 "..\..\..\..\Windows\RandWindow.xaml"
#line 28 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border BorderBtnMinus;
@@ -99,7 +99,7 @@ namespace Ink_Canvas {
#line hidden
#line 52 "..\..\..\..\Windows\RandWindow.xaml"
#line 51 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock LabelNumberCount;
@@ -107,7 +107,7 @@ namespace Ink_Canvas {
#line hidden
#line 53 "..\..\..\..\Windows\RandWindow.xaml"
#line 52 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border BorderBtnAdd;
@@ -115,7 +115,7 @@ namespace Ink_Canvas {
#line hidden
#line 78 "..\..\..\..\Windows\RandWindow.xaml"
#line 77 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.CheckBox NoHotStudents;
@@ -123,7 +123,7 @@ namespace Ink_Canvas {
#line hidden
#line 81 "..\..\..\..\Windows\RandWindow.xaml"
#line 80 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.CheckBox NoShengPiZi;
@@ -131,7 +131,7 @@ namespace Ink_Canvas {
#line hidden
#line 86 "..\..\..\..\Windows\RandWindow.xaml"
#line 85 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.ComboBox ComboBoxRandMode;
@@ -139,7 +139,7 @@ namespace Ink_Canvas {
#line hidden
#line 96 "..\..\..\..\Windows\RandWindow.xaml"
#line 95 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border BorderBtnRand;
@@ -147,7 +147,7 @@ namespace Ink_Canvas {
#line hidden
#line 99 "..\..\..\..\Windows\RandWindow.xaml"
#line 98 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal iNKORE.UI.WPF.Modern.Controls.SymbolIcon SymbolIconStart;
@@ -155,7 +155,7 @@ namespace Ink_Canvas {
#line hidden
#line 104 "..\..\..\..\Windows\RandWindow.xaml"
#line 103 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border BorderBtnIslandCaller;
@@ -163,7 +163,7 @@ namespace Ink_Canvas {
#line hidden
#line 114 "..\..\..\..\Windows\RandWindow.xaml"
#line 113 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border BorderBtnHelp;
@@ -171,7 +171,7 @@ namespace Ink_Canvas {
#line hidden
#line 122 "..\..\..\..\Windows\RandWindow.xaml"
#line 121 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock TextBlockPeopleCount;
@@ -179,7 +179,7 @@ namespace Ink_Canvas {
#line hidden
#line 125 "..\..\..\..\Windows\RandWindow.xaml"
#line 124 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border BtnClose;
@@ -239,7 +239,7 @@ namespace Ink_Canvas {
case 6:
this.BorderBtnMinus = ((System.Windows.Controls.Border)(target));
#line 29 "..\..\..\..\Windows\RandWindow.xaml"
#line 28 "..\..\..\..\Windows\RandWindow.xaml"
this.BorderBtnMinus.MouseUp += new System.Windows.Input.MouseButtonEventHandler(this.BorderBtnMinus_MouseUp);
#line default
@@ -251,7 +251,7 @@ namespace Ink_Canvas {
case 8:
this.BorderBtnAdd = ((System.Windows.Controls.Border)(target));
#line 53 "..\..\..\..\Windows\RandWindow.xaml"
#line 52 "..\..\..\..\Windows\RandWindow.xaml"
this.BorderBtnAdd.MouseUp += new System.Windows.Input.MouseButtonEventHandler(this.BorderBtnAdd_MouseUp);
#line default
@@ -269,7 +269,7 @@ namespace Ink_Canvas {
case 12:
this.BorderBtnRand = ((System.Windows.Controls.Border)(target));
#line 96 "..\..\..\..\Windows\RandWindow.xaml"
#line 95 "..\..\..\..\Windows\RandWindow.xaml"
this.BorderBtnRand.MouseUp += new System.Windows.Input.MouseButtonEventHandler(this.BorderBtnRand_MouseUp);
#line default
@@ -281,7 +281,7 @@ namespace Ink_Canvas {
case 14:
this.BorderBtnIslandCaller = ((System.Windows.Controls.Border)(target));
#line 104 "..\..\..\..\Windows\RandWindow.xaml"
#line 103 "..\..\..\..\Windows\RandWindow.xaml"
this.BorderBtnIslandCaller.MouseUp += new System.Windows.Input.MouseButtonEventHandler(this.BorderBtnIslandCaller_MouseUp);
#line default
@@ -290,7 +290,7 @@ namespace Ink_Canvas {
case 15:
this.BorderBtnHelp = ((System.Windows.Controls.Border)(target));
#line 114 "..\..\..\..\Windows\RandWindow.xaml"
#line 113 "..\..\..\..\Windows\RandWindow.xaml"
this.BorderBtnHelp.MouseUp += new System.Windows.Input.MouseButtonEventHandler(this.BorderBtnHelp_MouseUp);
#line default
@@ -302,7 +302,7 @@ namespace Ink_Canvas {
case 17:
this.BtnClose = ((System.Windows.Controls.Border)(target));
#line 125 "..\..\..\..\Windows\RandWindow.xaml"
#line 124 "..\..\..\..\Windows\RandWindow.xaml"
this.BtnClose.MouseUp += new System.Windows.Input.MouseButtonEventHandler(this.BtnClose_MouseUp);
#line default
@@ -1,4 +1,4 @@
#pragma checksum "..\..\..\..\Windows\RandWindow.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "A29F1514A9DC6332F074303F230464CD5C24A898"
#pragma checksum "..\..\..\..\Windows\RandWindow.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "4254CE0F9A30960C1D574123EA132E6F47F23758"
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
@@ -59,7 +59,7 @@ namespace Ink_Canvas {
public partial class RandWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector {
#line 22 "..\..\..\..\Windows\RandWindow.xaml"
#line 21 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Label LabelOutput;
@@ -67,7 +67,7 @@ namespace Ink_Canvas {
#line hidden
#line 23 "..\..\..\..\Windows\RandWindow.xaml"
#line 22 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Label LabelOutput2;
@@ -75,7 +75,7 @@ namespace Ink_Canvas {
#line hidden
#line 24 "..\..\..\..\Windows\RandWindow.xaml"
#line 23 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Label LabelOutput3;
@@ -83,7 +83,7 @@ namespace Ink_Canvas {
#line hidden
#line 27 "..\..\..\..\Windows\RandWindow.xaml"
#line 26 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal iNKORE.UI.WPF.Modern.Controls.SimpleStackPanel PeopleControlPane;
@@ -91,7 +91,7 @@ namespace Ink_Canvas {
#line hidden
#line 29 "..\..\..\..\Windows\RandWindow.xaml"
#line 28 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border BorderBtnMinus;
@@ -99,7 +99,7 @@ namespace Ink_Canvas {
#line hidden
#line 52 "..\..\..\..\Windows\RandWindow.xaml"
#line 51 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock LabelNumberCount;
@@ -107,7 +107,7 @@ namespace Ink_Canvas {
#line hidden
#line 53 "..\..\..\..\Windows\RandWindow.xaml"
#line 52 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border BorderBtnAdd;
@@ -115,7 +115,7 @@ namespace Ink_Canvas {
#line hidden
#line 78 "..\..\..\..\Windows\RandWindow.xaml"
#line 77 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.CheckBox NoHotStudents;
@@ -123,7 +123,7 @@ namespace Ink_Canvas {
#line hidden
#line 81 "..\..\..\..\Windows\RandWindow.xaml"
#line 80 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.CheckBox NoShengPiZi;
@@ -131,7 +131,7 @@ namespace Ink_Canvas {
#line hidden
#line 86 "..\..\..\..\Windows\RandWindow.xaml"
#line 85 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.ComboBox ComboBoxRandMode;
@@ -139,7 +139,7 @@ namespace Ink_Canvas {
#line hidden
#line 96 "..\..\..\..\Windows\RandWindow.xaml"
#line 95 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border BorderBtnRand;
@@ -147,7 +147,7 @@ namespace Ink_Canvas {
#line hidden
#line 99 "..\..\..\..\Windows\RandWindow.xaml"
#line 98 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal iNKORE.UI.WPF.Modern.Controls.SymbolIcon SymbolIconStart;
@@ -155,7 +155,7 @@ namespace Ink_Canvas {
#line hidden
#line 104 "..\..\..\..\Windows\RandWindow.xaml"
#line 103 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border BorderBtnIslandCaller;
@@ -163,7 +163,7 @@ namespace Ink_Canvas {
#line hidden
#line 114 "..\..\..\..\Windows\RandWindow.xaml"
#line 113 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border BorderBtnHelp;
@@ -171,7 +171,7 @@ namespace Ink_Canvas {
#line hidden
#line 122 "..\..\..\..\Windows\RandWindow.xaml"
#line 121 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock TextBlockPeopleCount;
@@ -179,7 +179,7 @@ namespace Ink_Canvas {
#line hidden
#line 125 "..\..\..\..\Windows\RandWindow.xaml"
#line 124 "..\..\..\..\Windows\RandWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border BtnClose;
@@ -239,7 +239,7 @@ namespace Ink_Canvas {
case 6:
this.BorderBtnMinus = ((System.Windows.Controls.Border)(target));
#line 29 "..\..\..\..\Windows\RandWindow.xaml"
#line 28 "..\..\..\..\Windows\RandWindow.xaml"
this.BorderBtnMinus.MouseUp += new System.Windows.Input.MouseButtonEventHandler(this.BorderBtnMinus_MouseUp);
#line default
@@ -251,7 +251,7 @@ namespace Ink_Canvas {
case 8:
this.BorderBtnAdd = ((System.Windows.Controls.Border)(target));
#line 53 "..\..\..\..\Windows\RandWindow.xaml"
#line 52 "..\..\..\..\Windows\RandWindow.xaml"
this.BorderBtnAdd.MouseUp += new System.Windows.Input.MouseButtonEventHandler(this.BorderBtnAdd_MouseUp);
#line default
@@ -269,7 +269,7 @@ namespace Ink_Canvas {
case 12:
this.BorderBtnRand = ((System.Windows.Controls.Border)(target));
#line 96 "..\..\..\..\Windows\RandWindow.xaml"
#line 95 "..\..\..\..\Windows\RandWindow.xaml"
this.BorderBtnRand.MouseUp += new System.Windows.Input.MouseButtonEventHandler(this.BorderBtnRand_MouseUp);
#line default
@@ -281,7 +281,7 @@ namespace Ink_Canvas {
case 14:
this.BorderBtnIslandCaller = ((System.Windows.Controls.Border)(target));
#line 104 "..\..\..\..\Windows\RandWindow.xaml"
#line 103 "..\..\..\..\Windows\RandWindow.xaml"
this.BorderBtnIslandCaller.MouseUp += new System.Windows.Input.MouseButtonEventHandler(this.BorderBtnIslandCaller_MouseUp);
#line default
@@ -290,7 +290,7 @@ namespace Ink_Canvas {
case 15:
this.BorderBtnHelp = ((System.Windows.Controls.Border)(target));
#line 114 "..\..\..\..\Windows\RandWindow.xaml"
#line 113 "..\..\..\..\Windows\RandWindow.xaml"
this.BorderBtnHelp.MouseUp += new System.Windows.Input.MouseButtonEventHandler(this.BorderBtnHelp_MouseUp);
#line default
@@ -302,7 +302,7 @@ namespace Ink_Canvas {
case 17:
this.BtnClose = ((System.Windows.Controls.Border)(target));
#line 125 "..\..\..\..\Windows\RandWindow.xaml"
#line 124 "..\..\..\..\Windows\RandWindow.xaml"
this.BtnClose.MouseUp += new System.Windows.Input.MouseButtonEventHandler(this.BtnClose_MouseUp);
#line default