Выделить текущую строку RichTextBox

Это выделяет всю ширину каждой строки, рисуя прозрачный цвет в качестве цвета фона на текущей строке. При переключении линии восстанавливается исходный цвет фона.

Итак, что мы хотим сделать, это:

  1. Убедитесь, что предыдущий и текущий прямоугольники не совпадают, чтобы не закрашивать одну и ту же область дважды
  2. Замените выделение последней строки, используя фоновый цвет элементов управления
  3. Выделите текущую строку прозрачным цветом
  4. Установите mLastHighlightс индексом и прямоугольником для каждой применяемой линии

. Однако при снятии выделения текст закрашивается. Этого не происходит при применении подсветки.

Одним из решений было бы перерисовать текст обратно на элементе управления после сброса цвета фона. хотя форматирование текста, цвета выделения, стили шрифта, гиперссылки и т. д. было бы утомительно фильтровать. Не очень элегантно.

Это приводит к более простому решению, обновляющему элемент управления. Хотя это вызвало бы массовое мерцание. Тоже не приемлемо.

Есть элегантное решение? Я совершенно сбит с толку, почему это происходит.

РЕДАКТИРОВАТЬ:Отредактировано, чтобы отразить ответ Кода Грея.

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
}
5
задан Mark S 31 July 2012 в 00:42
поделиться