Mikael Dúi Bolinder
Mikael Dúi Bolinder

Reputation: 2284

How do you make an UWP TextBlock editable with handwriting?

I'm currently showing a TextBlock with text that can be manipulated by the user in various ways using game pads, mouse and keyboard.

I'd like the user to be able to write text right on this TextBlock and then the writing will replace the text of the TextBlock.

The app works like this:

<TextBlock x:Name="TheTextBlock" Text="Sample Text" />

And the code behind is like this:

private void Page_KeyDown(object sender, KeyEventArgs args)
{
    if (args.Key = VirtualKey.LeftButton)
        TheTextBlock.Text = "Left Button Pressed";
}

So, when something is written, with i.e. an InkCanvas or a <TextBox IsHandwritingViewEnabled="False" /> the text should appear in the TextBlock and the ink should disappear.

How can you do this? An InkCanvas on top of the TextBlock that will clear the text when a pen is pressed against the canvas? An invisible handwriting textbox?

Upvotes: 0

Views: 383

Answers (1)

Nico Zhu
Nico Zhu

Reputation: 32775

How can you do this? An InkCanvas on top of the TextBlock that will clear the text when a pen is pressed against the canvas? An invisible handwriting textbox?

From your description, it looks that you want to make handwriting pad to recognition the text then display it in the TextBlock. Please refer this document. And I have make sample that you could refer.

Xaml

<Grid>
    <TextBlock x:Name="TheTextBlock" Text="Sample Text"/>
    <InkCanvas x:Name="TheInkCanvas" />
</Grid>

Code Behind

InkAnalyzer inkAnalyzer;
DispatcherTimer recoTimer;
public MainPage()
{
    this.InitializeComponent();
    TheInkCanvas.InkPresenter.InputDeviceTypes =
       Windows.UI.Core.CoreInputDeviceTypes.Mouse |
       Windows.UI.Core.CoreInputDeviceTypes.Pen;

    TheInkCanvas.InkPresenter.StrokesCollected += inkCanvas_StrokesCollected;
    // StrokeStarted is fired when ink input is first detected.
    TheInkCanvas.InkPresenter.StrokeInput.StrokeStarted +=
        inkCanvas_StrokeStarted;

    inkAnalyzer = new InkAnalyzer();

    // Timer to manage dynamic recognition.
    recoTimer = new DispatcherTimer();
    recoTimer.Interval = TimeSpan.FromSeconds(1);
    recoTimer.Tick += recoTimer_TickAsync;
}

private async void recoTimer_TickAsync(object sender, object e)
{
    recoTimer.Stop();
    if (!inkAnalyzer.IsAnalyzing)
    {
        InkAnalysisResult result = await inkAnalyzer.AnalyzeAsync();

        // Have ink strokes on the canvas changed?
        if (result.Status == InkAnalysisStatus.Updated)
        {
            // Find all strokes that are recognized as handwriting and 
            // create a corresponding ink analysis InkWord node.
            var inkwordNodes =
                inkAnalyzer.AnalysisRoot.FindNodes(
                    InkAnalysisNodeKind.InkWord);

            // Iterate through each InkWord node.
            // Display the primary recognized text (for this example, 
            // we ignore alternatives), and then delete the 
            // ink analysis data and recognized strokes.
            foreach (InkAnalysisInkWord node in inkwordNodes)
            {
                string recognizedText = node.RecognizedText;
                // Display the recognition candidates.
                TheTextBlock.Text = recognizedText;

                foreach (var strokeId in node.GetStrokeIds())
                {
                    var stroke =
                        TheInkCanvas.InkPresenter.StrokeContainer.GetStrokeById(strokeId);
                    stroke.Selected = true;
                }
                inkAnalyzer.RemoveDataForStrokes(node.GetStrokeIds());
            }
            TheInkCanvas.InkPresenter.StrokeContainer.DeleteSelected();
        }
    }
    else
    {
        // Ink analyzer is busy. Wait a while and try again.
        recoTimer.Start();
    }
}

private void inkCanvas_StrokeStarted(InkStrokeInput sender, PointerEventArgs args)
{
    recoTimer.Stop();
}

private void inkCanvas_StrokesCollected(InkPresenter sender, InkStrokesCollectedEventArgs args)
{
    recoTimer.Stop();
    foreach (var stroke in args.Strokes)
    {
        inkAnalyzer.AddDataForStroke(stroke);
        inkAnalyzer.SetStrokeDataKind(stroke.Id, InkAnalysisStrokeKind.Writing);
    }
    recoTimer.Start();
}

Upvotes: 1

Related Questions