9

我有一个小的 C# (.NET 4.0) 控制台应用程序,我希望用户能够通过在右键单击系统托盘图标时显示菜单来进行交互。我可以毫无问题地将图标添加到托盘,但我无法让菜单出现。我正在使用以下代码:

NotifyIcon trayIcon = new NotifyIcon();
trayIcon.Text = "TestApp";
trayIcon.Icon = new Icon(SystemIcons.Application, 40, 40);

ContextMenu trayMenu = new ContextMenu();

trayMenu.MenuItems.Add("Blah", item1_Click);
trayMenu.MenuItems.Add("Blah2", item1_Click);
trayMenu.MenuItems.Add("Blah3", item1_Click);

trayIcon.ContextMenu = trayMenu;
trayIcon.Visible = true;

...将图标放在托盘中。但是,右键单击该图标不会执行任何操作。我尝试了 的各种排列MenuItems.Add,但没有任何东西会使菜单出现。我确定我错过了一些简单的东西 - 有什么想法吗?

4

4 回答 4

20

创建图标后尝试添加:

Application.Run()

注意这个方法不会返回,所以调用后不能做任何事情。这意味着您必须在单独的线程中完成所有其他工作。

发生的情况是操作系统向您的应用程序发送一条消息,告诉它托盘图标已被右键单击,但托盘图标代码从未看到它(因为这些消息由 处理Application.Run),因此无法通过打开菜单来响应。

于 2012-10-10T10:47:20.530 回答
9

关于Application.Run(),这是将所有其他代码放在另一个线程中的替代方法,即在主线程以外的线程上创建NotifyIcon, menu,等。events

这应该包括Application.Run(),因为这允许标准应用程序消息循环在当前线程上工作。然后由于事件是在同一个线程上创建的,Application.Exit()可以用来关闭通知消息,但仍然允许主线程继续。这是控制台应用程序的一个小示例...

class Program 
{
    public static ContextMenu menu;
    public static MenuItem mnuExit;
    public static NotifyIcon notificationIcon;

    static void Main(string[] args)
    {
        Thread notifyThread = new Thread(
            delegate()
            {
                menu = new ContextMenu();
                mnuExit = new MenuItem("Exit");
                menu.MenuItems.Add(0, mnuExit);

                notificationIcon = new NotifyIcon()
                {
                    Icon = Properties.Resources.Services,
                    ContextMenu = menu,
                    Text = "Main"
                };
                mnuExit.Click += new EventHandler(mnuExit_Click);

                notificationIcon.Visible = true;
                Application.Run();
            }
        );

        notifyThread.Start();

        Console.ReadLine();          
    }

    static void mnuExit_Click(object sender, EventArgs e)
    {
        notificationIcon.Dispose();
        Application.Exit();
    }

}
于 2013-03-28T13:23:04.467 回答
1

这是解决方案:您必须使用Application.Run(),因为控制台模式下的 gui 事件不起作用。但是您可以使用此解决方案:

var task = System.Threading.Tasks.Task.Factory.StartNew(() => ShowTrayIcon());

void ShowTrayIcon()
{
    some code with tray icon ...
}

这将开始您在新线程中设置尝试图标...

于 2013-12-05T20:14:06.700 回答
0

您是否为托盘图标鼠标单击添加了事件处理程序?

trayIcon .MouseDown += new MouseEventHandler(trayIcon_MouseDown);

创建上下文菜单并在 trayIcon_MouseDown 函数中执行以下操作

private void trayIcon_MouseDown (object sender,MouseEventArgs e)
{
  //add you menu items to context menu
  contextMenu.Items.Add(item);
  contextMenu.IsOpen = true;  
}

试试这个。认为这会对您有所帮助。

于 2012-10-10T11:17:42.757 回答