2012-07-25 32 views
5

Esto resalta el ancho completo de cada línea pintando un color transparente como el color de fondo en la línea actual. Cuando la línea cambia, se restaura el color de fondo original.Resalte línea actual de RichTextBox

lo tanto, lo que queremos hacer es:

  1. Verificar los rectángulos anteriores y actuales no coinciden, por lo que no pintar la misma área dos veces
  2. Reemplazar más destacado de la última línea con el color de fondo controles
  3. Resalte la línea actual con un color transparente
  4. Set mLastHighlight con el índice y el rectángulo para cada línea aplicada

Sin embargo, al quitar el resaltado, se pinta el texto. Esto no ocurre al aplicar el resaltado.

Una solución sería volver a pintar el texto en el control después de restablecer el color de fondo. aunque el formato de texto, colores de selección, estilos de fuente, hipervínculos, etc. sería tedioso de filtrar. No muy elegante.

Esto conduce a una solución más simple, refrescando el control. Aunque eso causaría un parpadeo masivo. No es aceptable tampoco.

¿Existe una solución elegante? Estoy completamente desconcertado por qué ocurre esto.

EDIT: Editado para reflejar la respuesta de Code Gray.

using System; 

public class RTBHL : RichTextBox 
{ 
    private LastHighlight mLastHighlight = new LastHighlight(0, Rectangle.Empty); 

    private class LastHighlight 
    { 
     public int mCharIndex; 
     public Rectangle mRectangle; 

     public LastHighlight(int index, Rectangle r) 
     { 
      mCharIndex = index; 
      mRectangle = r; 
     } 
    } 

    public void PaintLineHighlight() 
    { 
     using (Graphics g = this.CreateGraphics) 
     { 
      // highlight color 
      Color c = Color.Beige; 
      // current pen color 
      Pen cp = new Pen(Color.Beige); 
      // color for removing highlight 
      Pen lp = new Pen(this.BackColor); 
      // brush for removing highlight 
      SolidBrush lb = new SolidBrush(this.BackColor); 
      // brush for applying highlight 
      SolidBrush cb = new SolidBrush(Color.FromArgb(64, c.R, c.G, c.B)); 
      // index of the current line 
      int index = this.GetFirstCharIndexOfCurrentLine; 
      // rectangle to specify which region to paint too 
      Rectangle r = new Rectangle(); 

      // specify dimensions 
      r.X = 0; 
      r.Y = this.GetPositionFromCharIndex(index).Y; 
      r.Width = this.HorizontalScrollBarWidth; 
      r.Height = Convert.ToInt32(this.Font.Height * this.ZoomFactor); 

      // this will always be true unless the current line remains the same 
      if (!(mLastHighlight.mCharIndex == index) && !(mLastHighlight.mRectangle == r)) 
      { 
       // remove the last highlight. regardless of the brush specified, white is always applied, and the text is painted over 
       g.DrawRectangle(lp, mLastHighlight.mRectangle); 
       g.FillRectangle(lb, mLastHighlight.mRectangle); 
       // apply highlight to the current line 
       g.DrawRectangle(cp, r); 
       g.FillRectangle(cb, r); 
      } 

      mLastHighlight = new LastHighlight(index, r); 
     } 
    } 

#region RichScrollBars 
    [DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    private static extern bool GetScrollInfo(IntPtr hWnd, int fnBar, ref SCROLLINFO si); 

    [StructLayout(LayoutKind.Sequential)] 
    public class SCROLLINFO 
    { 
     public int cbSize; 
     public int fMask; 
     public int nMin; 
     public int nMax; 
     public int nPage; 
     public int nPos; 
     public int nTrackPos; 
     public SCROLLINFO() 
     { 
      this.cbSize = Marshal.SizeOf(typeof(SCROLLINFO)); 
     } 

     public SCROLLINFO(int mask, int min, int max, int page, int pos) 
     { 
      this.cbSize = Marshal.SizeOf(typeof(SCROLLINFO)); 
      this.fMask = mask; 
      this.nMin = min; 
      this.nMax = max; 
      this.nPage = page; 
      this.nPos = pos; 
     } 
    } 

    private const int SIF_ALL = 0X17; 
    private const int SB_HORZ = 0; 
    private const int SB_VERT = 1; 

    public int HorizontalScrollBarWidth() 
    { 
     SCROLLINFO si = new SCROLLINFO() {fMask = SIF_ALL}; 
     GetScrollInfo(this.Handle, SB_HORZ, si); 

     return Math.Max(si.nMax, this.Width); 
    } 

    public int VerticalScrollBarHeight() 
    { 
     SCROLLINFO si = new SCROLLINFO() {fMask = SIF_ALL}; 
     GetScrollInfo(this.Handle, SB_VERT, si); 

     return Math.Max(si.nMax, this.Height); 
    } 
#endregion 
} 

Respuesta

3

El problema aquí es que el código que está copiando está diseñado para Scintilla. Las constantes SCI_* están definidas internamente por los encabezados de Scintilla, y los mensajes a los que hacen referencia solo tienen significado para los controles de Scintilla.

El envío de esos mensajes al control nativo de edición rich Win32 no va a hacer nada porque no fue diseñado para procesar esos mensajes. (O, peor aún, una o más de las constantes SCI_* suceder a chocar con uno o más de los identificadores de mensaje que el control de edición enriquecida hace reconocer, produciendo un comportamiento potencialmente interesantes.)

A no ser que en realidad estás usando una El control de edición de Scintilla en tu proyecto (que dijiste que no querías hacer), ese código no hará nada interesante. No está escrito para el control de edición enriquecido Win32, está escrito para interactuar con el control Scintilla.

El control Scintilla es mucho más que un simple envoltorio alrededor del control de edición rich Win32. Tiene que hacer un lote de dibujo personalizado para hacer su magia, y todo ese código es difícil de conseguir por sí mismo. Es por eso que mucha gente usa Scintilla en primer lugar. Si necesita su conjunto de características, le recomiendo que siga su ejemplo.

De todos modos, realmente no sé si esto es posible con el control de edición rich Win32. No creo que sea así, pero no podría jurar ese hecho. Supongo que podría hackear estableciendo el color de selección, pero esa no parece una solución muy buena. Algo así como Daniel suggests here. No soy un experto en Scintilla, pero para mis ojos inexpertos, esto se parece al equivalente moral de tu código basado en Scintilla, pero escrito para el control de edición rich Win32 (a través de.Envoltorio de WinForms NET de la misma).

+0

Gracias por su respuesta y aclarar eso. Pensé eso después de pensarlo un poco. La sugerencia de Daniels no colorea la totalidad de la línea, sin embargo. He editado mi código para incluir un intento de lograr esto. –