获取NotifyIcon的所有者表单?

时间:2015-11-26 13:22:49

标签: c# .net vb.net forms winforms

在C#或Vb.Net中,使用托管代码或非托管代码,我如何检索Form的所有者NotifyIcon

我已经检查了NotifyIcon类的基本类型以及ComponentConverter试图找出可能的类型转换以获取表单,但我无法做到。

我也看到了NotifyIcon.ContextMenuStrip.FindForm()函数,但出于任何原因,当我分配一个contextmenustrip时,FindForm()函数总是返回一个空引用异常,反正即使它可以工作也不会是安全的因为我可以在没有上下文菜单的情况下使用notifyicon。

我的目的是将NotifyIcon作为参数传递给某些方法,这些方法将执行常见任务以节省时间和减少代码。

伪示例:

Public Shared Sub MinimizeToSystray(ByVal ntfy As NotifyIcon)

    If (ntfy Is Nothing) Then
        Throw New ArgumentNullException(paramName:="ntfy")

    ElseIf (ntfy.Icon Is Nothing) Then
        Throw New ArgumentException(message:="The NotifyIcon doesn't have an icon.",
                                    paramName:="ntfy")

    Else
        Dim f As Form = ntfy.GetOwnerForm()
        f.WindowState = FormWindowState.Minimized
        f.Hide()

        ntfy.Visible = True

    End If

End Sub

2 个答案:

答案 0 :(得分:4)

FindForm()方法只能找到控件的表单。从Control派生的类型,通过其Parent属性嵌入到表单中。但是NotifyIcon不是一个控件,它是Component。 Component仅具有Site属性,其值仅在设计时定义。

组件和表单之间存在着偶然的关系,Winforms承诺自动处理具有带有IContainer参数的构造函数重载的任何组件。并非所有人都这样做,例如OpenFormDialog和BackgroundWorker,NotifyIcon。当他们不需要处置时,他们会省略构造函数。

这使得技术上可以找回该表单。您需要迭代Application.OpenForms()。并使用反射来迭代其私有components集合。请注意,这只能在窗体实际打开时才能工作,必须调用其Show()方法。

这是一个得分为-100分的解决方案,它既丑陋又容易出错。简单且始终正确的解决方案是只为方法添加一个额外的参数,以允许传递"所有者"形成。假设由于调用者需要知道NotifyIcon实例,因此它也应该知道表单。通常是Me

答案 1 :(得分:2)

组件没有类似控件的FindForm方法,如果您需要此类属性,则应自定义组件并应用变通方法。很遗憾,NotifyIconsealed,无法继承。

正如评论中Ivan Stoev所述,您可以使用Tag属性存储对容器表单的引用。

但是如果您正在寻找一种基于设计人员的解决方案,无需编写此类初始化代码即可设置Tag,作为一个不错的选择,您可以创建一个extender component来添加属性{{1在您的ParentForm组件中设置属性,然后您可以在运行时使用它,在设计时设置NotifyIcon属性时可以设置ParentForm组件代码中的属性,然后在运行时使用它。

以下是用法:

Tag(请参阅帖子末尾的代码)添加到项目中,然后构建项目。然后:

  1. ComponentExtender从工具箱添加到表单
  2. 使用属性网格
  3. 在设计师处设置ComponentExtender的{​​{1}}属性

    enter image description here

    使用此代码查找通知图标的父表单:

    ParentForm on componentExtender1

    <强>代码

    以下是我使用并正常运行的实现:

    notifyIcon1