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.


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:

if (Window.Current.CoreWindow.GetKeyState(VirtualKey.Control) == 
    //do something

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:

[ContractVersion(typeof(UniversalApiContract), 65536)]
public enum CoreVirtualKeyStates : uint
   None = 0,
   Down = 1,
   Locked = 2

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:

if (Window.Current.CoreWindow.GetKeyState(VirtualKey.Control).
    //Ctrl is pressed

Alternatively, you can also utilize the bitwise AND operator:

if ((Window.Current.CoreWindow.GetKeyState(VirtualKey.Control) &
    == CoreVirtualKeyStates.Down)
    //Ctrl is pressed

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):

if (!Window.Current.CoreWindow.GetKeyState(VirtualKey.Control).
    //Ctrl is not pressed

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.


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.

Buy me a coffeeBuy me a coffee

6 thoughts on “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)
    Dim TextBox1 As TextBox = CType(sender, TextBox)
    If e.Key = VirtualKey.Tab Then
    If TextBox1.Text.IsEmptyNullOrWhitespace Then
    e.Handled = True
    End If
    If (Window.Current.CoreWindow.GetKeyState(VirtualKey.Control) And Windows.UI.Core.CoreVirtualKeyStates.Down) = CoreVirtualKeyStates.Down Then

  2. wow, had no idea about this!
    Very informative and useful post, THANK YOU.

    So I have a UWP game that runs in a loop.
    Merely handling keydown event is not good (because of the loop) so i used your suggestion (checking the key state of the window).
    However i found out that sometimes the player would get stuck in a certain state. For example it would continue to move right even after you released the Right arrow key.
    Sure enough, the GetKeyState wrongly indicated that the Right key was down (even after doing the HasFlag trick)!
    I then discovered a different method called GetAsyncKeyState that -at least in my case- doesn’t have this problem. It correctly reports whether the Right arrow key is down and my player nevers gets stuck.
    Why did you not mention the Async form of the method? Perhaps it wasn’t available at the time of writing?
    Thanks again!

  3. “not reflected immediately” – it seems that the state is not reflected correctly until after the first keypress.
    I am trying to show the numlock state, so I try to updated it after the page was (re)activated (as it may have changed). But I always get state None, until I press any key (even shift is enough).

Leave a Reply to Martin Cancel 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> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>


This site uses Akismet to reduce spam. Learn how your comment data is processed.