1. Introdução

Tenho visto nos fóruns muita gente perguntando como fazer para abrir Forms dentro de um Form principal em aplicações Windows Forms, para isso é necessário entender o que é MDI e suas utilidades.

MDI significa “Multiple Document Interface”, o conceito dessa interface é abrir várias janelas dentro de uma janela principal, ou seja, adicionar diversas “janelas filhas” dentro de uma “janela pai”, exemplos dessa interface são os conhecidos Microsoft Word, Excel, etc..

Uma interface diferente seria o SDI, que significa “Single Document Interface”, nesse caso cada Form aberto representa uma janela diferente na aplicação, um exemplo é o Internet Explorer.

Neste artigo, vamos criar um projeto em C# que engloba os principais conceitos da interface MDI, para quem prefere VB.NET não se preocupe, no final do artigo está disponível o sample também em VB.NET.

2. Crie a Interface

Crie um novo projeto do tipo Windows Forms e chame de ProjetoMDI, adicione 4 novos Forms com os seguintes nomes: FormPrincipal, FormFilho1, FormFilho2 e FormFilho3.

Para o FormPrincipal, vá até a janela de propriedades e defina a propriedade WindowState como Maximized para que a janela abra em tela cheia.

Crie um MenuStrip no FormPrincipal  e chame-o de mnuPrincipal e crie a seguinte estrutura de itens de menu (MenuItems):

Estrutura do menu principal

Figura 1: Estrutura do menu principal

3. Mão no Código!

Clique duas vezes no mnuAbrirFilho1 e adicione o seguinte código:

Listagem 1: Abrindo um form da forma comum

private void mnuAbrirFilho1_Click(object sender, EventArgs e)
{
    FormFilho1 form = new FormFilho1();
    form.Show();
}

Compile e execute a aplicação, clique no menu “Abrir Filho 1″ e repare que o FormFilho1 foi aberto em outra janela (interface SDI), veja que ao minimizar a janela aberta esta, fica na barra do menu iniciar.

Como fazer para abrir dentro da janela principal? Serão dois passos simples. Primeiro precisamos dizer que o FormPrincipal é um MdiContainer, ou seja, ele pode ter Forms filhos dentro dele, para isso configure a propriedade IsMdiContainer como true no FormPrincipal. Feito isso, precisamos fazer uma alteração no nosso código onde abrimos o FormFilho1 dizendo quem será o “pai” dele, ou seja, dentro de qual janela ele abrirá, fazemos isso pela propriedade MdiParentde FormFilho1:

Listagem 2: Abrindo um form dentro do form principal

private void mnuAbrirFilho1_Click(object sender, EventArgs e)
{
    FormFilho1 form = new FormFilho1();
    form.MdiParent = this;
    form.Show();
}

Se você não sabe o que significa esse “this”, nada mais é que a instância do Form no qual você está trabalhando, dessa forma, falamos que o “pai” de FormFilho1 é o Form atual “this” que é o FormPrincipal (No VB.NET o “this” é o mesmo que “Me”).

Agora adicione os códigos para abrir os outros Forms:

Listagem 3: Abrindo os demais forms no formato MDI

private void mnuAbrirFilho2_Click(object sender, EventArgs e)
{
    FormFilho2 form = new FormFilho2();
    form.MdiParent = this;
    form.Show();
}
 
private void mnuAbrirFilho3_Click(object sender, EventArgs e)
{
    FormFilho3 form = new FormFilho3();
    form.MdiParent = this;
    form.Show();
}

Compile e execute a aplicação, abra várias vezes cada Form e veja que todos eles abrem dentro do FormPrincipal, minimize e maximize as janelas filhas abertas e veja que diferente da interface SDI, as janelas não aparecem na barra do menu iniciar, mas sim dentro de apenas uma janela, o FormPrincipal.

4. Forms Abertos

Imagine agora que você tem uma aplicação grande com a interface MDI e tem vários Forms abertos, uns minimizados e outros não e deseja ter um local no menu onde mostre todas as janelas abertas dentro da aplicação e que facilite a navegação entre elas? Você deve estar pensando que é algo muito complicado, mas verá a seguir como é tão simples fazer isso.

Vá para a janela de propriedades de mnuPrincipal e altere a propriedade MdiWindowListItem para o nosso item de menu responsável por essa tarefa que no nosso caso é mnuFormsAbertos. Pronto! Compile e execute sua aplicação, abra os Forms e veja como “magicamente” os Forms abertos foram parar lá no menu “Forms Abertos”:

Menu Forms Abertos

Figura 2: Menu Forms Abertos

5. Layout dos Forms Filhos

E se agora você quiser organizar as janelas abertas em cascata, lado a lado horizontal ou vertical ou até arranjar os Forms que estão minimizados?

Para isso, clique duas vezes em cada item do menu mnuJanela e adicione os seguintes códigos:

Listagem 4: Definindo a forma de exibição das janelas

private void mnuCascata_Click(object sender, EventArgs e)
{
    this.LayoutMdi(MdiLayout.Cascade);
}
 
private void mnuHorizontal_Click(object sender, EventArgs e)
{
    this.LayoutMdi(MdiLayout.TileHorizontal);
}
 
private void mnuVertical_Click(object sender, EventArgs e)
{
    this.LayoutMdi(MdiLayout.TileVertical);
}
 
private void mnuIconesMinimizados_Click(object sender, EventArgs e)
{
    this.LayoutMdi(MdiLayout.ArrangeIcons);
}

Explicando o código acima, a função LayoutMdi é responsável por organizar o layout dos Forms filhos de FormPrincipal e aceita como parâmetro a Enum MdiLayout que contém 4 modos diferentes:

  • Cascade: os Forms são arranjados em cascata;
  • TileHorizontal: os Forms são arranjados lado a lado horizontalmente;
  • TileVertical: os Forms são arranjados lado a lado verticalmente;
  • ArranjeIcons: os Forms estão minimizados são arranjados abaixo e a esquerda do FormPrincipal.

Compile e execute a aplicação, abra os 3 forms filhos e após clique no menu cascata, lado a lado horizontal e lado a lado vertical e veja as mudanças:

Lado a lado horizontalmente

Figura 3: Lado a lado horizontalmente

Lado a lado verticalmente

Figura 4: Lado a lado verticalmente

Agora minimize os 3 forms filhos, clique e arraste as janelas minimizadas para algum local da janela principal e depois clique no menu “Ícones Minimizados”, veja o resultado:

Ícones minimizados

Figura 5: Ícones minimizados

6. Algo mais com MDI

Você ainda pode obter uma coleção de todos os forms filhos que estão dentro do FormPrincipal através da coleção this.MdiChildren, veja o código a seguir que altera a propriedade Text de todos os forms filhos de FormPrincipal para “Novo Texto” contido em um evento de um botão chamado btnMdiChildren:

Listagem 5: Alterando o texto de todos os forms abertos

private void btnMdiChildren_Click(object sender, EventArgs e)
{
    foreach (Form form in this.MdiChildren)
    {
        form.Text = "Novo Texto";
    }
}

Também podemos utilizar a propriedade this.ActiveMdiChild para obter a instância do Form ativo na aplicação. O código a seguir escreve “Novo Texto 2″ apenas no Form ativo, evento criado para o botão btnActiveMdiChild:

Listagem 6: Alterando o texto do form ativo

private void btnActiveMdiChild_Click(object sender, EventArgs e)
{
    this.ActiveMdiChild.Text = "Novo Texto 2";
}

Sabendo então que podemos pegar a instância de qualquer Form aberto no FormPrincipal, temos um leque de operações para serem feitas entre as janelas, eu ensino como fazer comunicação entre Forms de 3 formas diferentes neste post.

Por hoje isso é tudo, o código fonte encontra-se disponível para download no topo desta página.

Espero ter ajudado à todos, abraços e até logo!