The right way to check for key state in UWP apps

UWP apps should work great with any kind of input including the keyboard. That includes support for keyboard shortcuts and checking for the state the keys are in. It turns out however that there are some things we have to watch out for.

Problem

Let’s suppose we want to write a KeyDown event handler and check if the Ctrl key is pressed. The simple approach would look like this:

This looks perfectly valid, but there is a hidden caveat. Once we run the app and test it, we will find out that the code inside the if block is run only once for each two presses. Why is that?

Locked key state

If we use the debugger, we can see that when pressed, the Ctrl key state toggles between values Down  and Down|Locked. This means the CoreVirtualKeyStates enum has a [Flags] attribute:

The key can be Down and Locked at once! But what does Locked mean?

The documentation says that Locked means:

The key is in a toggled or modified state (for example, Caps Lock) for the input event.

This definitely makes sense for Caps Lock and Num Lock keys, but the documentation further says:

All keys support the Locked state (not just the standard Caps Lock and Num Lock keys).

This is very interesting! It means that every single key on the keyboard acts as if it can be toggled, including the classic keys like simple letters!

You can even see that even when the key is released, it stays in the Locked state until it is pressed again.

I have also confirmed that the “locked” state is system-wide, although non-function keys like letters it is not reflected immediately after the app is launched and before that the GetKeyState method returns simply None.

The right way to check

To make sure the key is really pressed down, you can use the enum’s HasFlag method:

Alternatively, you can also utilize the bitwise AND operator:

Both ways will yield the expected results.

Also interestingly, to check if the key is not pressed we should use the following (note the ! operator before the condition):

We cannot use == CoreVirtualKeyStates.None because as mentioned above, key could be released, but still in the Locked state.

Source code

Source code sample that shows how key states are toggled is available here on my GitHub.

Summary

UWP has small intricacies we should be aware of to reliably check for pressed down keys. The key (pun intended 🙂 ) takeaway is that keys can be in two states at once so we cannot rely on simple equality checking and should rather use the HasFlag  method appropriately.

2 Replies to “The right way to check for key state in UWP apps”

  1. I am trying to trap C and V and other control characters but many of them do not seem to show up in the UWP KeyPress Event. (C,A, X don’t show up but V for example does so I don’t think it is completely related to Clipboard. I print out all keys at the top of the function so I don’t think it is anything I am going.

    Private Async Sub TextBox_KeyDownAsync(ByVal sender As Object, e As KeyRoutedEventArgs)
    Debug.WriteLine($”e.Key={e.Key}”)
    Dim TextBox1 As TextBox = CType(sender, TextBox)
    If e.Key = VirtualKey.Tab Then
    If TextBox1.Text.IsEmptyNullOrWhitespace Then
    e.Handled = True
    End If
    Else
    If (Window.Current.CoreWindow.GetKeyState(VirtualKey.Control) And Windows.UI.Core.CoreVirtualKeyStates.Down) = CoreVirtualKeyStates.Down Then

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

*