@@ -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("1.7.1.12")]
|
||||
[assembly: AssemblyFileVersion("1.7.1.12")]
|
||||
[assembly: AssemblyVersion("1.7.1.14")]
|
||||
[assembly: AssemblyFileVersion("1.7.1.14")]
|
||||
|
||||
@@ -57,6 +57,11 @@ namespace Ink_Canvas.Helpers
|
||||
VersionUrl = "https://kkgithub.com/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt",
|
||||
DownloadUrlFormat = "https://kkgithub.com/InkCanvasForClass/community/releases/download/{0}/InkCanvasForClass.CE.{0}.zip",
|
||||
LogUrl = "https://kkgithub.com/InkCanvasForClass/community/raw/refs/heads/main/UpdateLog.md"
|
||||
},
|
||||
new UpdateLineGroup
|
||||
{
|
||||
GroupName = "智教联盟",
|
||||
DownloadUrlFormat = "https://get.smart-teach.cn/d/Ningbo-S3/shared/jiangling/community/InkCanvasForClass.CE.{0}.zip",
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -82,6 +87,11 @@ namespace Ink_Canvas.Helpers
|
||||
VersionUrl = "https://kkgithub.com/InkCanvasForClass/community-beta/raw/refs/heads/main/AutomaticUpdateVersionControl.txt",
|
||||
DownloadUrlFormat = "https://kkgithub.com/InkCanvasForClass/community-beta/releases/download/{0}/InkCanvasForClass.CE.{0}.zip",
|
||||
LogUrl = "https://kkgithub.com/InkCanvasForClass/community-beta/raw/refs/heads/main/UpdateLog.md"
|
||||
},
|
||||
new UpdateLineGroup
|
||||
{
|
||||
GroupName = "智教联盟",
|
||||
DownloadUrlFormat = "https://get.smart-teach.cn/d/Ningbo-S3/shared/jiangling/community-beta/InkCanvasForClass.CE.{0}.zip",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,6 +169,12 @@ namespace Ink_Canvas.Helpers
|
||||
|
||||
foreach (var group in groups)
|
||||
{
|
||||
// 跳过“智教联盟”线路组,不参与延迟检测和排序
|
||||
if (group.GroupName == "智教联盟")
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 跳过智教联盟线路组延迟检测");
|
||||
continue;
|
||||
}
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 检测线路组: {group.GroupName} ({group.VersionUrl})");
|
||||
var delay = await GetUrlDelay(group.VersionUrl);
|
||||
if (delay >= 0)
|
||||
@@ -178,6 +194,14 @@ namespace Ink_Canvas.Helpers
|
||||
.Select(x => x.group)
|
||||
.ToList();
|
||||
|
||||
// 将“智教联盟”线路组插入到最前面(如果存在)
|
||||
var zhiJiaoGroup = groups.FirstOrDefault(g => g.GroupName == "智教联盟");
|
||||
if (zhiJiaoGroup != null)
|
||||
{
|
||||
orderedGroups.Insert(0, zhiJiaoGroup);
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 智教联盟线路组已插入到首位");
|
||||
}
|
||||
|
||||
if (orderedGroups.Count > 0)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 找到 {orderedGroups.Count} 个可用线路组,按延迟排序:");
|
||||
@@ -458,6 +482,43 @@ namespace Ink_Canvas.Helpers
|
||||
return await DownloadSetupFileWithFallback(version, new List<UpdateLineGroup> { group });
|
||||
}
|
||||
|
||||
// 获取智教联盟真实下载地址
|
||||
private static async Task<string> GetZhijiaoRealDownloadUrl(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var handler = new HttpClientHandler { AllowAutoRedirect = false })
|
||||
using (var client = new HttpClient(handler))
|
||||
{
|
||||
client.Timeout = RequestTimeout;
|
||||
var resp = await client.GetAsync(url);
|
||||
// 优先取Location头
|
||||
if (resp.StatusCode == System.Net.HttpStatusCode.Found || resp.StatusCode == System.Net.HttpStatusCode.Redirect || resp.StatusCode == System.Net.HttpStatusCode.MovedPermanently)
|
||||
{
|
||||
if (resp.Headers.Location != null)
|
||||
{
|
||||
var realUrl = resp.Headers.Location.ToString();
|
||||
if (realUrl.Contains(" ")) realUrl = realUrl.Replace(" ", "%20");
|
||||
return realUrl;
|
||||
}
|
||||
}
|
||||
// 有些服务器直接返回真实地址在内容里
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (Uri.IsWellFormedUriString(content.Trim(), UriKind.Absolute))
|
||||
{
|
||||
var realUrl = content.Trim();
|
||||
if (realUrl.Contains(" ")) realUrl = realUrl.Replace(" ", "%20");
|
||||
return realUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 获取智教联盟真实下载地址失败: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 使用多线路组下载新版(支持自动切换)
|
||||
public static async Task<bool> DownloadSetupFileWithFallback(string version, List<UpdateLineGroup> groups, Action<double, string> progressCallback = null)
|
||||
{
|
||||
@@ -484,10 +545,32 @@ namespace Ink_Canvas.Helpers
|
||||
|
||||
SaveDownloadStatus(false);
|
||||
|
||||
// 优先尝试“智教联盟”线路组
|
||||
var zhiJiaoGroup = groups.FirstOrDefault(g => g.GroupName == "智教联盟");
|
||||
if (zhiJiaoGroup != null)
|
||||
{
|
||||
groups = new List<UpdateLineGroup> { zhiJiaoGroup }.Concat(groups.Where(g => g.GroupName != "智教联盟")).ToList();
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 下载时优先尝试智教联盟线路组");
|
||||
}
|
||||
|
||||
// 依次尝试每个线路组
|
||||
foreach (var group in groups)
|
||||
{
|
||||
string url = string.Format(group.DownloadUrlFormat, version);
|
||||
// 智教联盟需要先获取真实下载地址
|
||||
if (group.GroupName == "智教联盟")
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 获取智教联盟真实下载地址: {url}");
|
||||
var realUrl = await GetZhijiaoRealDownloadUrl(url);
|
||||
if (string.IsNullOrEmpty(realUrl))
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 智教联盟真实下载地址获取失败,跳过", LogHelper.LogType.Warning);
|
||||
progressCallback?.Invoke(0, "智教联盟真实下载地址获取失败,跳过");
|
||||
continue;
|
||||
}
|
||||
url = realUrl;
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 智教联盟真实下载地址: {url}");
|
||||
}
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 尝试从线路组 {group.GroupName} 下载: {url}");
|
||||
|
||||
bool downloadSuccess = await DownloadFile(url, zipFilePath, progressCallback);
|
||||
@@ -529,9 +612,93 @@ namespace Ink_Canvas.Helpers
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 正在尝试多线程下载: {fileUrl}");
|
||||
int maxRetry = 3;
|
||||
int[] threadOptions = new int[] { 32, 4 };
|
||||
|
||||
// 检查服务器是否支持Range分块下载
|
||||
bool supportRange = false;
|
||||
long totalSize = -1;
|
||||
try
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
|
||||
var req = new HttpRequestMessage(HttpMethod.Head, fileUrl);
|
||||
req.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(0, 0);
|
||||
var resp = await client.SendAsync(req);
|
||||
if (resp.StatusCode == System.Net.HttpStatusCode.PartialContent)
|
||||
{
|
||||
supportRange = true;
|
||||
if (resp.Content.Headers.ContentRange != null && resp.Content.Headers.ContentRange.Length.HasValue)
|
||||
{
|
||||
totalSize = resp.Content.Headers.ContentRange.Length.Value;
|
||||
}
|
||||
else if (resp.Content.Headers.ContentLength.HasValue)
|
||||
{
|
||||
totalSize = resp.Content.Headers.ContentLength.Value;
|
||||
}
|
||||
}
|
||||
else if (resp.StatusCode == System.Net.HttpStatusCode.OK)
|
||||
{
|
||||
supportRange = false;
|
||||
if (resp.Content.Headers.ContentLength.HasValue)
|
||||
{
|
||||
totalSize = resp.Content.Headers.ContentLength.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 检查Range支持时异常: {ex.Message}", LogHelper.LogType.Warning);
|
||||
}
|
||||
|
||||
if (!supportRange)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 服务器不支持分块下载,自动降级为单线程下载");
|
||||
progressCallback?.Invoke(0, "服务器不支持分块下载,自动降级为单线程下载");
|
||||
try
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
|
||||
using (var resp = await client.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead))
|
||||
{
|
||||
resp.EnsureSuccessStatusCode();
|
||||
using (var fs = new FileStream(destinationPath, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
var stream = await resp.Content.ReadAsStreamAsync();
|
||||
byte[] buffer = new byte[8192];
|
||||
int read;
|
||||
long downloaded = 0;
|
||||
while ((read = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
await fs.WriteAsync(buffer, 0, read);
|
||||
downloaded += read;
|
||||
if (totalSize > 0)
|
||||
{
|
||||
double percent = (double)downloaded / totalSize * 100;
|
||||
progressCallback?.Invoke(percent, $"单线程下载中: {percent:F1}%");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
progressCallback?.Invoke(100, "单线程下载完成");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 单线程下载失败: {ex.Message}", LogHelper.LogType.Error);
|
||||
progressCallback?.Invoke(0, $"单线程下载失败: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (int threadCount in threadOptions)
|
||||
{
|
||||
long totalSize = await GetContentLength(fileUrl);
|
||||
if (totalSize <= 0)
|
||||
{
|
||||
totalSize = await GetContentLength(fileUrl);
|
||||
}
|
||||
if (totalSize <= 0)
|
||||
{
|
||||
progressCallback?.Invoke(0, "无法获取文件大小,取消下载");
|
||||
@@ -563,6 +730,7 @@ namespace Ink_Canvas.Helpers
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
|
||||
var req = new HttpRequestMessage(HttpMethod.Get, fileUrl);
|
||||
req.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(block.Start, block.End);
|
||||
|
||||
@@ -573,6 +741,7 @@ namespace Ink_Canvas.Helpers
|
||||
|
||||
using (var resp = await client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, downloadCts.Token))
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 分块{block.Index} 响应状态: {resp.StatusCode}");
|
||||
resp.EnsureSuccessStatusCode();
|
||||
string tempPath = destinationPath + $".part{block.Index}";
|
||||
using (var fs = new FileStream(tempPath, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
@@ -792,7 +961,6 @@ namespace Ink_Canvas.Helpers
|
||||
|
||||
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}\"");
|
||||
@@ -833,8 +1001,9 @@ namespace Ink_Canvas.Helpers
|
||||
}
|
||||
else
|
||||
{
|
||||
batchContent.AppendLine($"echo taskkill /F /IM \"InkCanvasForClass.exe\" >nul 2>nul >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo :: 检查应用程序是否已经在运行 >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo tasklist /FI \"IMAGENAME eq Ink Canvas.exe\" | find /i \"Ink Canvas.exe\" > nul >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo tasklist /FI \"IMAGENAME eq InkCanvasForClass.exe\" | find /i \"InkCanvasForClass.exe\" > nul >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo echo 启动应用程序... >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo start \"\" \"{appPath}\" >> \"{updateBatPath}\"");
|
||||
|
||||
@@ -854,12 +854,13 @@
|
||||
<Line HorizontalAlignment="Center" X1="0" Y1="0" X2="400" Y2="0" Stroke="#3f3f46"
|
||||
StrokeThickness="1" Margin="0,4,0,4" />
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||
<TextBlock Foreground="#fafafa" Text="启用手掌擦" VerticalAlignment="Center" FontSize="14" Margin="0,0,16,0" />
|
||||
<ui:ToggleSwitch OnContent="" OffContent="" Name="ToggleSwitchEnablePalmEraser" IsOn="True"
|
||||
FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
||||
<TextBlock Foreground="#fafafa" Text="启用手掌擦" VerticalAlignment="Center"
|
||||
FontSize="14" Margin="0,0,16,0" />
|
||||
<ui:ToggleSwitch OnContent="" OffContent="" Name="ToggleSwitchEnablePalmEraser"
|
||||
IsOn="False" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
||||
Toggled="ToggleSwitchEnablePalmEraser_Toggled" />
|
||||
</ui:SimpleStackPanel>
|
||||
<TextBlock Text="# 关闭后,手掌将无法触发橡皮擦功能" TextWrapping="Wrap" Foreground="#a1a1aa" />
|
||||
<TextBlock Text="# 开启后,两个及以上触点且触摸面积较大时自动切换为橡皮擦,抬手后恢复原编辑模式。" TextWrapping="Wrap" Foreground="#a1a1aa" />
|
||||
</ui:SimpleStackPanel>
|
||||
</GroupBox>
|
||||
<GroupBox Name="GroupBoxInkRecognition">
|
||||
@@ -945,7 +946,7 @@
|
||||
<TextBlock Foreground="#fafafa" Text="长度阈值" VerticalAlignment="Center"
|
||||
FontSize="14" Margin="0,0,16,0" />
|
||||
<Slider Name="AutoStraightenLineThresholdSlider" Width="150" Minimum="30" Maximum="300"
|
||||
Value="30" TickFrequency="30" IsSnapToTickEnabled="True"
|
||||
Value="80" TickFrequency="30" IsSnapToTickEnabled="True"
|
||||
ValueChanged="AutoStraightenLineThresholdSlider_ValueChanged" />
|
||||
<TextBlock Foreground="#fafafa" Text="{Binding ElementName=AutoStraightenLineThresholdSlider, Path=Value, StringFormat={}{0:0}}"
|
||||
VerticalAlignment="Center" FontSize="14" Margin="16,0,0,0" />
|
||||
|
||||
@@ -265,25 +265,10 @@ namespace Ink_Canvas {
|
||||
catch { }
|
||||
}
|
||||
|
||||
// 新增:记录上一个模式
|
||||
private InkCanvasEditingMode lastEditingMode = InkCanvasEditingMode.Ink;
|
||||
|
||||
private void inkCanvas_EditingModeChanged(object sender, RoutedEventArgs e) {
|
||||
var inkCanvas1 = sender as InkCanvas;
|
||||
if (inkCanvas1 == null) return;
|
||||
|
||||
// 只负责显示/隐藏覆盖层,不再强制切换模式
|
||||
var eraserOverlay = this.FindName("AdvancedEraserOverlay") as Border;
|
||||
if (eraserOverlay != null) {
|
||||
if (inkCanvas1.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
eraserOverlay.IsHitTestVisible = true;
|
||||
Trace.WriteLine("Advanced Eraser: Overlay enabled in eraser mode");
|
||||
} else {
|
||||
eraserOverlay.IsHitTestVisible = false;
|
||||
DisableAdvancedEraserSystem();
|
||||
Trace.WriteLine("Advanced Eraser: Overlay disabled in non-eraser mode");
|
||||
}
|
||||
}
|
||||
// 使用辅助方法设置光标
|
||||
SetCursorBasedOnEditingMode(inkCanvas1);
|
||||
if (Settings.Canvas.IsShowCursor) {
|
||||
@@ -294,13 +279,31 @@ namespace Ink_Canvas {
|
||||
else
|
||||
inkCanvas1.ForceCursor = false;
|
||||
} else {
|
||||
// 套索选择模式下始终强制显示光标,即使用户设置不显示光标
|
||||
if (inkCanvas1.EditingMode == InkCanvasEditingMode.Select) {
|
||||
inkCanvas1.ForceCursor = true;
|
||||
} else {
|
||||
inkCanvas1.ForceCursor = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (inkCanvas1.EditingMode == InkCanvasEditingMode.Ink) forcePointEraser = !forcePointEraser;
|
||||
|
||||
// 处理高级橡皮擦覆盖层的启用/禁用
|
||||
var eraserOverlay = this.FindName("AdvancedEraserOverlay") as Border;
|
||||
if (eraserOverlay != null) {
|
||||
if (inkCanvas1.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
// 橡皮擦模式下启用覆盖层
|
||||
eraserOverlay.IsHitTestVisible = true;
|
||||
Trace.WriteLine("Advanced Eraser: Overlay enabled in eraser mode");
|
||||
} else {
|
||||
// 其他模式下禁用覆盖层
|
||||
eraserOverlay.IsHitTestVisible = false;
|
||||
// 同时禁用高级橡皮擦系统
|
||||
DisableAdvancedEraserSystem();
|
||||
Trace.WriteLine("Advanced Eraser: Overlay disabled in non-eraser mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Ink Canvas
|
||||
@@ -311,16 +314,48 @@ namespace Ink_Canvas {
|
||||
public static string settingsFileName = "Settings.json";
|
||||
private bool isLoaded = false;
|
||||
private bool forcePointEraser = false;
|
||||
public static bool EnablePalmEraser = true;
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e) {
|
||||
loadPenCanvas();
|
||||
//加载设置
|
||||
LoadSettings(true);
|
||||
// 同步手掌擦开关
|
||||
EnablePalmEraser = Settings.Canvas.EnablePalmEraser;
|
||||
if (ToggleSwitchEnablePalmEraser != null)
|
||||
ToggleSwitchEnablePalmEraser.IsOn = EnablePalmEraser;
|
||||
// 检查保存路径是否可用,不可用则修正
|
||||
try
|
||||
{
|
||||
string savePath = Settings.Automation.AutoSavedStrokesLocation;
|
||||
bool needFix = false;
|
||||
if (string.IsNullOrWhiteSpace(savePath) || !System.IO.Directory.Exists(savePath))
|
||||
{
|
||||
needFix = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 检查是否可写
|
||||
try
|
||||
{
|
||||
string testFile = System.IO.Path.Combine(savePath, "test.tmp");
|
||||
System.IO.File.WriteAllText(testFile, "test");
|
||||
System.IO.File.Delete(testFile);
|
||||
}
|
||||
catch
|
||||
{
|
||||
needFix = true;
|
||||
}
|
||||
}
|
||||
if (needFix)
|
||||
{
|
||||
string newPath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "saves");
|
||||
Settings.Automation.AutoSavedStrokesLocation = newPath;
|
||||
if (!System.IO.Directory.Exists(newPath))
|
||||
System.IO.Directory.CreateDirectory(newPath);
|
||||
SaveSettingsToFile();
|
||||
LogHelper.WriteLogToFile($"自动修正保存路径为: {newPath}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"检测或修正保存路径时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
// 加载自定义背景颜色
|
||||
LoadCustomBackgroundColor();
|
||||
@@ -400,14 +435,6 @@ namespace Ink_Canvas {
|
||||
|
||||
// 初始化插件系统
|
||||
InitializePluginSystem();
|
||||
|
||||
// 新增:确保EditingModeChanged事件已绑定
|
||||
var inkCanvas = this.FindName("inkCanvas") as InkCanvas;
|
||||
if (inkCanvas != null)
|
||||
{
|
||||
inkCanvas.EditingModeChanged -= inkCanvas_EditingModeChanged;
|
||||
inkCanvas.EditingModeChanged += inkCanvas_EditingModeChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void SystemEventsOnDisplaySettingsChanged(object sender, EventArgs e) {
|
||||
@@ -1351,13 +1378,5 @@ namespace Ink_Canvas {
|
||||
BorderSettings.Visibility = Visibility.Visible;
|
||||
BorderSettingsMask.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void ToggleSwitchEnablePalmEraser_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!isLoaded) return;
|
||||
EnablePalmEraser = ToggleSwitchEnablePalmEraser.IsOn;
|
||||
Settings.Canvas.EnablePalmEraser = EnablePalmEraser;
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -689,7 +689,6 @@ namespace Ink_Canvas {
|
||||
private void BoardLassoIcon_Click(object sender, RoutedEventArgs e) {
|
||||
forceEraser = false;
|
||||
forcePointEraser = false;
|
||||
isLastTouchEraser = false;
|
||||
drawingShapeMode = 0;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Select;
|
||||
SetCursorBasedOnEditingMode(inkCanvas);
|
||||
|
||||
@@ -634,68 +634,52 @@ namespace Ink_Canvas {
|
||||
|
||||
// 绑定事件处理
|
||||
overlay.MouseDown += (sender, e) => {
|
||||
if (!MainWindow.EnablePalmEraser) return;
|
||||
var inkCanvas = this.FindName("inkCanvas") as InkCanvas;
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
lastEditingMode = inkCanvas.EditingMode;
|
||||
overlay.CaptureMouse();
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.None;
|
||||
StartAdvancedEraserOperation(sender);
|
||||
}
|
||||
};
|
||||
|
||||
overlay.MouseUp += (sender, e) => {
|
||||
if (!MainWindow.EnablePalmEraser) return;
|
||||
var inkCanvas = this.FindName("inkCanvas") as InkCanvas;
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.None) {
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
overlay.ReleaseMouseCapture();
|
||||
EndAdvancedEraserOperation(sender);
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Ink; // 抬手后自动回到画笔
|
||||
}
|
||||
};
|
||||
|
||||
overlay.MouseMove += (sender, e) => {
|
||||
if (!MainWindow.EnablePalmEraser) return;
|
||||
var inkCanvas = this.FindName("inkCanvas") as InkCanvas;
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.None) {
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
var position = e.GetPosition((UIElement)this.FindName("inkCanvas"));
|
||||
Trace.WriteLine($"Advanced Eraser: Mouse move event triggered at ({position.X:F1}, {position.Y:F1})");
|
||||
UpdateAdvancedEraserPosition(sender, position);
|
||||
} else {
|
||||
Trace.WriteLine($"Advanced Eraser: Mouse move ignored - not in eraser mode, current mode: {inkCanvas.EditingMode}");
|
||||
}
|
||||
};
|
||||
|
||||
// 触控笔事件
|
||||
overlay.StylusDown += (sender, e) => {
|
||||
if (!MainWindow.EnablePalmEraser) return;
|
||||
var inkCanvas = this.FindName("inkCanvas") as InkCanvas;
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
e.Handled = true;
|
||||
if (e.StylusDevice.TabletDevice.Type == TabletDeviceType.Stylus) {
|
||||
overlay.CaptureStylus();
|
||||
}
|
||||
lastEditingMode = inkCanvas.EditingMode;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.None;
|
||||
StartAdvancedEraserOperation(sender);
|
||||
}
|
||||
};
|
||||
|
||||
overlay.StylusUp += (sender, e) => {
|
||||
if (!MainWindow.EnablePalmEraser) return;
|
||||
var inkCanvas = this.FindName("inkCanvas") as InkCanvas;
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.None) {
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
e.Handled = true;
|
||||
if (e.StylusDevice.TabletDevice.Type == TabletDeviceType.Stylus) {
|
||||
overlay.ReleaseStylusCapture();
|
||||
}
|
||||
EndAdvancedEraserOperation(sender);
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Ink; // 抬手后自动回到画笔
|
||||
}
|
||||
};
|
||||
|
||||
overlay.StylusMove += (sender, e) => {
|
||||
if (!MainWindow.EnablePalmEraser) return;
|
||||
var inkCanvas = this.FindName("inkCanvas") as InkCanvas;
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.None) {
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
e.Handled = true;
|
||||
var position = e.GetPosition((UIElement)this.FindName("inkCanvas"));
|
||||
UpdateAdvancedEraserPosition(sender, position);
|
||||
|
||||
@@ -1449,7 +1449,6 @@ namespace Ink_Canvas {
|
||||
bool isAlreadyEraser = inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint;
|
||||
forceEraser = false;
|
||||
forcePointEraser = true;
|
||||
isLastTouchEraser = false;
|
||||
drawingShapeMode = 0;
|
||||
|
||||
// 切换到橡皮擦模式时,确保保存当前图片信息
|
||||
@@ -1489,7 +1488,6 @@ namespace Ink_Canvas {
|
||||
bool isAlreadyEraser = inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint;
|
||||
forceEraser = false;
|
||||
forcePointEraser = true;
|
||||
isLastTouchEraser = false;
|
||||
drawingShapeMode = 0;
|
||||
|
||||
// 启用新的高级橡皮擦系统
|
||||
|
||||
@@ -322,13 +322,9 @@ namespace Ink_Canvas {
|
||||
}
|
||||
|
||||
private void GridInkCanvasSelectionCover_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) {
|
||||
// 手掌擦时禁止移动/缩放
|
||||
if (isLastTouchEraser || inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint)
|
||||
return;
|
||||
// 三指及以上禁止缩放
|
||||
bool disableScale = dec.Count >= 3;
|
||||
try {
|
||||
if (dec.Count >= 1) {
|
||||
bool disableScale = dec.Count >= 3;
|
||||
var md = e.DeltaManipulation;
|
||||
var trans = md.Translation; // 获得位移矢量
|
||||
var rotate = md.Rotation; // 获得旋转角度
|
||||
@@ -426,7 +422,6 @@ namespace Ink_Canvas {
|
||||
ExitMultiTouchModeIfNeeded();
|
||||
forceEraser = false;
|
||||
forcePointEraser = false;
|
||||
isLastTouchEraser = false;
|
||||
drawingShapeMode = 0;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Select;
|
||||
SetCursorBasedOnEditingMode(inkCanvas);
|
||||
@@ -436,7 +431,6 @@ namespace Ink_Canvas {
|
||||
ExitMultiTouchModeIfNeeded();
|
||||
forceEraser = false;
|
||||
forcePointEraser = false;
|
||||
isLastTouchEraser = false;
|
||||
drawingShapeMode = 0;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Select;
|
||||
inkCanvas.IsManipulationEnabled = true;
|
||||
|
||||
@@ -1599,7 +1599,7 @@ namespace Ink_Canvas {
|
||||
Settings.PowerPointSettings.IsNotifyHiddenPage = false;
|
||||
Settings.PowerPointSettings.IsEnableTwoFingerGestureInPresentationMode = false;
|
||||
Settings.PowerPointSettings.IsEnableFingerGestureSlideShowControl = false;
|
||||
Settings.PowerPointSettings.IsSupportWPS = true;
|
||||
Settings.PowerPointSettings.IsSupportWPS = false;
|
||||
|
||||
Settings.Canvas.InkWidth = 2.5;
|
||||
Settings.Canvas.IsShowCursor = false;
|
||||
@@ -1615,7 +1615,7 @@ namespace Ink_Canvas {
|
||||
Settings.Canvas.EnablePressureTouchMode = false;
|
||||
Settings.Canvas.DisablePressure = false;
|
||||
Settings.Canvas.AutoStraightenLine = true;
|
||||
Settings.Canvas.AutoStraightenLineThreshold = 30;
|
||||
Settings.Canvas.AutoStraightenLineThreshold = 80;
|
||||
Settings.Canvas.LineEndpointSnapping = true;
|
||||
Settings.Canvas.LineEndpointSnappingThreshold = 15;
|
||||
Settings.Canvas.UsingWhiteboard = false;
|
||||
@@ -2189,5 +2189,11 @@ namespace Ink_Canvas {
|
||||
Settings.Automation.IsAutoEnterAnnotationAfterKillHite = ToggleSwitchAutoEnterAnnotationAfterKillHite.IsOn;
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchEnablePalmEraser_Toggled(object sender, RoutedEventArgs e) {
|
||||
if (!isLoaded) return;
|
||||
Settings.Canvas.EnablePalmEraser = ToggleSwitchEnablePalmEraser.IsOn;
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -554,6 +554,11 @@ namespace Ink_Canvas {
|
||||
Settings.Canvas = new Canvas();
|
||||
}
|
||||
|
||||
// Palm Eraser
|
||||
if (Settings.Canvas != null) {
|
||||
ToggleSwitchEnablePalmEraser.IsOn = Settings.Canvas.EnablePalmEraser;
|
||||
}
|
||||
|
||||
// Advanced
|
||||
if (Settings.Advanced != null) {
|
||||
TouchMultiplierSlider.Value = Settings.Advanced.TouchMultiplier;
|
||||
|
||||
@@ -113,7 +113,6 @@ namespace Ink_Canvas {
|
||||
// 否则只切换到批注模式,不弹出子面板
|
||||
forceEraser = false;
|
||||
forcePointEraser = false;
|
||||
isLastTouchEraser = false;
|
||||
drawingShapeMode = 0;
|
||||
penType = 0;
|
||||
drawingAttributes.IsHighlighter = false;
|
||||
@@ -379,25 +378,10 @@ namespace Ink_Canvas {
|
||||
SetCursorBasedOnEditingMode(inkCanvas);
|
||||
}
|
||||
|
||||
// 如果处于手掌擦状态,继续使用相同的橡皮形状
|
||||
if (isLastTouchEraser && currentPalmEraserShape != null) {
|
||||
inkCanvas.EraserShape = currentPalmEraserShape;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
|
||||
return;
|
||||
}
|
||||
if (isSingleFingerDragMode) return;
|
||||
|
||||
// 处理几何绘制模式
|
||||
if (drawingShapeMode != 0) {
|
||||
if (isLastTouchEraser) return;
|
||||
//EraserContainer.Background = null;
|
||||
//ImageEraser.Visibility = Visibility.Visible;
|
||||
// 修复触屏状态下几何绘制功能不可用的问题
|
||||
// 在几何绘制模式下,即使isWaitUntilNextTouchDown为true,也应该处理触摸移动事件
|
||||
// 只有当多点触控时才需要等待下一次触摸
|
||||
if (isWaitUntilNextTouchDown && dec.Count > 1) return;
|
||||
if (dec.Count > 1) {
|
||||
isWaitUntilNextTouchDown = true;
|
||||
try {
|
||||
inkCanvas.Strokes.Remove(lastTempStroke);
|
||||
inkCanvas.Strokes.Remove(lastTempStrokeCollection);
|
||||
@@ -1653,7 +1637,6 @@ namespace Ink_Canvas {
|
||||
private void EnterShapeDrawingMode(int mode) {
|
||||
forceEraser = true;
|
||||
forcePointEraser = false;
|
||||
isLastTouchEraser = false;
|
||||
drawingShapeMode = mode;
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.None;
|
||||
SetCursorBasedOnEditingMode(inkCanvas);
|
||||
|
||||
@@ -622,9 +622,10 @@ namespace Ink_Canvas {
|
||||
Point start = stroke.StylusPoints.First().ToPoint();
|
||||
Point end = stroke.StylusPoints.Last().ToPoint();
|
||||
double lineLength = GetDistance(start, end);
|
||||
|
||||
// 线条必须足够长才考虑拉直,使用设置中的阈值
|
||||
if (lineLength < Settings.Canvas.AutoStraightenLineThreshold)
|
||||
// 分辨率自适应阈值
|
||||
double adaptiveThreshold = Settings.Canvas.AutoStraightenLineThreshold * GetResolutionScale();
|
||||
// 线条必须足够长才考虑拉直,使用自适应阈值
|
||||
if (lineLength < adaptiveThreshold)
|
||||
return false;
|
||||
|
||||
// 获取用户设置的灵敏度值,确保使用正确的设置
|
||||
@@ -691,16 +692,14 @@ namespace Ink_Canvas {
|
||||
|
||||
// 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 < Settings.Canvas.AutoStraightenLineThreshold) {
|
||||
// 分辨率自适应阈值
|
||||
double adaptiveThreshold = Settings.Canvas.AutoStraightenLineThreshold * GetResolutionScale();
|
||||
// 如果线条太短,不进行拉直处理,使用自适应阈值
|
||||
if (lineLength < adaptiveThreshold) {
|
||||
// 显示调试信息 - 线条长度不足
|
||||
// MessageBox.Show($"线条太短: {lineLength} < {Settings.Canvas.AutoStraightenLineThreshold}", "调试信息");
|
||||
return false;
|
||||
@@ -1172,5 +1171,19 @@ namespace Ink_Canvas {
|
||||
public StylusPoint GetCenterPoint(StylusPoint point1, StylusPoint point2) {
|
||||
return new StylusPoint((point1.X + point2.X) / 2, (point1.Y + point2.Y) / 2);
|
||||
}
|
||||
|
||||
// 分辨率自适应:以1080P为基准,返回当前分辨率下的阈值倍数
|
||||
private double GetResolutionScale()
|
||||
{
|
||||
// 以1920x1080为基准
|
||||
double baseWidth = 1920.0;
|
||||
double baseHeight = 1080.0;
|
||||
double screenWidth = SystemParameters.PrimaryScreenWidth;
|
||||
double screenHeight = SystemParameters.PrimaryScreenHeight;
|
||||
// 取宽高平均缩放,防止极端比例
|
||||
double scaleW = screenWidth / baseWidth;
|
||||
double scaleH = screenHeight / baseHeight;
|
||||
return (scaleW + scaleH) / 2.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@ namespace Ink_Canvas {
|
||||
#region Multi-Touch
|
||||
|
||||
private bool isInMultiTouchMode = false;
|
||||
private InkCanvasEditingMode prePalmEraserEditingMode = InkCanvasEditingMode.Ink;
|
||||
private List<int> dec = new List<int>();
|
||||
private bool isSingleFingerDragMode = false;
|
||||
private Point centerPoint = new Point(0, 0);
|
||||
@@ -35,16 +34,8 @@ namespace Ink_Canvas {
|
||||
inkCanvas.Children.Clear();
|
||||
isInMultiTouchMode = false;
|
||||
|
||||
// 退出多指书写模式后,恢复手掌擦功能
|
||||
// 这里不需要特别操作,因为设置了isInMultiTouchMode = false后,
|
||||
// 下次触发Main_Grid_TouchDown时会自动判断并启用手掌擦功能
|
||||
}
|
||||
else {
|
||||
// 进入多指书写模式前,如果当前处于手掌擦状态,先关闭手掌擦
|
||||
if (isLastTouchEraser) {
|
||||
isLastTouchEraser = false;
|
||||
currentPalmEraserShape = null;
|
||||
}
|
||||
|
||||
inkCanvas.StylusDown += MainWindow_StylusDown;
|
||||
inkCanvas.StylusMove += MainWindow_StylusMove;
|
||||
@@ -69,33 +60,11 @@ namespace Ink_Canvas {
|
||||
HideSubPanels(); // 书写时自动隐藏二级菜单
|
||||
}
|
||||
|
||||
double boundWidth = e.GetTouchPoint(null).Bounds.Width, eraserMultiplier = 1.0;
|
||||
if (!Settings.Advanced.EraserBindTouchMultiplier && Settings.Advanced.IsSpecialScreen)
|
||||
eraserMultiplier = 1 / Settings.Advanced.TouchMultiplier;
|
||||
if ((Settings.Advanced.TouchMultiplier != 0 || !Settings.Advanced.IsSpecialScreen)) //启用特殊屏幕且触摸倍数为 0 时禁用橡皮
|
||||
|
||||
|
||||
// 修复:只有多指且面积大时才允许手掌擦,单指始终为批注
|
||||
if (dec != null && dec.Count >= 2 && (Settings.Advanced.TouchMultiplier != 0 || !Settings.Advanced.IsSpecialScreen)
|
||||
&& boundWidth > BoundsWidth * 2.5) {
|
||||
if (drawingShapeMode == 0 && forceEraser) return;
|
||||
currentPalmEraserShape = GetPalmRectangleEraserShape(eraserMultiplier);
|
||||
inkCanvas.EraserShape = currentPalmEraserShape;
|
||||
TouchDownPointsList[e.TouchDevice.Id] = InkCanvasEditingMode.EraseByPoint;
|
||||
isLastTouchEraser = true;
|
||||
if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint) {
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
|
||||
}
|
||||
Trace.WriteLine($"[PalmEraser] 触发手掌擦: TouchId={e.TouchDevice.Id}, boundWidth={boundWidth:F2}, eraserMultiplier={eraserMultiplier:F2}, EraserShape={currentPalmEraserShape?.GetType().Name}, TouchCount={dec.Count}");
|
||||
}
|
||||
else {
|
||||
TouchDownPointsList[e.TouchDevice.Id] = InkCanvasEditingMode.None;
|
||||
// 修复面积擦时不显示橡皮形状:无论 forcePointEraser 状态,均显示 50x50 橡皮
|
||||
inkCanvas.EraserShape = new EllipseStylusShape(50, 50);
|
||||
if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint) {
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
|
||||
}
|
||||
Trace.WriteLine($"[PalmEraser] 非手掌擦: TouchId={e.TouchDevice.Id}, boundWidth={boundWidth:F2}, eraserMultiplier={eraserMultiplier:F2}, TouchCount={(dec != null ? dec.Count : 0)}");
|
||||
// 只保留普通橡皮逻辑
|
||||
TouchDownPointsList[e.TouchDevice.Id] = InkCanvasEditingMode.None;
|
||||
inkCanvas.EraserShape = new EllipseStylusShape(50, 50);
|
||||
if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint) {
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.None;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,37 +188,6 @@ namespace Ink_Canvas {
|
||||
private int lastTouchDownTime = 0, lastTouchUpTime = 0;
|
||||
|
||||
private Point iniP = new Point(0, 0);
|
||||
private bool isLastTouchEraser = false;
|
||||
// 用于记录手掌擦的尺寸和形状
|
||||
private StylusShape currentPalmEraserShape = null;
|
||||
|
||||
/// <summary>
|
||||
/// 根据用户在设置面板中选择的橡皮大小,生成"手掌橡皮"默认的矩形黑板擦形状。
|
||||
/// 该形状大小不随触控面积等实时变化,仅受设置的橡皮大小影响。
|
||||
/// </summary>
|
||||
/// <param name="multiplier">特殊屏幕触摸倍数修正系数</param>
|
||||
/// <returns>RectangleStylusShape</returns>
|
||||
private StylusShape GetPalmRectangleEraserShape(double multiplier = 1.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.5;
|
||||
break;
|
||||
}
|
||||
|
||||
// 参照圆形橡皮 k*90 的基准,将矩形宽度压缩到 0.6,保持高度一致
|
||||
double baseLen = k * 90 * multiplier;
|
||||
return new RectangleStylusShape(baseLen * 0.6, baseLen);
|
||||
}
|
||||
|
||||
private void Main_Grid_TouchDown(object sender, TouchEventArgs e) {
|
||||
SetCursorBasedOnEditingMode(inkCanvas);
|
||||
@@ -281,6 +219,12 @@ namespace Ink_Canvas {
|
||||
}
|
||||
}
|
||||
|
||||
// 手掌擦相关变量
|
||||
private bool isPalmEraserActive = false;
|
||||
private InkCanvasEditingMode palmEraserLastEditingMode = InkCanvasEditingMode.Ink;
|
||||
private bool palmEraserLastIsHighlighter = false;
|
||||
private bool palmEraserWasEnabledBeforeMultiTouch = false;
|
||||
|
||||
private void inkCanvas_PreviewTouchDown(object sender, TouchEventArgs e) {
|
||||
// 橡皮状态下不做任何切换,直接return,保证橡皮可持续
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
@@ -293,6 +237,19 @@ namespace Ink_Canvas {
|
||||
BlackboardUIGridForInkReplay.IsHitTestVisible = false;
|
||||
|
||||
dec.Add(e.TouchDevice.Id);
|
||||
// Palm Eraser 逻辑
|
||||
if (Settings.Canvas.EnablePalmEraser && dec.Count >= 2 && !isPalmEraserActive) {
|
||||
var bounds = e.GetTouchPoint(inkCanvas).Bounds;
|
||||
double palmThreshold = 40; // 触摸面积阈值,可根据实际调整
|
||||
if (bounds.Width >= palmThreshold || bounds.Height >= palmThreshold) {
|
||||
// 记录当前编辑模式和高光状态
|
||||
palmEraserLastEditingMode = inkCanvas.EditingMode;
|
||||
palmEraserLastIsHighlighter = drawingAttributes.IsHighlighter;
|
||||
// 切换为橡皮擦
|
||||
EraserIcon_Click(null, null);
|
||||
isPalmEraserActive = true;
|
||||
}
|
||||
}
|
||||
//设备1个的时候,记录中心点
|
||||
if (dec.Count == 1) {
|
||||
var touchPoint = e.GetTouchPoint(inkCanvas);
|
||||
@@ -320,13 +277,30 @@ namespace Ink_Canvas {
|
||||
|
||||
private void inkCanvas_PreviewTouchUp(object sender, TouchEventArgs e) {
|
||||
// 橡皮状态下不做任何切换,直接return,保证橡皮可持续
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint && !isPalmEraserActive) {
|
||||
return;
|
||||
}
|
||||
inkCanvas.ReleaseAllTouchCaptures();
|
||||
ViewboxFloatingBar.IsHitTestVisible = true;
|
||||
BlackboardUIGridForInkReplay.IsHitTestVisible = true;
|
||||
|
||||
// Palm Eraser 逻辑:所有点抬起后恢复原编辑模式
|
||||
dec.Remove(e.TouchDevice.Id);
|
||||
if (isPalmEraserActive && dec.Count == 0) {
|
||||
// 恢复高光状态
|
||||
drawingAttributes.IsHighlighter = palmEraserLastIsHighlighter;
|
||||
// 恢复编辑模式
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
if (palmEraserLastEditingMode == InkCanvasEditingMode.Ink) {
|
||||
PenIcon_Click(null, null);
|
||||
} else if (palmEraserLastEditingMode == InkCanvasEditingMode.Select) {
|
||||
SymbolIconSelect_MouseUp(null, null);
|
||||
} else {
|
||||
inkCanvas.EditingMode = palmEraserLastEditingMode;
|
||||
}
|
||||
}
|
||||
isPalmEraserActive = false;
|
||||
}
|
||||
// 新增:几何绘制模式下,触摸抬手时自动落笔
|
||||
if (drawingShapeMode != 0) {
|
||||
var mouseArgs = new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left)
|
||||
@@ -343,37 +317,8 @@ namespace Ink_Canvas {
|
||||
if (lastInkCanvasEditingMode != InkCanvasEditingMode.EraseByPoint) {
|
||||
inkCanvas.EditingMode = lastInkCanvasEditingMode;
|
||||
}
|
||||
dec.Remove(e.TouchDevice.Id);
|
||||
inkCanvas.Opacity = 1;
|
||||
|
||||
// 如果是手掌触发的面积擦抬起,需要确保橡皮擦形状被正确重置
|
||||
if (isLastTouchEraser && dec.Count == 0) {
|
||||
isLastTouchEraser = false;
|
||||
currentPalmEraserShape = null; // 清除保存的手掌擦形状
|
||||
|
||||
// 当手掌擦消失时,恢复到之前的编辑模式
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
// 根据之前的编辑模式模拟点击相应的选项卡
|
||||
if (prePalmEraserEditingMode == InkCanvasEditingMode.Ink) {
|
||||
// 模拟点击批注选项卡
|
||||
PenIcon_Click(null, null);
|
||||
HideSubPanels("pen", true); // 新增:确保高光切换
|
||||
} else if (prePalmEraserEditingMode == InkCanvasEditingMode.None ||
|
||||
prePalmEraserEditingMode == InkCanvasEditingMode.Select) {
|
||||
// 模拟点击光标选项卡
|
||||
CursorIcon_Click(null, null);
|
||||
HideSubPanels("cursor", true); // 新增:确保高光切换
|
||||
} else {
|
||||
// 其他编辑模式时恢复之前的模式
|
||||
inkCanvas.EditingMode = prePalmEraserEditingMode;
|
||||
if (forcePointEraser) {
|
||||
// 重新应用当前设置的橡皮擦形状
|
||||
ApplyCurrentEraserShape();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dec.Count == 0)
|
||||
if (lastTouchDownStrokeCollection.Count() != inkCanvas.Strokes.Count() &&
|
||||
!(drawingShapeMode == 9 && !isFirstTouchCuboid)) {
|
||||
@@ -391,15 +336,14 @@ namespace Ink_Canvas {
|
||||
|
||||
private void Main_Grid_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) {
|
||||
if (e.Manipulators.Count() != 0) return;
|
||||
if (forceEraser) return;
|
||||
if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint) {
|
||||
if (drawingShapeMode == 0 && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint) {
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
|
||||
}
|
||||
}
|
||||
|
||||
private void Main_Grid_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) {
|
||||
// 手掌擦时禁止移动/缩放
|
||||
if (isLastTouchEraser || inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint)
|
||||
if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint)
|
||||
return;
|
||||
// 三指及以上禁止缩放
|
||||
bool disableScale = dec.Count >= 3;
|
||||
@@ -504,6 +448,12 @@ namespace Ink_Canvas {
|
||||
}
|
||||
inkCanvas.Children.Clear();
|
||||
isInMultiTouchMode = false;
|
||||
// 关闭多指书写时,恢复手掌擦开关
|
||||
if (palmEraserWasEnabledBeforeMultiTouch) {
|
||||
Settings.Canvas.EnablePalmEraser = true;
|
||||
if (ToggleSwitchEnablePalmEraser != null)
|
||||
ToggleSwitchEnablePalmEraser.IsOn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,6 +473,11 @@ namespace Ink_Canvas {
|
||||
}
|
||||
inkCanvas.Children.Clear();
|
||||
isInMultiTouchMode = true;
|
||||
// 启用多指书写时,自动禁用手掌擦
|
||||
palmEraserWasEnabledBeforeMultiTouch = Settings.Canvas.EnablePalmEraser;
|
||||
Settings.Canvas.EnablePalmEraser = false;
|
||||
if (ToggleSwitchEnablePalmEraser != null)
|
||||
ToggleSwitchEnablePalmEraser.IsOn = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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("1.7.1.12")]
|
||||
[assembly: AssemblyFileVersion("1.7.1.12")]
|
||||
[assembly: AssemblyVersion("1.7.1.14")]
|
||||
[assembly: AssemblyFileVersion("1.7.1.14")]
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Ink_Canvas
|
||||
[JsonProperty("autoStraightenLine")]
|
||||
public bool AutoStraightenLine { get; set; } = true; // 是否启用直线自动拉直
|
||||
[JsonProperty("autoStraightenLineThreshold")]
|
||||
public int AutoStraightenLineThreshold { get; set; } = 30; // 直线自动拉直的长度阈值(像素)
|
||||
public int AutoStraightenLineThreshold { get; set; } = 80; // 直线自动拉直的长度阈值(像素)
|
||||
[JsonProperty("highPrecisionLineStraighten")]
|
||||
public bool HighPrecisionLineStraighten { get; set; } = true; // 是否启用高精度直线拉直
|
||||
[JsonProperty("lineEndpointSnapping")]
|
||||
@@ -238,7 +238,7 @@ namespace Ink_Canvas
|
||||
[JsonProperty("isEnableFingerGestureSlideShowControl")]
|
||||
public bool IsEnableFingerGestureSlideShowControl { get; set; } = true;
|
||||
[JsonProperty("isSupportWPS")]
|
||||
public bool IsSupportWPS { get; set; } = true;
|
||||
public bool IsSupportWPS { get; set; } = false;
|
||||
[JsonProperty("enableWppProcessKill")]
|
||||
public bool EnableWppProcessKill { get; set; } = true;
|
||||
[JsonProperty("isAlwaysGoToFirstPageOnReenter")]
|
||||
|
||||
Reference in New Issue
Block a user