Contextualizando

Um dos fatores de maior importância atualmente no desenvolvimento de software e que, por muitas vezes, são fundamentais para a decisão do cliente em escolher o um ou outro sistema, é a interface gráfica oferecida.

Um dos padrões mais comumente utilizados para o desenvolvimento de aplicações desktop de formulários é o MDI (Multilple Document Interface), onde várias telas são abertas dentro da tela principal. Apesar de funcional, observou-se que mesmo abrindo várias janelas, boa parte da tela principal ficava sem uso, como vemos na Figura 1.

Parte (em amarelo) da tela principal fica sem uso

Figura 1: Parte (em amarelo) da tela principal fica sem uso

Na Figura 1 a interface já é favorecida pelo uso do Ribbon, porém, antes da existência deste componente, tínhamos apenas um menu principal que não passava de uma barra no topo com algumas palavras.

Uma ideia que, apesar de não ser nova, ainda é um pouco complexa de ser posta em prática é a de abrir os forms secundários em abas na tela principal. Assim, toda região útil estaria em uso, dando à aplicação um visual um tanto quanto inovador.

A complexidade citada se deve a falta de componentes nativos em várias IDE’s que permitam inserir janelas em abas com facilidade. Com o advento do WPF (Windows Presentation Foundation) isso se torna mais fácil, porém, como ficam as aplicações Windows Forms?

Neste artigo, apresentarei uma solução que desenvolvi para obter o resultado citado (forms em abas) utilizando o componente XtraTabControl da biblioteca DXperience (DevExpress para .NET). Certamente este componente não foi desenvolvido visando esta situação, mas ele possui uma funcionalidade que, para este caso, é o diferencial e fator decisivo para sua escolha e aplicação: um botão para fechar as abas.

Neste exemplo estarei utilizando Ribbon e skins, porém estes itens aparecem como adicionais, não sendo fundamentais para a obtenção do resultado final visado.


Mãos à obra

Então, para iniciar, precisamos criar uma “Windows Forms Application” e adicionar ao form principal dois botões (o nome de cada um não terá influencia direta, logo, podemos manter o original) e um XtraTabControl, o qual chamei de “tbcPrincipal”. O primeiro botão será usado para abrir um segundo form já na estrutura de abas e o segundo abrirá o form como janela modal, para que se possa comparar os dois métodos.

Devemos então definir a propriedade “IsMdiContainer” do form como true e a propriedade “ClosePageButtonShowMode” do XtraTabControl como “InTabControlHeader”.

Sabendo que são muitas as janelas a serem abertas em uma aplicação real, optei por criar um método para gerenciar esse processo. Para abrir cada form, invocaremos este método, passando o form a ser aberto como parâmetro, juntamente com uma variável booleana que indica se desejamos abrir o form em uma aba ou usando a forma comum. Vejamos então a Listagem 1.

Listagem 1: Método AbrirForm

private void AbrirForm(Form frm, Boolean modal = false)
{
    foreach (XtraTabPage p in tbcPrincipal.TabPages)
    {
        if (p.Text.Equals(frm.Text))
        {
            tbcPrincipal.SelectedTabPage = p;
            return;
        }
    }
    if (modal)
    {
        frm.ShowDialog();
    }
    else
    {
 XtraTabPage t = new XtraTabPage();
        frm.MdiParent = this;
        frm.Dock = DockStyle.Fill;
        frm.FormBorderStyle = FormBorderStyle.None;
        frm.Show();
        t.Text = frm.Text;
        t.Controls.Add(frm);
        tbcPrincipal.TabPages.Add(t);
        tbcPrincipal.SelectedTabPage = t;
    }
}

No método acima, primeiramente “varremos” todas as abas já abertas para verificar se alguma delas já contém o form a ser aberto, comparando a propriedade Text da aba com a mesma propriedade do form. Caso localizemos alguma aba com o mesmo texto do form, a selecionamos e encerramos o método.

Caso o parâmetro “modal” seja verdadeiro, exibimos o form normalmente com o método ShowDialog. Caso contrário, instanciamos um objeto XtraTabPage e definimos algumas propriedades dos objetos, tornamos o form visível e selecionamos a aba que acabou de ser criada.

Resta agora programar o botão de fechar as guias, o que vem a ser ainda mais simples. No evento CloseButtonClick do XtraTabControl, basta que a guia selecionada seja destruída conforme mostra a Listagem 2.

Listagem 2: Evento Click do botão para fechar as guias

private void tbcPrincipal_CloseButtonClick_1(object sender, EventArgs e)
{
    tbcPrincipal.SelectedTabPage.Dispose();
}

O código em si não é complexo, o principal ponto aqui é saber como e quando usar cada propriedade e método.


Conclusões e testes

Para visualizar o método em ação, podemos tratar o evento Click dos botões para que cada um abra o form de uma maneira, como mostra as listagens 3 e 4 a seguir.

Listagem 3: Abrindo form na guia

private void simpleButton1_Click(object sender, EventArgs e)
{
    AbrirForm(new Form2());
}

Listagem 4: Abrindo form como janela modal

private void simpleButton2_Click(object sender, EventArgs e)
{
    AbrirForm(new Form2(), true);
}

O resultado do código da Listagem 3 deve ser semelhante ao que ilustra a Figura 2.

Form aberto no XtraTabControl

Figura 2: Form aberto no XtraTabControl

Já a execução do código da Listagem 4 deve ter resultado semelhante ao da Figura 1, com os forms secundários abertos sobre a janela principal.

Concluímos que não é difícil dar uma aparência diferenciada às nossas aplicações, alterando apenas a forma como as janelas secundárias são abertas. Vale notar ainda que os componentes da biblioteca DevExpress DXperience tornaram possível, além de facilitar o alcance do resultado desejado.

Finalizo então este artigo, o qual espero que possa ser útil no auxílio ao desenvolvimento de aplicações desktop para os desenvolvedores interessados.

Agradeço a atenção e até a próxima!