Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RichTextBox cursor keeps changing to IBeam

I have a readonly RichTextBox, with its cursor set to Arrow. Even so, when I hover it, the cursor flickers, and switches very quickly between Arrow and IBeam. How can I make it stay on Arrow and not flicker?

like image 685
Michael Haddad Avatar asked Feb 07 '19 23:02

Michael Haddad


2 Answers

I'm assuming this is the WinForms' RichTextBox, because the WPF one doesn't have this problem.

The RichTextBox handles WM_SETCURSOR messages, to change the Cursor to Cursors.Hand if the Mouse Pointer ends up on a Link. A note from the developers:

RichTextBox uses the WM_SETCURSOR message over links to allow us to change the cursor to a hand. It does this through a synchronous notification message. So we have to pass the message to the DefWndProc first, and then, if we receive a notification message in the meantime (indicated by changing "LinkCursor", we set it to a hand. Otherwise, we call the WM_SETCURSOR implementation on Control to set it to the user's selection for the RichTextBox's cursor.

You could set the Capture when the Mouse enters the Control's bounds and then release it when the Mouse Pointer leaves the area. The capture needs to be released otherwise, when you first click on another control, the cursor will be set to RichTextBox instead:

private void richTextBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (!richTextBox1.ClientRectangle.Contains(e.Location)) {
        richTextBox1.Capture = false;
    }
    else if (!richTextBox1.Capture) {
        richTextBox1.Capture = true;
    }
}
like image 129
Jimi Avatar answered Nov 11 '22 00:11

Jimi


Jimi's answer works well to stop flickering, but I don't have a good feeling about capturing mouse on mouse move. For example one issue that I see in that solution, is if you set the capture on mouse move, then keyboard shortcuts like Alt+F4 or Alt+Space will stop working.

I'd prefer to handle WndProc and set the cursor when received WM_SETCURSOR:

using System.Windows.Forms;
public class ExRichTextBox : RichTextBox
{
    const int WM_SETCURSOR = 0x0020;
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_SETCURSOR)
            Cursor.Current = this.Cursor;
        else
            base.WndProc(ref m);
    }
}

It stops flickering. Not a perfect solution, but at least those important shortcuts will continue working.

like image 25
Reza Aghaei Avatar answered Nov 11 '22 01:11

Reza Aghaei