tags:

views:

138

answers:

3

Hi,

I'm catching key hits with PreviewKeyDown event in my WPF component. I need to distinguish characters being typed: letters vs. numbers vs. underscore vs. anything else.

Letters and numbers work fine (just convert the Key property of the KeyEventArgs object to string and work with character 0 of that string), but this won't work for underscore.

It's ToString value depends on localized keyboard settings (it shows up as "OemMinus" on EN/US keyboard and "OemQuestion" on CZ/QWERTY keyboard).

So how can I RELIABLY find out, if the typed char is underscore in the PreviewKeyDown event?

Thanks for any help

A: 

The ToString value is coming back as those various keys because it's getting the Key's name, not necessarily the character value that you're wanting to test. I'd really recommend using the Key enumeration there...

As far as your question goes, I'm not 100% certain what you're trying to do (this won't help in video games, etc.), but perhaps the UIElement.PreviewTextInput event can help out - rather than having to catch individual key presses, you get the actual text input, which helps out in other situations such as when dealing with voice recognition, etc.

It appears from your comments that you're trying to capture both non-character indicators as well as character indicators; these can potentially conflict with each other (especially on compressed keyboards), so it seems MS built out the framework in such a way that a situation wasn't accidentally overlooked. (Your particular situation shows the difference between Shift+dash and Shift+? on two different keyboards; I'm certain there's more.) I'd recommend looking for only keypresses and giving the ability to the end user of your app to rework the key bindings.

Which reminds me, be careful with the "MouseDown" events, because they won't occur on touch surfaces (such as Microsoft Surface) - it's best to code for all the events available.

Good luck with your project!

mattdekrey
A: 

UPDATE:

This is a bit messy, but it might help you after some refactoring. I capture text using the preview event and force sending the Key I want; I ignore all other keys in my preview handler. I did switch from KeyDown to KeyUp to get the preview event to fire first. I use the _clearNext flag to skip/clear the key event.

In XAML

<Window x:Class="EmployeeNavigator.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    PreviewTextInput="Window_PreviewTextInput"
    Keyup="Window_KeyUp"
    Height="400" 
    Width="600"
    MinWidth="600">
</Window>

Code-behind detects and processes _

  private bool _clearNext = false;
  private void Window_KeyUp(object sender, KeyEventArgs e)
  {
     if ( _clearNext )
     {
        _clearNext = false;
        e.Handled = true;
     }
     else if (e.Key == Key.OemMinus)
     {
        e.Handled = true;
     }
     else if (e.Key == Key.OemQuestion)
     {
        e.Handled = true;
     }
  }

  private void Window_PreviewTextInput(object sender, TextCompositionEventArgs e)
  {
     if (e.Text.Equals("_"))
     {
        KeyEventArgs args = new KeyEventArgs(Keyboard.PrimaryDevice,
           Keyboard.PrimaryDevice.ActiveSource, 0, Key.OemMinus);
        args.RoutedEvent = Keyboard.KeyUpEvent;
        InputManager.Current.ProcessInput(args);
        e.Handled = true;
        _clearNext = true;
     }
     else if (e.Text.Equals("?"))
     {
        KeyEventArgs args = new KeyEventArgs(Keyboard.PrimaryDevice,
           Keyboard.PrimaryDevice.ActiveSource, 0, Key.OemQuestion);
        args.RoutedEvent = Keyboard.KeyUpEvent;
        InputManager.Current.ProcessInput(args);
        e.Handled = true;
        _clearNext = true;
     }
  }

I'll add there must be a better way.

Zamboni
The problem is I need to detect also Esc, Return and Shift keys, which won't work with TextInput :(There must be a way to convert the Key to the char which is being typed :(
CommanderZ
A: 

In the end, I had to rewrite the whole thing (and base it on text of the textarea which is being typed into),

CommanderZ