views:

2412

answers:

3

I have a multi-line text box on a Winforms app that I want to be able to click on in some states of the app without changing the Text selection.

I still want to subscribe to the MouseDown (or Click) event, I just don't want the text selection to react to it.

I was hoping for a Handled or Cancel property on the MouseEventArgs, but sadly, no.

I could listen to the selection changed event and try to reset it when required, but this feels a little hack-like as I would have to remember current selection before the selection change event. Does anyone have any better suggestions than that?

A: 

Layer a transparent panel over top of it.

Joel Coehoorn
I considered that too, but it felt equally as cludgy. May be simpler than rolling back a selection change event though
johnc
transparent as a BackColor doesn't seem to work, anyway. I could be missing something though
johnc
+1  A: 

How about handling the Enter event and setting the focus to a different control in this event? Still pretty "hack-like" though, just with less code.

marcc
It's ugly, but it seems to work, I just need to move my functionality to the enter event after I focus on a dummy empty label. I won't accept this as an answer quite yet though, unless I get no better suggestions, Thanks
johnc
Actually no, as I need the Mouse Event args. Dammit
johnc
I don't blame you for not accepting it yet. I'm watching this one to see if anyone has a better idea too :)
marcc
+5  A: 

You could create your own Textbox inheriting from System.Windows.Forms.Textbox and then override the WndProc.

The WndProc is the initial method which receives messages about everything from the operating system, power messages, input, etc. The name of the method is a throwback to the Win32 (and Win16) days where one of the two main functions you would implement was the "WndProc" or Windows Procedure.

By doing so, you can now intercept the windows messages for the mouse (or any other message) prior to the events being dispatched to the base implementation.

In the below example, we do not pass on any Left button down, up or double click to the base control to process.

public partial class MyTextBox : TextBox
{
    int WM_LBUTTONDOWN = 0x0201; //513
    int WM_LBUTTONUP = 0x0202; //514
    int WM_LBUTTONDBLCLK = 0x0203; //515

    public MyTextBox()
    {
        InitializeComponent();
    }

    protected override void WndProc(ref Message m)
    {

        if (m.Msg == WM_LBUTTONDOWN || 
           m.Msg == WM_LBUTTONUP || 
           m.Msg == WM_LBUTTONDBLCLK // && Your State To Check
           )
        {
            //Dont dispatch message
            return;
        }

        //Dispatch as usual
        base.WndProc(ref m);
    }
}

Only thing left to do is adding checking for your state to determine when to pass on the messages or not.

You can find a list of the Windows messages to process here.

Darien Ford
Very nice, thanks, I knew I'd have to drill below the .Net stack
johnc
Still doesn't get me the mouse event args, but I like this solution and can work around
johnc
You could add an additional event to your textbox in which you pass the mouse event args and use the same event handler in your form.That way you could circumvent the default mouse handling implementation.
Darien Ford