27 julio 2006

Efectos de animación en las ventanas

En este artículo explicaré de forma detallada cómo crear animaciones para las ventanas de delphi con los mismos efectos que disponen los sistemas operativos Windows, y aclararé cuándo aplicarlos y los problemas que tienen.

La función encargada de animar ventanas es la siguiente (api de windows):

AnimateWindow

Y los parámetros que la definen son los siguientes:

hWnd - Manejador o Handle de la ventana, a la cuál se aplica el efecto.
dwTime - Velocidad para reproducir el efecto. A más tiempo, más suave y con más lentitud es el efecto.
dwFlags - Parámetros que definen el tipo de efecto, la orientación y la activación de la ventana.
Se pueden combinar varios parámetros para conseguir efectos personalizados.

Dentro del parámetro dwFlags, se pueden realizar los efectos de animación que detallo:

Tipos de efectos

AW_SLIDE

Esta es una animación de deslizamiento. Este parámetro es ignorado si se utiliza la bandera AW_CENTER. De forma predeterminada, y si no se indica este parámetro, todas las ventanas utilizan el efecto de persiana, o enrollamiento.

AW_BLEND

Aplica un efecto de aparición gradual. Recuerde utilizar este parámetro si la ventana tiene prioridad sobre las demás. Este efecto sólo funciona con Windows 2000 y Windows XP.

AW_HIDE

Oculta la ventana, sin animación. Hay que combinar con otro parámetro para que la ocultación muestre animación. Por ejemplo con AW_SLIDE o AW_BLEND.

AW_CENTER

Este efecto provoca que la ventana aparezca desde el centro de la pantalla o escritorio. Para que funcione, debe ser combinado con el parámetro AW_HIDE para mostrar la ventana, o no utilizar AW_HIDE para ocultarla.

Orientación al mostrar u ocultar

AW_HOR_POSITIVE

Animar la ventana de izquierda a derecha. Este parámetro puede ser combinado con las animaciones de deslizamiento o persiana. Si utiliza AW_CENTER o AW_BLEND, no tendrá efecto.

AW_HOR_NEGATIVE

Animar la ventana de derecha a izquierda. Este parámetro puede ser combinado con las animaciones de deslizamiento o persiana. Si utiliza AW_CENTER o AW_BLEND, no tendrá efecto.

AW_VER_POSITIVE

Animar la ventana de arriba hacia abajo. Este parámetro puede ser combinado con las animaciones de deslizamiento o persiana. Si utiliza AW_CENTER o AW_BLEND, no tendrá efecto.

AW_VER_NEGATIVE

Animar la ventana de abajo hacia arriba. Este parámetro puede ser combinado con las animaciones de deslizamiento o persiana. Si utiliza AW_CENTER o AW_BLEND, no tendrá efecto.


Otros parámetros

AW_ACTIVATE

Este parámetro traspasa el foco de activación a la ventana antes de aplicar el efecto. Recomiendo utilizarlo, sobre todo cuando las ventanas contiene algún tema de Windows XP. No utilizar con la bandera AW_HIDE.


Utilizando la función en Delphi

¿En qué evento utilizar esta función?

Normalmente, y a nivel personal y por experiencias negativas, siempre la utilizo en el evento FormShow de la ventana a la cuál aplicar el efecto. Un ejemplo sería el siguiente:

procedure TFForm1.FormShow(Sender: TObject);
begin
AnimateWindow( Handle, 400, AW_ACTIVATE or AW_SLIDE or AW_VER_POSITIVE );
end;

(Este efecto va mostrando la ventana de arriba hacia abajo con deslizamiento).


Problemas con los temas de Windows XP y las ventanas de Delphi

Naturalmente, no todo es una maravilla, y entre los problemas que pueden surgir al crear estos efectos, están los siguientes:

- Temas visuales de Windows XP:

Cuando un efecto de animación es mostrado, a veces ciertos controles de la ventana, cómo los TEdit, ComboBox, etc, no terminan de actualizarse, quedando con el aspecto antiguo de Windows 98. Para solucionar este problema, hay que escribir la función "RedrawWindow" a continuación de AnimateWindow:

procedure TFForm1.FormShow(Sender: TObject);
begin
AnimateWindow( Handle, 400, AW_ACTIVATE or AW_SLIDE or AW_VER_POSITIVE );
RedrawWindow( Handle, nil, 0, RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN );
end;

- Ocultando ventanas entre ventanas de Delphi:

Por un problema desconocido de delphi (por lo menos desconozco si Delphi 2006 lo hace), ocultar una ventana con animación, teniendo otras ventanas de delphi (de tu aplicación) detrás, produce un efecto de redibujado fatal, que desmerece totalmente el efecto realizado. Esto no pasa si las ventanas que aparecen detrás no son de Delphi, o de tu propia aplicación. Por ese motivo, personalmente nunca utilizo este efecto de ocultación de ventanas.

Últimos consejos

Por último, permitidme daros un consejo. Estos efectos también son válidos en Windows 2000, pero los efectos pueden no ser tan fluidos como en Windows XP. Por ello, no estaría mal que estos efectos sean una opción de configuración de vuestra aplicación, es decir, permitir al usuario activarlos o desactivarlos.

También recomiendo no abusar de estos efectos, al final terminan siendo un poco molestos. Realizarlos en las ventanas principales es mejor que en todas las ventanas.

Espero que el artículo sea de utilidad, y dé un toque de elegancia a vuestras aplicaciones.

Pruebas realizadas en Delphi 7.

8 comentarios:

Anónimo dijo...

Es Bueno encontrar este tipo de codigos, mis felicitaciones. Bacan el efecto

nelson ordonez dijo...

saludos exelente tutorial, e aplicado los codigos y me a funcionado, queria saber como puedo alplicar el efecto blend a un splashscreen, cuando lo hago me sale en el borde izquierdo sup de la pantalla y quiero que salga en el centro

Administrador dijo...

Para hacer efecto de blending tienes que utilizar las propiedades AlphaBlend y AlphaBlendValue, aunque esto sólo está disponible en las últimas versiones de Delphi.

Respecto a centrarlo en la pantalla sólo tienes que utilizar la propiedad Position del formulario.

Saludos.

Alejandro dijo...

Buen tuto!!

Tengo una duda, y es como puedo animar un objecto sin que se pare la ejecucion del programa. Por ejemplo un boton que al pulsarlo se vaya moviendo de izquierda a derecha. Probe a hacerlo con un fuche for, pero eso me para el programa mientras se mueve.

Gracias y saludos.

Administrador dijo...

Eso puedes hacerlo poniendo en tu bucle cerrado el comando:

Application.ProcessMessages;

o bién metiendo toda esa rutina en un hilo de ejecución.

Saludos.

Joel Rosales dijo...

Hola, me agrada mucho tu Blog, quisiera que me ayudes con un problema:

En delphi, usando un Image, logro abrir un archivo PNG, ahora bien quisiera modificar en ese archivo algunos pixeles para cambiarles su propiedad de transparencia. Es decir hacer que una parte sea semitransparente no totalmente transparente. Pero lo quiero hacer con codigo. Una vez hecho eso, guardar el PNG modificado en un archivo.

Agradezco mucho tu ayuda de antemano.

Administrador dijo...

Pues eso que pides es bastante difícil porque el objeto TImage se comporta de dos modos: cuando cargamos un Bitmap (BMP) y cuando cargamos otro (JPG, GIF, PNG), etc.

Sólo cuando cargamos con Bitmap podemos modificar los pixels del mismo. Hace tiempo leí no se donde que se puede hacer un truco para convertir estos JPG, GIF o PNG a bitmap para poder manipularlos.

Había que hacer transferencias de memoria de un lugar a otro con memcopy o algo de eso.

De todas formas, tiene que haber algún componente o librería que permita hacerlo más fácil.

A lo mejor se puede hacer con la librería SDL de la que he hablado en la serie de artículos dedicados a los videojuegos.

Todo es cuestión de investigar.

Saludos.

kalxyfer dijo...

Uhmmm Tengo una pregunta, es posible animar la ventana depues de pulsar un boton o algo asi, o solo cuando se muestra????

Publicidad