【问题标题】:Checking the visibility of a ContextMenu when associated with a NotifyIcon在与 NotifyIcon 关联时检查 ContextMenu 的可见性
【发布时间】:2011-11-07 05:15:50
【问题描述】:

根据this answer 的另一个问题,只有在调用Show() 之前关联到控件时才会引发ContextMenu 的Collapsed 事件。

因为NotifyIcon 不算作控件,所以我无法挂钩Collapsed 事件来检测与之关联的菜单何时被隐藏。

有什么解决方法吗?

【问题讨论】:

标签: c# winforms event-handling


【解决方案1】:

TrackPopupMenuEx 上的 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();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-10
    • 2012-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-02
    • 1970-01-01
    相关资源
    最近更新 更多