E_Blue
E_Blue

Reputation: 1151

Is there any way to disable mouse click on a RichTextBox?

I'm using a visible RitchTextBox to write an automatic log and I don't want that the user change the cursor position. I can't just disable the control because it loses its background color (when the log is full it's saved as RTF file).
I've already set ReadOnly = True and ShorcutsEnabled = False.

My code:

Protected Friend Sub PrintPort(ByVal NewText As String, Optional ByVal ForeColor As Color = Nothing, Optional ByVal NewLine As Boolean = True)
    If Me.InvokeRequired Then
        Dim Txt As New PrintSmsLogDelegate(AddressOf PrintPort)
        Me.BeginInvoke(Txt, NewText, ForeColor, NewLine)
    Else
        If ClearLogFl Then
            ClearLogFl = False
            Me.RTB1.Clear()
        End If

        If NewText.Length < 1 Then
            Return
        End If

        If ForeColor = Nothing Then
            ForeColor = Color.White
        End If

        If NewLine Then
            If Me.RTB1.TextLength > 1 Then
                NewText = vbCrLf + NewText
            End If
        End If

        Me.RTB1.SelectionColor = ForeColor 'Set color
        Me.RTB1.SelectedText = NewText 'Add text

        If Me.LogAutoScrollChk.Checked And NewText.Contains(vbLf) Then
            Me.RTB1.ScrollToCaret()
        End If
    End If
End Sub

Upvotes: 0

Views: 856

Answers (2)

Jimi
Jimi

Reputation: 32288

An example, using a Threaded Timer (System.Timers.Timer) to simulate a method called from a Thread other than the UI Thread.

The RichTexBox Control needs to refuse User interaction: neither the text or the caret position can be modified and the User cannot interfere with the scrolling procedure, activated or not.

  • We can set the RichTextBox as ReadOnly and remove the Scrollbars (neither of these are actually required, but it's a better option, IMO).

  • In the Enter event of the RicheTextBox, the Form.ActiveControl is set to null (Nothing), so the RichTextBox is not the ActiveControl anymore, thus it doesn't receive the Keyboard or Mouse Input.
    Note that with this setup, there's no chance to directly interact with the RTB, even if it's the only Control in the Form that can receive the Focus.

  • Since your PrintPort() method is apparently called from another Thread, you need to Invoke the UI Thread to append to the Control.
    BeginInvoke() can simplify the invocation procedure, using a Lambda as the Action delegate.
    There's no need to check InvokeRequired, BeginInvoke() can be safely called also from the same Thread where the invocation is performed (the UI Thread).

Private Shared rndColor As New Random()
Private threadedTimer As System.Timers.Timer = Nothing

Protected Overrides Sub OnLoad(e As EventArgs)
    MyBase.OnLoad(e)
    rtb1.ReadOnly = True
    rtb1.ScrollBars = RichTextBoxScrollBars.None
    AddHandler rtb1.Enter, Sub() ActiveControl = Nothing

    threadedTimer = New System.Timers.Timer() With {.Interval = 1000}
    AddHandler threadedTimer.Elapsed, AddressOf TimerElapsedHandler
    threadedTimer.Start()
End Sub

Private Sub TimerElapsedHandler(s As Object, e As EventArgs)
    BeginInvoke(New Action(
        Sub()
            If Not rtb1.IsHandleCreated Then Return
            Dim rndValue = rndColor.Next(2)
            rtb1.SelectionStart = rtb1.TextLength
            rtb1.SelectionColor = If(rndValue = 1, Color.Orange, Color.YellowGreen)
            rtb1.AppendText(If(rndValue = 1, "Some other Text", "Some new text") & VbLf)
            If LogAutoScrollChk.Checked Then rtb1.ScrollToCaret()
        End Sub)
    )
End Sub

Protected Overrides Sub OnFormClosing(e As FormClosingEventArgs)
    threadedTimer.Stop()
    RemoveHandler threadedTimer.Elapsed, AddressOf TimerElapsedHandler
    threadedTimer.Dispose()
    MyBase.OnFormClosing(e)
End Sub

ReadOnly RichTextBox BeginInvoke

Upvotes: 2

LarsTech
LarsTech

Reputation: 81675

You can make your own RichTextBox for this. I converted the c# answer in make richtextbox not respond to mouse events and added the handling of the Paging keys:

Public Class DisplayBox
  Inherits RichTextBox

  Private Const WM_SETFOCUS As Integer = &H7
  Private Const WM_ENABLE As Integer = &HA
  Private Const WM_SETCURSOR As Integer = &H20

  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    If Not (m.Msg = WM_SETFOCUS OrElse m.Msg = WM_ENABLE OrElse m.Msg = WM_SETCURSOR) Then
      MyBase.WndProc(m)
    End If
  End Sub

  Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
    If (e.KeyCode = Keys.PageDown Or e.KeyCode = Keys.PageUp) Then
      e.Handled = True
    End If
    MyBase.OnKeyDown(e)
  End Sub

End Class

Works when the ReadOnly = True and ScrollBars = None properties are set.

Upvotes: 1

Related Questions