Обнаружение, если событие вставки произошло в расширенном текстовом поле

Есть ли способ, с помощью которого мы можем узнать, произошло ли событие вставки клипа в поле с большим текстовым полем? Это событие будет использоваться для того, чтобы сделать определенные вещи, с вставленным блоком текста.

спасибо

Вот мой код

 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 или что-то подобное можно перехватить. Я пробовал отслеживать ключи, события мыши, и это не очень.

Ответ 1

Немного сложно обнаружить операцию вставки в RichTextBox.

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

Наивное обнаружение

Для обнаружения событий клавиатуры могут работать (вы должны переопределить функцию OnKeyDown), затем проверьте, есть ли комбинации клавиш (CTRL + V и SHIFT + 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();
}

Он работает хорошо, но вы не можете поймать операцию вставки, сделанную с помощью мыши (щелкните правой кнопкой мыши, чтобы открыть контекстное меню) и операции вставки, сделанные с помощью перетаскивания. Если они вам не нужны, вы можете использовать это решение (по крайней мере, это просто и просто).

Лучшее обнаружение

Предположение: когда пользователь вводит внутри RichTextBox, он вставляет один символ за время. Как вы можете это использовать? Ну, когда вы обнаруживаете большее изменение, вы обнаружили операцию вставки, потому что пользователь не может вводить более одного символа за раз (хорошо, вы можете утверждать, что это не всегда верно из-за суррогатов Unicode). См. Также версия VB.NET и подробнее об Unicode.

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

Обратите внимание, что вы не можете (из-за того, как работают разные IME) использовать OnKeyDown (или аналогичный). Это хорошо работает только для западных языков, но у него есть проблемы с материалом Unicode (потому что, например, свойство String.Length может быть увеличено на два Char, когда пользователь вводит один символ. См. Также этот пост для получения более подробной информации об этом (ну, это настоятельно рекомендуется прочитать даже, даже если - в этом случае - вам все равно). В этом посте вы также найдете код для лучшего алгоритм для определения длины строки. Короче говоря, вы должны заменить:

   int currentLength = richTextBox.Text.Length;

При этом:

   int currentLength = StringInfo.GetTextElementEnumerator(richTextBox.Text)
       .Cast<string>()
       .Count();

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

Идеальное решение

Разумеется, идеальное решение (если вы работаете в Windows 8) существует, встроенный редактор edit edit отправляет сообщение уведомления EN_CLIPFORMAT. Он предназначен для уведомления о расширенном родительском окне управления редактированием, в котором произошла вставка с определенным форматом буфера обмена. Затем вы можете переопределить WndProc своего родителя, чтобы обнаружить сообщение WM_NOTIFY для этого уведомления. В любом случае, это не так много строк кода, проверьте эту статью статью MSDN для деталей.

Ответ 2

Начиная с .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();
}