C# 检查与Notify图标关联时上下文菜单的可见性

C# 检查与Notify图标关联时上下文菜单的可见性,c#,winforms,event-handling,C#,Winforms,Event Handling,根据另一个问题,只有在调用Show()之前,上下文菜单的Collapsed事件与控件关联时,才会引发该事件 由于NotifyIcon不算作控件,因此我无法钩住Collapsed事件来检测与某个图标关联的菜单何时隐藏 有什么解决办法吗?在MSDN文档的“备注”部分,它说: 要显示通知图标的上下文菜单,请选择当前窗口 在应用程序调用之前,必须是前台窗口 TrackPopupMenu或TrackPopupMenuEx。否则,菜单将不会显示 当用户在菜单或显示的窗口外单击时消失 创建菜单(如果可见)。如

根据另一个问题,只有在调用
Show()
之前,上下文菜单的
Collapsed
事件与控件关联时,才会引发该事件

由于
NotifyIcon
不算作控件,因此我无法钩住
Collapsed
事件来检测与某个图标关联的菜单何时隐藏

有什么解决办法吗?

在MSDN文档的“备注”部分,它说:

要显示通知图标的上下文菜单,请选择当前窗口 在应用程序调用之前,必须是前台窗口 TrackPopupMenu或TrackPopupMenuEx。否则,菜单将不会显示 当用户在菜单或显示的窗口外单击时消失 创建菜单(如果可见)。如果当前窗口是子窗口 窗口,则必须将(顶级)父窗口设置为前景 窗户

因此,这可能意味着当
ContextMenu
可见时,
NotifyIcon
上的窗口将成为前台窗口。通过查看
NotifyIcon.ShowContextMenu()
可以看出,情况确实如此:

    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);
            }
        }
    }
然后使用ILSpy,我注意到
NotifyIcon
有一个私有成员
window
,它引用了一个基类型为
NativeWindow
的私有类。因此,您可以这样检查:

[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();

问题的可能重复之处在于询问如何检查上下文菜单的可见性,而不是如何显示它。