How to stop Control-I from inserting a tab in a UW

2019-07-12 14:37发布

问题:

Strange behavior (to me) when I have a TextBox in a UWP app.

  • Create a Universal, Blank App UWP app in Windows 10.
  • Add a TextBox to the default grid with this code:
    <TextBox Text="There's not much spam in it" Name="textBox" />
  • Build and run the application.
  • Click inside of the TextBox
  • Type Control-I.

A tab is inserted.

What causes this behavior?

I'm trying to set up window level shortcuts in a Windows 10 application by hooking up a handler to Window.Current.CoreWindow.KeyDown, but I think that's too late in the event game to catch the Control-I's tab insertion and call it handled. That, I think the TextBox's KeyDown is completely handled before the CoreWindow's event occurs.

So for now I'm settling for handling the event on each TextBox whenever someone selects Control-I like this...

Edit XAML to this:

<TextBox Text="There's not much spam in it" 
    Name="textBox" KeyDown="textBox_KeyDown" AcceptsReturn="True" />

Add event handler:

private void textBox_KeyDown(object sender, KeyRoutedEventArgs e)
{
    if (e.OriginalKey.Equals(VirtualKey.I) 
        && Window.Current.CoreWindow.GetKeyState(VirtualKey.Control)
        .HasFlag(CoreVirtualKeyStates.Down))
    {
        this.textBox.SelectedText += "X";
        e.Handled = true;
    }
}

... which seems to work okay, except that now I have to slap my "window" scope event handler for Control-I into each TextBox (or extend TextBox, both of which seem crazy for what seems to be a non-standard keyboard shortcut).

So primarily I'm asking what action it is that inserts a Tab into a TextBox when Control-I is pressed, and if there's a better way to avoid that action at the CoreWindow level. A better means of capturing keyboard shortcuts at the CoreWindow level (eg, Ctrl-K means insert a link) would also be appreciated, but wouldn't really answer the "real" question.

回答1:

The best solution I've found to date is to insert an event handler for KeyDown that will eat Ctrl-I.

I have a fuller solution on GitHub that addresses this and some other issues here, but here's the operative Ctrl-I eating code:

public UWPBox() : base()
{
    this.KeyDown += this.KeyDownHandler;
}

public virtual async void KeyDownHandler(object sender, KeyRoutedEventArgs e)
{
    bool isCtrlDown = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control)
        .HasFlag(CoreVirtualKeyStates.Down);

    try
    {
        switch (e.OriginalKey)
        {
            case VirtualKey.I:
                // First, kill the default "Ctrl-I inserts a tab" action.
                if (isCtrlDown)
                {
                    e.Handled = true;
                    this.HandleCtrlI(); // Just in case we want to do 
                                        // something different with Ctrl-I
                }
                break;

            // "Fixes" for Ctrl-V and Tab removed.
            // Fuller solution here: https://github.com/ruffin--/UWPBox
        }
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(
            DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + ": " 
            + ex.Message);
    }
}

public virtual void HandleCtrlI()
{
    System.Diagnostics.Debug.WriteLine("Ctrl-I pressed.");
}