1

I have a control that inherits from RichTextBox and the idea is, that the user types in numbers per line and the control colors each line read or green depending on if the text in the line is a valid number.

On TextChanged each line is checked and by applying SelectionColor the color of each line is adjusted accordingly. Please find the full code below.

In order to keep that somewhat speedy I suspend redrawing of the control before updating the colors by sending the WM_SETREDRAW message, as is described in various questions/answers on this site, e.g. this one about RichTextBox in particular.

I have used this for quite a while without issue but recently reused the control in a project that targets .NET Framework 4.7.2 instead of older frameworks like 4.5 or 4.6.

Here I run into the problem of graphical glitches as soon as the control contains enough lines to cause scrolling. The colors are not applied correctly, ghost cursors appear and so on. I tried to show that in the picture:

enter image description here

The only thing I changed between the second and third picture was to change the target framework to 4.6.2 and recompile.

Does someone have an idea what causes this and how to work around the problem? Please feel free to use VB or C# to your taste, I don't judge :-)

Here is the code of the control I used to reproduce the behavior:

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
Jens
  • 6,275
  • 2
  • 25
  • 51
  • 1
    .Net 4.7+ are using RICHEDIT50W. Prior versions used RichEdit20W. That may be part of the issue. – TnTinMn Apr 03 '19 at 16:55
  • @TnTinMn that's good to know that there is at least a definite difference between the versions, thanks – Jens Apr 03 '19 at 17:02
  • Also, are you possibly overriding the form's CreateParms to set WS_EX_TRANSPARENT or some other non-standard effect? – TnTinMn Apr 03 '19 at 17:21
  • @TnTinMn No, the code above is basically all there is. The control is just dragged onto the basic form of the new project, nothing more – Jens Apr 03 '19 at 17:23
  • If all else fails, you can configure your application to use the RichEdit20W class. [Details here](https://stackoverflow.com/a/48391710/2592875) – TnTinMn Apr 03 '19 at 20:15
  • @TnTinMn Thank you, I'll look into that and also in more details into the differences. – Jens Apr 04 '19 at 09:02

0 Answers0