调用 NotifyIcon 的上下文菜单

发布于 2024-08-20 13:59:41 字数 399 浏览 4 评论 0原文

我希望左键单击 NotifyIcon 也会导致上下文菜单(使用 ContextMenuStrip 属性设置)打开。我将如何实现这一目标?我必须自己处理 Click 并找出定位吗?
编辑:使用托盘Icon.ContextMenuStrip.Show() 结果显示菜单是一些不良行为:

菜单不会显示在与右键单击 NotifyIcon 相同的位置(看来您无法将 x 和 y 坐标设置为任务栏在哪里,至少在我运行的 Windows 7 上是这样)。它将出现在任务栏上方(没什么大不了的,但一致性会很好)。

显示菜单时,任务栏中会添加一个额外的图标。

单击菜单以外的其他位置不会将其关闭(而如果右键单击以调出上下文菜单,则单击其他位置会自动关闭上下文菜单)。

是否可以仅调用菜单,但是内置的右键单击处理程序正在执行此操作?

I want to have it such that left clicking on the NotifyIcon also causes the context menu (set with the ContextMenuStrip property) to open as well. How would I achieve this? Do I have to handle Click and figure out the positioning myself?
Edit: showing the menu with trayIcon.ContextMenuStrip.Show() results is a few undesirable behaviors:

The menu is not shown at the same location as if right click the NotifyIcon (it appears that you can't set the x and y coords to where the taskbar is, at least on Windows 7 which is what I'm running). It will appear above the task bar (not that big of a deal, but consistency would be nice).

While the menu is shown, there is an extra icon added to the task bar.

Clicking somewhere other than the menu does not close it (whereas if you right click to bring up the context menu clicking else where automatically closes the context menu).

Is it at all possible to just invoke the menu however the built in right click handler is doing it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

莫多说 2024-08-27 13:59:41

您通常会处理 MouseClick 事件来检测单击并调用 ContextMenuStrip.Show() 方法:

    private void notifyIcon1_MouseClick(object sender, MouseEventArgs e) {
        contextMenuStrip1.Show(Control.MousePosition);
    }

但这实际上无法正常工作,当您在 CMS 外部单击时,CMS 不会关闭。根本问题是此知识库文章中描述的 Windows 怪癖(也称为“错误”)。

在您自己的代码中调用此解决方法非常痛苦,pinvoke 也令人不快。 NotifyIcon 类在其 中具有此解决方法ShowContextMenu() 方法,它们只是使访问变得困难,因为它是私有方法。反射可以绕过这个限制。我 5 年前就发现了这个 hack,至今还没有人报告过它的问题。设置 NFI 的 ContextMenuStrip 属性并实现 MouseUp 事件,如下所示:

using System.Reflection;
...
    private void notifyIcon1_MouseUp(object sender, MouseEventArgs e) {
      if (e.Button == MouseButtons.Left) {
        MethodInfo mi = typeof(NotifyIcon).GetMethod("ShowContextMenu", BindingFlags.Instance | BindingFlags.NonPublic);
        mi.Invoke(notifyIcon1, null);
      }
    }

You would normally handle the MouseClick event to detect the click and call the ContextMenuStrip.Show() method:

    private void notifyIcon1_MouseClick(object sender, MouseEventArgs e) {
        contextMenuStrip1.Show(Control.MousePosition);
    }

But that doesn't actually work properly, the CMS won't close when you click outside of it. Underlying issue is a Windows quirk (aka "bug") that is described in this KB article.

Invoking this workaround in your own code is pretty painful, the pinvoke is unpleasant. The NotifyIcon class has this workaround in its ShowContextMenu() method, they just made it difficult to get to since it is a private method. Reflection can bypass that restriction. I discovered this hack 5 years ago and nobody reported a problem with it yet. Set the NFI's ContextMenuStrip property and implement the MouseUp event like this:

using System.Reflection;
...
    private void notifyIcon1_MouseUp(object sender, MouseEventArgs e) {
      if (e.Button == MouseButtons.Left) {
        MethodInfo mi = typeof(NotifyIcon).GetMethod("ShowContextMenu", BindingFlags.Instance | BindingFlags.NonPublic);
        mi.Invoke(notifyIcon1, null);
      }
    }
习惯成性 2024-08-27 13:59:41

如果您处理 MouseUp 而不是 Click,您将能够知道单击了哪个按钮,以及 点击的位置。您可以使用此位置作为显示 ContextMenu 的位置

notifyIcon.MouseUp += new MouseEventHandler(delegate(object sender, MouseEventArgs e) { contextMenu.Show(e.Location); });

If you handle MouseUp rather than Click, you will be able to tell which button was clicked, as well as the location of the click. You can use this location as the location to show the ContextMenu

notifyIcon.MouseUp += new MouseEventHandler(delegate(object sender, MouseEventArgs e) { contextMenu.Show(e.Location); });
静谧 2024-08-27 13:59:41

您可以在 onClick 事件中连接通知图标,然后在单击时调用 show

private void wire()
{
     notifyIcon1.Click += new EventHandler(notifyIcon1_Click);
}

void notifyIcon1_Click(object sender, EventArgs e)
 {
    contextMenuStrip1.Show(Cursor.Position);
 }

You can wire in a onClick event for notify icon then call show in the on click

private void wire()
{
     notifyIcon1.Click += new EventHandler(notifyIcon1_Click);
}

void notifyIcon1_Click(object sender, EventArgs e)
 {
    contextMenuStrip1.Show(Cursor.Position);
 }
℡寂寞咖啡 2024-08-27 13:59:41

使用以下代码在通知图标上的右键和左键单击上显示上下文菜单,如果您发现任何问题,请给我发短信 [电子邮件受保护](来自伊斯兰堡的arshad)
//System.Runtime.InteropServices使用thi作为参考

    [DllImport("User32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
    public static extern bool SetForegroundWindow(HandleRef hWnd);

    private void notifyIcon1_Click(object sender, EventArgs e)
    {
        SetForegroundWindow(new HandleRef(this, this.Handle));
        int x = Control.MousePosition.X;
        int y = Control.MousePosition.Y;
         x = x - 10;
        y = y - 40;
        this.contextMenuStrip1.Show(x,y );
        //this.PointToClient(Cursor.Position)
    }

use the following code to show context menu on both right and left click on notifyicon, if you find any issue then text me at [email protected] (arshad from Islamabd)
//System.Runtime.InteropServices use thi as reference

    [DllImport("User32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
    public static extern bool SetForegroundWindow(HandleRef hWnd);

    private void notifyIcon1_Click(object sender, EventArgs e)
    {
        SetForegroundWindow(new HandleRef(this, this.Handle));
        int x = Control.MousePosition.X;
        int y = Control.MousePosition.Y;
         x = x - 10;
        y = y - 40;
        this.contextMenuStrip1.Show(x,y );
        //this.PointToClient(Cursor.Position)
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文