Uno de los grandes cambios de Windows XP a la versión de Windows Vista es el nuevo sistema gráfico que éste último incorpora, el cual ha sido denominado Aero. Se puede decir que Aero de divide en dos niveles, Aero Basic que ya incorpora una diferencia sustancial respecto a la interfaz gráfica de Windows XP y, Aero Glass (que no esta soportado por la versión “Home Basic”) proporciona una funcionalidad mayor como la aplicación de efectos de cristal a las ventanas o una gestión avanzada de las mismas, a parte de la experiencia visual que puede resultar más o menos gratificante dependiendo de los gustos particulares de cada uno.


Aero Glass hace que los bordes de nuestras ventanas hagan uso de transparencias para dar la sensación de cómo si estuviésemos viendo a través de un cristal, que tengamos vistas en miniatura de las aplicaciones que aparecen minimizadas en la barra de tareas o Windows Flip y Flip 3D. Esta funcionalidad queda expuesta a  través de DWM (Desktop Windows Management) que es quien se encarga de componer la apariencia que tiene el escritorio en cada momento.  Para poder ofrecer al usuario todo esto se hace uso directo de las aceleradoras gráficas, aquí es donde aparece el WDDM (Windows Display Diver Model), esta es la interfaz con la que DWM hace uso de los recursos de las tarjetas gráficas, así que si no disponemos de una gráfica más o menos reciente que soporte WDDM nos quedaremos sin "apreciar" todos estos efectos visuales. Se puede trabajar directamente con DWM pero es solo una posibilidad disponible para Vista, aun así, puesto que disponemos del Framework 3.0 en Windows XP y haciendo uso de WPF podemos simular este efecto de transparencia para los bordes de nuestras ventanas, aunque eso sí, no con la misma espectacularidad.


Vamos a trabar con Blend, así que creamos un nuevo proyecto de aplicación y listos para empezar con esto. Lo primero que tenemos que hacer es eliminar el típico marco de las aplicaciones de escritorio de XP. Para ello, en el objeto Window activamos la propiedad AllowsTransaprency, esto hará que automáticamente la propiedad WindowStyle cambie a None, a parte queremos darle a nuestra ventana el aspecto de borde redondeado con lo que tendremos que cambiar el valor de la propiedad Background a un color transparente así no aparecera un pico en las esquinas con el color de fondo de la ventana. El código quedaría en xaml del siguiente modo:


      AllowsTransparency="True"

      WindowStyle="None"

      Background="#00FFFFFF">


La ventana contiene un Grid en el que vamos a introducir un objeto de tipo Border que hará de marco de nuestra ventana y que pintaremos con un degradado. Para darle una apariencia más vistosa en realidad vamos a utilizar dos objetos border con un degradado diferente cada uno, de este modo el degradado no resultará tan "líneal", podemos usar los colores que más nos gusten y además tendremos que hacer uso de la componente alfa de los colores que formen parte del degradado para permitir ver lo que hay por detrás, es decir, darle transparencia al degradado. También modificaremos la propiedad CornerRadius para suavizar las esquinas:


  <Grid x:Name="LayoutRoot">

    <Border Margin="0,0,0,0" CornerRadius="5,5,5,5" ...>

      <Border.Background>

        <LinearGradientBrush>

           

        </LinearGradientBrush>

      </Border.Background>

    </Border>

    <Border Margin="0,0,0,0" CornerRadius="5,5,5,5" ...>

      <Border.Background>

        <LinearGradientBrush>

           

        </LinearGradientBrush>

      </Border.Background>

    </Border>

  </Grid>


El resultado es el siguiente:

 
 

 

Podemos observar como se ve lo que hay por detrás de lo que será nuestra ventana. El siguiente paso es definir el aérea cliente e incorporar un icono, el titulo de la ventana y los botones para poder minimizar, maximizar y cerrar. Se puede hacer de diferentes modos, pero lo haremos añadiendo un elemento de tipo DockPanel al que llamaremos rootDockPanel que a su vez contendrá un Grid (llamado areaClienteGrid) para definir el area de cliente de la ventana y otro DockPanel (llamado barraDockPanel) fijado en la parte superior (Top) del primero para hacer de contenedor del titulo de la ventana y los botones para minimizar, maximizar y cerrar. Un contenedor de tipo DockPanel coloca los elementos que contiene en la parte de arriba, abajo, izquierda o derecha. Los elementos se colocan según el orden que aparezcan en el código xaml pero también podemos definir de forma explícita la ubicación de los elementos. Este contenedor tiene una propiedad llamada LastChildFill mediante la que podemos determinar si el último elemento agregado a DockPanel ocupa todo el espacio que queda libre o no. Como dije antes, el contenerdor que alberga la barra de titulo lo fijaremos en la parte superior y al tener activada la propiedad LastChildFill el grid que representa el area de cliente ocupará el espacio restante disponible.

 

 

 

En la imagen superior está la jerarquía completa de todos los elementos que forman la ventana. El icono de la ventana y el titulo se encuentran dentro de un StackPanel (llamado tituloStackPanel) que esta alineado a la parte izquierda del elemento que lo contiene (barraDockPanel). El StackPanel es un contenedor que premite colocar los elementos que contiene uno seguido detrás de otro de forma tanto horizontal como vertical. Lo mismo haríamos con el StackPanel (llamado botonesStackPanel) que contiene los botones de minimizar, maximizar y cerrar. El resultado final es el siguiente:

 

 

 

Ahora solo nos queda añadir los eventos que nos permitan interactuar con la ventana. Para permitir que la ventana cambie de tamaño basta con establecer la propiedad ResizeMode a CanResizeWithGrip del objeto Window. Para añadir un evento basta con seleccionar el elemento al que queremos añadirle el evento y acceder a todos los eventos que tiene a través del panel de propiedades de Blend. Haciendo doble click en uno de los eventos automáticamente se lanza Visual Studio para añadir el código al evento. El código de todos los eventos es trivial, pero es interesante ver el código del evento que permite desplazar la ventana por el escritorio:


        private void borderTop_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)

        {

            object o = e.OriginalSource;

            if (o is Border)

                this.DragMove();

        }


WPF incorpora un nuevo modelo para la gestión de eventos que permite que la respuesta a un evento se propague a través de la jerarquía de controles. En el código de arriba lo que hacemos es controlar el origen del evento para ver si fue el borde quien produjo el evento MuseLeftButtonDown. Si no controlamos quien originó el evento y probamos a mover la ventana pinchando en el área blanca, el grid, como esta en la jerarquía de otro objeto que si controla ese mismo evento (el borde) la ventana se movería, pero ese no es el resultado que deseamos.


A parte de lo ya expuesto, hay otras propiedades con las que he jugado como margen, padding… para que los elementos tengan la apariencia y la ubicación que deseaba pero las más importantes han sido decritas. Adjunto el código para que le deis un vistazo a todo eso y juguéis con él, si os apetece.