Я подключил некоторый код к событиям MouseDown и Click ToolStripMenuItem для создания меню во время выполнения, но меню появляется в верхнем левом углу экрана, а не под пунктом меню. Не имеет значения, находится ли код в MouseDown или Click, меню всегда не в том месте. Что я делаю неправильно?
Вот пример кода:
private void windowToolStripMenuItem_MouseDown(object sender, MouseEventArgs e)
{
windowToolStripMenuItem.BuildOpenWindowsDropDown(Program.windowManager, (Form f) => (f.SomeProperty == SomeValue));
}
Метод расширения:
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;
});
}
}
}
И фрагмент из класса WindowManager:
public List<Form> FindOpenWindows(Predicate<Form> constraint)
{
var foundTs = from form in windows
where constraint(form)
&& form.Created
select form;
return foundTs.ToList();
}
Переместите код из события MouseDown
в событие DropDownOpening
; что должно дать вам правильное поведение.
Скорее всего, вы используете координаты, которые являются локальными для элемента управления (как они появятся в событиях мыши), но создавая ваше меню с помощью плавающего окна, которое ожидало бы экранных координат. Вы можете использовать функцию Control.PointToScreen()
для преобразования координат локально в элемент управления в глобальные координаты экрана. Просто вызовите PointToScreen()
в элементе управления, который поднимает события.