2015-06-18 6 views
1

Я пишу текстовый редактор в WPF (используя C#), который имитирует чат-программу с использованием RichTextBox. Когда пользователь нажимает кнопку ввода, соответствующее имя пользователя автоматически добавляется в следующую строку. Однако, если пользователь набирает достаточно быстро, чередуя ввод и другие нажатия клавиш, их текст может отображаться перед сгенерированным именем пользователя. Вот скриншот, который может продемонстрировать это лучше: http://oi62.tinypic.com/fusv1j.jpgОстановить пользователя от ввода до сгенерированного текста

Проблема была намного хуже, и после поиска я попытался вручную установить положение каретки до конца после вставки; к сожалению, все еще можно получить текст до инициалов, если вы сделаете достаточно быстро.

Вот мой C# для события KeyUp в RichTextBox, и соответствующие вспомогательные методы:

private void textBoxEnterPressed(object sender, KeyEventArgs e) 
{ 
    if (e.Key != Key.Enter || initialsCheckBox.IsChecked == false) 
     return; 

    Chumhandle active = getActiveHandleBox().SelectedItem as Chumhandle; 
    AppendText(mainTextBox, active.Initials + ": ", active.HexCode); 

    TextPointer caretPos = mainTextBox.CaretPosition; 
    caretPos = caretPos.DocumentEnd; 
    mainTextBox.CaretPosition = caretPos; 
} 

private ComboBox getActiveHandleBox() 
{ 
    if (activeBox == 1) 
     return handleBox1; 
    else 
     return handleBox2; 
} 

public static void AppendText(RichTextBox box, string text, string color) 
{ 
    BrushConverter bc = new BrushConverter(); 
    TextRange tr = new TextRange(box.Document.ContentEnd, box.Document.ContentEnd); 
    tr.Text = text; 
    try 
    { 
     tr.ApplyPropertyValue(TextElement.ForegroundProperty, bc.ConvertFromString(color)); 
    } 
    catch (FormatException) { } 

    box.Selection.ApplyPropertyValue(RichTextBox.ForegroundProperty, bc.ConvertFromString(color)); 
} 

а также XAML для RichTextBox:

<RichTextBox Name="mainTextBox" Grid.Row="3" FontFamily="Courier New" AcceptsReturn="True" VerticalScrollBarVisibility="Visible" BorderThickness="0" KeyUp="textBoxEnterPressed"> 
    <RichTextBox.Resources> 
     <Style TargetType="{x:Type Paragraph}"> 
      <Setter Property="Margin" Value="0" /> 
     </Style> 
    </RichTextBox.Resources> 
</RichTextBox> 

Правда, я не уверен, если это можно исправить, и я должен просто надеяться, что пользователь не пойдет так быстро ...

+1

У вас есть _race_ с вашей коробкой. Оба хотят обработать ключ ввода: вы в 'textBoxEnterPressed' и' RichTextBox', чтобы добавить новую строку. Я бы остановил эту настройку конкурса 'AcceptsReturn' на' False'. Он ничего не меняет (если у вас нет кнопки по умолчанию в вашем диалоговом окне), но я также установил бы «e.Handled» на «true». –

+0

О, мальчик, проблемы с резьбой. Ха-ха. Ну, это почти все. Гонка определенно исправлена ​​(я просто должен был «textBoxEnterPressed» также вставить новую строку вручную), но теперь, если я поместил курсор в середину текста и нажал клавишу ввода, все будет добавлено до самого конца, а не на позиция курсора как интуитивная. Заставляет меня задаться вопросом, не упускаю ли я некоторые другие функции, которые «RichTextBox» автоматически обрабатывает. –

+1

Нет нитей, это было сделано последовательно. Вы можете даже сохранить его таким, каким он есть, и установите e.Handled в true (richtextbox не будет обрабатывать ввод, если вы это сделали). На самом деле, я просто попробую сделать что-то ТОЛЬКО, если вы на последней строке. Следующий шаг? Два окна ... один для просмотра беседы и один для ввода текста (как почти каждый чат делает ... что, если кто-то еще печатает сообщение, когда вы все еще печатаете?) –

ответ

0

Я поиграл немного с вашим кодом, и это то, что мне удалось:

private void textBoxEnterPressed(object sender, KeyEventArgs e) 
    { 
     if (e.Key != Key.Enter) 
      return; 

     // ADDED THIS TO SIMULATE AcceptsReturn = True 
     if (initialsCheckBox.IsChecked == false) 
     { 
      AppendText(mainTextBox, Environment.NewLine, "#000000"); 
      return; 
     } 

     Chumhandle active = getActiveHandleBox().SelectedItem as Chumhandle; 

     // ADDED Environment.NewLine TO INSERT LINE BREAKS 
     AppendText(mainTextBox, Environment.NewLine + active.Initials + ": ", active.HexCode); 

     // COMMENTED THIS BECAUSE IT WAS FORCING UNWANTED BEHAVIOR 
     //TextPointer caretPos = mainTextBox.CaretPosition; 
     //caretPos = caretPos.DocumentEnd; 
     //mainTextBox.CaretPosition = caretPos; 
    } 

    public static void AppendText(RichTextBox box, string text, string color) 
    { 
     BrushConverter bc = new BrushConverter(); 

     // INSTEAD OF USING box.Document, I'VE USED box.Selection TO INSERT 
     // THE TEXT WHEREVER THE CURSOR IS (OR IF YOU HAVE TEXT SELECTED) 
     TextRange tr = new TextRange(box.Selection.Start, box.Selection.End); 
     tr.Text = text; 
     try 
     { 
      tr.ApplyPropertyValue(TextElement.ForegroundProperty, bc.ConvertFromString(color)); 
     } 
     catch (FormatException) { } 

     // I DON'T UNDERSTAND WHAT THIS IS DOING SO I KEPT IT -_^ 
     box.Selection.ApplyPropertyValue(RichTextBox.ForegroundProperty, bc.ConvertFromString(color)); 

     // FINALLY, I SET THE CARET TO THE END OF THE INSERTED TEXT 
     box.CaretPosition = tr.End; 
    } 
+0

О, черт возьми, как только я переключил 'mainTextBox.AcceptsReturn' на false и использовал это вместо этого, обе проблемы на 100% исправлены ! Спасибо огромное! : D –

+0

Рад, что я мог бы помочь :) Да, я забыл упомянуть о том, что «AcceptsReturn» хехе (kudos @AdrianoRepetti) – almulo

1

Adriano Repetti получил это в комментариях; Мне пришлось отключить AcceptsReturn для текстового поля и обрабатывать вставку новых строк при вводе самих нажатий.

У вас есть гонка с вашей коробкой. Оба хотят обработать ключ ввода: вы в textBoxEnterPressed и RichTextBox добавили новую строку. Я бы остановил эту настройку конкурса AcceptsReturn to False. Здесь ничего не должно меняться (если у вас нет кнопки по умолчанию в вашем диалоговом окне), но я также установил e.Handled в true.

Смежные вопросы