FoxPress – Noviembre 2001

 

Un Formulario con “Efectos Especiales”

http://www.fpress.com/

 

Por Abel Sorzano                                                                                     formanimado.zip
 

Si en Word invocas la opción de ‘encontrar’ verás que la pantalla se te abre no de golpe sino con un efecto especial empezando, al menos en mi caso, desde el angulo inferior derecho.

 

¿Cómo hacer eso en Fox? No es fácil pero se puede hacer. El truco consiste en usar la función del API llamada DrawAnimatedRects.  La ayuda del API nos la define así:

 

 

BOOL WINAPI DrawAnimatedRects(
  HWND hwnd,            // handle to clipping window
  int idAni,            // type of animation
  CONST RECT *lprcFrom, // rectangle coordinates (minimized)
  CONST RECT *lprcTo    // rectangle coordinates (restored)
);
 
 

· hwnd
[in] Handlede la ventana a la que se llama.Si el parámetro es nulo se usará el area de trabajo del monitor.

· idAni
[in] Especifica el tipo de animación.Puedes Puedes ir jugando con diversos valores para ver los tipos de efectos que se producen (esto no lo dice la ayuda sino que lo digo yo)

 
· lprcFrom
[in]
establece el lugar donde empezará la animación.

· lprcTo
[in]
lprcTo  el valor donde terminará.

 

Return Values

Si todo va bien devolverá un valor diferente a cero.

Si la función falla se devolverá cero y la llamada a GetLastError.

 

 

 

La primera dificultad es cómo traducir a Fox esta función del API. La traducción sería:

 

DECLARE Integer DrawAnimatedRects IN User32.dll Integer, Integer, String @, String @

 

(recuerdo que las funciones del API son sensibles a mayúsculas/minúsculas)

 

El ejemplo más sencillo que he conseguido hacer con el uso de esta función es el siguiente que implica usar otras dos funciones del API:

 

DECLARE Integer DrawAnimatedRects IN User32.dll Integer, Integer, String @, String @

 

DECLARE Integer SetRect IN User32.dll String @, Integer, Integer, Integer, Integer

 

DECLARE Integer GetActiveWindow IN user32.dll

 

lc_FromRect = SPACE(16)

lc_ToRect = SPACE(16)

 

SetRect(@lc_FromRect, 10, 10, 10, 10)

SetRect(@lc_ToRect, 200, 200, 600, 400)

 

DrawAnimatedRects(GetActiveWindow(), 3, @lc_FromRect, @lc_ToRect)

 

Ejecútalo desde Fox con una ventana abierta o sin ninguna ventana abierta y verás el efecto óptico que se produce.

 

El código es curioso pero aparentemente poco útil. La principal dificultad estriba en que no tenemos un handle de ventana que queramos tratar y por eso realiza esos efectos.

 

Para continuar con el ejemplo nos construiremos un  formulario (formulario origen) y pondremos en un botón de comandos y escribiremos en el click del botón de comandos:

 

DO FORM nuevo.scx NOSHOW NAME toWindow

 

DECLARE Integer DrawAnimatedRects IN User32.dll Integer, Integer, String @, String @

DECLARE Integer SetRect IN User32.dll String @, Integer, Integer, Integer, Integer

 

Set Library to (Home()+"\FoxTools.Fll") Additive

 

LOCAL lc_FromRect, lc_ToRect, lnHwnd

 

lc_FromRect = SPACE(16)

lc_ToRect = SPACE(16)

lnHwnd = 0

 

SetRect(@lc_FromRect, 10, 10, 10, 10)

SetRect(@lc_ToRect, 200, 200, 600, 400)

 

 

* conseguimos el Hwnd (window handle)

lnHwnd = _WhToHwnd( _WFindTitl(toWindow.Caption) )

 

DrawAnimatedRects(lnHwnd, 3, @lc_FromRect, @lc_ToRect)

toWindow.visible = .t.

 

A continuación nos construiremos un formulario de destino que en mi caso he llamado Nuevo.

 

En el código anterior fíjate como llamamos al formulario con la instrucción:

 

DO FORM nuevo.scx NOSHOW NAME toWindow

 

La opción de NAME nos permite meter el objeto formulario destino en una variable y como le decimos que no lo muestre, tenemos que el formulario se ha lanzado pero no se ha mostrado.

 

Al tener el formulario en una variable, puedo conseguir su handle (el handle de cada ventana es único) pero para eso tengo que acudir a la Foxtools.

 

Mediante la instrucción:

 

lnHwnd = _WhToHwnd( _WFindTitl(toWindow.Caption) )

 

consigo el handle del formulario que hemos ejecutado (pero no mostrado). Fíjate como para conseguir el handle se usa el nombre del Caption. En lnHwnd ya tengo el Handle de la ventana sobre la que quiero efectuar el efecto optico en la apertura. Para realizar ese efecto óptico basta con primero ejecutar el DRAWAnimatedRects y después hacerla visible y Voila!

 

DrawAnimatedRects(lnHwnd, 3, @lc_FromRect, @lc_ToRect)

toWindow.visible = .t.

 

La función del API SetRect nos define la posición de la ventana. En nuestro ejemplo como le ponemos unos valores fijos verás que te la posiciona en el angulo superior izquierdo y el tamaño de la ventana que se abre no es igual al del formulario que habíamos diseñado.

 

Para calcular la posición y el tamaño tenemos que escribir otro poco más de código. Además como los valores hay que pasarselos en hexadecimal la cosa se complica un poco pero por el contrario nos liberamos de esta función del API.

 

La nueva forma de llamarla sería:

 

DO FORM nuevo.scx NOSHOW NAME toWindow

 

DECLARE Integer DrawAnimatedRects IN User32.dll Integer, Integer, String @, String @

 

Set Library to (Home()+"\FoxTools.Fll") Additive

 

LOCAL lc_FromRect, lc_ToRect, lnHwnd

 

lc_FromRect = SPACE(16)

lc_ToRect = SPACE(16)

lnHwnd = 0

 

nTop1 = thisform.Top + SYSMETRIC(4) + SYSMETRIC(9) + Thisform.Top

nLeft1= thisform.Left + SYSMETRIC(4) + Thisform.left

 

nTop2 = thisform.Top + SYSMETRIC(4) + SYSMETRIC(9) + Thisform.Top + Thisform.Height

nLeft2= thisform.Left + SYSMETRIC(4) + thisform.left + Thisform.width

 

lc_FromRect = lc_FromRect + THISFORM.DecToHex(nLeft1)

lc_FromRect = lc_FromRect + THISFORM.DecToHex(nTop1)

lc_FromRect = lc_FromRect + THISFORM.DecToHex(nLeft2)

lc_FromRect = lc_FromRect + THISFORM.DecToHex(nTop2)

 

lc_ToRect   = THISFORM.DecToHex(ABS(toWindow.left))

lc_ToRect   = lc_ToRect + THISFORM.DecToHex(ABS(toWindow.top))

lc_ToRect   = lc_ToRect + THISFORM.DecToHex(ABS(toWindow.left) + toWindow.width)

lc_ToRect   = lc_ToRect + THISFORM.DecToHex(ABS(toWindow.top) + toWindow.height)

 

* conseguimos el Hwnd (window handle)

lnHwnd = _WhToHwnd( _WFindTitl(toWindow.Caption) )

DrawAnimatedRects(lnHwnd, 3, @lc_FromRect, @lc_ToRect)

toWindow.visible = .t.

 

que además necesita una función para convertir a Hexadecimal del tipo:

 

LPARAMETERS lnNumber

 

LOCAL ln1, ln2, lcResult

lnNumber = ABS(lnNumber)

lcResult = ""

FOR ln1 = 3 TO 0 STEP -1

      ln2 = INT(lnNumber / 256 ^ ln1)

      lnNumber = lnNumber - ln2 * (256 ^ ln1)

      lcResult = CHR(ln2) + lcResult

ENDFOR

RETURN lcResult

 

Pero como lo mejor es un ejemplo. En los fuentes tenéis un ejemplo más acabado y ordenado que te permite ver lo que quizás tanto código seguido no permite vislumbrar.

 

En el ejemplo verás los dos formularios y como uno al llamar al otro realiza ese efecto. También al cerrar el formulario llamado se ve la misma operación pero a la inversa.

 

 

 

 

FoxPress – Noviembre de 2001

© 2001 FoxPress. All rights reserved