C# 容器窗体中的控件是否超过子窗体?

C# 容器窗体中的控件是否超过子窗体?,c#,winforms,.net-3.5,mdi,mdichild,C#,Winforms,.net 3.5,Mdi,Mdichild,在容器表单中,我有菜单和按钮来打开其他表单。 在这里,我面临一个问题,当我打开任何形式,这些烟头和标签来新打开的形式。 请指导我如何处理此问题?我想打开一个新窗体,并将这些容器窗体的控件保留在它的后台。该窗体似乎是其他子控件的同级。你必须像孩子一样打开那扇窗户吗?它不能像一个非模态对话框,而不是主窗体的子窗口吗 如果它必须在主窗体和这些控件的同级中,那么您必须设置它的Z顺序。没有该属性,因此您必须查看Win32 API调用,SetWindowPos: [DllImport("user32.d

在容器表单中,我有菜单和按钮来打开其他表单。

在这里,我面临一个问题,当我打开任何形式,这些烟头和标签来新打开的形式。


请指导我如何处理此问题?我想打开一个新窗体,并将这些容器窗体的控件保留在它的后台。

该窗体似乎是其他子控件的同级。你必须像孩子一样打开那扇窗户吗?它不能像一个非模态对话框,而不是主窗体的子窗口吗

如果它必须在主窗体和这些控件的同级中,那么您必须设置它的Z顺序。没有该属性,因此您必须查看Win32 API调用,
SetWindowPos

[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern bool SetWindowPos(
int hWnd, // window handle
int hWndInsertAfter, // placement-order handle
int X, // horizontal position
int Y, // vertical position
int cx, // width
int cy, // height
uint uFlags); // window positioning flags


const uint SWP_NOSIZE = 0x1;
const uint SWP_NOMOVE = 0x2;
const uint SWP_SHOWWINDOW = 0x40;
const uint SWP_NOACTIVATE = 0x10;
我们可以这样称呼它:

SetWindowPos((int)form.Handle,   // that form
             (int)insertAfter.Handle,  // some other control
             0, 0, 0, 0,
             SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
显示每个子窗体后,对其调用BringToFront()。或者,将其挂接到每个子窗体的OnLoad方法:

childForm.OnLoad += (s, e) => (s as Form).BringToFront();

如果它是一个MDI应用程序,并且您将控件放在父窗口中,那么它们将显示在任何创建的子窗口的顶部。您还需要在子窗口中设置菜单,而不是在父窗体上

看看这个,然后

特别是:

父窗体可能不包含任何控件。>


编辑:添加了附加信息

我想我知道你做了什么。您正在使用MDI,并将菜单标签和按钮放在MDI父窗体上。您对MDI客户端窗口做了一些操作,它通常是深灰色的。也许你知道如何改变它的背景色或者改变Windows系统的颜色。是的,你的屏幕截图显示了结果。问题是MDI客户端窗体是MDI客户端窗口的父级。这使得它们显示在您放置在父窗体上的控件后面


没有解决方法,您必须更改您的UI。要保留MDI,请在父窗体上放置一个面板,并将其Dock属性设置为左侧。移动该菜单上的菜单控件。MDI客户端窗口现在将收缩,占据父窗体的其余部分。子窗体将自己约束到该区域。最痛苦的一点是,您必须重新组织菜单以适应面板中更小的可用空间。

@Hans Passant给出了正确的答案,但您也可以通过根本不使用MDI表单来解决问题。一些选择:

  • 使用单独的表单:拥有一个菜单表单,通常是大的/最大化的,并通过将其
    父属性设置为菜单表单来启动前面的子表单,或者
  • 使用单个表单,但使用停靠库(我以前使用过)。这本质上是MDI表单的重新实现,具有额外的功能。这需要做一些工作才能运行,但它可以让您构建一些漂亮的UI

不过,这两种情况都需要对UI代码进行重大更改。

我也遇到了同样的问题。我得到了如下所述的替代解决方案:

  • 插入计时器控件
  • 我已经在面板容器中添加了控件
  • 然后做了下面的事情

    private void timer1_Tick(object sender, EventArgs e)
    {
        if ((int)MdiChildren.GetLength(0) > 0)
        {
            panel1.Visible = false;
        }
        else
        {
            panel1.Visible = true;
        }
    }
    

  • 这里的主要技巧是将子窗体视为控件。您将像创建任何其他控件一样创建子窗体。当您使用此方法时,必须将其TopLevel设置为false,否则将无法工作

    以下代码行用于创建子窗体:

    Form childForm = new Form(); //initialize a child form
    
    childForm.TopLevel = false; //set it's TopLevel to false
    
    Controls.Add(childForm); //and add it to the parent Form
    childForm.Show(); //finally display it
    
    childForm.BringToFront(); //use this it there are Controls over your form.
    

    更多详细信息

    我遇到了这个问题,并通过以下方式解决了它:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
    
        Form2 F2;
        public Form1()
        {
            InitializeComponent();
            F2 = new Form2();
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
            Panel P1 = new Panel();
            P1.Location = new Point(0, 0);
            P1.Height = this.Height;
            P1.Width = this.Width;
            P1.BackColor = Color.Transparent;
            this.Controls.Add(P1);
    
            SetParent(F2.Handle, P1.Handle);
            F2.Owner = this;
    
            F2.Show();
        }
    }
    
    这很简单

  • 在mdi表单之后创建新表单(frm_chiled_mdi),并根据需要装饰它(如按钮、图片、标签等)

  • 在MDI表单加载中加载它

     MDI Form Load Coding..
    
     Dim frm As New frm_chiled_mdi        
     frm.MdiParent = Me
     frm.Show()
    
  • frm_chiled_mdi的表单加载编码

     Me.WindowState = FormWindowState.Maximized
     Me.BackgroundImageLayout = ImageLayout.Stretch
     Me.MaximizeBox = False
     Me.MinimizeBox = False
    
     Try
         Me.BackgroundImage = Image.FromFile(Application.StartupPath + "\\logo.jpg")
     Catch ex As Exception
     End Try
    

  • 你的意思是说一个窗体上的按钮被绘制在另一个活动窗体的顶部。。。这很奇怪…是的,我有一个带菜单的容器表单。它有按钮,只显示控制面板一样的按钮和链接。打开表单时,btton保持在顶部,打开的表单位于容器表单和按钮之间。任何帮助plzPlz请查看我的编辑(附加图像)以了解说明。父窗体是MDI容器吗?请不要发布重复的问题。你已经在这里问过这个问题:标记问题不在菜单上。他们工作得很好。问题在于按钮和标签。是的,它是一个MDIapplication@haansi您的父窗体中是否有控件?Mark是否没有办法满足我的要求?看看这个Stackoverflow问题:+1这篇文章很好地描述了为什么您不应该在MDI应用程序中的父窗体上放置任何控件:是的,我担心可能没有。问题是您的父表单是MDI表单-我不认为有任何正确的方法,正如Hans所解释的。先生,请给出您提到的第1点的示例。