8 de mayo de 2007

Diversión con Vista Aero y la función DwmExtend Frame IntoClientArea

Usted puede tener un poco de diversión con Windows Vista Aero utilizando la función API DwmExtendFrameIntoClientArea.

Calvin Hsia nos comenta en su Blog que con la función API DwmExtendFrameIntoClientArea (solo para Vista) podemos hacer que los bordes de VFP se pinten con el efecto de cristal alrededor del borde del zorro.

Podemos intentar lo siguiente en nuestros formularios:
Public loForm
loForm = CreateObject("MyForm")
loForm.Show
Define Class MyForm  As Form
  ShowWindow = 2 && formulario de nivel superior
  Procedure Init
    Declare Integer DwmExtendFrameIntoClientArea  In dwmapi ;
      Integer HWnd, String  @ daMargins
    cStr = Replicate(BinToC(100,"4rs"),4)
    This.BackColor = 0
    This.ForeColor = -1
    DwmExtendFrameIntoClientArea (This.HWnd, @cStr)
  Endproc
Enddefine

El enlace al el artículo original de Calvin Hsia es: Fun with Vista Aero using the DwmExtendFrameIntoClientArea

4 de mayo de 2007

Funciones API para la barra de tareas

Existen algunas funciones API que nos permiten ajustar algunas configuraciones de la Barra de Tareas de Windows.

En este artículo veremos la manera de mostrar, ocultar, habilitar, deshabilitar y hacer porcentualmente transparente la barra de tareas.

También podremos controlar los objetos contenidos en la barra de tareas, como el área de notificación (SysTray) y sus elementos, como los íconos y el reloj.

Guarde el siguiente código como TaskBar.PRG:

Define Class TaskBar As Custom

  Procedure Init
    Declare Integer FindWindow In "user32" ;
      String lpClassName, String lpWindowName

    Declare Integer FindWindowEx In "user32" ;
      Integer HWnd, Integer hWnd2, ;
      String lpsz1, String lpsz2

    Declare Integer GetWindowLong In "user32" ;
      Integer HWnd, Integer nIndex

    Declare Integer SetWindowLong In "user32" ;
      Integer HWnd, Integer nIndex, Integer dwNewLong

    Declare Integer SetLayeredWindowAttributes In "user32" ;
      Integer HWnd, Integer crey, ;
      Integer bAlpha, Integer dwFlags

    Declare Integer ShowWindow In "user32" ;
      Integer HWnd, Integer nCmdShow

    Declare Integer EnableWindow In "user32" ;
      Integer  HWnd, Integer fEnable

  Endproc

  Proc BarraDeTareaVisible(tlVisible)
    Local lnHWndShell_TrayWnd
    lnHWndShell_TrayWnd = FindWindow("Shell_TrayWnd", 0)
    If lnHWndShell_TrayWnd <> 0
      ShowWindow(lnHWndShell_TrayWnd, Iif(tlVisible, 1, 0))
    Endif
  Endproc

  Proc BarraDeTareaHabilitada(tlEnabled)
    Local lnHWndShell_TrayWnd
    lnHWndShell_TrayWnd = FindWindow("Shell_TrayWnd", 0)
    If lnHWndShell_TrayWnd <> 0
      EnableWindow(lnHWndShell_TrayWnd, tlEnabled)
    Endif
  Endproc

  Procedure RelojVisible(tlVisible)
    Local lnHWndShell_TrayWnd, lnHWndTrayNotifyWnd, lnHWndTrayClockWClass
    lnHWndShell_TrayWnd = FindWindow("Shell_TrayWnd", 0)
    lnHWndTrayNotifyWnd = FindWindowEx(lnHWndShell_TrayWnd, 0, "TrayNotifyWnd", 0)
    lnHWndTrayClockWClass = FindWindowEx(lnHWndTrayNotifyWnd, 0, "TrayClockWClass", 0)
    If lnHWndTrayClockWClass <> 0
      ShowWindow(lnHWndTrayClockWClass, Iif(tlVisible,1,0))
    Endif
  Endproc

  Procedure SystrayVisible(tlVisible)
    Local lnHWndShell_TrayWnd, lnHWndTrayNotifyWnd
    lnHWndShell_TrayWnd = FindWindow("Shell_TrayWnd", 0)
    lnHWndTrayNotifyWnd = FindWindowEx(lnHWndShell_TrayWnd, 0, "TrayNotifyWnd", 0)
    If lnHWndTrayNotifyWnd <> 0
      ShowWindow(lnHWndTrayNotifyWnd, Iif(tlVisible,1,0))
    Endif
  Endproc

  Procedure IconosVisible(tlVisible)
    Local lnHWndShell_TrayWnd, lnHWndTrayNotifyWnd, lnHWndSyspager
    lnHWndShell_TrayWnd = FindWindow("Shell_TrayWnd", 0)
    lnHWndTrayNotifyWnd = FindWindowEx(lnHWndShell_TrayWnd, 0, "TrayNotifyWnd", 0)
    lnHWndSyspager = FindWindowEx(lnHWndTrayNotifyWnd, 0, "Syspager", 0)
    If lnHWndSyspager <> 0
      ShowWindow(lnHWndSyspager, Iif(tlVisible,1,0))
    Endif
  Endproc

  Procedure InicioRapidoVisible(tlVisible)
    Local lnHWndShell_TrayWnd, lnHWndReBarWindow32, lnHWndToolbarWindow32
    lnHWndShell_TrayWnd = FindWindow("Shell_TrayWnd", 0)
    lnHWndReBarWindow32 = FindWindowEx(lnHWndShell_TrayWnd, 0, "ReBarWindow32", 0)
    lnHWndToolbarWindow32 = FindWindowEx(lnHWndReBarWindow32, 0, "ToolbarWindow32", 0)
    If lnHWndToolbarWindow32 <> 0
      ShowWindow(lnHWndToolbarWindow32, Iif(tlVisible,1,0))
    Endif
  Endproc

  Procedure BarraDeTareaTransparente(tnLevel)
    Local lnLevel, lnOldStyle, lnWndShell_TrayWnd
    lnLevel = 0xFF - Max(0,Min(Int(tnLevel*255/100),255))
    lnHWndShell_TrayWnd = FindWindow("Shell_TrayWnd", 0)
    If lnHWndShell_TrayWnd <> 0
      lnOldStyle = GetWindowLong(lnHWndShell_TrayWnd, -20)
      SetWindowLong(lnHWndShell_TrayWnd, -20, Bitor(lnOldStyle, 0x80000))
      SetLayeredWindowAttributes(lnHWndShell_TrayWnd, 0, lnLevel, 0x2)
    Endif
  Endproc

Enddefine
A continuación la instancia de la clase y algunos ejemplos de sus métodos.
*-- Instanciamos la clase TaskBar en TaskBar.prg
loTB = NEWOBJECT("TaskBar", "TaskBar.prg")

*-- Barra de tarea no visible
loTB.BarraDeTareaVisible(.F.)

*-- Barra de tarea visible
loTB.BarraDeTareaVisible(.T.)

*-- Area de notificación no visible
loTB.SysTrayVisible(.F.)

*-- Area de notificación visible
loTB.SysTrayVisible(.T.)

*-- Barra de tarea 75% transparente
loTB.BarraDeTareaTransparente(75)

*-- Barra de tarea 25% transparente
loTB.BarraDeTareaTransparente(25)

*-- Barra de tarea 0% transparente
loTB.BarraDeTareaTransparente(0)

Hasta la próxima,

Luis María

3 de mayo de 2007

Arreglar los bordes de los formularios en Windows Vista (Aero)

Calvin Hsia en su Blog nos explica que cuando se ejecuta un formulario de VFP, éste solicita a Windows crear una ventana, entonces configura el estilo del borde (BorderStyle) de la ventana. Al parecer, en Windows Vista con Aero (excepto como administrador), el estilo del borde no puede ser configurado después que la ventana se ha creado.

Para reproducir el problema, Calvin nos indica los siguientes pasos:

  1. Iniciar Visual FoxPro (Calvin ejecutó VFP7 lanzado a mediados de 2001)
  2. Crear un nuevo formulario
  3. En la ventana de propiedades, cambiar la propiedad BorderStyle a 1 ó 2
    • 0 = ningún borde (ningún problema, porque no hay bordes para dibujar)
    • 1 = fijo simple
    • 2 = fijo doble
    • 3 = ajustable (por omisión) (ningún problema, porque es por omisión)
  4. Guardar y ejecutar el formulario
  5. Mover el formulario por la pantalla de modo que los bordes y la barra de título deban ser repintadas

Resultado: La ventana se comporta como si no tuviera bordes, y no puede repintarlo.

Calvin continua diciendo que es bastante asombroso que funcionando bajo modo administrador, el problema desaparece. Quizás una aplicación ejecutada como no administrador, que cambia el estilo del borde puede ser un riesgo en la seguridad.

Cuando VFP ejecuta un formulario, lee las propiedades y las configura en el orden que se encuentran. Para un formulario, la pseudo propiedad DoCreate significa crear la ventana. La propiedad BorderStyle suele estar escrita después de DoCreate, así que no hace caso del ajuste de BorderStyle.

Calvin nos brinda las siguientes opciones para solucionar el problema:

  • Abrir el formulario como una tabla y manualmente colocar la propiedad BorderStyle antes de DoCreate.
  • Ejecutar el programa (ver artículo original) que corrige los archivos SCX colocando la propiedad BorderStyle antes de DoCreate.
  • Convertir los formularios de SCX a VCX (clases visuales), donde el BorderStyle se configura al momento de la creación de la ventana.
  • Esperar el lanzamiento del próximo SP de VFP.
  • Ejecutar Windows Vista sin la interface Aero.
  • Ejecutar la aplicación como Administrador.

El enlace al artículo original en el Blog de Calvin Hsia es: Fix your forms to paint borders correctly under Vista Aero. Allí se encuentra el procedimiento FixDir() que corrige todos los formularios SCX del directorio y subdirectorios pasado como parámetro.

NOTA: Esto también sucede en Visual Studio 2005 según comenta Calvin en la siguente entrada de su blog: Windows Vista Aero BorderStyle Paint problem as non Administrator