According to this answer on another question, the Collapsed
event of a ContextMenu is only raised if it's associated to a control before calling Show()
.
SInce a NotifyIcon
does not count as a control, I can't hook onto the Collapsed
event to detect when the menu associated to one is hidden.
Are there any workarounds?
Under the "Remarks" section for the MSDN docs on TrackPopupMenuEx , it says:
To display a context menu for a notification icon, the current window must be the foreground window before the application calls TrackPopupMenu or TrackPopupMenuEx. Otherwise, the menu will not disappear when the user clicks outside of the menu or the window that created the menu (if it is visible). If the current window is a child window, you must set the (top-level) parent window as the foreground window.
So that could mean that when the ContextMenu
is visible, the window on the NotifyIcon
will be the foreground window. You can see from by looking at NotifyIcon.ShowContextMenu()
that it is indeed the case:
private void ShowContextMenu()
{
if (this.contextMenu != null || this.contextMenuStrip != null)
{
NativeMethods.POINT pOINT = new NativeMethods.POINT();
UnsafeNativeMethods.GetCursorPos(pOINT);
UnsafeNativeMethods.SetForegroundWindow(new HandleRef(this.window, this.window.Handle));
if (this.contextMenu != null)
{
this.contextMenu.OnPopup(EventArgs.Empty);
SafeNativeMethods.TrackPopupMenuEx(new HandleRef(this.contextMenu, this.contextMenu.Handle), 72, pOINT.x, pOINT.y, new HandleRef(this.window, this.window.Handle), null);
UnsafeNativeMethods.PostMessage(new HandleRef(this.window, this.window.Handle), 0, IntPtr.Zero, IntPtr.Zero);
return;
}
if (this.contextMenuStrip != null)
{
this.contextMenuStrip.ShowInTaskbar(pOINT.x, pOINT.y);
}
}
}
Using ILSpy I then noticed NotifyIcon
has a private member window
, which refers to a private class with base type NativeWindow
. Therefore, you can check like this:
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetForegroundWindow();
...
FieldInfo notifyIconNativeWindowInfo = typeof(NotifyIcon).GetField("window", BindingFlags.NonPublic | BindingFlags.Instance);
NativeWindow notifyIconNativeWindow = (NativeWindow)notifyIconNativeWindowInfo.GetValue(notifyIcon1);
bool visible = notifyIcon1.Handle == GetForegroundWindow();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.