以编程方式为 WPF InkCanvas 创建 Strokes 的性能问题

Performance problem of creating Strokes for an WPF InkCanvas programmatically

我在 Cancel touch event on InkCanvas (.Net Framework) 中问了一个问题但没有得到答案,所以我尝试将 InkCanvas 设置为 HitTestVisiblefalse 并获得 StylusPoints 在 driver 的 API 之上。这些点现在被手动放入 Strokes 中,然后放入边界 StrokeCollection 中。这样,我只从手写笔而不是触摸或鼠标获得点数(我知道 UWP InkCanvas 默认情况下可以做到这一点,但遗憾的是 WPF 太旧了,没有得到 Microsoft 的正确支持)。

但是我对这种方法的速度有疑问。我从每个点(以及之前的点)中提取出 Stroke,并将它们放在 StrokeCollection 中。这导致“缓慢”Stroke。如果我写了一些东西,当我已经用笔完成它时,它只会显示大约 3/4,然后在半秒后完全显示。您是否有任何想法可以使它更快,使其看起来像 InkCanvas 的正常使用?或者可以回答之前的问题 ;)

这是我的代码:

private void TabLib_DataReceived(object sender, EventArgs e)
{
    float pressureFactor = e.pressure / 1024f;

    StylusPoint newPoint = new StylusPoint()
    {
        PressureFactor = pressureFactor,
        X = e.xPos,
        Y = e.yPos
    };

    if (pressureFactor == 0) // that means the pen has left or entered the tablet
    {
        _oldPressurePoint = newPoint;
        return;
    }

    StylusPointCollection pointList = new StylusPointCollection();
    pointList.Add(_oldPressurePoint);
    pointList.Add(newPoint);
    Stroke stroke = new Stroke(pointList, _penDrawingAttributes);
    // used a dispatcher begininvoke because of DrawnStrokes are bound to the UI thread.
    _tabletWindow.Dispatcher.BeginInvoke(new Action<Stroke>((newStroke) =>
    {
        DrawnStrokes.Add(newStroke); // DrawnStrokes is the bound StrokeCollection
    }), stroke);

    _oldPressurePoint = newPoint;
}

我也想过画一笔,只加点,但是好像不行。如果你已经添加了一个笔画,你就不能在这个笔画上加点了,可以吗?

只在必要时创建新的Stroke,并在当前Stroke的StylusPoints集合中添加点。

这是一个流畅运行的示例,它根据鼠标输入在 Canvas 覆盖 InkCanvas 上创建笔画数据Canvas。

<Grid>
    <InkCanvas x:Name="inkCanvas" IsHitTestVisible="False"/>
    <Canvas Background="Transparent"
            MouseLeftButtonDown="CanvasMouseLeftButtonDown"
            MouseLeftButtonUp="CanvasMouseLeftButtonUp"
            MouseMove="CanvasMouseMove"/>
</Grid>

后面有这段代码:

private Stroke stroke;

private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    var pos = e.GetPosition(inkCanvas);
    var points = new StylusPointCollection
    {
        new StylusPoint(pos.X, pos.Y)
    };

    stroke = new Stroke(points, inkCanvas.DefaultDrawingAttributes);
    inkCanvas.Strokes.Add(stroke);
}

private void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    stroke = null;
}

private void CanvasMouseMove(object sender, MouseEventArgs e)
{
    if (stroke != null)
    {
        var pos = e.GetPosition(inkCanvas);
        stroke.StylusPoints.Add(new StylusPoint(pos.X, pos.Y));
    }
}