views:

209

answers:

2

Related (but not a dupe!) to this question: http://stackoverflow.com/questions/1053210/help-with-the-wpf-textcompositionmanager-events

When using the TextCompositionManager I'm having an issue where, if an input control such as the TextBox has focus, the TextBox will "steal" the space character before I can get a chance to act on it.

For example, we have the following code:

public Window1()
{
  TextCompositionManager.AddPreviewTextInputStartHandler
    (this, PreviewTextInputStartHandler);
}

private void PreviewTextInputHandler(object sender, TextCompositionEventArgs e)
{
  CaptureTextBlock.Text += e.Text;
  e.Handled = true;
}

where Window1 looks like:

<!--standard window crap above here-->
<StackPanel>
  <TextBlock Name="CaptureTextBlock" />
  <TextBox Name="ThievingBastard" />
</StackPanel>
<!-- snip -->

Now, if I run this application and immediately type "I haet thieving bastards", the TextBlock will contain the text "I haet thieving bastards" and the textbox will be empty.

If, however, I focus the textbox (i.e., textbox has keyboard focus), after typing the above line the textblock will contain the text "Ihaetthievingbastards" and the textbox will contain the text " " (3 spaces).


I have two questions:
1) Can I prevent this from happening with just the facilities provided by the TextCompositionManager?
2) If not, where the hell do I plug into the text input stack so that I can fully control text input within my WPF application (negative points for even thinking about p/invoking) (you just thought about it, negative points added)?


Update

I'm using a hacky workaround where I handle the tunneling KeyDown event from the InputManager for spaces only. This method is very awkward, inefficient and basically stinks. Still looking for a better way.

A: 

Did you find an answer to this? I am facing the same issue. I have a checkbox which is stealing hyphen and plu s (- and +).

Ragha J
My code is added.
Will
A: 

For the benefit of others, my hacky code.

My particular app is waiting for a card swipe from a card reader. The following lives in the constructor of the object that watches for a card swipe (this is a side project; most comment cursing edited out):

// this is where we handle the space and other keys wpf f*s up.
System.Windows.Input.InputManager.Current.PreNotifyInput += 
    new NotifyInputEventHandler(PreNotifyInput);
// This is where we handle all the rest of the keys
TextCompositionManager.AddPreviewTextInputStartHandler(
    Application.Current.MainWindow, 
    PreviewTextInputHandler);

The two methods:

/// <summary>
/// Handles the PreNotifyInput event of the input manager.
/// </summary>
/// <remarks>Because some controls steal away space (and other) characters, 
/// we need to intercept the space and record it when capturing.</remarks>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The 
/// <see cref="System.Windows.Input.NotifyInputEventArgs"/> 
/// instance containing the event data.</param>
private void PreNotifyInput(object sender, NotifyInputEventArgs e)
{
    // I'm only interested in key down events
    if (e.StagingItem.Input.RoutedEvent != Keyboard.KeyDownEvent)
        return;
    var args = e.StagingItem.Input as KeyEventArgs;
    // I only care about the space key being pressed
    // you might have to check for other characters
    if (args == null || args.Key != Key.Space)
        return;
    // stop event processing here
    args.Handled = true;
    // this is my internal method for handling a keystroke
    HanleKeystroke(" ");
}


/// <summary>
/// This method passes the event to the HandleKeystroke event and turns
/// off tunneling depending on whether or not Capturing is true.
/// Also calls StopCapturing when appropriate.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The 
/// <see cref="System.Windows.Input.TextCompositionEventArgs"/> 
/// instance containing the event data.</param>
private void PreviewTextInputHandler(object sender, 
    TextCompositionEventArgs e)
{
    HanleKeystroke(e.Text);
}

When somebody presses a key (or a keystroke is sent to the system) the PreNotifyInput event fires. In this case, I determine if it is a special key (for me I have to worry about the space, but other keys apparently need special attention). If it is a special key, I "handle" the event, stopping all further processing of this keystroke. I then call my internal processing method passing in the space (or whatever special key I just intercepted).

All other keys are handled by the PreviewTextInputHandler method.

This code has a lot of stuff stripped out of it. Determining when a swipe event has happened, determining when the swipe has completed, safeguards (timeouts in case I never stop capturing a swipe), etc is removed. How you do this stuff will depend on your code requirements.

Will