我有一个继承自RichTextBox的控件,其思想是,用户在每行中键入数字,并且控件根据行中的文本是否为有效数字为每行读取的颜色或绿色。
在TextChanged
上检查每行,并通过应用SelectionColor
相应地调整每行的颜色。请在下面找到完整的代码。
为了保持一定的速度,我在发送颜色之前通过发送WM_SETREDRAW消息来暂停重新绘制控件,如本网站上各种问题/答案所述。 this one about RichTextBox in particular。
我已经使用了很长时间没有问题,但是最近在针对.NET Framework 4.7.2而不是诸如4.5或4.6之类的较旧框架的项目中重用了控件。
在这里,一旦控件包含足以引起滚动的行,我就会遇到图形故障的问题。颜色未正确应用,出现幻影光标等。我试图在图片中显示出来:
我在第二张图片和第三张图片之间进行的唯一更改是将目标框架更改为4.6.2并重新编译。
有人知道导致此问题的原因以及如何解决该问题吗? 请随便使用VB或C#,我不认为:-)
这是我用来重现行为的控件的代码:
Public Class RichtextNumberlist
Inherits RichTextBox
Private Sub tbValues_TextChanged(sender As Object, e As EventArgs) Handles Me.TextChanged
SuspendDrawing(Me)
UpdateColor(Me)
ResumeDrawing(Me)
End Sub
<DllImport("user32.dll")>
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Boolean, ByVal lParam As IntPtr) As Integer
End Function
Private Const WM_SETREDRAW As Integer = 11
Public Sub SuspendDrawing(ByVal Target As Control)
SendMessage(Me.Handle, WM_SETREDRAW, False, 0)
End Sub
Public Sub ResumeDrawing(ByVal Target As Control)
SendMessage(Me.Handle, WM_SETREDRAW, True, 0)
Target.Invalidate()
End Sub
Private Function CheckLine(line As String) As Boolean
Dim d As Double
Return Double.TryParse(line, d)
End Function
Private Sub UpdateColor(tbValues As RichTextBox)
Dim t = Threading.Thread.CurrentThread
Console.WriteLine($"Updating color from thread STA={t.GetApartmentState().ToString()}, BG={t.IsBackground}")
'Save selection parameters to reset them afterwards
Dim oldsel As Integer = tbValues.SelectionStart
Dim oldsell As Integer = tbValues.SelectionLength
Dim pos As Integer = 0
Dim lCount = tbValues.Lines.Count
Dim lines = tbValues.Lines
For i = 0 To lCount - 1
'Set selection on the ith line
tbValues.SelectionStart = pos
tbValues.SelectionLength = lines(i).Length
Dim lineok = CheckLine(lines(i))
'Adjust the color accordingly
If lineok Then
tbValues.SelectionColor = Color.ForestGreen
Else
tbValues.SelectionColor = Color.Red
End If
'Move forward
pos += lines(i).Length + 1
Next
'Reset the selection
tbValues.SelectionStart = oldsel
tbValues.SelectionLength = oldsell
End Sub
End Class