首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Windows 8 Store Apps 開發實戰(51):從簡易塗鴉板到專業 InkManager 手寫識別完整實作

     編輯:關於.NET

前言

Windows 8 提供兩種手寫繪圖路徑:Pointer 事件手動繪製 (教學/輕量) 與 InkManager 完整管線 (生產級)。本文從零實作兩版塗鴉板,涵蓋貝塞爾曲線渲染、選取/移動/刪除、剪貼簿、儲存載入 GIF、中文手寫辨識。

版本一:Pointer 事件簡易塗鴉板 (教學用)

核心邏輯

  • 用 Dictionary<uint, Point?> 追蹤多點觸控各指針上一座標。
  • PointerMoved 計算兩點距離 > 4 像素時繪製 Line 直線段。
  • PointerReleased/Exited 清除追蹤。
void canvas_PointerMoved(object sender, PointerRoutedEventArgs e)
{
    var pt = e.GetCurrentPoint(canvas);
    if (_dicPoint.ContainsKey(pt.PointerId) && _dicPoint[pt.PointerId].HasValue)
    {
        var curr = pt.Position;
        var prev = _dicPoint[pt.PointerId].Value;
        if (Distance(curr, prev) > 4)
        {
            canvas.Children.Add(new Line { X1=prev.X, Y1=prev.Y, X2=curr.X, Y2=curr.Y,
                StrokeThickness=5, Stroke=Orange, StrokeEndLineCap=PenLineCap.Round });
            _dicPoint[pt.PointerId] = curr;
        }
    }
}

版本二:InkManager 專業塗鴉板 (生產就緒)

架構分層

  1. InkManager:筆跡資料模型、輸入模式 (Inking/Erasing/Selecting)、剪貼簿、序列化 GIF、手寫辨識。
  2. InkRenderer:自訂渲染器,將 InkStroke 轉三次貝塞爾曲線 Path,支援即時筆跡、選取高亮、完整重繪。
  3. UI 層:Canvas 接收 Pointer 事件,轉發給 InkManager 與 InkRenderer。

InkRenderer 核心:貝塞爾曲線渲染

public static Path InkStroke2BezierPath(InkStroke stroke)
{
    var figure = new PathFigure();
    var segs = stroke.GetRenderingSegments().GetEnumerator();
    segs.MoveNext();
    figure.StartPoint = segs.Current.Position;
    while (segs.MoveNext())
    {
        figure.Segments.Add(new BezierSegment
        {
            Point1 = segs.Current.BezierControlPoint1,
            Point2 = segs.Current.BezierControlPoint2,
            Point3 = segs.Current.Position
        });
    }
    return new Path
    {
        Data = new PathGeometry { Figures = { figure } },
        Stroke = new SolidColorBrush(stroke.DrawingAttributes.Color),
        StrokeThickness = stroke.DrawingAttributes.Size.Width,
        StrokeLineJoin = PenLineJoin.Round,
        StrokeStartLineCap = PenLineCap.Round
    };
}

功能完整清單

功能API / 實作要點
三種模式切換InkManager.Mode = Inking/Erasing/Selecting + RadioButton 綁定
即時筆跡渲染EnterLiveRendering/UpdateLiveRender/ExitLiveRendering 畫直線預覽,筆跡完成後換貝塞爾曲線
選取高亮UpdateSelectionRender 疊加白色較粗 Path 表示選取狀態
刪除選取/全部InkManager.DeleteSelected() / 遍歷 Selected=true 後刪除
移動選取筆跡InkManager.MoveSelected(new Point(50,5))
剪切/複製/貼上CopySelectedToClipboard/PasteFromClipboard/DeleteSelected
儲存/載入 GIFInkManager.SaveAsync/LoadAsync(stream) + FileSavePicker/FileOpenPicker
中文手寫辨識RecognizeAsync(InkRecognitionTarget.All) + 設定 Microsoft 中文(簡體)手寫識別器

UI 事件轉發關鍵代碼

void canvas_PointerPressed(object sender, PointerRoutedEventArgs e)
{
    _pointerId = (int)e.GetCurrentPoint(canvas).PointerId;
    switch (_inkManager.Mode)
    {
        case Inking: _renderer.EnterLiveRendering(pt, _inkDrawingAttributes); break;
        case Selecting: _renderer.EnterLiveRendering(pt, _inkDrawingAttributesForSelect); break;
    }
    _inkManager.ProcessPointerDown(pt);
}

void canvas_PointerMoved(object sender, PointerRoutedEventArgs e)
{
    var pt = e.GetCurrentPoint(canvas);
    if (_pointerId == (int)pt.PointerId)
    {
        if (_inkManager.Mode == Erasing)
        {
            var rect = _inkManager.ProcessPointerUpdate(pt);
            if (rect.Width>0) { _renderer.Clear(); _renderer.UpdateInkRender(_inkManager.GetStrokes()); }
        }
        else // Inking/Selecting
        {
            foreach (var ipt in e.GetIntermediatePoints(canvas).Reverse())
                _inkManager.ProcessPointerUpdate(ipt);
            _renderer.UpdateLiveRender(pt);
        }
    }
}

void canvas_PointerReleased(object sender, PointerRoutedEventArgs e)
{
    if (_pointerId == (int)e.GetCurrentPoint(canvas).PointerId)
    {
        _pointerId = -1;
        _inkManager.ProcessPointerUp(e.GetCurrentPoint(canvas));
        if (_inkManager.Mode == Inking)
            _renderer.UpdateInkRender(_inkManager.GetStrokes().Last());
        else if (_inkManager.Mode == Selecting)
            _renderer.UpdateSelectionRender();
    }
}

關鍵類別速查

類別核心屬性/方法
InkManagerMode, SetDefaultDrawingAttributes, ProcessPointerDown/Update/Up, GetStrokes, SaveAsync/LoadAsync, RecognizeAsync, CopySelectedToClipboard, PasteFromClipboard, MoveSelected, DeleteSelected
InkDrawingAttributesColor, Size, FitToCurve (貝塞爾/直線), PenTip (Circle/Rectangle), IgnorePressure
InkStrokeDrawingAttributes, BoundingRect, Selected, Recognized, Clone(), GetRenderingSegments()
InkStrokeRenderingSegmentBezierControlPoint1, BezierControlPoint2, Position

總結

簡易版適合理解 Pointer 事件機制;專業版 InkManager + InkRenderer 是生產環境標準架構,支援完整筆跡生命週期管理、跨裝置儲存格式 (GIF)、中文手寫辨識,可直接擴充為簽名板、批註工具、手寫記事本核心模組。

原始碼下載**:https://files.cnblogs.com/webabcd/Windows8.rar

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved