これにより、現在の行の背景色として透明な色をペイントすることで、各行の幅全体が強調されます。回線が切り替わると、元の背景色が復元されます。
したがって、私たちがやりたいことは次のとおりです。
- 以前の長方形と現在の長方形が一致しないことを確認して、同じ領域を 2 回ペイントしないようにします。
- コントロールの背景色を使用して、最後の行のハイライトを置き換えます
- 透明色を使用して現在の行を強調表示します
mLastHighlight
適用された各行のインデックスと長方形で設定
ただし、ハイライトを削除すると、テキストが塗りつぶされます。これは、ハイライトを適用する場合には発生しません。
1 つの解決策は、背景色をリセットした後で、コントロールのテキストを再描画することです。ただし、テキストの書式設定、選択色、フォント スタイル、ハイパーリンクなどをフィルタリングするのは面倒です。あまりエレガントではありません。
これにより、コントロールが更新され、よりシンプルなソリューションにつながります。それは大きなちらつきを引き起こすでしょうが。どちらも受け入れられません。
エレガントなソリューションはありますか?なぜこれが起こるのか、私は完全に困惑しています。
編集: 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
}