如何防止在父控件中处理菜单项上的单击?

本文关键字:菜单项 单击 处理 何防止 控件 | 更新日期: 2023-09-27 18:18:57

我有一个NotifyIcon和一个ContextMenu

myNotifyIcon = new NotifyIcon(new Container());
myNotifyIcon.Click += new EventHandler(myNotifyIcon_Click);
MenuItem entQuit = new MenuItem("Menu Item Text");
entQuit.Click += new EventHandler(entQuit_Click);
myNotifyIcon.ContextMenu = new ContextMenu();
myNotifyIcon.ContextMenu.MenuItems.Add(entQuit);

当我点击菜单中的MenuItem, myNotifyIcon.Click火灾,导致myNotifyIcon_Click()运行(这是我不想要的)。我怎样才能防止这种行为呢?

我已经看了这个问题的答案,但他们似乎并没有真正解决这个问题。需要明确的是,问题是当我在上下文菜单中左键单击项时,不是用右键单击打开菜单。<标题>编辑

我错了,这个问题的答案不工作。这个答案似乎确实有效,尽管我不知道为什么。

如何防止在父控件中处理菜单项上的单击?

如果可能的话,您应该考虑使用较新的ContextMenuStrip

但是,如果这是不可能的,那么解决方案是通过查看鼠标的位置来确定是否单击了菜单项。这个解决方案使用GetMenuItemRect来确定一个菜单项是否被点击。

例如:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class Form2 : Form {
    NotifyIcon myNotifyIcon = new NotifyIcon() { Icon = SystemIcons.Exclamation };
    MenuItem entQuit = new MenuItem("Menu Item Text");
    MenuItem entQuit2 = new MenuItem("Menu Item Text2");
    List<Rectangle> rectangles = new List<Rectangle>();
    public Form2() {
        //ContextMenuStrip cms;
        myNotifyIcon.Click += myNotifyIcon_Click;
        entQuit.Click += entQuit_Click;
        var cm = new ContextMenu();
        myNotifyIcon.ContextMenu = cm;
        myNotifyIcon.ContextMenu.MenuItems.Add(entQuit);
        myNotifyIcon.ContextMenu.MenuItems.Add(entQuit2);
        myNotifyIcon.Visible = true;
        myNotifyIcon.ContextMenu.Popup += delegate {
            this.BeginInvoke((Action) delegate {
                var h = myNotifyIcon.ContextMenu.Handle;
                rectangles = new List<Rectangle>();
                for (int i = 0; i < cm.MenuItems.Count; i++) {
                    RECT cr = new RECT();
                    GetMenuItemRect(IntPtr.Zero, h, (uint) i, ref cr);
                    rectangles.Add(new Rectangle(cr.Left, cr.Top, cr.Right - cr.Left, cr.Bottom - cr.Top));
                }
            });
        };
    }
    void entQuit_Click(object sender, EventArgs e) {
    }
    void myNotifyIcon_Click(object sender, EventArgs e) {
        bool OnMenuItem = false;
        var mp = Form.MousePosition;
        foreach (var r in rectangles) {
            if (r.Contains(mp)) {
                OnMenuItem = true;
                break;
            }
        }
        // reset rectangles to prevent icon click from scanning previous rectangles
        rectangles = new List<Rectangle>();
        if (OnMenuItem) { // detect if click was on a menu item
            return;
        }
    }
    [DllImport("user32.dll")]
    static extern bool GetMenuItemRect(IntPtr hWnd, IntPtr hMenu, uint uItem, ref RECT rect);
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }
}

最后看起来这个答案可能真的有帮助。我能够通过处理NotifyIcon.MouseClick而不是NotifyIcon.Click来解决问题,并检查MouseEventArgs.Button属性

最后,这似乎行得通:

myNotifyIcon = new NotifyIcon(new Container());
myNotifyIcon.MouseClick += new MouseEventHandler(myNotifyIcon_Click);
MenuItem entQuit = new MenuItem("Menu Item Text");
entQuit.Click += new EventHandler(entQuit_Click);
myNotifyIcon.ContextMenu = new ContextMenu();
myNotifyIcon.ContextMenu.MenuItems.Add(entQuit);

myNotifyIcon_Click看起来像这样:

void myNotifyIcon_Click(object source, MouseEventArgs e)
{
 if(e.Button == MouseButtons.Left) //For some reason this is necessary.
    { //Do stuff here }
}

我不能说我理解为什么这解决了问题,或者为什么我需要检查if(e.Button == MouseButtons.Left)当点击导致整个问题左键点击,但它确实工作。