2011-06-28 14 views
6

He notado que muchas aplicaciones que esperan que usted haga mucha edición de texto proporcionarán un comportamiento no predeterminado al hacer doble clic en el texto, ya que la aplicación resalta el texto con el que cree que probablemente intente interactuar.Especifique el comportamiento de resaltado al hacer doble clic en un área de texto o cuadro de texto.

Como un ejemplo rápido, esta frase se comporta de manera diferente en diferentes aplicaciones:

Esta es una sentencia "muestra"

Si escribo que en el Bloc de notas y haga doble clic en la palabra 'muestra' (idealmente en el medio de la palabra, por ejemplo, entre la 'm' y 'p' de la muestra), a continuación, el bloc de notas resalta desde la primera cita hasta el espacio después de la segunda cita inclusive. Si esa oración está en un comentario en Visual Studio y hago doble clic en la misma ubicación, se resalta desde la "s" hasta la "e" de la muestra sin resaltar las comillas.

¿Cómo puedo personalizar estos comportamientos resaltantes en mi propia aplicación? ¿Es diferente de winforms a WPF? Supongo que podría hackear mi camino para que funcione en un evento de doble clic, pero ¿hay alguna solución más elegante/deliberada destinada exclusivamente a esto?

+0

¿Mi respuesta fue de algún uso o esta pregunta es una pregunta muerta? – Skintkingle

+0

Tu respuesta es lo que haría si quisiera hacer mi propio tipo de cosas. Estaba buscando enfoques orientados a un evento orientado al contexto, forma sensible para tener condiciones personalizadas para qué texto resaltar con un doble clic. Aparentemente no hay una manera de hacer esto. –

Respuesta

2

Sí, utilizar el evento DoubleClick para hacer lo que quiera es kludgy, ya que parece que está haciendo la selección dos veces, que es más lenta, se ve peor y podría desencadenar eventos/códigos no deseados.

Así que el siguiente código debería hacer el truco para Winforms al menos. Cree una nueva clase y amplíe el TextBox (o RichTextBox) de la manera habitual (utilizando el control recién creado que debería aparecer mágicamente en el diseñador). He hecho una rutina simple donde puedes especificar el delimitador a usar. Con un poco más de trabajo, debería ser fácil representar un rango de caracteres en lugar de solo uno, o incluso crear otras formas más avanzadas de selección.

Si estás utilizando un cuadro de texto en lugar de un RichTextBox, basta con quitar el bit de "rico" que aparece dos veces en la definición de clase.

class RichTextBoxX : RichTextBox 
{ 
    char delimiter = ','; // Specify what character to use for start and end of selection 

    protected override void WndProc(ref System.Windows.Forms.Message m) 
    { 
     if (m.Msg==0x0203) // WM_LBUTTONDBLCLK 
     { 
      // Perfect situation for off-by-one bugs! Checked thoroughly for at least 10 mins, so should be okay now: 
      int start = this.SelectionStart; 
      if (start < 1) start = 1; 
      int left = this.Text.LastIndexOf(delimiter, start - 1); 
      int right = this.Text.IndexOf(delimiter, start); 
      if (right == -1) right = Text.Length; 
      this.SelectionStart = left + 1; 
      this.SelectionLength = right - left - 1; 
      return;    
     } 

     base.WndProc(ref m); 
    } 
} 
+0

cómo obtengo múltiples delimitadores, ¿puedes dar un ejemplo con un char []? – DarkPh03n1X

0

Añadiendo al trabajo de DanW he agregado múltiples delimitadores, que parecen funcionar muy bien.

class RichTextBoxX : RichTextBox 
{ 
    private char[] delimiterList = new[] { ',', ' '}; 

    protected override void WndProc(ref System.Windows.Forms.Message m) 
    { 
     if (m.Msg == 0x0203) // WM_LBUTTONDBLCLK 
     { 
      int start = this.SelectionStart; 
      if (start < 1) start = 1; 

      int left = -1; 
      int right = Text.Length; 

      foreach (char c in delimiterList) 
      { 
       if (this.Text.LastIndexOf(c, start - 1) > left) 
       { 
        left = this.Text.LastIndexOf(c, start - 1); 
       } 

       if (this.Text.IndexOf(c, start) < right) 
       { 
        right = this.Text.IndexOf(c, start); 
        if (right == -1) right = Text.Length; 
       } 
      } 

      this.SelectionStart = left + 1; 
      this.SelectionLength = right - left - 1; 
      return; 
     } 

     base.WndProc(ref m); 
    } 
} 

Una cosa más: para implementar pegar el código anterior en "código" de su formulario que se va a utilizar, ahora utilizar el "diseñador de la forma" arrastrar y soltar un RichTextBox en su forma, ahora ir a la clase de diseño en la forma en mi caso form1.desigener.cs y encontrar la cadena aplicación por ejemplo:

this.richTextBox1 = new System.Windows.Forms.RichTextBox(); 

y reemplazarlo con

this.richTextBox1 = new project.form1.RichTextBoxX(); 

Después de esto que el control funcionará como un RichTex normales aplicación de caja en T con la función overide adicional

1

La respuesta mejorada de DarkPh03n1X fue casi trabajando para mí, sin embargo, tiene un error desagradable: si un carácter delimitador no se pudo encontrar, Text.IndexOf(c, start) volverá -1 que establecerá right a -1 y luego se activa if (right == -1) right = Text.Length.

Así que ahora hemos seleccionado hasta el final del texto, aunque la selección esperada debería ser más corta.El comienzo se maneja correctamente, creo.

He eliminado if (right == -1) right = Text.Length pero he añadido && pos != -1. Aquí está la versión fija:

class RichTextBoxX : RichTextBox 
{ 
    // implement selection to work with "whole words" on double-click 
    // and without selecting the leading/trailing spaces/blanks/line breaks 
    private char[] delimiterList = new[] { '\n', ',', ' ', '(', ')', '_', '/' }; 

    protected override void WndProc(ref Message m) 
    { 
     if (m.Msg == 0x0203) // WM_LBUTTONDBLCLK 
     { 
      int start = SelectionStart; 
      if (start < 1) start = 1; 

      int left = -1; 
      int right = Text.Length; 
      int pos; 

      foreach (char c in delimiterList) 
      { 
       pos = Text.LastIndexOf(c, start - 1); 
       if (pos > left) left = pos; 

       pos = Text.IndexOf(c, start); 
       if (pos < right && pos != -1) right = pos; 
      } 

      SelectionStart = left + 1; 
      SelectionLength = right - left - 1; 
      return; 
     } 

     base.WndProc(ref m); 
    } 
} 

Para verificar la behavour, aquí está el texto de la muestra que estaba usando:

12.34.56.78 (ab1-2-3-4-5.test-1.example.com) 
Jersey City 
New Jersey 
US, United States 
ASN: Example.com/12345 

he añadido algunos otros delimitador, no dude en elegir lo que necesita.

Cuestiones relacionadas