#1,077 – Checking for Single Modifer vs. Multiple Modifier Keys

In keypress events, you can check to see if the user is also holding down one of the modifier keys (Ctrl, Alt, Shift, or Windows key).  You do this by checking the KeyEventArgs.KeyboardDevice.Modifiers property.

You sometimes want to check to see if one and only one modifier key is being held down (e.g. Ctrl key without Alt, Shift, or Windows).  You do this by checking to see if the Modifiers property is equal to one of the ModifierKeys enumerated values.

            if ((e.Key == Key.G) &&
                (e.KeyboardDevice.Modifiers == ModifierKeys.Control))
                MessageBox.Show("Ctrl+G detected, NO Alt/Shift/Windows");

You may also want to check to see if the control key is being pressed, either alone or in conjunction with one of the other modifier keys.  You do this by using a mask.

            if ((e.Key == Key.G) &&
                ((e.KeyboardDevice.Modifiers & ModifierKeys.Control) == ModifierKeys.Control))
                MessageBox.Show("Ctrl+G or Ctrl+Alt+G, Ctrl+Alt+Windows+G, etc.");

#1,075 – Triggering on IsKeyboardFocusWithin Property

You can set up a trigger that fires whenever a control’s IsKeyboardFocused property becomes truechanging the value of some other property when the control gains keyboard focus.

You can also trigger on the IsKeyboardFocusWithin property.  This property will get set to true for an element when any child of that element has keyboard focus.

In the example below, we set the background color of either StackPanel when any element within the StackPanel has focus.  This technique may be useful when you want to keep track of what section of a window the user is working in and do something based on that knowledge.

    <Window.Resources>
        <Style x:Key="HoneydewFocus" TargetType="StackPanel">
            <Style.Triggers>
                <Trigger Property="IsKeyboardFocusWithin" Value="true">
                    <Setter Property="Background" Value="Honeydew"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    
    <StackPanel>
        <StackPanel Orientation="Horizontal" Margin="10"
                    Style="{StaticResource HoneydewFocus}">
            <Button Content="Click Me" VerticalAlignment="Center"/>
            <TextBox Width="200" Height="25" Margin="10"/>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Margin="10"
                    Style="{StaticResource HoneydewFocus}">
            <Button Content="Or Me" VerticalAlignment="Center"/>
            <TextBox Width="200" Height="25" Margin="10"/>
        </StackPanel>
    </StackPanel>

1075-001

1075-002

#921 – Keyboard Shortcuts Available in a TextBox Control

There are a number of keys that you can use as shortcuts for editing text within a TextBox control.  The most common are:

  • Left/Right Arrow keys:  Move cursor left or right within text
  • Up/Down Arrow keys:  Move cursor to previous/next line, maintaining position within line
  • Ctrl+Left/Right Arrow:  Move to beginning of previous/next word
  • Ctrl+Up Arrow:  Move to start of text
  • Ctrl+Down Arrow:  Move to end of text
  • Shift+Left/Right/Up/Down Arrow:  Move cursor while selecting text
  • Home key:  Move to beginning of current line
  • End key:  Move to end of current line
  • Shift+Home/End:  Select text to beginning/end of current line
  • Page Up/Down:  Move up/down full page
  • Insert key:  Toggle Insert/Overwrite mode
  • Delete key:  Delete character to right of cursor
  • Backspace key:  Delete character to right of cursor
  • Ctrl+A:  Select all text
  • Ctrl+X:  Cut selected text
  • Ctrl+C:  Copy selected text
  • Ctrl+V:  Paste text at current position

#651 – Using Static Members of the Keyboard Class

The KeyboardDevice class represents the current state of the keyboard and is accessible from within keypress event handlers using the KeyEventArgs.KeyboardDevice property.

        private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            Console.WriteLine(string.Format("A key pressed? {0}", e.KeyboardDevice.IsKeyDown(Key.A)));
        }

You can also use the Keyboard.PrimaryDevice property to access the current KeyboardDevice object.

        public void CheckForA()
        {
            Console.WriteLine(string.Format("A key pressed? {0}", Keyboard.PrimaryDevice.IsKeyDown(Key.A)));
        }

In addition to providing access to the KeyboardDevice object, the Keyboard class also provides several static methods that give you the same information.  This is easier than referencing the PrimaryDevice property.

        public void CheckForA()
        {
            Console.WriteLine(string.Format("A key pressed? {0}", Keyboard.IsKeyDown(Key.A)));
        }

#650 – Getting Information About Keyboard Keys from Any Method

You can use the KeyEventArgs.KeyboardDevice property within a keypress handler to get information about any keyboard key.  For example:

private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    Console.WriteLine(string.Format("Toggle info: Caps Lock:{0}, Scroll Lock: {1}, Num Lock: {2}",
        e.KeyboardDevice.IsKeyToggled(Key.CapsLock),
        e.KeyboardDevice.IsKeyToggled(Key.Scroll),
        e.KeyboardDevice.IsKeyToggled(Key.NumLock)));
}

You can also access the same KeyboardDevice object from any method, using the Keyboard.PrimaryDevice property (found in System.Windows.Input). This property will refer to an instance of a KeyboardDevice object.

        public void MyFunctionToGetKeyInfo()
        {
            Console.WriteLine(string.Format("Toggle info: Caps Lock:{0}, Scroll Lock: {1}, Num Lock: {2}",
                Keyboard.PrimaryDevice.IsKeyToggled(Key.CapsLock),
                Keyboard.PrimaryDevice.IsKeyToggled(Key.Scroll),
                Keyboard.PrimaryDevice.IsKeyToggled(Key.NumLock)));
        }

#649 – KeyStates Property Combines IsDown and IsToggled

In a keypress handler, you can check several states for the key that triggered the event.  The IsDown and IsToggled properties indicate whether the key in question is currently down and whether it’s in the toggled state, respectively.

You can also get information on the current state of the key using the KeyStates property.  The property is an enumerated value containing a bitwise combination of the Down and Toggled values.

        private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            Console.WriteLine(string.Format("--- PreviewKeyDown for key {0}", e.Key));
            Console.WriteLine(string.Format("  IsDown={0}, IsToggled={1}", e.IsDown, e.IsToggled));
            Console.WriteLine(string.Format("  KeyStates={0}", e.KeyStates));
        }

#646 – Detecting a Key’s Toggle State in a Keypress Handler

There are several keys on the keyboard that typically act as toggles–when you first press the key, it is considered toggled, or on–and when you press it again, it is considered untoggled, or off.

The keys that are typically used as toggle keys are: Caps Lock, Scroll Lock and Num Lock.  (Note–the normal Shift key is not typically used as a toggle key).

When a key is pressed, you can determine whether it is entering the toggled state or the untoggled state by checking the KeyEventArgs.IsToggled property in one of the keypress event handlers.

        private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            Trace.WriteLine(string.Format("----- PreviewKeyDown for key {0}, toggled = {1}", e.Key, e.IsToggled));
        }

For example, if I press the Caps Lock four times, I’ll see the following output:

The Caps Lock key is toggling on and off.

#636 – Keyboard Events that Fire When A Key Is Held Down

When you hold a key down in Windows, the key begins to repeat after a short delay, as if you you were repeatedly pressing it.

While a key is held down, the PreviewKeyDown, KeyDown and PreviewTextInput events will fire repeatedly.

You can detect whether a keypress is the original/first keypress, or one of the repeats, by checking the KeyEventArgs.IsRepeat property.

Let’s say we press the ‘a’ key while a TextBox has focus and hold it down long enough for three ‘a’ characters to be inserted.  We’ll get the following events:

  • PreviewKeyDown, Key = A, IsRepeat = False
  • KeyDown, Key = A, IsRepeat = False
  • PreviewTextInput, Text = a
  • (TextBox contains “a”)
  • PreviewKeyDown, Key = A, IsRepeat = True
  • KeyDown, Key = A, IsRepeat = True
  • PreviewTextInput, Text = a
  • (TextBox contains “aa”)
  • PreviewKeyDown, Key = A, IsRepeat = True
  • KeyDown, Key = A, IsRepeat = True
  • PreviewTextInput, Text = a
  • (TextBox  contains “aaa”)
  • PreviewKeyUp, Key = A, IsRepeat = False
  • KeyUp, Key = A, IsRepeat = False

#624 – Information Available to Key Up/Down Events

All four of the keypress-related events (PreviewKeyDown, KeyDown, PreviewKeyUp, and KeyUp) send an instance of the KeyEventArgs object to the associated event handler.

private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
}

Here are some of the more important properties available in the KeyEventArgs object:

  • Key property – The System.Windows.Input.Key being pressed.  E.g. Key.Q
  • Timestamp – Time of key press, in # ticks (milliseconds) since last reboot
  • IsDown / IsUp – Is the key currently down or up?
  • IsRepeat – Is this keystroke a repeat due to holding a key down?
  • IsToggled – For keys that toggle, like Caps Lock, indicates current toggled state
  • Source – The control that had focus when the key was pressed
  • OriginalSource – Either the control where the key was pressed, or a lower-level child element
  • Handled – Can set to true to indicate that you’ve handled the event, short-circuiting the event routing (generally)

#617 – Input Events

Elements in WPF fire various type of input events, as a user interacts with the element.  There are four basic types of input events.

  • Keyboard events – Fire when user presses keys on the keyboard
  • Mouse events – Fire when a user does something with the mouse–e.g. moves the mouse or presses a mouse button
  • Touch events – Fire when a user uses their finger to touch an element (requires touch-sensitive screen)
  • Stylus events – Fire when the user uses a stylus device to touch an element on the screen  (requires a stylus device and touch-sensitive screen)