C# 用户界面问题:让MDI子项显示在任务栏中的方法?

C# 用户界面问题:让MDI子项显示在任务栏中的方法?,c#,user-interface,C#,User Interface,我想听听您对以下问题的建议:我们正在为正在开发的Windows窗体应用程序研究不同的用户界面解决方案,我们得出的结论是,在我看来,最好的解决方案似乎是一个单一的文档界面,就像MS Word那样:也就是说,每次我们创建一个新文档时,它都会在一个新的“主”窗口中打开当所有“主”窗口关闭时,进程将被终止 然而,MS Excel处理MDI接口的方式也很有趣,而且由于我们的应用程序的工作方式,它可能是一个很好的解决方案。问题在于,由于一个主要原因,此解决方案似乎更加复杂:在任务栏中显示MDI子窗体 所以我

我想听听您对以下问题的建议:我们正在为正在开发的Windows窗体应用程序研究不同的用户界面解决方案,我们得出的结论是,在我看来,最好的解决方案似乎是一个单一的文档界面,就像MS Word那样:也就是说,每次我们创建一个新文档时,它都会在一个新的“主”窗口中打开当所有“主”窗口关闭时,进程将被终止

然而,MS Excel处理MDI接口的方式也很有趣,而且由于我们的应用程序的工作方式,它可能是一个很好的解决方案。问题在于,由于一个主要原因,此解决方案似乎更加复杂:在任务栏中显示MDI子窗体

所以我的问题是:有谁能给我一些建议,如何让MDI儿童出现在任务栏上。我几乎可以肯定,在.NET框架中绝对没有办法做到这一点。我一直在研究如何去寻找相关的WindowsAPI,但我似乎没有看到一个明显的方法来尝试和达到我们想要的

提前谢谢

编辑


我忘了提到应用程序目标主要是Win XP平台。

你是对的,没有办法直接从C#实现这一点,因为该功能不是在.Net Fx中实现的,而是在Windows API中实现的。幸运的是,微软提供了一个托管库来访问Windows7(以及一些WindowsVista)中的这些功能。请看下面的图片。您正在寻找的功能称为“选项卡式缩略图”

您是对的,无法直接从C#实现此功能,因为此功能不是在.Net Fx中实现的,而是在Windows API中实现的。幸运的是,微软提供了一个托管库来访问Windows7(以及一些WindowsVista)中的这些功能。请看下面的图片。您正在寻找的功能称为选项卡式缩略图,按设计,MDI表单的子项不会显示在任务栏中。最好坚持这个原则

在Windows 7上,可以将MDI子级的“缩略图”添加到任务栏,但此功能在.net中不直接可用。您可以查看MSDN以了解其他API

不过,有一个解决办法:选择表单时,可以将其与MDI父级分离。您必须确保在选择新的子窗体时重新附加该窗体。将以下代码添加到MDI容器窗体:

    private Form focusedChild;

    private void CreateWindow()
    {
        Form window = new Form();
        window.GotFocus += new EventHandler(Child_GotFocus);
        window.Show();
    }

    void Child_GotFocus(object sender, EventArgs e)
    {
        Form window = sender as Form;

        if (null != window)
        {
            if (focusedChild != null && window!=focusedChild)
            {
                focusedChild.SuspendLayout();
                focusedChild.MdiParent = null;
                focusedChild.WindowState = FormWindowState.Minimized;
                focusedChild.ResumeLayout();
            }


            window.SuspendLayout();
            window.MdiParent = this;
            window.WindowState = FormWindowState.Maximized;
            window.ResumeLayout();

            focusedChild = window;
        }
    }

不过,我不建议这样做。如果应用程序将在Windows 7上运行,请坚持默认行为,或者查看Windows 7缩略图。

根据设计,MDI表单的子项不会显示在任务栏中。最好坚持这个原则

在Windows 7上,可以将MDI子级的“缩略图”添加到任务栏,但此功能在.net中不直接可用。您可以查看MSDN以了解其他API

不过,有一个解决办法:选择表单时,可以将其与MDI父级分离。您必须确保在选择新的子窗体时重新附加该窗体。将以下代码添加到MDI容器窗体:

    private Form focusedChild;

    private void CreateWindow()
    {
        Form window = new Form();
        window.GotFocus += new EventHandler(Child_GotFocus);
        window.Show();
    }

    void Child_GotFocus(object sender, EventArgs e)
    {
        Form window = sender as Form;

        if (null != window)
        {
            if (focusedChild != null && window!=focusedChild)
            {
                focusedChild.SuspendLayout();
                focusedChild.MdiParent = null;
                focusedChild.WindowState = FormWindowState.Minimized;
                focusedChild.ResumeLayout();
            }


            window.SuspendLayout();
            window.MdiParent = this;
            window.WindowState = FormWindowState.Maximized;
            window.ResumeLayout();

            focusedChild = window;
        }
    }

不过,我不建议这样做。如果您的应用程序将在Windows 7上运行,请坚持默认行为,或者查看Windows 7的缩略图。

这有点像黑客攻击,但在XP中可以工作。在Windows7中,它看起来不太好,因此您需要实现选项卡式缩略图API

基本上,它会为每个MDI子控件创建一个不可见的代理项窗体,当代理项接收到焦点时(当您在任务栏中选择它时),它会将其传递到相应的子窗口

假设一个名为Form1的MDI容器,此代码将执行以下操作:

    private void Form1_Load(object sender, EventArgs e)
    {
        CreateWindow("child 1");
        CreateWindow("child 2");
    }

    private void CreateWindow(string name)
    {
        Form window = new Form();
        window.MdiParent = this;
        window.Text = name;
        window.Show();

        Form surrogate = new Form();
        surrogate.FormBorderStyle = FormBorderStyle.None;
        surrogate.Text = name;
        surrogate.Show(this);
        surrogate.Size = Size.Empty;
        surrogate.GotFocus += new EventHandler(surrogate_GotFocus);

        surrogate.Tag = window;
        window.Tag = surrogate;
    }

    void surrogate_GotFocus(object sender, EventArgs e)
    {
        Form surrogate = sender as Form;
        if (null != surrogate && null != surrogate.Tag)
        {
            Form target = surrogate.Tag as Form;
            target.Focus();
        }
    }

再说一次,我不认为偏离设计是一件好事。您最好遵守MDI限制,并在较新的操作系统安装上实现适当的API。如果你真的需要在任务栏中显示windows,那么你可以使用类似这样的黑客攻击。

这有点黑客攻击,但在XP中可以使用。在Windows7中,它看起来不太好,因此您需要实现选项卡式缩略图API

基本上,它会为每个MDI子控件创建一个不可见的代理项窗体,当代理项接收到焦点时(当您在任务栏中选择它时),它会将其传递到相应的子窗口

假设一个名为Form1的MDI容器,此代码将执行以下操作:

    private void Form1_Load(object sender, EventArgs e)
    {
        CreateWindow("child 1");
        CreateWindow("child 2");
    }

    private void CreateWindow(string name)
    {
        Form window = new Form();
        window.MdiParent = this;
        window.Text = name;
        window.Show();

        Form surrogate = new Form();
        surrogate.FormBorderStyle = FormBorderStyle.None;
        surrogate.Text = name;
        surrogate.Show(this);
        surrogate.Size = Size.Empty;
        surrogate.GotFocus += new EventHandler(surrogate_GotFocus);

        surrogate.Tag = window;
        window.Tag = surrogate;
    }

    void surrogate_GotFocus(object sender, EventArgs e)
    {
        Form surrogate = sender as Form;
        if (null != surrogate && null != surrogate.Tag)
        {
            Form target = surrogate.Tag as Form;
            target.Focus();
        }
    }

再说一次,我不认为偏离设计是一件好事。您最好遵守MDI限制,并在较新的操作系统安装上实现适当的API。如果您确实需要窗口显示在任务栏中,那么您可以使用类似这样的破解方法。

这取决于您希望支持的windows版本。Windows 7的任务栏为每个应用程序图标提供了多个缩略图来表示MDI文档。@BoltClock:我编辑了这个问题。我的应用程序不支持它,因为Windows不支持它。XP只支持顶级windows的任务栏按钮。@Hans Passant:windows支持它,因为MS Excel就是这样工作的。另一个问题是,我们使用的Windows API无法完成此操作。这取决于您希望支持的Windows版本。Windows 7的任务栏为每个应用程序图标提供了多个缩略图来表示MDI文档。@BoltClock:我编辑了这个问题。我的应用程序不支持它,因为Windows不支持它。XP只支持顶级windows的任务栏按钮。@Hans Passant:windows支持它,因为MS Excel就是这样工作的。另一个问题是,我们可以使用的Windows API无法完成。请参阅KilZone的答案-就在我前面,并带有指向Windows 7 API的正确链接。我对MDI界面的不满是,没有向用户指示打开了多少个窗口。MS Excel修复了在任务栏中漂亮地显示MDI子项的问题。