RichTextBox中的WM_SETREDRAW在.NET Framework 4.7.2中失败,但在4.6.2中可用

时间:2019-04-03 16:27:17

标签: vb.net winforms richtextbox

我有一个继承自RichTextBox的控件,其思想是,用户在每行中键入数字,并且控件根据行中的文本是否为有效数字为每行读取的颜色或绿色。

TextChanged上检查每行,并通过应用SelectionColor相应地调整每行的颜色。请在下面找到完整的代码。

为了保持一定的速度,我在发送颜色之前通过发送WM_SETREDRAW消息来暂停重新绘制控件,如本网站上各种问题/答案所述。 this one about RichTextBox in particular

我已经使用了很长时间没有问题,但是最近在针对.NET Framework 4.7.2而不是诸如4.5或4.6之类的较旧框架的项目中重用了控件。

在这里,一旦控件包含足以引起滚动的行,我就会遇到图形故障的问题。颜色未正确应用,出现幻影光标等。我试图在图片中显示出来:

enter image description here

我在第二张图片和第三张图片之间进行的唯一更改是将目标框架更改为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

0 个答案:

没有答案