[GIS] ToolStrip Button click event is not fired on first click

arcmaparcobjectsnet

I have a dockable window in a custom ArcMap extension. The dockable window has a regular windows forms ToolStrip control in it with ToolStripButtons on the ToolStrip. When the parent dockable window is not Active and I try to click a button on the toolstrip within the dockable window, I have to click it twice – once to set the focus and then again to fire the click event. I only want to click the button once even if the dockable window is not currently active.

Best Answer

I found a work around to this by using Rick Brewster's suggestions.

First, I modified Rick's class by adding a constructor public ToolStripEx() : base() { }

Then in my dockable window's designer class "MyClass.Designer.cs" I changed the toolstrip's declared type from System.Windows.Forms.ToolStrip to ToolStripEx.

Next, in the InitializeComponent() method of the same designer class, I changed the initialization type for the toolstrip the same way from this.MyToolStrip = new System.Windows.Forms.ToolStrip() to this.MyToolStrip = new ToolStripEx().

Finally, I set this.MyToolStrip.ClickThrough = true; in the default property assignment section in the same designer class.

Now the buttons on the toolstrip fire the onClick event every time - even when the dockable window is not active!

UPDATE:

Rick's original ToolStripEx class is below in case the link above ever breaks:

/// <summary>
/// This class adds on to the functionality provided in System.Windows.Forms.ToolStrip.
/// </summary>
public class ToolStripEx
: ToolStrip
{
private bool clickThrough = false;

/// <summary>
/// Gets or sets whether the ToolStripEx honors item clicks when its containing form does
/// not have input focus.
/// </summary>
/// <remarks>
/// Default value is false, which is the same behavior provided by the base ToolStrip class.
/// </remarks>
public bool ClickThrough
{
    get
    {
        return this.clickThrough;
    }

    set
    {
        this.clickThrough = value;
    }
}

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    if (this.clickThrough &&
        m.Msg == NativeConstants.WM_MOUSEACTIVATE &&
        m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT)
    {
        m.Result = (IntPtr)NativeConstants.MA_ACTIVATE;
    }
}
}

internal sealed class NativeConstants
{
private NativeConstants()
{
}

internal const uint WM_MOUSEACTIVATE = 0x21;
internal const uint MA_ACTIVATE = 1;
internal const uint MA_ACTIVATEANDEAT = 2;
internal const uint MA_NOACTIVATE = 3;
internal const uint MA_NOACTIVATEANDEAT = 4;
}