C# 调用 NotifyIcon 的上下文菜单

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2208690/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:27:06  来源:igfitidea点击:

Invoke NotifyIcon's Context Menu

c#winformsnotifyicon

提问by BarrettJ

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:

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

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).

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

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?

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

采纳答案by Hans Passant

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

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

    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.

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

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:

在您自己的代码中调用此解决方法非常痛苦,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);
      }
    }

回答by Patrick Kafka

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

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

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

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

回答by scottm

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

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

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

回答by Arshad

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

使用以下代码在右击和左击通知图标上显示上下文菜单,如果您发现任何问题,请发送电子邮件至 [email protected](来自伊斯兰堡的 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)
    }