首页 > 解决方案 > 在 WPF RichTextBox 中快速键入会混淆事件

问题描述

我正在尝试在 WPF 中实现一个简单的自动更正功能RichTextBox。特别是,其中两个功能是 1.) 缩写扩展(当您键入“idk”和一个空格时,“idk”被替换为“我不知道”)和 2.)在末尾添加句点一条线。我正在通过PreviewKeyDown事件来实现这一点,检测何时出现单词分隔符(用于缩写扩展)或回车(用于添加句点)。它在大多数情况下都有效,但我在打字速度极快时看到了一种奇怪的行为。似乎可以在后续键的事件之后将字符插入到文本中。PreviewKeyDown

例如,假设您想输入缩写“idk”,然后输入回车,那么您将得到“我不知道”这一行。如果您键入“id”,然后键入“k”,然后ENTER快速连续,键的PreviewKeyDown事件会“k”插入文本之前发生。所以事件代码看不到要扩展的完整“idk”缩写——它只看到“id”。然后它将句点放在“id”的末尾(由于密钥)。之后最后将“k”插入到文本中,因此结果是“id.k”ENTERPreviewKeyDownENTER

这是一个非常奇特的案例。如果您几乎不同时按“k”和ENTER键,则不会发生。我有一个演示应用程序,我在其中使用 WPF 密钥模拟器库来立即发送字符。该应用程序在这里:https ://github.com/garzooma/RichTextBoxDemo 。密钥模拟器库在这里https://archive.codeplex.com/?p=wpfsendkeys]

我已经尝试设置标志来延迟第二次击键的处理,但这只会让一切都挂起——第一次击键永远不会被处理。

PreviewTextInput在我的演示应用程序中,我尝试了一个 hack,其中代码通过在事件处理程序中设置一个标志并在处理程序中清除它来检测在后续按键发生之前何时未处理字符TextChanged。当PreviewKeyDown代码看到标志时,我设置了一个在后续TextChanged事件中处理的 Action 变量。这似乎有效。但我希望找到一种方法来避免问题发生。

基本代码是:

private void PreviewKeyDownHandler(object sender, KeyEventArgs e)
{
  // See if we're at the end of a word
  if (delimiterKeys.Contains(e.Key))
  {
    string word = GetPrecedingText();
    // Is the word an abbreviation?
    if (abbreviations.ContainsKey(word.ToUpper()))
    {
      TextPointer pointer = textbox1.CaretPosition.GetPositionAtOffset(-word.Length);
      if (pointer.LogicalDirection == LogicalDirection.Backward)  // change direction, if needed
      {
        pointer = pointer.GetPositionAtOffset(0, LogicalDirection.Forward);
        textbox1.CaretPosition = pointer;
      }
      // replace abbreviation w/expansion
      pointer.DeleteTextInRun(word.Length);
      pointer.InsertTextInRun(abbreviations[word.ToUpper()]);
    }
    // Are we at the end of a line, and don't have a period?
    if (e.Key == Key.Enter && !word.EndsWith("."))
    {
      TextPointer pointer = textbox1.CaretPosition;
      if (pointer.LogicalDirection == LogicalDirection.Backward)  // change direction, if needed
      {
        pointer = pointer.GetPositionAtOffset(0, LogicalDirection.Forward);
        textbox1.CaretPosition = pointer;
      }
      pointer.InsertTextInRun(".");
    }
}

标签: c#wpfeventsrichtextbox

解决方案


推荐阅读