MrSparkly
MrSparkly

Reputation: 639

C# WinForms RichTextBox middle mouse scrolling: prevent the arrow cursor

In C# WinForms, I have a custom RichTextBox where I handle middle-mouse scrolling by myself. When it's done, I want to show my own cursor. I switch to this cursor in the MouseDown event, when the middle button is pressed.

    void richText_MouseDown(object sender, MouseEventArgs e) {
        if (e.Button == MouseButtons.Middle) {
            Cursor.Current = MainForm.cursors["hand_NS"];
        }
    }

However, the text box then instantly switches to the Windows "arrow" cursor. This seems to be part of the RichTextBox autom. behavior, either in MouseDown or in MouseMove. I can override this by constantly showing my cursor in MouseMove, but it looks flickery, as the two cursors fight each other. Can I block this automatic switch to the "arrow" cursor somehow?

EDIT: Tried setting the Cursor property:

 void richText_MouseDown(object sender, MouseEventArgs e) {
        if (e.Button == MouseButtons.Middle) {
            richText.Cursor = MainForm.cursors["hand_NS"];
            //Cursor.Current = MainForm.cursors["hand_NS"];
        }
    }

Restoring the I-beam cursor:

void richText_MouseUp(object sender, MouseEventArgs e) {
    if (e.Button == MouseButtons.Middle) {
        richText.Cursor = Cursors.IBeam;
        //Cursor.Current = Cursors.IBeam;
    }

}

Upvotes: 2

Views: 404

Answers (1)

MrSparkly
MrSparkly

Reputation: 639

Finally got it to work decently (virtually no flicker) by throwing at it all the artillery I could find. What's done in MouseMove (below) is also done in MouseDown.

    public const uint LVM_SETHOTCURSOR = 4158;
    [DllImport("user32.dll")]
    public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);


    void richText_MouseMove(object sender, MouseEventArgs e) {
        if (e.Button == MouseButtons.Middle) {
                this.TopLevelControl.Cursor = Cursors.PanNorth;
                richText.Cursor = Cursors.PanNorth;
                SendMessage(richText.Handle, LVM_SETHOTCURSOR, IntPtr.Zero, Cursors.PanNorth.Handle);
                Cursor.Current = Cursors.PanNorth;
         }
    }

Overriding the SETCURSOR message in the RTB control:

    [DllImport("user32.dll")]
    public static extern int SetCursor(IntPtr cursor);
    private const int WM_SETCURSOR = 0x20;

    protected override void WndProc(ref System.Windows.Forms.Message m) {
        if (m.Msg == WM_SETCURSOR) {
            SetCursor(Cursors.PanNorth.Handle);
            m.Result = new IntPtr(1);
            return;
        }
        base.WndProc(ref m);
    }

Sources:

ListView Cursor changing & flickering

Mouse cursor flickers over selected text - how to prevent this?

Upvotes: 0

Related Questions