Closed bbsuuo closed 1 year ago
Expected behavior PreviewKeyDown should be able to block any text manipulation actions.
Where does this expectation come from? Even the name suggests at best this can prevent key presses to be processed. You can still paste text using context menu. You can still enter text using voice input or other input methods that do not necessarily involve key presses processing.
You can prevent the event going to the TextEditor if you create your own class deriving from RichTextBox and overriding the OnPreviewKeyDown method, but that still does not handle the case when the text change is initiated by an IME composition.
If you want to prevent input, make the textbox readonly. If you need input only on the bottom line, put another textbox at the bottom and remove the border between them. If you need fixed character space with random cursor placement then you probably need a different solution than a textbox.
Expected behavior PreviewKeyDown should be able to block any text manipulation actions.
Where does this expectation come from? Even the name suggests at best this can prevent key presses to be processed. You can still paste text using context menu. You can still enter text using voice input or other input methods that do not necessarily involve key presses processing.
You can prevent the event going to the TextEditor if you create your own class deriving from RichTextBox and overriding the OnPreviewKeyDown method, but that still does not handle the case when the text change is initiated by an IME composition.
If you want to prevent input, make the textbox readonly. If you need input only on the bottom line, put another textbox at the bottom and remove the border between them. If you need fixed character space with random cursor placement then you probably need a different solution than a textbox.
Sorry... Upon rechecking the source code, I realized that I can indeed correct my issue by overriding the PreviewKeyDown of TextBoxBase. Initially, I mistook the root cause of the problem as OnTextContainerChanged.
The other thing you can do is set InputMethod.IsInputMethodSuspended
(or IsInputMethodEnabled
) on the RTB. That might help with preventing IME to modify your text without prior key events. Still does not help with paste, possibly drag&drop and there might be other ways to get text in.
Expected behavior PreviewKeyDown should be able to block any text manipulation actions.
Where does this expectation come from? Even the name suggests at best this can prevent key presses to be processed. You can still paste text using context menu. You can still enter text using voice input or other input methods that do not necessarily involve key presses processing.
You can prevent the event going to the TextEditor if you create your own class deriving from RichTextBox and overriding the OnPreviewKeyDown method, but that still does not handle the case when the text change is initiated by an IME composition.
If you want to prevent input, make the textbox readonly. If you need input only on the bottom line, put another textbox at the bottom and remove the border between them. If you need fixed character space with random cursor placement then you probably need a different solution than a textbox.
Although I still believe it is not very reasonable, in TextBoxBase, it defaults to calling _textEditor.OnPreviewKeyDown(e);, which then calls the method TextEditorTyping.OnPreviewKeyDown(_uiScope, e);. In this method, This.SetText(This.Selection, String.Empty, InputLanguageManager.Current.CurrentInputLanguage); is called. In the comments, it is mentioned that this is done to address some issues with IMEs. However, in terms of the process, text manipulation should not be handled during the pre-notification input event phase in OnPreviewKeyDown.
The other thing you can do is set
InputMethod.IsInputMethodSuspended
(orIsInputMethodEnabled
) on the RTB. That might help with preventing IME to modify your text without prior key events. Still does not help with paste, possibly drag&drop and there might be other ways to get text in.
Thank you for your guidance! I am now attempting to write the code.
Description
I'm developing a page similar to a terminal using RichTextBox, so I want to control user input. I registered the PreviewKeyDown event, which theoretically should be able to block all events. However, when I select a portion of text and then press any key, the selected text gets deleted. It seems that this triggers a precondition for replacing text in the session. The code looks something like this:
ConsoleRichTextBox.PreviewKeyDown += OnPreviewKeyDown; void OnPreviewKeyDown(object sender, KeyEventArgs e) { e.Handled = true; }
I tried popping the stack in the TextChanged event (which gets triggered first in this case), and I got the following stack:
在 TranslateStudio.Views.Pages.UnityTranslate.UnityConsolePage.OnTextChanged(Object sender, TextChangedEventArgs e) 在 E:\GitLibrary\JustTranslate\ChatGptServer\TranslateStudio\Views\Pages\UnityTranslate\UnityConsolePage.xaml.cs 中: 第 114 行
在 System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
在 System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
在 System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
在 System.Windows.Controls.Primitives.TextBoxBase.OnTextContainerChanged(Object sender, TextContainerChangedEventArgs e)
在 System.Windows.Documents.TextContainer.EndChange(Boolean skipEvents)
在 System.Windows.Documents.TextRangeBase.EndChange(ITextRange thisRange, Boolean disableScroll, Boolean skipEvents)
在 System.Windows.Documents.TextSelection.System.Windows.Documents.ITextRange.set_Text(String value)
在 System.Windows.Documents.TextEditor.SetText(ITextRange range, String text, CultureInfo cultureInfo)
在 System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
在 System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
在 System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
在 System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
在 System.Windows.Input.InputManager.ProcessStagingArea()
在 System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
在 System.Windows.Interop.HwndKeyboardInputProvider.ProcessKeyAction(MSG& msg, Boolean& handled)
在 System.Windows.Interop.HwndSource.CriticalTranslateAccelerator(MSG& msg, ModifierKeys modifiers)
在 System.Windows.Interop.HwndSource.OnPreprocessMessage(Object param)
在 System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
在 System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
How can I prevent the Session from replacing the text?
Reproduction Steps
RichTextBox.PreviewKeyDown += OnPreviewKeyDown;
void OnPreviewKeyDown(object sender, KeyEventArgs e) { e.Handled = true; }
//You can reproduce this issue on any page.
Expected behavior
PreviewKeyDown should be able to block any text manipulation actions.
Actual behavior
PreviewKeyDown cannot effectively block all events.
Regression?
No response
Known Workarounds
Currently, it seems that modifying the events registered by TextEditor can only be achieved through reflection.
Impact
No response
Configuration
No response
Other information
No response