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:
- Verificar los rectángulos anteriores y actuales no coinciden, por lo que no pintar la misma área dos veces
- Reemplazar más destacado de la última línea con el color de fondo controles
- Resalte la línea actual con un color transparente
- 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
}
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. –