SHsuperCM
SHsuperCM

Reputation: 110

ContextMenuStrip not showing on the first time of being right clicked

I've added a contextmenustrip programmatically through the extension of panel along with some other stuff, It is being set into the panel's contextmenu through the panel's constructor.

The first time I right click does not work and then it will after the first time always.

I have tried also to put the constructor of the contextmenustrip and the assigning of it to the panel's context menu in other places such as Load and the form's constructor and even in a timer with a flag, All produced the same result..

EDIT:(Some code as requested(as it is and cut to important points))

class FiniteAutomationController : System.Windows.Forms.Panel
{
    public FiniteAutomationController()
        : base()
    {
    this.ContextMenuStrip = (cms = new ContextMenuStrip());
    }
    public ContextMenuStrip cms;
}

EDIT:(Per blaze_125's request, some more code)

//at form designer initializecomponents after Controller(FiniteAutomationController)'s initialization

this.Controller.cms.Opening += new System.ComponentModel.CancelEventHandler(this.cms_Load);

//at form code class
    static State contextS = null;
    static Action contextA = null;
    private void cms_Load(object sender, CancelEventArgs e)
    {
        Controller.cms.Items.Clear();

        if ((contextS = FiniteAutomationData.GetStateFrom(mouseX, mouseY)) != null) // Rclick States
        {
            Controller.cms.Items.Add("Delete"); Controller.cms.Items[0].Click += new EventHandler(cms_DeleteState);
            Controller.cms.Items.Add("Rename"); Controller.cms.Items[1].Click += new EventHandler(cms_RenameState);
            Controller.cms.Items.Add((contextS.final ? '\u2714' : ' ') + " Final"); Controller.cms.Items[2].Click += new EventHandler(cms_Final);
            Controller.cms.Items.Add((contextS.initial ? '\u2714' : ' ') + " Initial"); Controller.cms.Items[3].Click += new EventHandler(cms_Initial);
            Controller.cms.Items.Add("Trap"); Controller.cms.Items[4].Click += new EventHandler(cms_Trap);
            if (!contextS.error.Equals(""))
            {
                Controller.cms.Items.Add("Error: " + contextS.error); 
                Controller.cms.Items[5].Enabled = false;
            }
        }
        else if((contextA = FiniteAutomationData.GetActionFrom(mouseX,mouseY)) != null) // Rclick Action
        {
            Controller.cms.Items.Add("Delete"); Controller.cms.Items[0].Click += new EventHandler(cms_DeleteAction);
        }
        else // Rclick null
        {
            Controller.cms.Items.Add("Add State"); Controller.cms.Items[0].Click += new EventHandler(cms_AddState);
        }
    }

Upvotes: 1

Views: 2601

Answers (4)

DreTaX
DreTaX

Reputation: 836

Add a MouseClick event to notifyicon. Handle the event as the following:

private void NotifyIconClicked(object sender, MouseEventArgs e)
{
    _dashboard.ShowHiddenWindow();
    if (e.Button == MouseButtons.Right)
    {
        MethodInfo ShowContextMenu = typeof(NotifyIcon).GetMethod("ShowContextMenu", BindingFlags.Instance | BindingFlags.NonPublic);
        if (ShowContextMenu != null)
        {
            ShowContextMenu.Invoke(_notifyIcon, null);
        }
    }
}

I believe the main window has to be made active for this, but I haven't tested this conditional for sure. This is something that i had to implement anyway.

    internal static void ShowHiddenWindow(this Window window)
    {
        try
        {
            if (!window.IsVisible)
            {
                window.Show();
            }

            if (!window.IsFocused)
            {
                window.Activate();
            }
            window.WindowState = WindowState.Normal;
        }
        catch
        {
            // Avoids "Cannot set visibility while window is closing".
        }
    }

Upvotes: 0

Leak
Leak

Reputation: 173

I found (well, with the help of DotPeek) that when using a blank ContextMenuStrip for a Control's ContextMenuStrip property so that you can add the items dynamically the code in System.Windows.Forms actually sets the Cancel property of the CancelEventArgs that are passed to the Opening handler to true because the context menu at first is empty and contains no items.

On subsequent calls, even if the first thing you do in the Opening handler is clear all items, the Cancel property will be set to false.

So my fix to make sure the context menu shows up at all times (including the first one) was to always set the CancelEventArgs' Cancel property to true or false and not (falsely) relying on it to be initialized to false anyway...

Upvotes: 4

Yargo
Yargo

Reputation: 58

For my case, I need to show the context menu by clicking on ToolStripButton. It is not shown for the first click. I managed this problem in this way

    void _TsiMenu_Click(object sender, EventArgs e)
    {
        AdjustableMenu.Show(this, this.PointToClient(Cursor.Position), ToolStripDropDownDirection.Default);
        Application.DoEvents();
        if (AdjustableMenu.Visible == false)
            AdjustableMenu.Show(this, this.PointToClient(Cursor.Position), ToolStripDropDownDirection.Default);
    }

Upvotes: 0

SHsuperCM
SHsuperCM

Reputation: 110

Throughout the last 3 days I've managed to find a solution which I think is a really bad one, but a solution still..

What I did is used the MouseDown Event of the Controller and using a flag, Showed the context menu on the first time using it's Show(Point) method.

The show method placed the menu a bit off and I settled on "new Point(e.X,e.Y+45)" to place it correctly which still I don't like that I'm doing as it seems really unprofessional..

Thanks anyways I guess..

Upvotes: 0

Related Questions