NotifyIcon 不响应其上下文菜单中的更改
NotifyIcon not responsing to changes in its ContextMenu
我的(仅限无格式系统托盘)程序有一个 NotifyIcon
,其 ContextMenu
值必须在程序的 运行 过程中动态更改。程序启动时实例化通知图标对象如下:
notifyIcon = new NotifyIcon()
{
Icon = new Icon(@"C:\Users\basil\documents\visual studio 2015\Projects\Project Repository\Project Repository\Program Icon.ico"),
Text = "My Program Name",
Visible = false // Don't make it visible yet!
};
notifyIcon.ContextMenu = new ContextMenu();
notifyIcon.ContextMenu.MenuItems.AddRange(new MenuItem[] { new MenuItem("Host Service") { Index = 0 }, new MenuItem("Backup Configurations", new EventHandler(delegate { bckConf.Show(); })) { Index = 1 }, new MenuItem("Network Info", new EventHandler(delegate { new form_NetworkInfo().Show(); })) { Index = 2 }, new MenuItem("About", new EventHandler(delegate { new form_AboutUs().Show(); })) { Index = 3 }, new MenuItem("Exit", new EventHandler(delegate { TerminateProgram(ProgramTerminateReason.UserRequest); })) { Index = 4 } });
为了更改 NotifyIcon
的 ContextMenu
,创建了一个名为 ChangeNotifyIconState
的 public 方法,因为需要根据生成的结果更改菜单项由程序中其他 classes 的对象声明如下:(请忽略 "CurrentServiceState" 数据类型的变量,并注意 NotifyIcon
对象被声明为 class变量)
static public void ChangeNotifyIconState(CurrentServiceState state)
{
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Clear(); // First clear all menu items of the to-be-updated block
if (state==CurrentServiceState.Running)
{ // Service has started running; disable the start button and activate the stop and restart buttons
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Start service", new EventHandler(delegate { HostServices.Start(); })) { Index = 0, Enabled = false });
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Stop service", new EventHandler(delegate { HostServices.Stop(); })) { Index = 0, Enabled = true });
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Restart service", new EventHandler(delegate { HostServices.Restart(); })) { Index = 0, Enabled = true });
} else if (state==CurrentServiceState.Stopped)
{ // Service has stopped running; disable the stop and restart button and activate the start button
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Start service", new EventHandler(delegate { HostServices.Start(); })) { Index = 0, Enabled = true });
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Stop service", new EventHandler(delegate { HostServices.Stop(); })) { Index = 0, Enabled = false });
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Restart service", new EventHandler(delegate { HostServices.Restart(); })) { Index = 0, Enabled = false })};
}
}
问题是:当我调用 ChangeNotifyIconState(CurrentServiceState.Running)
时,ContextMenu
所需的 MenuItems
不是 changed/updated。有人可以帮助我摆脱这种意外行为并向我解释其背后的原因吗?
提前致谢。
编辑:
我什至将 NotifyIcon
对象标记为可变对象,因为我推测这是因为编译器缓存。结果证明这不是因为制作对象 volatile
没有解决手头的问题。
下面是如何创建没有表单但带有 NotifyIcon
的应用程序的示例,以及如何更改 NotifyIcon
的 menuContextItems
例如点击事件:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApp5
{
static class Program
{
private static Random rd = new Random();
private static NotifyIcon notifyIcon;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
NotifyIcon ni = new NotifyIcon(new System.ComponentModel.Container());
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add(new MenuItem("First", Click));
cm.MenuItems.Add(new MenuItem("Second", Click));
cm.MenuItems.Add(new MenuItem("Third", Click));
cm.MenuItems.Add(new MenuItem("Exit", (obj,e)=> { Application.Exit(); }));
ni.Icon = new Icon(@"c:\Users\Admin\Desktop\img.ico");
ni.Text = "Form1 (NotifyIcon example)";
ni.ContextMenu = cm;
ni.Visible = true;
notifyIcon = ni;
Application.Run();
}
public static bool SomeCondition()
{
return (rd.Next(0, 9999) % 2) == 1;
}
public static void Click(object sender, EventArgs e)
{
if (SomeCondition())
{
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add(new MenuItem("Fourth", Click));
cm.MenuItems.Add(new MenuItem("Fifth", Click));
cm.MenuItems.Add(new MenuItem("Sixth", Click));
cm.MenuItems.Add(new MenuItem("Exit", (obj, args) => { Application.Exit(); }));
notifyIcon.ContextMenu = cm;
}
else
{
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add(new MenuItem("Third", Click));
cm.MenuItems.Add(new MenuItem("Sixth", Click));
cm.MenuItems.Add(new MenuItem("Fourth", Click));
cm.MenuItems.Add(new MenuItem("Exit", (obj, args) => { Application.Exit(); }));
notifyIcon.ContextMenu = cm;
}
}
}
}
下面是屏幕截图:
在应用程序启动时,将出现 notifyIcon,菜单如下所示:
因为我的条件是在 click
之后返回随机 true
或 false
任何 menuItem
除了 "Exit" 将工作 Click event handler
和改变menucontext
。结果,您将获得如下菜单之一:
或
我的(仅限无格式系统托盘)程序有一个 NotifyIcon
,其 ContextMenu
值必须在程序的 运行 过程中动态更改。程序启动时实例化通知图标对象如下:
notifyIcon = new NotifyIcon()
{
Icon = new Icon(@"C:\Users\basil\documents\visual studio 2015\Projects\Project Repository\Project Repository\Program Icon.ico"),
Text = "My Program Name",
Visible = false // Don't make it visible yet!
};
notifyIcon.ContextMenu = new ContextMenu();
notifyIcon.ContextMenu.MenuItems.AddRange(new MenuItem[] { new MenuItem("Host Service") { Index = 0 }, new MenuItem("Backup Configurations", new EventHandler(delegate { bckConf.Show(); })) { Index = 1 }, new MenuItem("Network Info", new EventHandler(delegate { new form_NetworkInfo().Show(); })) { Index = 2 }, new MenuItem("About", new EventHandler(delegate { new form_AboutUs().Show(); })) { Index = 3 }, new MenuItem("Exit", new EventHandler(delegate { TerminateProgram(ProgramTerminateReason.UserRequest); })) { Index = 4 } });
为了更改 NotifyIcon
的 ContextMenu
,创建了一个名为 ChangeNotifyIconState
的 public 方法,因为需要根据生成的结果更改菜单项由程序中其他 classes 的对象声明如下:(请忽略 "CurrentServiceState" 数据类型的变量,并注意 NotifyIcon
对象被声明为 class变量)
static public void ChangeNotifyIconState(CurrentServiceState state)
{
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Clear(); // First clear all menu items of the to-be-updated block
if (state==CurrentServiceState.Running)
{ // Service has started running; disable the start button and activate the stop and restart buttons
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Start service", new EventHandler(delegate { HostServices.Start(); })) { Index = 0, Enabled = false });
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Stop service", new EventHandler(delegate { HostServices.Stop(); })) { Index = 0, Enabled = true });
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Restart service", new EventHandler(delegate { HostServices.Restart(); })) { Index = 0, Enabled = true });
} else if (state==CurrentServiceState.Stopped)
{ // Service has stopped running; disable the stop and restart button and activate the start button
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Start service", new EventHandler(delegate { HostServices.Start(); })) { Index = 0, Enabled = true });
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Stop service", new EventHandler(delegate { HostServices.Stop(); })) { Index = 0, Enabled = false });
notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Restart service", new EventHandler(delegate { HostServices.Restart(); })) { Index = 0, Enabled = false })};
}
}
问题是:当我调用 ChangeNotifyIconState(CurrentServiceState.Running)
时,ContextMenu
所需的 MenuItems
不是 changed/updated。有人可以帮助我摆脱这种意外行为并向我解释其背后的原因吗?
提前致谢。
编辑:
我什至将 NotifyIcon
对象标记为可变对象,因为我推测这是因为编译器缓存。结果证明这不是因为制作对象 volatile
没有解决手头的问题。
下面是如何创建没有表单但带有 NotifyIcon
的应用程序的示例,以及如何更改 NotifyIcon
的 menuContextItems
例如点击事件:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApp5
{
static class Program
{
private static Random rd = new Random();
private static NotifyIcon notifyIcon;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
NotifyIcon ni = new NotifyIcon(new System.ComponentModel.Container());
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add(new MenuItem("First", Click));
cm.MenuItems.Add(new MenuItem("Second", Click));
cm.MenuItems.Add(new MenuItem("Third", Click));
cm.MenuItems.Add(new MenuItem("Exit", (obj,e)=> { Application.Exit(); }));
ni.Icon = new Icon(@"c:\Users\Admin\Desktop\img.ico");
ni.Text = "Form1 (NotifyIcon example)";
ni.ContextMenu = cm;
ni.Visible = true;
notifyIcon = ni;
Application.Run();
}
public static bool SomeCondition()
{
return (rd.Next(0, 9999) % 2) == 1;
}
public static void Click(object sender, EventArgs e)
{
if (SomeCondition())
{
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add(new MenuItem("Fourth", Click));
cm.MenuItems.Add(new MenuItem("Fifth", Click));
cm.MenuItems.Add(new MenuItem("Sixth", Click));
cm.MenuItems.Add(new MenuItem("Exit", (obj, args) => { Application.Exit(); }));
notifyIcon.ContextMenu = cm;
}
else
{
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add(new MenuItem("Third", Click));
cm.MenuItems.Add(new MenuItem("Sixth", Click));
cm.MenuItems.Add(new MenuItem("Fourth", Click));
cm.MenuItems.Add(new MenuItem("Exit", (obj, args) => { Application.Exit(); }));
notifyIcon.ContextMenu = cm;
}
}
}
}
下面是屏幕截图:
在应用程序启动时,将出现 notifyIcon,菜单如下所示:
因为我的条件是在 click
之后返回随机 true
或 false
任何 menuItem
除了 "Exit" 将工作 Click event handler
和改变menucontext
。结果,您将获得如下菜单之一:
或