代码优化
This commit is contained in:
+3
-2
@@ -2,6 +2,7 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Ink_Canvas"
|
||||
xmlns:props="clr-namespace:Ink_Canvas.Properties"
|
||||
xmlns:tb="clr-namespace:H.NotifyIcon;assembly=H.NotifyIcon.Wpf"
|
||||
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
|
||||
@@ -35,7 +36,7 @@
|
||||
<MenuItem Name="TempShowMainWindowTrayIconMenuItem" Click="TempShowMainWindowTrayIconMenuItem_Clicked">
|
||||
<MenuItem.Header>
|
||||
<ikw:SimpleStackPanel Orientation="Horizontal" Margin="-4,0,0,0">
|
||||
<TextBlock FontSize="14" VerticalAlignment="Center" Foreground="#18181b" Text="显示主窗口(2分钟)" />
|
||||
<TextBlock FontSize="14" VerticalAlignment="Center" Foreground="#18181b" Text="{x:Static props:Strings.Tray_TempShowMainWindow}" />
|
||||
</ikw:SimpleStackPanel>
|
||||
</MenuItem.Header>
|
||||
<MenuItem.Icon>
|
||||
@@ -55,7 +56,7 @@
|
||||
<MenuItem Name="OpenSettingsTrayIconMenuItem" Click="OpenSettingsTrayIconMenuItem_Clicked">
|
||||
<MenuItem.Header>
|
||||
<ikw:SimpleStackPanel Orientation="Horizontal" Margin="-4,0,0,0">
|
||||
<TextBlock FontSize="14" VerticalAlignment="Center" Foreground="#18181b" Text="打开设置" />
|
||||
<TextBlock FontSize="14" VerticalAlignment="Center" Foreground="#18181b" Text="{x:Static props:Strings.Tray_OpenSettings}" />
|
||||
</ikw:SimpleStackPanel>
|
||||
</MenuItem.Header>
|
||||
<MenuItem.Icon>
|
||||
|
||||
@@ -48,13 +48,17 @@ namespace Ink_Canvas.Helpers
|
||||
break;
|
||||
}
|
||||
if (alternates.Count > 0)
|
||||
analysisAlternate = alternates[0];
|
||||
{
|
||||
var altFinal = alternates[0];
|
||||
if (altFinal?.AlternateNodes != null && altFinal.AlternateNodes.Count > 0)
|
||||
analysisAlternate = altFinal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
analyzer.Dispose();
|
||||
|
||||
if (analysisAlternate != null && analysisAlternate.AlternateNodes.Count > 0)
|
||||
if (analysisAlternate != null && analysisAlternate.AlternateNodes != null && analysisAlternate.AlternateNodes.Count > 0)
|
||||
{
|
||||
var node = analysisAlternate.AlternateNodes[0] as InkDrawingNode;
|
||||
if (node == null)
|
||||
|
||||
@@ -49,16 +49,13 @@ namespace Ink_Canvas.Helpers
|
||||
if (string.IsNullOrWhiteSpace(softwareName))
|
||||
return null;
|
||||
|
||||
// 64 位进程默认只枚举 64 位注册表视图;32 位希沃常写在 WOW6432Node 下,需一并扫描。
|
||||
string[] uninstallRoots =
|
||||
// 须用 OpenBaseKey + RegistryView 显式指定视图:Registry.LocalMachine.OpenSubKey 跟随进程位数,
|
||||
// 32 位进程下无法靠拼接 WOW6432Node 路径进入 64 位视图,会找不到 64 位安装的展台。
|
||||
const string uninstallSubKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
|
||||
foreach (RegistryView view in new[] { RegistryView.Registry64, RegistryView.Registry32 })
|
||||
{
|
||||
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
|
||||
@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
|
||||
};
|
||||
|
||||
foreach (string root in uninstallRoots)
|
||||
{
|
||||
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(root))
|
||||
using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, view))
|
||||
using (RegistryKey key = baseKey.OpenSubKey(uninstallSubKey))
|
||||
{
|
||||
if (key == null) continue;
|
||||
string found = FindInUninstallKey(key, softwareName);
|
||||
|
||||
@@ -100,8 +100,8 @@ namespace Ink_Canvas.Helpers
|
||||
var item = _currentStrokeHistory[_currentIndex];
|
||||
item.StrokeHasBeenCleared = !item.StrokeHasBeenCleared;
|
||||
_currentIndex--;
|
||||
OnUndoStateChanged?.Invoke(_currentIndex > -1);
|
||||
OnRedoStateChanged?.Invoke(_currentStrokeHistory.Count - _currentIndex - 1 > 0);
|
||||
OnUndoStateChanged?.Invoke(CanUndo);
|
||||
OnRedoStateChanged?.Invoke(CanRedo);
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -137,8 +137,8 @@ namespace Ink_Canvas.Helpers
|
||||
}
|
||||
private void NotifyUndoRedoState()
|
||||
{
|
||||
OnUndoStateChanged?.Invoke(_currentIndex > -1);
|
||||
OnRedoStateChanged?.Invoke(_currentStrokeHistory.Count - _currentIndex - 1 > 0);
|
||||
OnUndoStateChanged?.Invoke(CanUndo);
|
||||
OnRedoStateChanged?.Invoke(CanRedo);
|
||||
}
|
||||
|
||||
/// <summary>当前历史是否允许撤销。</summary>
|
||||
|
||||
@@ -40,7 +40,9 @@ namespace Ink_Canvas.Helpers
|
||||
{
|
||||
try
|
||||
{
|
||||
await RecognizeHandwritingAsync(new StrokeCollection()).ConfigureAwait(true);
|
||||
await RecognizeHandwritingAsync(
|
||||
WinRtInkShapeRecognizer.CreateMinimalWarmupStrokeCollection(),
|
||||
verboseTrace: false).ConfigureAwait(true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -59,12 +61,15 @@ namespace Ink_Canvas.Helpers
|
||||
/// 再对每一分词用 <see cref="WinRtInk.InkRecognizerContainer"/> 取 <c>GetTextCandidates</c>(与当前 SDK 中部分版本的
|
||||
/// <see cref="WinRtInk.InkRecognitionResult"/> 未暴露笔画映射的局限兼容)。
|
||||
/// </summary>
|
||||
public static async Task<HandwritingRecognitionResult> RecognizeHandwritingAsync(StrokeCollection strokes)
|
||||
/// <param name="verboseTrace">为 false 时跳过详细识别日志(用于 <see cref="Warmup"/> 等)。</param>
|
||||
public static async Task<HandwritingRecognitionResult> RecognizeHandwritingAsync(
|
||||
StrokeCollection strokes,
|
||||
bool verboseTrace = true)
|
||||
{
|
||||
if (!IsApiAvailable || strokes == null || strokes.Count == 0)
|
||||
return HandwritingRecognitionResult.Empty;
|
||||
|
||||
var traceRecognition = strokes.Count > 0;
|
||||
var traceRecognition = verboseTrace;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -28,7 +28,8 @@ namespace Ink_Canvas.Helpers
|
||||
{
|
||||
try
|
||||
{
|
||||
await RecognizeShapeAsync(new StrokeCollection());
|
||||
// 空 StrokeCollection 在 RecognizeShapeAsync 入口会直接返回,无法预热 WinRT InkAnalyzer。
|
||||
await RecognizeShapeAsync(CreateMinimalWarmupStrokeCollection()).ConfigureAwait(true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -99,6 +100,23 @@ namespace Ink_Canvas.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 极短合成笔画,供 <see cref="Warmup"/> 等场景走完整 WinRT 转换与分析管线(空集合在入口处会被直接返回)。
|
||||
/// </summary>
|
||||
internal static StrokeCollection CreateMinimalWarmupStrokeCollection()
|
||||
{
|
||||
var da = new DrawingAttributes { Color = Colors.Black, Width = 2, Height = 2 };
|
||||
var pts = new StylusPointCollection
|
||||
{
|
||||
new StylusPoint(8, 8),
|
||||
new StylusPoint(14, 10),
|
||||
new StylusPoint(20, 8),
|
||||
};
|
||||
var col = new StrokeCollection();
|
||||
col.Add(new Stroke(pts, da));
|
||||
return col;
|
||||
}
|
||||
|
||||
/// <summary>供 WinRT 手写等模块复用:将 WPF <see cref="Stroke"/> 转为 WinRT <see cref="global::Windows.UI.Input.Inking.InkStroke"/>。</summary>
|
||||
internal static global::Windows.UI.Input.Inking.InkStroke CreateInkStrokeFromWpf(Stroke stroke)
|
||||
{
|
||||
|
||||
@@ -176,85 +176,89 @@ namespace Ink_Canvas
|
||||
}
|
||||
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
|
||||
|
||||
switch (Settings.Canvas.InkStyle)
|
||||
// 「屏蔽压感」已在收笔主路径将点集归一成 0.5;此处若再跑 InkStyle 0/1 会重写 PressureFactor,造成假压感。
|
||||
if (!Settings.Canvas.DisablePressure)
|
||||
{
|
||||
case 1:
|
||||
if (penType == 0)
|
||||
try
|
||||
{
|
||||
var stylusPoints = new StylusPointCollection();
|
||||
var n = e.Stroke.StylusPoints.Count - 1;
|
||||
|
||||
for (var i = 0; i <= n; i++)
|
||||
switch (Settings.Canvas.InkStyle)
|
||||
{
|
||||
case 1:
|
||||
if (penType == 0)
|
||||
try
|
||||
{
|
||||
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
|
||||
{
|
||||
PressureFactor = RateBasedPressureFactorFromPointSpeed(speed),
|
||||
X = e.Stroke.StylusPoints[i].X,
|
||||
Y = e.Stroke.StylusPoints[i].Y
|
||||
};
|
||||
stylusPoints.Add(point);
|
||||
}
|
||||
var stylusPoints = new StylusPointCollection();
|
||||
var n = e.Stroke.StylusPoints.Count - 1;
|
||||
|
||||
e.Stroke.StylusPoints = stylusPoints;
|
||||
}
|
||||
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
|
||||
|
||||
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 e.Stroke;
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
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
|
||||
{
|
||||
PressureFactor = RateBasedPressureFactorFromPointSpeed(speed),
|
||||
X = e.Stroke.StylusPoints[i].X,
|
||||
Y = e.Stroke.StylusPoints[i].Y
|
||||
};
|
||||
stylusPoints.Add(point);
|
||||
}
|
||||
|
||||
e.Stroke.StylusPoints = stylusPoints;
|
||||
}
|
||||
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
|
||||
|
||||
e.Stroke.StylusPoints = stylusPoints;
|
||||
}
|
||||
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
|
||||
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 e.Stroke;
|
||||
if (n >= x)
|
||||
{
|
||||
for (var i = 0; i < n - x; i++)
|
||||
{
|
||||
var point = new StylusPoint();
|
||||
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
|
||||
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
|
||||
@@ -507,7 +511,11 @@ namespace Ink_Canvas
|
||||
|
||||
// 实时笔锋:勿依赖 DrawingAttributes.IgnorePressure。无压感触摸/鼠标等设备上,运行时仍可能为 true,
|
||||
// 会导致不进入逻辑或进入后渲染仍忽略 PressureFactor;具体在 ApplyVelocityBrushTipFromSpeed 内关闭。
|
||||
// 「屏蔽压感」时必须跳过:否则会重写 PressureFactor 并强制 IgnorePressure=false,与归一压感冲突。
|
||||
// VelocityBrushTipMix <= 0 时 ApplyVelocityBrushTipFromSpeed 为空操作,无需调用。
|
||||
if (Settings.Canvas.InkStyle == 3
|
||||
&& Settings.Canvas.VelocityBrushTipMix > 0
|
||||
&& !Settings.Canvas.DisablePressure
|
||||
&& !touchPressureSimulationApplied
|
||||
&& penType != 1
|
||||
&& e.Stroke?.DrawingAttributes != null
|
||||
@@ -2183,12 +2191,16 @@ namespace Ink_Canvas
|
||||
|
||||
/// <summary>
|
||||
/// 将沿线速度映射为压感并与硬件压感混合,快写略细、慢写略粗;在落笔时(及手写笔移动时由调用方)统一施加。
|
||||
/// 无压感设备上系统可能将 <see cref="DrawingAttributes.IgnorePressure"/> 置为 true,此处强制关闭以便粗细随合成压感变化(与「屏蔽压感」无关:调用方已保证未屏蔽)。
|
||||
/// 无压感设备上系统可能将 <see cref="DrawingAttributes.IgnorePressure"/> 置为 true,此处强制关闭以便粗细随合成压感变化。
|
||||
/// 若 <see cref="Settings.Canvas.DisablePressure"/> 为 true,本方法直接返回且不修改 IgnorePressure。
|
||||
/// </summary>
|
||||
private void ApplyVelocityBrushTipFromSpeed(Stroke stroke)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Settings.Canvas.DisablePressure)
|
||||
return;
|
||||
|
||||
var mix = Settings.Canvas.VelocityBrushTipMix;
|
||||
if (mix <= 0 || stroke == null) return;
|
||||
if (mix > 1) mix = 1;
|
||||
@@ -2885,7 +2897,11 @@ namespace Ink_Canvas
|
||||
|
||||
PruneHandwritingBeautifyBatch();
|
||||
while (_handwritingRecentStrokesForBeautify.Count > HandwritingBeautifyMaxRecentStrokes)
|
||||
{
|
||||
var evicted = _handwritingRecentStrokesForBeautify[0];
|
||||
_handwritingRecentStrokesForBeautify.RemoveAt(0);
|
||||
_handwritingBeautifyInkInputByCanvasStroke.Remove(evicted);
|
||||
}
|
||||
|
||||
EnsureHandwritingBeautifyDebounceTimer();
|
||||
_handwritingBeautifyDebounceTimer.Stop();
|
||||
|
||||
@@ -543,10 +543,12 @@ namespace Ink_Canvas
|
||||
foreach (var stylusPoint in stylusPointCollection)
|
||||
strokeVisual.Add(new StylusPoint(stylusPoint.X, stylusPoint.Y, stylusPoint.PressureFactor));
|
||||
|
||||
// 实时笔锋:在绘制过程中更新压感并整笔重绘预览;否则预览层固定线宽,收笔后改点集也看不到笔锋变化。
|
||||
// 实时笔锋:混合度 > 0 时在绘制过程中更新压感并整笔重绘预览;混合为 0 时与普通过程一致用增量 Redraw,避免每点 ForceRedraw 整笔清空(长笔画卡顿)。
|
||||
var committedStroke = strokeVisual.Stroke;
|
||||
if (committedStroke != null
|
||||
&& Settings.Canvas.InkStyle == 3
|
||||
&& Settings.Canvas.VelocityBrushTipMix > 0
|
||||
&& !Settings.Canvas.DisablePressure
|
||||
&& penType == 0
|
||||
&& committedStroke.DrawingAttributes != null
|
||||
&& !committedStroke.DrawingAttributes.IsHighlighter
|
||||
|
||||
+2
@@ -119,5 +119,7 @@ namespace Ink_Canvas.Properties
|
||||
public static string Nav_About => GetString(nameof(Nav_About)) ?? "关于";
|
||||
public static string App_Title => GetString(nameof(App_Title)) ?? "InkCanvasforClass";
|
||||
public static string Booth_Resolution_Tooltip => GetString(nameof(Booth_Resolution_Tooltip)) ?? "展台/截图分辨率";
|
||||
public static string Tray_TempShowMainWindow => GetString(nameof(Tray_TempShowMainWindow)) ?? "显示主窗口(2分钟)";
|
||||
public static string Tray_OpenSettings => GetString(nameof(Tray_OpenSettings)) ?? "打开设置";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,4 +763,6 @@
|
||||
<data name="FloatingBar_Gesture_TwoFingerRotate" xml:space="preserve"><value>Two-finger rotate</value></data>
|
||||
<data name="Board_Gesture" xml:space="preserve"><value>Gesture</value></data>
|
||||
<data name="Board_GestureOptions" xml:space="preserve"><value>Gesture options</value></data>
|
||||
<data name="Tray_TempShowMainWindow" xml:space="preserve"><value>Show main window (2 minutes)</value></data>
|
||||
<data name="Tray_OpenSettings" xml:space="preserve"><value>Open settings</value></data>
|
||||
</root>
|
||||
|
||||
@@ -782,4 +782,12 @@
|
||||
<data name="FloatingBar_Gesture_TwoFingerRotate" xml:space="preserve"><value>双指旋转</value></data>
|
||||
<data name="Board_Gesture" xml:space="preserve"><value>手势</value></data>
|
||||
<data name="Board_GestureOptions" xml:space="preserve"><value>手势选项</value></data>
|
||||
<data name="Tray_TempShowMainWindow" xml:space="preserve">
|
||||
<value>显示主窗口(2分钟)</value>
|
||||
<comment>系统托盘 - 临时显示主窗口</comment>
|
||||
</data>
|
||||
<data name="Tray_OpenSettings" xml:space="preserve">
|
||||
<value>打开设置</value>
|
||||
<comment>系统托盘 - 打开设置</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
Reference in New Issue
Block a user