Controls in container form come over child form?

ぃ、小莉子 提交于 2019-11-27 09:09:58
Anaya Upadhyay

I've also got the same problem. I got an alternative solution as described below:

  1. Insert a timer control
  2. I've added the controls in a panel container
  3. And did the following

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

I think I see what you did. You are using MDI and you put the menu labels and buttons on the MDI parent form. You did something with the MDI client window, it is normally dark-gray. Maybe you figured out how to change its BackColor or changed the Windows system color. Yes, your screen shot it the result. The problem is that MDI client forms are parented to the MDI client window. Which makes them show up behind the controls you put on the parent form.

There is no workaround for this, you are going to have to change your UI. To keep MDI, put a Panel on the parent form and set its Dock property to Left. Move the menu controls on that. The MDI client window will now shrink, occupying the remainder of the parent form. And the child forms will constrain themselves to that area. The wee painful bit is that you'll have to reorganize the menu to fit the much smaller space available in the panel.

Mark Hall

If it is a MDI application and you put controls in the parent window then they will be shown on top of any created child windows. You need to have your menu in a child window also, not on the parent form.

Look at this Article and this.

expecially this:

The parent Form may not contain any controls. >

Edit: Added Additional Information

@Hans Passant has the correct answer, but you could also solve your issue by not using MDI forms at all. Some options:

  • Use separate forms: have a menu form, typically large/maximized, and launch child forms in front of it by setting their Parent property to the menu form, or
  • Use a single form, but with a docking library (I've used DockPanel Suite in the past). This is essentially a re-implementation of MDI forms, with extra features. This is a bit of work to get running, but it can let you build some nice UIs.

Both of these would require significant changes to your UI code, though.

The main trick here is to treat child forms as Controls. You'll create a child form just like any other control. When you use this method, you have to set it's TopLevel to false - otherwise it won't work.

The following lines of code are used to create a child form:

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.

more details here

It appears as though that form is a sibling of those other child controls. Do you have to open it as a child of that window? Can't it be like a non-modal dialog box and not a child window of that main form?

If it has to be within that main form and a sibling of those controls, then you're going to have to set the Z-Order of it. There's no property for that, so you're going to have to look toward the Win32 API call, 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;

And call it something like this:

SetWindowPos((int)form.Handle,   // that form
             (int)insertAfter.Handle,  // some other control
             0, 0, 0, 0,
             SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);

Call BringToFront() on each child form after showing them. Alternately, hook it to each child form's OnLoad method:

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

I had this problem and solved it this way:

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();
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!