如何防止输入控件从 TextCompositionManager 窃取空格字符?

发布于 2024-07-25 19:35:30 字数 1340 浏览 6 评论 0原文

与此问题相关(但不是欺骗!):Help with the WPF TextCompositionManager events

使用 TextCompositionManager 时,我遇到一个问题,如果输入控件(例如 TextBox)具有焦点,则 TextBox 将在我有机会执行操作之前“窃取”空格字符它。

例如,我们有以下代码:

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

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

其中 Window1 如下所示:

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

现在,如果我运行此应用程序并立即键入“我讨厌小偷混蛋”,则 TextBlock 将包含文本“我讨厌小偷混蛋”,并且文本框将为空。

但是,如果我聚焦文本框(即文本框具有键盘焦点),则在输入上述行后,文本块将包含文本“Ihaetthifyingbastards”,并且文本框将包含文本“”(3 个空格)。


我有两个问题:
1) 我可以仅使用 TextCompositionManager 提供的功能来防止这种情况发生吗?
2)如果没有,我到底应该在哪里插入文本输入堆栈,以便我可以完全控制我的WPF应用程序中的文本输入(甚至考虑p/调用的缺点)(你只是想关于它,添加了负分)?


更新

我正在使用一种巧妙的解决方法,仅处理来自空间的 InputManager 的隧道 KeyDown 事件。 这种方法非常笨拙,效率低下,而且基本上很臭。 仍在寻找更好的方法。

Related (but not a dupe!) to this question: 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

左秋 2024-08-01 19:35:30

为了他人的利益,我的黑客代码。

我的特定应用程序正在等待读卡器刷卡。 以下内容存在于监视刷卡的对象的构造函数中(这是一个业余项目;大多数评论咒骂已被编辑掉):

// 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);

两种方法:

/// <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);
}

当有人按下某个键(或将击键发送到系统)时,PreNotifyInput事件发生。 在这种情况下,我确定它是否是一个特殊的键(对我来说,我必须担心空格,但其他键显然需要特别注意)。 如果它是一个特殊键,我将“处理”该事件,停止对该击键的所有进一步处理。 然后,我调用传入空格的内部处理方法(或我刚刚截获的任何特殊键)。

所有其他键均由 PreviewTextInputHandler 方法处理。

这段代码去掉了很多东西。 确定滑动事件何时发生、确定滑动何时完成、防护措施(超时,以防我永远不会停止捕获滑动)等都被删除。 您如何执行此操作将取决于您的代码要求。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文