问题描述
Public Class HighlightableRTB
Inherits RichTextBox
Private LineHeight As Integer = 15
Public Sub New()
HighlightColor = Color.Yellow
End Sub
<Category("Custom"),Description("Specifies the highlight color.")>
Public Property HighlightColor As Color
Protected Overrides Sub OnSelectionChanged(ByVal e As EventArgs)
MyBase.OnSelectionChanged(e)
Me.Invalidate()
End Sub
Private Const WM_PAINT As Integer = 15
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_PAINT Then
Dim selectLength = Me.SelectionLength
Dim selectStart = Me.SelectionStart
Me.Invalidate()
MyBase.WndProc(m)
If selectLength > 0 Then Return
Using g As Graphics = Graphics.FromHwnd(Me.Handle)
Dim b As Brush = New SolidBrush(Color.FromArgb(50,HighlightColor))
Dim line = Me.GetLineFromCharIndex(selectStart)
Dim loc = Me.GetPositionFromCharIndex(Me.GetFirstCharIndexFromLine(line))
g.FillRectangle(b,New Rectangle(loc,New Size(Me.Width,LineHeight)))
End Using
Else
MyBase.WndProc(m)
End If
End Sub
End Class
解决方法
正如您已经猜到的那样,文本并不是真正的“模糊” ...而是在其上绘制的黄色矩形使它看起来像这样。
这并不容易。实际上,我有一个解决方案,但是如果我有其他话要说,我不建议这样做。但是我还没有,所以这是解决此问题的一种方法:
您可以在文本上方绘制文本...。它不会删除已经存在的文本...而是在其上绘制。如果您的坐标有些偏离,它将看起来像胡扯,但是如果您找到了正确的位置,它将像魅力一样工作。骇人的魅力:
Using g As Graphics = Graphics.FromHwnd(Me.Handle)
Dim b As Brush = New SolidBrush(Color.FromArgb(50,HighlightColor))
Dim line = Me.GetLineFromCharIndex(Me.SelectionStart)
Dim loc = Me.GetPositionFromCharIndex(Me.GetFirstCharIndexFromLine(line))
g.FillRectangle(b,New Rectangle(loc,New Size(Me.Width,LineHeight)))
TextRenderer.DrawText(g,Me.Text,Font,New Point(-2,1),ForeColor) ' this is the important line!
End Using
不过,这是100%的hack,我当然希望有人比我更懂事。我写的位置(-2、1)应该可以解决问题,但是如果不行,您可以通过将Color.FromArgb(50,HighlightColor)
替换为Color.FromArgb(255,HighlightColor)
来摆脱透明度来掩饰自己的耻辱。 不会很明显,因为文本只会在有人选择(尝试!)时才会显示出这种肮脏的把戏。
玩得开心!