Fábio Gaspar
Fábio Gaspar

Reputation: 25

C# - Window.Current.CoreWindow.GetKeyState not working as expected

I am developing a simple Universal Windows App using C#. I have a RichEditBox and I found a weird behavior when using Control+I key combination, which for some reason inserts a Tab (is that expected?). Because I wanted the combination of keys to toggle Italic font style, I thought the best way was through the KeyDown event. So, this is my code:

    private void richbox_KeyDown(object sender, KeyRoutedEventArgs e)
    {
        System.Diagnostics.Debug.Write("\nKeyDown : " + e.Key.ToString());
        if (e.Key == VirtualKey.Tab)
        {
            richbox.Document.Selection.TypeText("\t");
            e.Handled = true;
        }
        else if (Window.Current.CoreWindow.GetKeyState(VirtualKey.Control) == Windows.UI.Core.CoreVirtualKeyStates.Down)
        {
            //If Control is pressed down, check if current key is B,I,U...
            System.Diagnostics.Debug.Write(" => Control is down!");
            switch (e.OriginalKey)
            {
                case VirtualKey.B:
                    toogleBold();
                    e.Handled = true;
                    break;
                case VirtualKey.I:
                    e.Handled = true;
                    toogleItalic(); 
                    break;
                case VirtualKey.U:
                    toogleUnderline();
                    e.Handled = true;
                    break;
            }

        }
    }

My problem is, the condition on the Else If is not always true when I press the Control key. I would like to understand why and what could I do to fix it. If I run the code and I press the control key a few times, this is the output:

KeyDown : Control => Control is down!

KeyDown : Control

KeyDown : Control => Control is down!

KeyDown : Control

...

Thanks in advance :)

Upvotes: 2

Views: 775

Answers (1)

Martin Zikmund
Martin Zikmund

Reputation: 39082

I tried your code and used debugger output to see what the actual state of Ctrl is in those situations:

var state = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control);
Debug.WriteLine(state);

What I found out is that the second time you press the key, its state is not Down, but Down|Locked, more specifically Windows.UI.Core.CoreVirtualKeyStates.Down | Windows.UI.Core.CoreVirtualKeyStates.Locked. It turns out CoreVirtualKeyStates is a flag enum and it can have multiple values at the same time. In this case you are comparing with == which means you don't get a match. You can first use the HasFlag method or bitwise AND (&) to get the right value out and then compare and you will be good to go!

That means either this:

else if ( Window.Current.CoreWindow.GetKeyState(VirtualKey.Control).
             HasFlag( CoreVirtualKeyStates.Down ) )
{
    //rest of the code
}

Or this:

else if ( 
  ( Window.Current.CoreWindow.GetKeyState(VirtualKey.Control) &
    Windows.UI.Core.CoreVirtualKeyStates.Down )
    == CoreVirtualKeyStates.Down )
{ 
    //rest of the code
}

Upvotes: 5

Related Questions