Обнаружение, если событие вставки произошло внутри текстового поля форматированного текста
Существует ли способ, с помощью которого мы можем узнать, произошло ли событие вставки клипа в текстовом поле rich? Это событие будет использоваться для того, чтобы сделать определенные вещи, с вставленным блоком текста.
Спасибо
Вот мой код
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == WM_PASTE)
{
OnPasteOccurred();
MessageBox.Show("Pas");
}
if (m.Msg == 0x000F)
{
if (PaintControl)
{
base.WndProc(ref m);
}
else
{
m.Result = IntPtr.Zero;
}
}
else
{
base.WndProc(ref m);
}
}
Edit
Я хочу сделать некоторые подсветки синтаксиса или отступы на основе событий вставки, то, что этот конкретный редактор кода , кажется, делает очень эффективно. Я не знаю, как он это делает. Потребовать помощь в этом конкретном направлении. Я почти уверен, что должен быть какой-то собственный код Win32 или что-то подобное, что может быть перехвачено. Я пробовал отслеживать клавиши, события мыши, и это не очень красиво.
2 ответа:
Немного сложно обнаружить операцию вставки в
RichTextBox
.Первым решением может быть обнаружение сообщения
WM_PASTE
, переопределяющегоWndProc
, но, к сожалению, элемент управления не отправляет это сообщение самому себе, когда он выполняет операцию вставки.Наивное обнаружение
Для обнаружения событий клавиатуры может работать (вы должны переопределить функцию
OnKeyDown
), Затем проверьте, если комбинации клавиш (CTRL+V и сдвиг+INS ). Что-то вроде этого:protected override OnKeyDown(KeyEventArgs e) { bool ctrlV = e.Modifiers == Keys.Control && e.KeyCode == Keys.V; bool shiftIns = e.Modifiers == Keys.Shift && e.KeyCode == Keys.Insert; if (ctrlV || shiftIns) DoSomething(); }
Он работает хорошо, но вы не можете поймать операцию вставки, выполненную с помощью мыши (щелкните правой кнопкой мыши, чтобы открыть контекстное меню) и операции вставки, выполненные с помощью drag & drop. Если они вам не нужны, вы можете использовать это решение (по крайней мере, оно простое и понятное).
Лучше
Предположение: когда пользователь вводит внутри
RichTextBox
, он вставляет один символ за раз. Как вы можете это использовать? Ну, когда вы обнаруживаете большее изменение, вы обнаруживаете операция вставки, поскольку пользователь не может вводить более одного символа за раз (хорошо, вы можете утверждать, что это не всегда верно из-за заменителей Юникода). См. также VB.NET версия и подробнее о Unicode материале.Обратите внимание, что вы не можете (из-за того, как работают различные IMEs) использоватьprivate int _previousLength = 0; private void richTextBox_TextChanged(object sender, EventArgs e) { int currentLength = richTextBox.Text.Length; if (Math.Abs(currentLength - _previousLength) > 1) ProcessAllLines(); _previousLength = currentLength; }
OnKeyDown
(или аналогичный). Это хорошо работает только для западных языков, но у него есть проблемы с юникодом (потому что, например, свойствоString.Length
может быть увеличено на дваChar
когда пользователь набрал один символ. Смотрите также этот пост для получения более подробной информации об этом (ну, это настоятельно рекомендуется читать даже, даже если - в этом случае - вы не заботитесь об этом). В этом посте вы также найдете код для лучшего алгоритма определения длины строки. Короче говоря, вы должны заменить:int currentLength = richTextBox.Text.Length;
С этим:
После всех этих усилий вы можете осознать это...пользователь может даже вставить один символ, и он может остаться незамеченным. Ты прав, вот почему. этолучшее обнаружение вместоидеального решения .int currentLength = StringInfo.GetTextElementEnumerator(richTextBox.Text) .Cast<string>() .Count();
Идеальное решение
Идеальное решение (если вы работаете в Windows 8), Конечно, существует, собственный rich edit control отправляет уведомление
EN_CLIPFORMAT
. Он предназначен для уведомления родительского окна элемента управления rich edit о том, что произошла вставка с определенным форматом буфера обмена. Затем вы можете переопределитьWndProc
своего родителя, чтобы обнаружить сообщениеWM_NOTIFY
для этого уведомления. В любом случае это не так несколько строк кода, проверьте эту статью MSDN для деталей.
Начиная с .Net 3.0, существует встроенный метод для обнаружения события вставки:
DataObject.AddPastingHandler(this, OnPaste);
Просто вызовите этот метод в конструкторе. Если вы хотите, например, обработать событие вставки самостоятельно, как если бы пользователь ввел текст вручную, вы можете использовать
private void OnPaste(object sender, DataObjectPastingEventArgs e) { if (e.DataObject.GetDataPresent(typeof(string))) { var text = (string)e.DataObject.GetData(typeof(string)); var composition = new TextComposition(InputManager.Current, this, text); TextCompositionManager.StartComposition(composition); } e.CancelCommand(); }