Click here to Skip to main content
15,896,377 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I've run into an issue when my application loses focus to another application and then when the user comes back to my application and their first action is to click on a toolstrip button then have to click it twice: once to activate the form and then second to execute the button's event.

If I go to another control first and that sets the focus (activates the form) then I can go to the toolstrip button and the button's click event fires.

I was wondering if anyone else has run into this issue? Known bug? Workaround? At this point it is annoying to the users.

This happens in XP (users) or in my dev. environment of Win7 x64. targetting .Net Framework 3.5 or 4.0.
Posted

Include this in your Form with ToolStrips... (;


C#
private bool handleFirstClickOnActivated = false;

/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Form.Activated" /> event.
/// Handle WinForms bug for first click during activation
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
protected override void OnActivated(EventArgs e)
{
    base.OnActivated(e);
    if (this.handleFirstClickOnActivated)
    {
        var cursorPosition = Cursor.Position;
        var clientPoint = this.PointToClient(cursorPosition);
        var child = this.GetChildAtPoint(clientPoint);
        while (this.handleFirstClickOnActivated && child != null)
        {
            var toolStrip = child as ToolStrip;
            if (toolStrip != null)
            {
                this.handleFirstClickOnActivated = false;
                clientPoint = toolStrip.PointToClient(cursorPosition);
                foreach (var item in toolStrip.Items)
                {
                    var toolStripItem = item as ToolStripItem;
                    if (toolStripItem != null && toolStripItem.Bounds.Contains(clientPoint))
                    {
                        var tsMenuItem = item as ToolStripMenuItem;
                        if (tsMenuItem != null)
                        {
                            tsMenuItem.ShowDropDown();
                        }
                        else
                        {
                            toolStripItem.PerformClick();
                        }
                        break;
                    }
                }
            }
            else
            {
                child = child.GetChildAtPoint(clientPoint);
            }
        }
        this.handleFirstClickOnActivated = false;
    }
}


/// <summary>
/// Handle WndProc
/// </summary>
/// <param name="m">The Windows <see cref="T:System.Windows.Forms.Message" /> to process.</param>
protected override void WndProc(ref Message m)
{
    const int WM_ACTIVATE = 0x0006;
    const int WA_CLICKACTIVE = 0x0002;
    if (m.Msg == WM_ACTIVATE && Low16(m.WParam) == WA_CLICKACTIVE)
    {
        handleFirstClickOnActivated = true;
    }
    base.WndProc(ref m);
}

private static int GetIntUnchecked(IntPtr value)
{
    return IntPtr.Size == 8 ? unchecked((int)value.ToInt64()) : value.ToInt32();
}

private static int Low16(IntPtr value)
{
    return unchecked((short)GetIntUnchecked(value));
}

private static int High16(IntPtr value)
{
    return unchecked((short)(((uint)GetIntUnchecked(value)) >> 16));
}
 
Share this answer
 
Comments
rj2Skipper 4-May-18 3:45am    
thanks for this solution #4
but there needs to be a slight improvement, for cases when you have multiple ToolStripContainer in a Form with a Splitcontainer
you need to modify the
else
{
child = child.GetChildAtPoint(clientPoint);
}
to
else
{
clientPoint = child.PointToClient(cursorPosition);
child = child.GetChildAtPoint(clientPoint);
}
It's standard behavior. You could handle the focus event in the parent form and pass the click onto the child control (in this case, the toolstrip button). It's kinda hacky, since you may also have to figure out what control is underneath the mouse when the click occurs.

One potential problem with this is if the user switches focus to the form using the keyboard, then it'd be kinda tricky to figure out if the form gained focus due to a click or if it got focus otherwise.
 
Share this answer
 
v2
That's because you need to get focus back (the 1st click) and then click the button (the 2nd click). All apps do this.

You could handle the focus event on the form, and reflect the mouse click event to the toolbar, or otherwise evaluate it's position in relation tot he toolbar and take the necessary actions manually.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900