I'm trying to figure out why the System.Windows.Forms.ContextMenu
in my Windows Forms application is closing immediately after I open it by right-clicking its tray icon on the taskbar.
This doesn't occur immediately, but strangely starts happening on the second opening. (i.e. I can open/close the context menu once normally and from then on the issue crops up) After right-clicking, I can visually see the menu appear for a fraction of a second before it automatically closes.
Here is the C# code in Program.cs
. I was originally following one of Barnacules Nerdgasm's "#Codegasm" tutorials (YouTube, GitHub), which involved removing the forms aspect of the project, leaving this as the only source file.
using System;
using System.Windows.Forms;
using System.Threading;
using System.Net.NetworkInformation;
using System.Net;
using System.Drawing;
namespace PingGoogleDNS
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
PingGoogleDNS pinger = new PingGoogleDNS();
pinger.StartPinger();
}
class PingGoogleDNS
{
#region Global Thread and Icon Objects
NotifyIcon pingIcon;
Icon goodIcon = new Icon("good_connection.ico");
Icon weakIcon = new Icon("weak_connection.ico");
Icon noIcon = new Icon("no_connection.ico");
Thread pingWorker;
MenuItem roundTripTime;
#endregion
#region StartPinger
public void StartPinger()
{
pingIcon = new NotifyIcon();
pingIcon.Icon = noIcon /*disconnectedIcon*/;
pingIcon.Visible = true;
MenuItem quit = new MenuItem("Quit / Exit");
MenuItem name = new MenuItem("Pings Google DNS (8.8.8.8)");
roundTripTime = new MenuItem("Latest ping: N/A ms");
ContextMenu contextMenu = new ContextMenu();
contextMenu.MenuItems.Add(quit);
contextMenu.MenuItems.Add(name);
contextMenu.MenuItems.Add(roundTripTime);
pingIcon.ContextMenu = contextMenu;
quit.Click += Quit_Click;
pingWorker = new Thread(new ThreadStart(PingSenderThread));
pingWorker.Start();
Console.WriteLine("Start");
}
#endregion
#region Quit Button Handler
private void Quit_Click(object sender, EventArgs e)
{
pingIcon.Dispose();
pingWorker.Abort();
Environment.Exit(1);
}
#endregion
#region Ping Sender Thread
public void PingSenderThread()
{
Ping pingSender = new Ping();
IPAddress iPAddress;
IPAddress.TryParse("8.8.8.8", out iPAddress);
PingReply reply;
try
{
while (true)
{
try
{
reply = pingSender.Send(iPAddress, 2000 /* ms */);
if (reply.Status == IPStatus.Success)
{
if (reply.RoundtripTime < 500 /* ms */)
pingIcon.Icon = goodIcon /*connectedIcon*/;
else
pingIcon.Icon = weakIcon;
pingIcon.Text = "8.8.8.8 ping success! (" + reply.RoundtripTime + " ms)";
roundTripTime.Text = "Latest ping: " + reply.RoundtripTime + " ms";
Thread.Sleep(1000);
}
}
catch (PingException pe)
{
pingIcon.Icon = noIcon /*disconnectedIcon*/;
pingIcon.Text = "8.8.8.8 ping failure.";
roundTripTime.Text = "Latest ping: N/A ms";
}
}
}
catch (ThreadAbortException)
{
// No need to do anything, just catch the ThreadAbortException.
}
}
#endregion
}
}
}
I tried to debug this by dummy adding listeners to the ContextMenu
's Popup
and Collapse
events to see if it registered being closed:
// In StartPinger()
contextMenu.Popup += ContextMenu_Popup;
contextMenu.Collapse += ContextMenu_Collapse;
// ...
private void ContextMenu_Popup(object sender, EventArgs e)
{
Console.WriteLine("menu opened");
}
private void ContextMenu_Collapse(object sender, EventArgs e)
{
Console.WriteLine("menu closed");
}
But, I only see "menu opened"
being printed to the console when I right-click and no "menu closed"
are ever printed. This has confused me and I don't know what to try next. Has anyone else encountered this before?