Detectando si el evento pegar ocurrió dentro de un cuadro de texto enriquecido

¿Hay alguna manera de averiguar si un evento de pegar tabla de recortes se produjo en un cuadro de texto enriquecido? Este evento se usaría para hacer ciertas cosas, con el bloque de texto pegado.

Gracias

Aquí está mi código

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

Editar

Deseo hacer algunos resaltados de syntax o sangría basados ​​en pegar eventos, algo que este editor de código particular parece estar haciendo muy eficientemente. No sé cómo lo está haciendo. Requeriría ayuda en esta dirección particular. Estoy bastante seguro de que debe haber algún código nativo Win32 o algo así que pueda ser interceptado. He intentado rastrear claves, eventos de mouse y no es bonita.

Es un poco complicado detectar una operación de pegado en el RichTextBox .

La primera solución puede ser detectar el mensaje WM_PASTE que WM_PASTE el WndProc pero desafortunadamente el control no se envía ese mensaje a sí mismo cuando realiza una operación de pegado.

Detección ingenua

Para detectar el teclado, los eventos pueden funcionar (debe sobrescribir la función OnKeyDown ) y luego verificar si las combinaciones de teclas ( CTRL + V y MAYÚS + INS ). Algo como esto:

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

Funciona bien, pero no se puede capturar la operación de pegar realizada con el mouse (clic derecho para abrir el menú contextual) y las operaciones de pegar realizadas mediante arrastrar y soltar. Si no los necesita, puede usar esta solución (al menos es simple y directa).

Mejor detección

Suposición: cuando el usuario escribe dentro de RichTextBox , inserta un carácter por vez. Como puedes usar esto? Bueno, cuando detecta un cambio mayor, detecta una operación de pegado porque el usuario no puede escribir más de una letra por vez (vale, puede argumentar que no siempre es así debido a los sustitutos de Unicode). Consulte también la versión VB.NET y más detalles sobre cosas 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; } 

Tenga en cuenta que no puede (debido a la forma en que funcionan los diferentes IME) utilizar OnKeyDown (o similar). Esto funciona bien solo para los idiomas occidentales, pero tiene problemas con las cosas Unicode (porque, por ejemplo, la propiedad String.Length puede boostse en dos Char cuando el usuario escribe un solo carácter. Consulte también esta publicación para obtener más detalles sobre esto (bueno, es una lectura muy sugerida, incluso si, en este caso, no le importa). En esa publicación también encontrará un código para un mejor algoritmo para determinar la longitud de la cadena. En resumen, debe reemplazar:

  int currentLength = richTextBox.Text.Length; 

Con este:

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

Después de todo este esfuerzo, puede darse cuenta de que … el usuario puede incluso pegar un solo personaje y puede pasar desapercibido. Tienes razón, es por eso que esta es una mejor detección en lugar de una solución perfecta .

Solución perfecta

La solución perfecta (si está ejecutando en Windows 8) existe, por supuesto, el control de edición rico nativo envía un mensaje de notificación EN_CLIPFORMAT . Está destinado a notificar a la ventana principal de un control de edición enriquecido que se produjo un pegado con un formato de portapapeles particular. A continuación, puede anular el WndProc de su principal para detectar el mensaje WM_NOTIFY para esta notificación. De todos modos, no son pocas las líneas de código; consulte este artículo de MSDN para obtener más información.

A partir de .Net 3.0, hay un método incorporado para detectar el evento pegar:

 DataObject.AddPastingHandler(this, OnPaste); 

Simplemente llame a este método en el constructor. Si desea, por ejemplo, manejar el evento pegar usted mismo como si el usuario ingresara el texto manualmente, puede usar

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