Merge branch 'net6' of https://github.com/InkCanvasForClass/community into net6
This commit is contained in:
@@ -1202,6 +1202,22 @@ namespace Ink_Canvas
|
||||
LogHelper.WriteLogToFile($"释放IACore DLL时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var shapeMode = ShapeRecognitionRouter.FromSettingsInt(
|
||||
Ink_Canvas.Windows.SettingsViews.Helpers.SettingsManager.Settings?.InkToShape?.ShapeRecognitionEngine ?? 0);
|
||||
if (!ShapeRecognitionRouter.ResolveUseWinRt(shapeMode))
|
||||
{
|
||||
LogHelper.WriteLogToFile("启动 IACore IPC 辅助进程");
|
||||
bool ipcStarted = IpcIACoreClient.Instance.Start();
|
||||
LogHelper.WriteLogToFile($"IACore IPC 辅助进程{(ipcStarted ? "启动成功" : "启动失败")}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"启动 IACore IPC 辅助进程时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LogHelper.WriteLogToFile("开始注册.icstk文件关联");
|
||||
@@ -1577,6 +1593,13 @@ namespace Ink_Canvas
|
||||
private void App_Exit(object sender, ExitEventArgs e)
|
||||
{
|
||||
CleanupTerminationMonitoring();
|
||||
|
||||
try
|
||||
{
|
||||
IpcIACoreClient.Instance.Dispose();
|
||||
}
|
||||
catch { }
|
||||
|
||||
// 卸载所有插件
|
||||
try
|
||||
{
|
||||
|
||||
@@ -96,8 +96,10 @@ namespace Ink_Canvas.Helpers
|
||||
return RecognizeShapeWinRtOnDispatcherContext(strokes);
|
||||
}
|
||||
|
||||
var legacy = InkRecognizeHelper.RecognizeShapeIACore(strokes);
|
||||
return Task.FromResult(InkRecognizeHelper.FromIACoreOrEmpty(legacy));
|
||||
// IACore 必须走 IPC 辅助进程(x86/.NET 4.7.2)。
|
||||
// 在 .NET 6 x64 主进程中本地加载 IAWinFX 会失败,故不再本地回退。
|
||||
var ipcResult = IpcIACoreClient.Instance.Recognize(strokes);
|
||||
return Task.FromResult(ipcResult);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -214,9 +216,11 @@ namespace Ink_Canvas.Helpers
|
||||
|
||||
public string GetSystemInfo()
|
||||
{
|
||||
return _isModernSystemAvailable
|
||||
? $"现代化墨迹识别系统 (Windows Runtime API) - 进程架构: {Environment.Is64BitProcess}"
|
||||
: $"传统墨迹识别系统 (IACore) - 进程架构: {Environment.Is64BitProcess}";
|
||||
if (_isModernSystemAvailable)
|
||||
return $"现代化墨迹识别系统 (Windows Runtime API) - 进程架构: {Environment.Is64BitProcess}";
|
||||
if (IpcIACoreClient.Instance.IsAvailable)
|
||||
return $"传统墨迹识别系统 (IACore via IPC) - 进程架构: {Environment.Is64BitProcess}";
|
||||
return $"传统墨迹识别系统 (IACore 本地) - 进程架构: {Environment.Is64BitProcess}";
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -1,79 +1,15 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Ink_Canvas.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// 墨迹形状/手写识别的对外门面。
|
||||
/// IACore 路径通过 IPC 调用 x86 辅助进程;WinRT 路径在主进程内直接调用。
|
||||
/// 主进程 (.NET 6 x64) 不再直接引用 IAWinFX 类型。
|
||||
/// </summary>
|
||||
public class InkRecognizeHelper
|
||||
{
|
||||
/// <summary>IACore / IAWinFX 形状识别(典型用于 32 位进程)。</summary>
|
||||
public static ShapeRecognizeResult RecognizeShapeIACore(StrokeCollection strokes)
|
||||
{
|
||||
if (strokes == null || strokes.Count == 0)
|
||||
return default;
|
||||
|
||||
var analyzer = new InkAnalyzer();
|
||||
analyzer.AddStrokes(strokes);
|
||||
analyzer.SetStrokesType(strokes, StrokeType.Drawing);
|
||||
|
||||
AnalysisAlternate analysisAlternate = null;
|
||||
int strokesCount = strokes.Count;
|
||||
var sfsaf = analyzer.Analyze();
|
||||
if (sfsaf.Successful)
|
||||
{
|
||||
var alternates = analyzer.GetAlternates();
|
||||
if (alternates.Count > 0)
|
||||
{
|
||||
while (strokesCount >= 2)
|
||||
{
|
||||
var alt0 = alternates[0];
|
||||
if (alt0?.AlternateNodes == null || alt0.AlternateNodes.Count == 0)
|
||||
break;
|
||||
var drawNode = alt0.AlternateNodes[0] as InkDrawingNode;
|
||||
if (drawNode == null)
|
||||
break;
|
||||
var shapeOk = IsContainShapeType(drawNode.GetShapeName());
|
||||
if (alt0.Strokes.Contains(strokes.Last()) && shapeOk)
|
||||
break;
|
||||
analyzer.RemoveStroke(strokes[strokes.Count - strokesCount]);
|
||||
strokesCount--;
|
||||
sfsaf = analyzer.Analyze();
|
||||
if (sfsaf.Successful)
|
||||
alternates = analyzer.GetAlternates();
|
||||
else
|
||||
break;
|
||||
if (alternates.Count == 0)
|
||||
break;
|
||||
}
|
||||
if (alternates.Count > 0)
|
||||
{
|
||||
var altFinal = alternates[0];
|
||||
if (altFinal?.AlternateNodes != null && altFinal.AlternateNodes.Count > 0)
|
||||
analysisAlternate = altFinal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
analyzer.Dispose();
|
||||
|
||||
if (analysisAlternate != null && analysisAlternate.AlternateNodes != null && analysisAlternate.AlternateNodes.Count > 0)
|
||||
{
|
||||
var node = analysisAlternate.AlternateNodes[0] as InkDrawingNode;
|
||||
if (node == null)
|
||||
return default;
|
||||
return new ShapeRecognizeResult(node.Centroid, node.HotPoints, analysisAlternate, node);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <summary>兼容旧调用:等价于 <see cref="RecognizeShapeIACore"/>。</summary>
|
||||
public static ShapeRecognizeResult RecognizeShape(StrokeCollection strokes) =>
|
||||
RecognizeShapeIACore(strokes);
|
||||
|
||||
/// <summary>按设置选择 WinRT(<see cref="InkRecognitionManager"/>)或 IACore;WinRT 请用 <see cref="RecognizeShapeUnifiedAsync"/>。</summary>
|
||||
public static InkShapeRecognitionResult RecognizeShapeUnified(
|
||||
StrokeCollection strokes,
|
||||
ShapeRecognitionEngineMode mode)
|
||||
@@ -84,11 +20,9 @@ namespace Ink_Canvas.Helpers
|
||||
if (ShapeRecognitionRouter.ResolveUseWinRt(mode))
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
|
||||
var legacy = RecognizeShapeIACore(strokes);
|
||||
return FromIACoreOrEmpty(legacy);
|
||||
return IpcIACoreClient.Instance.Recognize(strokes);
|
||||
}
|
||||
|
||||
/// <summary>与 CE 反编译版 <c>InkRecognitionManager.RecognizeShapeAsync</c> 对齐的统一入口。</summary>
|
||||
public static Task<InkShapeRecognitionResult> RecognizeShapeUnifiedAsync(
|
||||
StrokeCollection strokes,
|
||||
ShapeRecognitionEngineMode mode)
|
||||
@@ -109,7 +43,9 @@ namespace Ink_Canvas.Helpers
|
||||
WinRtHandwritingRecognizer.Warmup();
|
||||
}
|
||||
else
|
||||
RecognizeShapeIACore(new StrokeCollection());
|
||||
{
|
||||
IpcIACoreClient.Instance.Start();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -117,13 +53,11 @@ namespace Ink_Canvas.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>WinRT 手写识别(Windows 10+)。</summary>
|
||||
public static Task<HandwritingRecognitionResult> RecognizeHandwritingUnifiedAsync(
|
||||
StrokeCollection strokes,
|
||||
ShapeRecognitionEngineMode mode) =>
|
||||
InkRecognitionManager.Instance.RecognizeHandwritingAsync(strokes, mode);
|
||||
|
||||
/// <summary>WinRT 下将识别成功的词替换为手写体字形墨迹;是否应用由设置「WinRT 识别转手写体字形」控制。</summary>
|
||||
public static Task<StrokeCollection> CorrectHandwritingStrokesUnifiedAsync(
|
||||
StrokeCollection strokes,
|
||||
ShapeRecognitionEngineMode mode) =>
|
||||
@@ -133,7 +67,6 @@ namespace Ink_Canvas.Helpers
|
||||
MainWindow.Settings?.InkToShape?.EnableWinRtHandwritingStrokeBeautify ?? false,
|
||||
MainWindow.Settings?.InkToShape?.HandwritingCorrectionFontFamily);
|
||||
|
||||
/// <summary>显式指定是否应用手写体字形替换(忽略开关);字体仍从设置读取。</summary>
|
||||
public static Task<StrokeCollection> CorrectHandwritingStrokesUnifiedAsync(
|
||||
StrokeCollection strokes,
|
||||
ShapeRecognitionEngineMode mode,
|
||||
@@ -144,53 +77,18 @@ namespace Ink_Canvas.Helpers
|
||||
applyHandwritingBeautify,
|
||||
MainWindow.Settings?.InkToShape?.HandwritingCorrectionFontFamily);
|
||||
|
||||
internal static InkShapeRecognitionResult FromIACoreOrEmpty(ShapeRecognizeResult legacy)
|
||||
{
|
||||
if (legacy?.InkDrawingNode == null)
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
|
||||
var node = legacy.InkDrawingNode;
|
||||
var shape = node.GetShape();
|
||||
if (shape == null)
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
|
||||
var hot = ClonePointCollection(node.HotPoints);
|
||||
return new InkShapeRecognitionResult(
|
||||
node.GetShapeName(),
|
||||
legacy.Centroid,
|
||||
hot,
|
||||
shape.Width,
|
||||
shape.Height,
|
||||
node.Strokes);
|
||||
}
|
||||
|
||||
private static PointCollection ClonePointCollection(PointCollection src)
|
||||
{
|
||||
var dst = new PointCollection();
|
||||
if (src == null) return dst;
|
||||
foreach (System.Windows.Point p in src)
|
||||
dst.Add(p);
|
||||
return dst;
|
||||
}
|
||||
|
||||
public static bool IsContainShapeType(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
return false;
|
||||
|
||||
if (name.Contains("Triangle") || name.Contains("Circle") ||
|
||||
name.Contains("Rectangle") || name.Contains("Diamond") ||
|
||||
name.Contains("Parallelogram") || name.Contains("Square")
|
||||
|| name.Contains("Ellipse"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return name.Contains("Triangle") || name.Contains("Circle") ||
|
||||
name.Contains("Rectangle") || name.Contains("Diamond") ||
|
||||
name.Contains("Parallelogram") || name.Contains("Square") ||
|
||||
name.Contains("Ellipse");
|
||||
}
|
||||
}
|
||||
|
||||
//Recognizer 的实现
|
||||
|
||||
public enum RecognizeLanguage
|
||||
{
|
||||
SimplifiedChinese = 0x0804,
|
||||
@@ -198,127 +96,17 @@ namespace Ink_Canvas.Helpers
|
||||
English = 0x0809
|
||||
}
|
||||
|
||||
public class ShapeRecognizeResult
|
||||
{
|
||||
public ShapeRecognizeResult(Point centroid, PointCollection hotPoints, AnalysisAlternate analysisAlternate, InkDrawingNode node)
|
||||
{
|
||||
Centroid = centroid;
|
||||
HotPoints = hotPoints;
|
||||
AnalysisAlternate = analysisAlternate;
|
||||
InkDrawingNode = node;
|
||||
}
|
||||
|
||||
public AnalysisAlternate AnalysisAlternate { get; }
|
||||
|
||||
public Point Centroid { get; set; }
|
||||
|
||||
public PointCollection HotPoints { get; }
|
||||
|
||||
public InkDrawingNode InkDrawingNode { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 图形识别类
|
||||
/// </summary>
|
||||
//public class ShapeRecogniser
|
||||
//{
|
||||
// public InkAnalyzer _inkAnalyzer = null;
|
||||
|
||||
// private ShapeRecogniser()
|
||||
// {
|
||||
// this._inkAnalyzer = new InkAnalyzer
|
||||
// {
|
||||
// AnalysisModes = AnalysisModes.AutomaticReconciliationEnabled
|
||||
// };
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// 根据笔迹集合返回图形名称字符串
|
||||
// /// </summary>
|
||||
// /// <param name="strokeCollection"></param>
|
||||
// /// <returns></returns>
|
||||
// public InkDrawingNode Recognition(StrokeCollection strokeCollection)
|
||||
// {
|
||||
// if (strokeCollection == null)
|
||||
// {
|
||||
// //MessageBox.Show("dddddd");
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// InkDrawingNode result = null;
|
||||
// try
|
||||
// {
|
||||
// this._inkAnalyzer.AddStrokes(strokeCollection);
|
||||
// if (this._inkAnalyzer.Analyze().Successful)
|
||||
// {
|
||||
// result = _internalAnalyzer(this._inkAnalyzer);
|
||||
// this._inkAnalyzer.RemoveStrokes(strokeCollection);
|
||||
// }
|
||||
// }
|
||||
// catch (System.Exception ex)
|
||||
// {
|
||||
// //result = ex.Message;
|
||||
// System.Diagnostics.Debug.WriteLine(ex.Message);
|
||||
// }
|
||||
|
||||
// return result;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// 实现笔迹的分析,返回图形对应的字符串
|
||||
// /// 你在实际的应用中根据返回的字符串来生成对应的Shape
|
||||
// /// </summary>
|
||||
// /// <param name="ink"></param>
|
||||
// /// <returns></returns>
|
||||
// private InkDrawingNode _internalAnalyzer(InkAnalyzer ink)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// ContextNodeCollection nodecollections = ink.FindNodesOfType(ContextNodeType.InkDrawing);
|
||||
// foreach (ContextNode node in nodecollections)
|
||||
// {
|
||||
// InkDrawingNode drawingNode = node as InkDrawingNode;
|
||||
// if (drawingNode != null)
|
||||
// {
|
||||
// return drawingNode;//.GetShapeName();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch (System.Exception ex)
|
||||
// {
|
||||
// System.Diagnostics.Debug.WriteLine(ex.Message);
|
||||
// }
|
||||
|
||||
// return null;
|
||||
// }
|
||||
|
||||
|
||||
// private static ShapeRecogniser instance = null;
|
||||
// public static ShapeRecogniser Instance
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// return instance == null ? (instance = new ShapeRecogniser()) : instance;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//用于自动控制其他形状相对于圆的位置
|
||||
|
||||
public class Circle
|
||||
{
|
||||
public Circle(Point centroid, double r, Stroke stroke)
|
||||
public Circle(System.Windows.Point centroid, double r, Stroke stroke)
|
||||
{
|
||||
Centroid = centroid;
|
||||
R = r;
|
||||
Stroke = stroke;
|
||||
}
|
||||
|
||||
public Point Centroid { get; set; }
|
||||
|
||||
public System.Windows.Point Centroid { get; set; }
|
||||
public double R { get; set; }
|
||||
|
||||
public Stroke Stroke { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Pipes;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Ink_Canvas.Helpers
|
||||
{
|
||||
public sealed class IpcIACoreClient : IDisposable
|
||||
{
|
||||
private static IpcIACoreClient _instance;
|
||||
private static readonly object _instanceLock = new object();
|
||||
|
||||
public static IpcIACoreClient Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
lock (_instanceLock)
|
||||
if (_instance == null)
|
||||
_instance = new IpcIACoreClient();
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private Process _helperProcess;
|
||||
private readonly object _pipeLock = new object();
|
||||
private bool _disposed;
|
||||
private bool _available;
|
||||
|
||||
private static string HelperExePath =>
|
||||
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "InkCanvasForClass.IACoreHelper.exe");
|
||||
|
||||
private string PipeName =>
|
||||
string.Format("ICC_IACoreHelper_{0}", Process.GetCurrentProcess().Id);
|
||||
|
||||
private IpcIACoreClient() { }
|
||||
|
||||
public bool Start()
|
||||
{
|
||||
if (_disposed) return false;
|
||||
if (IsAvailable) return true;
|
||||
|
||||
if (!File.Exists(HelperExePath))
|
||||
{
|
||||
_available = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return LaunchHelper();
|
||||
}
|
||||
|
||||
public bool IsAvailable => _available && _helperProcess != null && !_helperProcess.HasExited;
|
||||
|
||||
public InkShapeRecognitionResult Recognize(StrokeCollection strokes)
|
||||
{
|
||||
if (strokes == null || strokes.Count == 0)
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
|
||||
EnsureHelperAlive();
|
||||
if (!IsAvailable)
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
|
||||
lock (_pipeLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
return SendRecognizeRequest(strokes);
|
||||
}
|
||||
catch
|
||||
{
|
||||
KillHelper();
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool LaunchHelper()
|
||||
{
|
||||
try
|
||||
{
|
||||
KillHelper();
|
||||
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = HelperExePath,
|
||||
Arguments = Process.GetCurrentProcess().Id.ToString(),
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory
|
||||
};
|
||||
_helperProcess = Process.Start(psi);
|
||||
if (_helperProcess == null)
|
||||
{
|
||||
_available = false;
|
||||
return false;
|
||||
}
|
||||
_helperProcess.EnableRaisingEvents = true;
|
||||
_helperProcess.Exited += OnHelperExited;
|
||||
|
||||
bool pipeReady = WaitForPipe(3000);
|
||||
_available = pipeReady;
|
||||
return pipeReady;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_available = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool WaitForPipe(int timeoutMs)
|
||||
{
|
||||
int elapsed = 0;
|
||||
while (elapsed < timeoutMs)
|
||||
{
|
||||
if (_helperProcess == null || _helperProcess.HasExited)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
using (var probe = new NamedPipeClientStream(".", PipeName, PipeDirection.InOut))
|
||||
{
|
||||
probe.Connect(200);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
elapsed += 300;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private InkShapeRecognitionResult SendRecognizeRequest(StrokeCollection strokes)
|
||||
{
|
||||
using (var client = new NamedPipeClientStream(".", PipeName, PipeDirection.InOut))
|
||||
{
|
||||
client.Connect(IpcTimeoutMs);
|
||||
|
||||
using (var writer = new BinaryWriter(client, System.Text.Encoding.UTF8, leaveOpen: true))
|
||||
using (var reader = new BinaryReader(client, System.Text.Encoding.UTF8, leaveOpen: true))
|
||||
{
|
||||
writer.Write(CmdRecognize);
|
||||
writer.Write(strokes.Count);
|
||||
foreach (var stroke in strokes)
|
||||
{
|
||||
var pts = stroke.StylusPoints;
|
||||
writer.Write(pts.Count);
|
||||
foreach (var pt in pts)
|
||||
{
|
||||
writer.Write((float)pt.X);
|
||||
writer.Write((float)pt.Y);
|
||||
writer.Write(pt.PressureFactor);
|
||||
}
|
||||
}
|
||||
writer.Flush();
|
||||
|
||||
bool success = reader.ReadBoolean();
|
||||
string shape = reader.ReadString();
|
||||
float cx = reader.ReadSingle();
|
||||
float cy = reader.ReadSingle();
|
||||
float width = reader.ReadSingle();
|
||||
float height = reader.ReadSingle();
|
||||
|
||||
int hotLen = reader.ReadInt32();
|
||||
var hotPoints = new PointCollection();
|
||||
for (int i = 0; i < hotLen; i++)
|
||||
hotPoints.Add(new Point(reader.ReadSingle(), reader.ReadSingle()));
|
||||
|
||||
int idxLen = reader.ReadInt32();
|
||||
var indices = new int[idxLen];
|
||||
for (int i = 0; i < idxLen; i++)
|
||||
indices[i] = reader.ReadInt32();
|
||||
|
||||
if (!success || string.IsNullOrEmpty(shape))
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
|
||||
var recognized = new StrokeCollection();
|
||||
foreach (int idx in indices)
|
||||
if (idx >= 0 && idx < strokes.Count)
|
||||
recognized.Add(strokes[idx]);
|
||||
|
||||
return new InkShapeRecognitionResult(
|
||||
shape,
|
||||
new Point(cx, cy),
|
||||
hotPoints,
|
||||
width,
|
||||
height,
|
||||
recognized);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureHelperAlive()
|
||||
{
|
||||
if (!IsAvailable)
|
||||
LaunchHelper();
|
||||
}
|
||||
|
||||
private void OnHelperExited(object sender, EventArgs e)
|
||||
{
|
||||
_available = false;
|
||||
}
|
||||
|
||||
private void KillHelper()
|
||||
{
|
||||
if (_helperProcess == null) return;
|
||||
try
|
||||
{
|
||||
try { _helperProcess.Exited -= OnHelperExited; } catch { }
|
||||
|
||||
if (!_helperProcess.HasExited)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var client = new NamedPipeClientStream(".", PipeName, PipeDirection.InOut))
|
||||
{
|
||||
client.Connect(500);
|
||||
using (var w = new BinaryWriter(client))
|
||||
w.Write(CmdShutdown);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!_helperProcess.WaitForExit(800))
|
||||
_helperProcess.Kill();
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
finally
|
||||
{
|
||||
_helperProcess?.Dispose();
|
||||
_helperProcess = null;
|
||||
_available = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
KillHelper();
|
||||
}
|
||||
|
||||
private const int IpcTimeoutMs = 5000;
|
||||
private const byte CmdRecognize = 0x01;
|
||||
private const byte CmdShutdown = 0xFF;
|
||||
}
|
||||
}
|
||||
@@ -101,20 +101,6 @@
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="IACore">
|
||||
<HintPath>.\IACore.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="IALoader">
|
||||
<HintPath>.\IALoader.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="IAWinFX">
|
||||
<HintPath>.\IAWinFX.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.manifest" />
|
||||
</ItemGroup>
|
||||
@@ -153,6 +139,10 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\InkCanvas.PluginSdk\InkCanvas.PluginSdk.csproj" />
|
||||
<ProjectReference Include="..\InkCanvas.Controls\InkCanvas.Controls.csproj" />
|
||||
<ProjectReference Include="..\InkCanvasForClass.IACoreHelper\InkCanvasForClass.IACoreHelper.csproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
<Private>false</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(MSBuildRuntimeType)' == 'Full'">
|
||||
<COMReference Include="IWshRuntimeLibrary">
|
||||
@@ -668,4 +658,11 @@
|
||||
<Target Name="CleanTelemetryDsn" AfterTargets="Build;Clean" Condition="Exists('$(MSBuildProjectDirectory)\telemetry_dsn.generated.txt')">
|
||||
<Delete Files="$(MSBuildProjectDirectory)\telemetry_dsn.generated.txt" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CopyIACoreHelper" AfterTargets="Build">
|
||||
<ItemGroup>
|
||||
<IACoreHelperFiles Include="$(MSBuildProjectDirectory)\..\InkCanvasForClass.IACoreHelper\bin\$(Configuration)\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(IACoreHelperFiles)" DestinationFolder="$(OutDir)" SkipUnchangedFiles="true" Condition="'@(IACoreHelperFiles)' != ''" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
@@ -589,7 +589,7 @@
|
||||
<value>识别引擎</value>
|
||||
</data>
|
||||
<data name="InkRecog_ShapeEngineHint" xml:space="preserve">
|
||||
<value> 自动:64 位进程使用 WinRT(Windows 10+),32 位使用 IACore。可强制指定 IACore 或 WinRT。</value>
|
||||
<value> 自动:在 Windows 10+ 使用 WinRT,否则使用 IACore。可强制指定 IACore 或 WinRT。IACore 通过 IPC 辅助进程运行,在 32/64 位主进程下均可用。</value>
|
||||
</data>
|
||||
<data name="InkRecog_ShapeEngineAuto" xml:space="preserve">
|
||||
<value>自动</value>
|
||||
|
||||
Reference in New Issue
Block a user