Gael
Gael

Reputation: 428

Custom In App Keyboard in UWP

I want to create a custom OnScreen keyboard in UWP. It need to be part the application because it will be used on Large Table or Board devices so full control of the keyboard placement is very important (rotation on the table).

In WPF, I already made a custom keyboard like this by creating a keyboard control whith a Target Property. When a key is pressed, it raise a KeyEvent or TextComposition on the target with UIElement.RaiseEvent(...). But in UWP, there is no RaiseEvent function and it seems there is no way to raise routed event for the developper.

I want to use native Text Event (KeyDown event, TextComposition event, etc...) so solution which manually edit the Text property of TextBox ( like this one ) are not acceptable.

This page explains how to create a control who listen to Text Services Framework. I think one solution would be to create a custom Text service but I didn't found any documentation on this.

Upvotes: 3

Views: 2718

Answers (1)

You can do at least part of what you were looking for using classes in the Windows.UI.Input.Preview.Injection namespace and the restricted inputInjectionBrokered capability.

This works for the KeyUp, KeyDown, PreviewKeyUp, and PreviewKeyDown events, and as long as you don't need to send key strokes to anything outside of your app.

Non-latin scripts are outside the scope of what I'm working on, so I don't know if it can be extended to IME's which would generate TextComposition events.

Martin Zikmund demonstrates doing so here, with a sample solution available on github.

The key points are that you need to edit your Package.appxmanifest file (as code not via the designer) to include:

<Package>
    xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
    IgnorableNamespaces="rescap"
</Package>

and

<Capabilities>
    <rescap:Capability Name="inputInjectionBrokered" />
<Capabilities>

From there you can simulate typing and raise native key events by:

private async void TypeText()
{
    Input.Focus(FocusState.Programmatic);
    //we must yield the UI thread so that focus can be acquired
    await Task.Delay(100); 

    InputInjector inputInjector = InputInjector.TryCreate();
    foreach (var letter in "hello")
    {
        var info = new InjectedInputKeyboardInfo();
        info.VirtualKey = (ushort)((VirtualKey)Enum.Parse(typeof(VirtualKey), 
                                   letter.ToString(), true));
        inputInjector.InjectKeyboardInput(new[] { info });

        //and generate the key up event next, doing it this way avoids
        //the need for a delay like in Martin's sample code.
        info.KeyOptions = InjectedInputKeyOptions.KeyUp;
        inputInjector.InjectKeyboardInput(new[] { info });
    }
}

Upvotes: 2

Related Questions