Colabora .NET
 

Ventanas AutoHide (Auto-Ocultables)

Implementando ventanas auto-ocultables en C#

 

Fecha: 20/Dic/2007 (19-12-07)
Autor: Fabián Chialli - [email protected]

 


Introducción

Una característica que me parece muy interesante en las últimas versiones del Visual Studio son las Ventanas AutoHide(auto-ocultables).
Una de las ventajas que brinda es aprovechar al máximo el área de trabajo del usuario, permitiendo que éste trabaje con varias ventanas a la vez de una manera eficiente.
Teniendo esto en cuenta me decidí a desarrollar mi propio componente en C# que permita emular algunas características de esta herramienta tan potente.

 

Acerca del Componente

El nombre del Componente o Ensamblado es AutoHidePanels. Como mencioné está desarrollado en C# y Visual Studio 2005 con la versión 2.0 del Framework.

A continuación se listan brevemente las clases más importantes que lo componen:

AutoHideItemPanel: Clase a nivel de Ensamblado. Hereda de System.Windows.Forms.Panel y representa la Ventana AutoHide, o auto-ocultable.
AutoHideItem: Clase a nivel Público. Hereda de System.Windows.Forms.Control y es el control mediante el cual se interactúa de forma directa con la Ventana auto-ocultable.
AutoHideContainer: Clase a nivel Público. Hereda de System.Windows.Forms.Panel y representa una "barra dockeada" a un formulario. Contiene AutoHideItems.
AutoHideManager: Clase a nivel Público. Permite administrar los AutoHideContainer de un formulario.


El componente en ejecución

 

Funcionamiento Interno

A continuación vamos a describir y profundizar algunas características del funcionamiento del componente.

La clase AutoHideManager administra los AutoHideContainers dentro del formulario al que pertenece y realiza tareas como por ejemplo, solicitar que se oculte la ventana auto-ocultable activa cuando otra intenta mostrarse. Mantiene internamente una colección que hereda de System.Collections.CollectionBase donde se almacenan los AutoHideContainers ya mencionados.

La clase AutoHideContainer representa un panel que se ubica en el formulario según su propiedad Dock. Permitirá contener los AutoHideItem que apuntarán a una ventana auto-ocultable determinada.

La clase AutoHideItem mantiene una referencia interna a una ventana auto-ocultable. Mediante sus constructores, permite especificar algunas propiedades de la ventana, como por ejemplo, su título, su tamaño (ancho o alto dependiendo del DockStyle), si funciona con movimiento o no, que implica como ha de mostrarse u ocultarse, y una cuestión fundamental, el control que representará el contenido de la ventana, que generalmente será un Panel que tendrá en su interior otros controles.
De forma automática, el AutoHideItem crea un AutoHideItemPanel (la ventana auto-ocultable) asociado.

La clase AutoHideItemPanel, como se mencionó antes, representa la ventana auto-ocultable. En ejecución, ajusta su tamaño y posición automáticamente para dibujarse correctamente en el formulario que lo contiene.
Además, toma el control "hijo" a contener y setea su propiedad Dock a Fill para que su tamaño se ajuste automáticamente al redimensionarse.
Para que el manejo del encabezado de la ventana auto-ocultable sea más eficiente, sobre todo al aplicarse movimiento, se implementa una clase llamada Header que hereda de System.Windows.Forms.Panel que se encarga de dibujar el Título de la ventana y el botón de cerrar.

También, dentro del componente existe una clase llamada AutoHidePanelSplitter que hereda de System.Windows.Forms.Control y permite redimensionar la ventana auto-ocultable.

Cuando el cursor del mouse se posiciona sobre un AutoHideItem, la ventana auto-ocultable(AutoHideItemPanel) asociada aparece en pantalla. A partir de ese momento, a través de un Timer, se comienza a chequear si se ha perdido el foco o si el cursor ya no está dentro de su área. Si se da el caso, la ventana auto-ocultable se oculta.

Internamente el componente trabaja con eventos, que informan de hechos como por ejemplo, cierre o inicio del proceso de mostrar una ventana auto-ocultable.

Nota:
El componente no permite hacer flotantes las ventanas o "dockearlas", sólo implementa la característica de ocultamiento automático.

 

Un poco de código

A continuación se muestra una porción de código del componente.

Código de uno de los constructores de la clase AutoHideItem:

/// <summary>
/// Inicializa una nueva instancia de la clase AutoHideItem
/// </summary>
/// <param name=Caption">Titulo del AutoHideItem</param>"
/// <param name=Icon">Icono del AutoHideItem</param>"
/// <param name=frmParent">Formulario que será el contenedor del AutoHidePanel</param>"
/// <param name=ChildControl">Control que se agregará al AutoHidePanel</param>"
/// <param name=withAnimation">Indica si el AutoHidePanel se despliega con movimiento</param>"
/// <param name=PanelSize">Tamaño del Panel (Ancho o Alto dependiendo del DockStyle)</param>"
public AutoHideItem(String Caption, Icon Icon,
                   Form frmParent, Control ChildControl,
                   bool withAnimation, int PanelSize)
    : base()
{

      if (ChildControl == null)
      {
        throw new NullReferenceException();
      }

      if (frmParent == null)
      {
            throw new NullReferenceException();
      }

      if (Icon == null)
      {
            throw new NullReferenceException();
      }

      this.SetStyle(ControlStyles.ResizeRedraw, true);
      this.SetStyle(ControlStyles.UserPaint, true);
      this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
      this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

      this.BackColor = SystemColors.Control;

      _Caption = Caption;
      _Icon = Icon;
      _AnimationPanelContainer = withAnimation;
      _frmParent = frmParent;
      _PanelSize = PanelSize;

      //
      //Se crea el AutoHideItemPanel
      //
      _PanelContainer = new AutoHideItemPanel(Caption,
                                              ChildControl,
                                              this,
                                              withAnimation);

      _PanelContainer.Closing += new EventHandler(_PanelContainer_Closing);

      //
      //Se agrega el AutoHideItemPanel al formulario correspondiente
      //
      _frmParent.Controls.Add(_PanelContainer);

}

 

Ejemplo de Uso

Es muy sencillo utilizar el componente. A continuación se expone un fragmento del código de ejemplo que se puede descargar.

private void CreaAutoHidePanels()
{

      //
      //Creamos un Manager para que maneje los Contenedores
      //
      AutoHidePanelsManager = new AutoHideManager();

      AutoHidePanelsContainer1 = new AutoHideContainer();

      //
      //Configuramos cada contenedor
      //
      AutoHidePanelsContainer1.Dock = DockStyle.Left;
      AutoHidePanelsContainer1.BackColor = SystemColors.GradientInactiveCaption;
      AutoHidePanelsContainer1.AddItem(new AutoHideItem("Registros - Lista", 
                                       this.imageList1.Images[1], 
                                       this, CreaPanelRegistrosLista(), true, 400));

      //
      //Agregamos los contenedores a un manager
      //
      AutoHidePanelsManager.AddAutoHideContainer(AutoHidePanelsContainer1);

      this.Controls.AddRange(new Control[] { AutoHidePanelsContainer2, 
                                             AutoHidePanelsContainer1, 
                                             AutoHidePanelsContainer3, 
                                             AutoHidePanelsContainer4});

}

private Panel CreaPanelRegistrosLista()
{

      //
      //Creamos el control, generalmente un panel, que se agregará al AutoHideItemPanel
      //El Panel estará formado por un ListView, un label para describir el ejemplo
      //y dos RadioButtons para seleccionar el estilo del ListView
      //Este control sera el "hijo" del AutoHideItemPanel
      //AutoHideItemPanel automaticamente setea a Fill el DockStyle de control
      //

      Panel thePanel = new Panel();
      FlowLayoutPanel pnlEstilos = new FlowLayoutPanel();
      lvwRegistros = new ListView();
      Label lblInfo = new Label();
      RadioButton optEstilosDetalle = new RadioButton();
      RadioButton optEstilosLista = new RadioButton();
 
      thePanel.Controls.Add(lvwRegistros);
      thePanel.Controls.Add(pnlEstilos);
      thePanel.Controls.Add(lblInfo);

      thePanel.Location = new System.Drawing.Point(0, 24);
      thePanel.Name = "pnlContainer";
      thePanel.Padding = new System.Windows.Forms.Padding(2);
      thePanel.Size = new System.Drawing.Size(342, 425);

      optEstilosLista.Name = "optLista";
      optEstilosLista.Text = "Lista";
      optEstilosDetalle.Name = "optDetalle";
      optEstilosDetalle.Text = "Detalle";
      optEstilosDetalle.Checked = true;

      optEstilosDetalle.CheckedChanged += new EventHandler(optEstilosDetalle_CheckedChanged);
      optEstilosLista.Click += optEstilosDetalle_CheckedChanged;

      pnlEstilos.FlowDirection = FlowDirection.LeftToRight;
      pnlEstilos.Dock = DockStyle.Top;
      pnlEstilos.AutoSize = false;
      pnlEstilos.Height = 30;
      pnlEstilos.Controls.Add(optEstilosLista);
      pnlEstilos.Controls.Add(optEstilosDetalle);

      lblInfo.Dock = System.Windows.Forms.DockStyle.Top;
      lblInfo.AutoSize = false;
      lblInfo.Height = 50;
      lblInfo.TextAlign = ContentAlignment.MiddleCenter;
      lblInfo.Text = "El objetivo de este ejemplo es seleccionar un registro de la Lista, " +
                           "haciendo doble click sobre la fila correspondiente. " +
                           "Al hacerlo el AutoHideItemPanel se ocultará " +
                           "y en el formulario se cargarán los datos del registro.";
      lblInfo.BorderStyle = BorderStyle.FixedSingle;
      lblInfo.BackColor = Color.AliceBlue;

      lvwRegistros.Dock = System.Windows.Forms.DockStyle.Fill;
      lvwRegistros.Location = new System.Drawing.Point(2, 35);
      lvwRegistros.Size = new System.Drawing.Size(338, 388);
      lvwRegistros.AllowColumnReorder = false;
      lvwRegistros.MultiSelect = false;
      lvwRegistros.FullRowSelect = true;
      lvwRegistros.View = View.Details;
      lvwRegistros.Name = "Lista";

      lvwRegistros.MouseDoubleClick += new MouseEventHandler(lvwRegistros_MouseDoubleClick);

      return thePanel;

 }

 

Comentarios finales

Este componente permite simular, de manera sencilla, una característica, a mi entender, muy destacada del Visual Studio utilizando un poco de herencia, permitiendo desplegar la información en pantalla de manera más eficiente en esos casos donde la pantalla quizás "no alcanza".

Nota:
El archivo del link de descarga contiene dos soluciones, una con el código del componente y otra con el del proyecto de prueba.

Saludos desde Argentina!!!

Fabián Chialli


Espacios de nombres usados en el código de este artículo:

System.Windows.Forms
System.Drawing
System.Collections
System.Runtime.InteropServices

 


Código de ejemplo (comprimido):

 

Fichero con el código de ejemplo: Fabi_ventanas_autohide_csharp.zip - 55.1 KB

(MD5 checksum: 7C0D32F4F67D82F20DC39E437C01CF11)

 


Ir al índice principal de el Guille