tags:

views:

44

answers:

2

I've plugged some code into the MouseDown and Click events of a ToolStripMenuItem to generate a menu at run-time, but the menu appears at the upper left corner of the screen instead of under the menu item. It doesn't matter if the code is in MouseDown or Click, the menu is always in the wrong place. What am I doing wrong?

Here's a code sample:

private void windowToolStripMenuItem_MouseDown(object sender, MouseEventArgs e)
{
    windowToolStripMenuItem.BuildOpenWindowsDropDown(Program.windowManager, (Form f) => (f.SomeProperty == SomeValue));
}

The extension method:

static class ExtensionMethods
{
    public static void BuildOpenWindowsDropDown(this ToolStripDropDownItem toModify, WindowManager windowManager, Predicate<Form> constraint)
    {
        toModify.DropDownItems.Clear();
        List<Form> windows = windowManager.FindOpenWindows(constraint);
        if (windows != null)
        {
            windows.ForEach((Form f) =>
            {
                ToolStripItem tsi = toModify.DropDownItems.Add(f.Text);
                tsi.Tag = f;
                EventHandler clickHandler = new EventHandler(
                    (object sender, EventArgs e) =>
                    {
                        Form fToShow = (Form)((ToolStripItem)sender).Tag;
                        fToShow.Show();
                    });
                tsi.Click += clickHandler;
            });
        }
    }
}

And the snippet from the WindowManager class:

    public List<Form> FindOpenWindows(Predicate<Form> constraint)
    {
        var foundTs = from form in windows
                          where constraint(form)
                                && form.Created
                          select form;

        return foundTs.ToList();
    }
A: 

You're likely using coordinates that are local to the control (as they would come in the mouse events) but creating your menu using a floating window, which would expect screen coordinates. You can use the Control.PointToScreen() function to translate coordinates local to a control into global screen coordinates. Just call PointToScreen() on the control that is raising the events.

Adam Robinson
Actually, instead of building the drop-down at design-time (I can't) I'm repeatedly calling the ToolStripMenuItem's DropDownItems property's Add method.
jasonh
+1  A: 

Move the code from the MouseDown event to the DropDownOpening event; that should give you the correct behavior.

Fredrik Mörk
That solved it! Thanks!
jasonh