Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows requires a click to activate a window before a second click will select a button. How can I change this?

Tags:

.net

winforms

My application is a C# Windows Forms Application and .Net somehow makes the default behavior of my main menu bar and tool strip buttons to be that you have to first click on my app's window (anywhere), before it will let you click the menu or tool strip button. How can I change this?

Old apps like Notepad and WordPad don't behave this way. But all the Microsoft Office apps do. But this is so annoying!

It gets worse because my app pops up secondary windows and each time I change windows, I have to first activate the blasted window before I can do anything. Ugh!

I am hoping there is some global way to change this behavior, so I don't have to override lots of controls individually (I haven't tried that). Does anybody know?

Note that controls on my app's dialogs don't exhibit this stupid behavior. Why are they different?

like image 621
AZDean Avatar asked Aug 06 '10 20:08

AZDean


2 Answers

Well, I ended up finding my own solution that it pretty simple. I derive my own ToolStrip class (and MenuStrip class) as follows:

// This version of ToolStrip enables mouse click's even when the main form is NOT active.
private class MyToolStrip : ToolStrip
{
    const uint WM_LBUTTONDOWN = 0x201;
    const uint WM_LBUTTONUP   = 0x202;

    static private bool down = false;

    protected override void WndProc(ref Message m)
    {
        if (m.Msg==WM_LBUTTONUP && !down) {
            m.Msg=(int)WM_LBUTTONDOWN; base.WndProc(ref m);
            m.Msg=(int)WM_LBUTTONUP;
            }

        if (m.Msg==WM_LBUTTONDOWN) down=true;
        if (m.Msg==WM_LBUTTONUP)   down=false;

        base.WndProc(ref m);
    }
}

It appears that, just like the Mac OS X, Windows has made a GUI style decision that requires one to first activate a window BEFORE it will allow any controls to be selected. However, Windows only does this for specific controls, like ToolStrip and MenuStrip. When your window is NOT active, these controls are not sent the mouse DOWN event. I'm not sure how WinForms enforces this GUI guideline, but perhaps it uses a message filter using Application.AddMessageFilter().

Regardless, the MenuStrip controls STILL get the mouse UP event. And that inspired my solution. I simply look for any mouse UP event that is missing it's corresponding DOWN event. When I see this peculiar case, I generate my own mouse DOWN event, and for the ToolStrip controls, the world is all happy. :-)

like image 67
AZDean Avatar answered Sep 24 '22 07:09

AZDean


easy and clean solution

public class MyToolStrip : System.Windows.Forms.ToolStrip
{
    protected override void OnMouseEnter(EventArgs e)
    {
        if (this.CanFocus && !this.Focused)
            this.Focus();

        base.OnMouseEnter(e);
    }
}
like image 22
Rahmat Anjirabi Avatar answered Sep 24 '22 07:09

Rahmat Anjirabi