Как отобразить контекстное меню при щелчке правой кнопкой мыши по пункту меню - PullRequest
10 голосов
/ 11 ноября 2008

Я портирую приложение MFC на .NET WinForms. В приложении MFC вы можете щелкнуть правой кнопкой мыши по меню или пункту контекстного меню, и мы покажем другое контекстное меню с элементами диагностики и конфигурации. Я пытаюсь перенести эту функцию на .NET, но у меня возникли проблемы.

Мне удалось зафиксировать щелчок правой кнопкой мыши, отключить щелчок основного меню и открыть контекстное меню в нужном месте, но исходное меню исчезает, как только теряет фокус.

В MFC мы показываем новое контекстное меню, вызывая TrackPopupMenuEx с флагом TPM_RECURSE .

ContextMenu и более новые ContextMenuStrip классы в .NET имеют только Show метод. Кто-нибудь знает, как это сделать в .NET?

EDIT

Я пытался использовать TrackPopupMenuEx через p / invoke, но это ограничивает вас использованием ContextMenu вместо ContextMenuStrip, который выглядит неуместным в нашем приложении. Это также все еще не работает правильно. Он не работает с новыми MenuStrip и ContextMenuStrip .

Я также попытался создать подкласс ToolStripMenuItem, чтобы посмотреть, смогу ли я добавить к нему контекстное меню. Это работает для MenuStrip , но ContextMenuStrip все еще позволяет событиям щелчка правой кнопкой мыши проходить как щелчки.

Ответы [ 3 ]

10 голосов
/ 12 ноября 2008

Редактировать, из-за комментария:

В:

protected override void OnClick(EventArgs e)
{
    if (SecondaryContextMenu == null || MouseButtons != MouseButtons.Right)
    {
        base.OnClick(e);
    }
}

эта часть

 MouseButtons != MouseButtons.Right

должен и действительно компилируется, поскольку это вызов Control.MouseButtons. Поскольку Form наследует класс Control, достаточно вызвать свойство MouseButtons напрямую.

Надеюсь, это поможет:

public partial class Form1 : Form
{
    class CustomToolStripMenuItem : ToolStripMenuItem
    {
        private ContextMenuStrip secondaryContextMenu;

        public ContextMenuStrip SecondaryContextMenu
        {
            get
            {
                return secondaryContextMenu;
            }
            set
            {
                secondaryContextMenu = value;
            }
        }

        public CustomToolStripMenuItem(string text)
            : base(text)
        { }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (secondaryContextMenu != null)
                {
                    secondaryContextMenu.Dispose();
                    secondaryContextMenu = null;
                }
            }

            base.Dispose(disposing);
        }

        protected override void OnClick(EventArgs e)
        {
            if (SecondaryContextMenu == null || MouseButtons != MouseButtons.Right)
            {
                base.OnClick(e);
            }
        }
    }

    class CustomContextMenuStrip : ContextMenuStrip
    {
        private bool secondaryContextMenuActive = false;
        private ContextMenuStrip lastShownSecondaryContextMenu = null;

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (lastShownSecondaryContextMenu != null)
                {
                    lastShownSecondaryContextMenu.Close();
                    lastShownSecondaryContextMenu = null;
                }
            }
            base.Dispose(disposing);
        }

        protected override void OnControlAdded(ControlEventArgs e)
        {
            e.Control.MouseClick += new MouseEventHandler(Control_MouseClick);
            base.OnControlAdded(e);
        }

        protected override void OnControlRemoved(ControlEventArgs e)
        {
            e.Control.MouseClick -= new MouseEventHandler(Control_MouseClick);
            base.OnControlRemoved(e);
        }

        private void Control_MouseClick(object sender, MouseEventArgs e)
        {
            ShowSecondaryContextMenu(e);
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            ShowSecondaryContextMenu(e);
            base.OnMouseClick(e);
        }

        private bool ShowSecondaryContextMenu(MouseEventArgs e)
        {
            CustomToolStripMenuItem ctsm = this.GetItemAt(e.Location) as CustomToolStripMenuItem;

            if (ctsm == null || ctsm.SecondaryContextMenu == null || e.Button != MouseButtons.Right)
            {
                return false;
            }

            lastShownSecondaryContextMenu = ctsm.SecondaryContextMenu;
            secondaryContextMenuActive = true;
            ctsm.SecondaryContextMenu.Closed += new ToolStripDropDownClosedEventHandler(SecondaryContextMenu_Closed);
            ctsm.SecondaryContextMenu.Show(Cursor.Position);
            return true;
        }

        void SecondaryContextMenu_Closed(object sender, ToolStripDropDownClosedEventArgs e)
        {
            ((ContextMenuStrip)sender).Closed -= new ToolStripDropDownClosedEventHandler(SecondaryContextMenu_Closed);
            lastShownSecondaryContextMenu = null;
            secondaryContextMenuActive = false;
            Focus();
        }

        protected override void OnClosing(ToolStripDropDownClosingEventArgs e)
        {
            if (secondaryContextMenuActive)
            {
                e.Cancel = true;
            }

            base.OnClosing(e);
        }
    }

    public Form1()
    {
        InitializeComponent();


        CustomToolStripMenuItem itemPrimary1 = new CustomToolStripMenuItem("item primary 1");
        itemPrimary1.SecondaryContextMenu = new ContextMenuStrip();
        itemPrimary1.SecondaryContextMenu.Items.AddRange(new ToolStripMenuItem[] { 
            new ToolStripMenuItem("item primary 1.1"),
            new ToolStripMenuItem("item primary 1.2"),
        });

        CustomToolStripMenuItem itemPrimary2 = new CustomToolStripMenuItem("item primary 2");
        itemPrimary2.DropDownItems.Add("item primary 2, sub 1");
        itemPrimary2.DropDownItems.Add("item primary 2, sub 2");
        itemPrimary2.SecondaryContextMenu = new ContextMenuStrip();
        itemPrimary2.SecondaryContextMenu.Items.AddRange(new ToolStripMenuItem[] { 
            new ToolStripMenuItem("item primary 2.1"),
            new ToolStripMenuItem("item primary 2.2"),
        });

        CustomContextMenuStrip primaryContextMenu = new CustomContextMenuStrip();
        primaryContextMenu.Items.AddRange(new ToolStripItem[]{
            itemPrimary1,
            itemPrimary2
        });

        this.ContextMenuStrip = primaryContextMenu;
    }
}
2 голосов
/ 11 ноября 2008

Вам, вероятно, придется п / вызвать метод.

[DllImport("user32.dll")]
static extern bool TrackPopupMenuEx(IntPtr hmenu, uint fuFlags, int x, int y,
IntPtr hwnd, IntPtr lptpm);

const int TPM_RECURSE = 0x0001; 
0 голосов
/ 29 декабря 2008

Здесь показано, как использовать несколько ContextMenus, а также разные с любой комбинацией щелчков мыши.

Подробнее здесь: http://code.msdn.microsoft.com/TheNotifyIconExample

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...