Restyling FoxFace -- > FoxFace II
02/04/2020 Capítulo anterior: FoxFace
Autor del proyecto FoxFace: RetailSystems http://www.retailsystems.cz/foxfaceEn.htm
Al igual que FoxRibbon 0.14 de Guillermo Carrero, FoxFace me ha enganchado. Debido al Corona Virus, estamos tranquilamente desde el 15 de Marzo con el Pc en casa y sin salir, y la verdad que esto me sirve de pasatiempo y me desconecta del mundo exterior. Esta temporada le he dedicado tiempo a esta Web, y ahora quiero hacer el manual de FoxFace y compartir con los lectores la puesta en funcionamiento, ajustes, mejoras y conclusiones.
Aquí le explico como he mejorado la clase. No remito a nadie la clase terminada para descarga. Si usted sigue estas instrucciones, puede tener la clase con mi mejora.
Restyling FoxFace -- > FoxFace II
Estoy modificando la clase foxface.vcx para mejorarla en lo que esté en mi mano.
Lo primero que hice fue reestructurar los directorios a mi gusto. Posteriormente fue necesario tocar el código en las llamadas a las bases de datos, carpeta data.
FoxFace 2.0 Es la carpeta donde se encuentra el proyecto y que tiene las siguientes subcarpetas:
config.fwp -> Archivo de configuración.
config.ini -> Lo lee FoxFace al iniciar. En el esta el nº de skin, de 1 a 6, que vamos a utilizar. Cualquier valor diferente nos deja la ventana sin skin.
foxface.VBR y fosface.tlb -> Estos archivos los crea FoxFace. Se pueden borrar pero aparecen en la próxima ejecución de FoxFace.
Las carpetas de imágenes con skins no se necesitan, pues están en campos memo de la tabla foxface.dbf.
Carpeta Data
Para las bases de datos he creado la carpeta Data donde he alojado las bases de datos y tenemos que modificar en la clase FoxFace el método skin USE data\foxface.dbf IN 0 SHARED
errores.dbf -> Aquí se almacenan los errores en tiempo de ejecución.
foxface.dbf -> Tabla con los skins. En el formulario config.scx Combo1: USE data\foxface.dbf IN 0 y FoxFace.vcx
foxface.fpt -> Memo
Carpeta Docs
FoxFace changelog.pdf en checo. Vea Registro de cambios de FoxFace
Notas FoxFace.docx -> Mis notas personales
Carpeta Img
Carpeta donde almaceno las imágenes que utilizo
Carpeta Menus
Los menús que venían con FoxFace. Se han personalizado y dado funcionalidad
Carpeta Prog
salir.prg -> Programa para salir de FoxFace desde la ventana principal en main.prg -> ON SHUTDOWN salir()
Carpeta Scx
config.scx -> Maneja el config.ini. Abre el archivo y le podemos indicar el nº de skin a utilizar. Luego lo guarda. Cuando iniciamos de nuevo FoxFace vemos los cambios.
formul1.scx -> Formulario de ejemplo.
menu.scx -> Formulario de mi autoría con un pequeño menú para probar FoxFace.
test.scx -> Formulario de ejemplo.
Carpeta Vcx
foxface.vcx -> la clase Vfp que estamos tratando
Inconvenientes de FoxFace al maximizar y en los botones Command
Los problemas mayores se presentaban al maximizar la ventana principal y los formularios de nivel superior:
- la tercera parte superior de la barra de títulos sobrepasaba los límites de nuestra pantalla
- tapaba la barra de Windows (barra inferior de la pantalla)
Lea primero Aplicaciones sin barra de títulos y se dará cuenta de lo que es un maximizado simulado.
El problema en skin de los botones Command se produce cuando la propiedad .ignorebuttons -> .F. que indica que aplique skin a los Commad. Les aplica bien el skin, pero a partir de aquí le es indiferente si queremos decirle al Command this.command1.enabled = .F., this.command1.visible = .F., etc., pues no va a alterar para nada el funcionamiento.
La librería Foxface.vcx
Contiene las siguientes clases:
Y aquí sus métodos y propiedades. La clase formimage está vacía.
clineresize
ctomovezone
ffmessagebox
formcontrol
foxbutton
foxface Estoy trabajando en esta clase.
Modificaciones efectuadas en FoxFace
1. Elimino archivos y carpetas que no tienen que ver con el proyecto para trabajar sólo en el ejemplo FoxFace.
2. Carpeta raíz FoxFace 2.0 y nueva estructura de subcarpetas que ya ha visto al inicio.
3. Incorporo Config.fpw archivo de configuración:
SCREEN=off
*RESOURCE=off -> Cuando estoy en un proyecto lo utilizo y el asterisco equivale a ON
4. Nueva carpeta Img -> Para las imágenes que utilizo
5. En la carpeta Data Renombro chyby.dbf -> errores.dbf
Colocar código correspondiente en main.prg: IF NOT FILE ( "data\errores.DBF") y modifico lo relacionado con esta tabla.
6. Reescribo main.prg y personalizo a mi gusto.
7. Creo el programa salir.prg para salir de FoxFace desde la ventana principal, en main.prg -> ON SHUTDOWN salir()
8. En la carpeta Menus les doy funcionalidad a los menús y elimino idioma checo
9. Clase FoxFace
9.1 Nueva propiedad multiscreen que sirve para indicar si vamos a utilizar un solo monitor .F. o varios .T.
9.2 Propiedad libpath Indica el directorio donde se encuentra la librería Foxface.vcx. Renombro lib\foxface.vcx. -> vcx\foxface.vcx
9.3 Nueva propiedad dataskin Indica el directorio y nombre de la base de datos que contiene los skins que utiliza FoxFace. En mi caso data\foxface.dbf. En el método skin (9.7) se reemplazó USE data\foxface.dbf IN 0 SHARED -> USE (this.dataskin) IN 0 SHARED. Esto me permite en un momento dado utilizar una tabla con distinto nombre, pero con la misma finalidad.
9.4 En el init introduzco el siguiente código como recordatorio para cuando arrastramos la clase a nuestro formulario. Una vez en el formulario la clase se llama FoxFace1 o cualquier oro nombre que se nos ocurra. si miramos FoxFace1.init -> Ver código heredado solo tenemos que copiar el siguiente código y pegarlo en el FoxFace1.init y quitarle los * para activarlo. Así le indicamos como utilizar el archivo config.ini
Esto está en FoxFace1.init -> Ver código heredado.
Se pega en FoxFace1.init y se deja así:
*- Copie y pegue en el init de su nuevo objeto FoxFace
*lh=FOPEN("config.ini")
*this.skinid=val(FGETS(lh))
*FCLOSE(lh)
*DODEFAULT()
*----------------------------------------------------*- Copie y pegue en el init de su nuevo objeto FoxFace
lh=FOPEN("config.ini")
this.skinid=val(FGETS(lh))
FCLOSE(lh)
DODEFAULT()
*----------------------------------------------------Y listo, nuestra clase ya funciona según el skin que encuentra en config.ini
También puede funcionar si cambia this.skinid=val(FGETS(lh)) por this.skinid= x (siendo x un número de 1 a 6 y cualquier otro nº lo dejara sin skin). Puede ahorrarse todo el código y ponerlo directamente en la propiedad de FoxFace1.skinid.
Manualmente usted puede abrir cada formulario con un skin diferente, yo sólo le cuento las posibilidades.
9.5 En el método drawborders. Algo personal que no altera el funcionamiento, pero que a mí personalmente me gusta mas. Utilicé el comando WITH thisform -> Todo eran thisform. WITH ... ENDWITH ofrece una forma cómoda de especificar un conjunto de propiedades para un solo objeto. Tenga en cuenta que también puede ejecutar métodos desde una estructura WITH ... ENDWITH.
*IF .WindowState= 0 AND .MaxButton= .T. && Eliminamos y sustituimos por FWindowState IF .maximg.FWindowState= 0 AND .MaxButton= .T. .maximg.picture=SYS(2023)+"\maximg1."+.maximg.image .maximg.stdimg=SYS(2023)+"\maximg1."+.maximg.image .maximg.overimg=SYS(2023)+"\maximg2."+.maximg.image .maximg.clickimg=SYS(2023)+"\maximg3."+.maximg.image .maximg.disableimg=SYS(2023)+"\maximg4."+.maximg.image ENDIF *IF .WindowState= 2 AND .MaxButton= .T. && Eliminamos y sustituimos por FWindowState IF .maximg.FWindowState = 2 AND .MaxButton= .T. .maximg.picture=SYS(2023)+"\stdimg1."+.maximg.image .maximg.stdimg=SYS(2023)+"\stdimg1."+.maximg.image .maximg.overimg=SYS(2023)+"\stdimg2."+.maximg.image .maximg.clickimg=SYS(2023)+"\stdimg3."+.maximg.image .maximg.disableimg=SYS(2023)+"\stdimg4."+.maximg.image ENDIF9.6 En el método setproperties he cambiado el siguiente código:
*- Camf En un maximizado por simulación WindowState siempre es # 2 Maximizado *- Por lo tanto elimino las siguientes lineas y las remplazo por las de abajo *- Tengo pendiente decir lee estado de FwindowState que en un maximizado simulado equivale a WindowState *IF setOffset=1 AND thisform.WindowState<>2 IF setOffset=1 thisform.Width=this.parent.Width+lz+rz thisform.Height=this.parent.Height+tz+bz ENDIF *IF setOffset=-1 AND thisform.WindowState<>2 IF setOffset=-1 thisform.Width=this.parent.Width-(lz+rz) thisform.Height=this.parent.Height-(tz+bz) ENDIFLea aplicaciones sin barra de títulos y se dará cuenta del porque de este cambio ya que vamos a utilizar un maximizado simulado.
Nota: Aquí tengo que pulir un poco el código, pero precisamente estoy trabajando en el proyecto
9.7 En el método skin utilicé WITH thisform, sin alterar el funcionamiento. También hice la modificación que explico en el apartado 9.3
En el apartado ***Buttons se ha insertado la siguiente línea;
thisform.maximg.MultiScreen=this.MultiScreen && Camf ---------------------------------
Y lo que hace es cambiar el valor de la propiedad que he creado en el evento init de la clase formcontrol (.ADDPROPERTY("MultiScreen", .F.)), indicando si trabajamos en multipantalla.
9.8 El método skinbuttons no tiene modificaciones.
10. Clase clineresize -> Sin modificaciones
11. Clase ctopmovezone -> Sin modificaciones
12. Clase ffmessagebox -> Trabajando en ella. es como MessageBox del sistema pero adaptada a FoxFace
13. Clase formcontrol -> Maneja el uso de la botonera maximizar,restaurar, minimizar de la barra de títulos. Cómo ya sabemos, la barra de títulos es personalizada, y en la ventana donde se utiliza, tenemos la propiedad titlebar=0 desactivada. Aquí es donde creamos la simulación del maximizado. Tenga en cuenta que es posible utilizar con FoxFace, tanto en la ventana principal como en formularios la barra de títulos del sistema, donde no se necesita la simulación de maximizado.
13.1 En el método init vacío en origen, se han añadido las siguientes propiedades que van a memorizar posteriormente en el método setparamform las coordenadas de la ventana en estado normal, justo antes de simular el maximizado. A esto le llamo el sistema de memoria.
FwindowState se encarga de informar del WindowState actual simulado. Si ha leído el artículo Aplicaciones sin barra de títulos, ya sabe que el WindowState real es siempre 0 -> Normal en un sistema simulado. Por eso cuando nuestra ventana simula maximizado tenemos que informar de algún modo que esto está sucediendo, y para eso está FwindowState. Otra cosa que sucede al simular max. es que la propiedad BorderStyle cambia su valor a 0 y para ello FormBorder memoriza el valor antes de que se maximice la ventana. MultiScreen ha recibido la información (en el punto 9.7) del método skin de la clase FoxFace, y ya sabemos si estamos trabajando o no en multipantalla. El resto son las coordenadas que no necesitan explicación.
*-- Camf -- he añadido este código WITH THIS .ADDPROPERTY("FwindowState", 0) && .WindowState toma su valor .ADDPROPERTY("FormLeft", 0) .ADDPROPERTY("FormTop", 0) .ADDPROPERTY("FormHeight", 0) .ADDPROPERTY("FormWidth", 0) .ADDPROPERTY("FormBorder", 0) .ADDPROPERTY("MultiScreen", .F.) .SetParamForm() ENDWITH13.2 Aquí en el evento mouseup, en nuestro caso, tiene lugar la simulación de maximizado y la memoria setparamform viene en el punto siguiente, 13.3
IF this.type=1 This.FWindowState = 1 thisform.WindowState= 1 ENDIF
WITH ThisForm IF this.type=2 IF .SHOWWINDOW # 2 AND .Name # "Screen" This.FWindowState = IIF(This.FWindowState = 0, 2, 0) .WindowState = IIF(.WindowState = 0, 2, 0) ELSE *- Tomamos las medidas que hemos guardado previamente en propiedades IF This.FWindowState = 2 This.FWindowState = 0 && FWindowState siempre primero que el redimensionado .BORDERSTYLE = THIS.FormBorder .LEFT = THIS.FormLeft .TOP = THIS.FormTop .HEIGHT = THIS.FormHeight .WIDTH = THIS.FormWidth ELSE *- Guardamos parámetros THIS.SetParamForm() .BorderStyle = 0 *- Variables locales para redimensionar las pantallas LOCAL lnHeightSysMenu, lnTopSysMenu, lnLeftMultiScreen, lnTopMultiScreen, lnHeightStatusBar lnHeightSysMenu = 0 lnTopSysMenu = 0 lnLeftMultiScreen = 0 lnTopMultiScreen = 0 lnHeightStatusBar = 0 *- Si tenemos selecionadas varias pantallas IF This.MultiScreen .WindowState = IIF(.WindowState = 0, 2, 0) ENDIF *- Si usamos los menús de Vfp IF !SET("SYSMENU") = "OFF" AND .Name = "Screen" && lnHeightSysMenu = 20 && 21*- Si no tenemos seleccionadas varias pantallas IF !This.MultiScreen lnTopSysMenu = 20 && 21 ENDIF ENDIF *- Si tenemos activado STATUS BAR en la ventana principal IF SET("STATUS BAR") = "ON" AND .Name = "Screen" lnHeightStatusBar = 25 ENDIF*- Si tenemos seleccionadas varias pantallas IF This.MultiScreen lnLeftMultiScreen = .LEFT + 8 lnTopMultiScreen = .TOP + 8 ENDIF *.LockScreen = .T. *- Maximizado por simulación*- Primero FWindowState This.FWindowState = 2
*- Situamos las coordenadas .LEFT = 0 + lnLeftMultiScreen .TOP = 0 + lnTopMultiScreen + lnTopSysMenu
* Redimensionamos alto y ancho .WIDTH = Sysmetric(1) .HEIGHT = Sysmetric(2) - (Sysmetric(2) - Sysmetric(22) - Sysmetric(9)) - lnHeightStatusBar - lnHeightSysMenu *.LockScreen = .F. ENDIF ENDIF ENDIFIF this.type=3 *- Camf - Salir de la ventana principal de Windows IF .Name ="Screen" QUIT ELSE .Release ENDIF ENDIF ENDWITH
13.3 el nuevo método setparamform. El sistema de memoria de nuestro maximizado por simulación.
*-- CaMF -- Método y Código -- Almacena medidas de ventana antes de maximizar WITH THISFORM THIS.FormBorder = .BORDERSTYLE THIS.FormLeft = .LEFT THIS.FormTop = .TOP THIS.FormHeight = .HEIGHT THIS.FormWidth = .WIDTH THIS.FwindowState = 0 ENDWITH14. Clase formimage -> Sin modificaciones
15. Clase foxbutton -> Sin modificaciones
16. Clase gpimage -> Sin modificaciones
Y aquí concluimos las modificaciones. Estoy seguro de que me quedan muchas cosas por pulir, pero ahora FoxFace es otra cosa.
Propiedades y métodos en la clase FoxFace
En azul las que se pueden modificar
Métodos
.drawbordes
.messagebox -> Método que se llama para obtener un MessageBox personalizado. Utiliza los mismos parámetros que MessageBox.
.setproperties
.skin
.skinbuttons
Propiedades
.dataskin - > Indica el directorio y nombre de la base de datos que contiene los skins que utiliza FoxFace. Nueva propiedad
.firstskin -> .T. es el valor predeterminado. De uso interno.
.ignorebuttons -> .F. Es el valor predeterminado. If .T. then buttons aren't skinned. .T. Ignora el skin en botones.
.isborderstyle -> 3 es el valor predeterminado. Toma la información de BorderStyle. Uso interno.
.istitlebar -> 0 es el valor por defecto. Desconozco funcionamiento.
.libpath El directorio donde se encuentra la librería Foxface.vcx cuando se descarga de sus sitio de origen es lib\foxface.vcx. Yo utilizo para las librerías un directorio Vcx, por lo tanto hay que tener en cuenta esto y mi valor actual es vcx\foxface.vcx
.lmaxx -> .F. Valor predeterminado.
.lmaxy -> .F. Valor predeterminado.
.msgbox -> Propiedad protegida
.multiscreen --> Indicar si vamos a utilizar un solo monitor .F. o varios .T.. Con la propiedad en .F. conseguimos una mejor y más rápida simulación de maximización de la ventana. Con .F. la ventana puede estar en cualquier monitor, excepto cuando maximizamos que lo hará siempre en la ventana principal. Nueva propiedad
.skinid -> 0 Valor que tengo asignado por defecto - De 1 a 6 son los skins que vienen por defecto con FoxFace. Lo habitual es configurar FoxFace para que esta información funcione a partir de config.ini. Lo que hacemos es sustituir el valor de skinid al leer config.ini. Una vez que ya tenemos esta información, tomamos los parámetros necesarios de la tabla foxface.dbf
.version - > 2.0 Versión que utilizamos de FoxFace. Propiedad protegida.
FoxFace
Parámetros:
La llamada la hacemos al evento Skin --> FoxFace.Skin( setOffset, isTitleBar )
setOffset as Integer
isTitleBar as Integer
Determina si se deben mover elementos para formar
Determina si el formulario debe tener bordes, pero desafortunadamente el método de máscara no puede use el valor establecido del parámetro TitleBar, ya que cambia a 0 después de cada escala
1 movimiento lejos del borde -> 1 alejarse del borde
0 - sin barra de título de FoxFace. Siempre utiliza las barras Vfp. Respeta TitleBar=0 o 1 pero cambia si: Ver conclusiones
Equivale a TitleBar = 0 pero sin borde en la pantalla
-1 volver al borde
1 - con TitleBar - Siempre barra FoxFace. No respeta TitleBar=0 o 1
0 dejar como están
2 - mantiene la configuración anterior. Es neutral. no cambia el estado de la barra de titulo. Sirve para cuando solo queremos manejar el setOffset
-1 Nos deja la pantalla sin bordes desplazables y sin barra de titulo
normalmente deja 0 solo cuando enciende o apaga la barra de título, así que use 1 o -1 para colocar los elementos en la ventana
-1 arrastra los objetos al exterior del borde
1 hacia dentro
Si primero La opción a utilizar por defecto es
_SCREEN.foxface1.skin(0, 1)
Esto es lo que utiliza la clase en el evento init
IF thisform.TitleBar=1 && -> Barra de títulos activada this.skin(1,1) ELSE && -> Barra de títulos desactivada this.skin(0,0) ENDIFEn _Screen creamos el objeto FoxFace1 por ej.:
- _SCREEN.NewObject("FoxFace1","FoxFace","lib\foxface.vcx") && Creamos el objeto
Elegimos si queremos o no barra de títulos :
- _SCREEN.TitleBar = 1 && 0 Desactivado - 1 Activado
Y luego hacemos la siguiente llamada:
- _SCREEN.foxface1.skin(setOffset, isTitleBar)
A continuación pulse sobre las imágenes para ampliar
El mismo resultado resultado:
_SCREEN.foxface1.skin(-1, 0)
_SCREEN.foxface1.skin(0, 0)
_SCREEN.foxface1.skin(1, 0)
_SCREEN.foxface1.skin(-1, 2)
_SCREEN.foxface1.skin(0, 2)
_SCREEN.foxface1.skin(0, 2)
Siempre barras de Vfp
_SCREEN.TitleBar = 1
Figura 3 - Barra de Vfp
_SCREEN.TitleBar = 0
_SCREEN.foxface1.skin(-1, 1) -> independientemente del titlebar
_SCREEN.foxface1.skin(0, 1)
_SCREEN.foxface1.skin(1, 1)
Siempre sale la barra de FoxFace sin importar TitleBar= 1 o 0
_SCREEN.TitleBar = 1
Figura 5 - Barra de Vfp
_SCREEN.TitleBar = 0
La opción a utilizar por defecto es _SCREEN.foxface1.skin(0, 1)
Luego ya utilizamos las otras opciones:
_SCREEN.TitleBar = 1
_SCREEN.foxface1.skin(0, 1)
_SCREEN.foxface1.skin(-1,0) - o - _SCREEN.foxface1.skin(0,0) - o - _SCREEN.foxface1.skin(1,0)
Esto ahora nos ha quitado la barra de título y nos ha dejado un borde no ajustable en la ventana. Amplíe la figura 4 y se nota un pequeño rectángulo en la parte superior en Windows 10 debido a que el borde es ajustable. Por lo que deducimos que isTitleBar=0 Equivale a TitleBar=0 dejando la ventana sin borde ajustable.
hasta donde hemos llegado setOffset no ha surtido ningún efecto
Capítulos
- FoxFace
- Ghangelog.pdf - Registro de cambios de FoxFace
- Puesta en funcionamiento -- > FoxFaceClassSourcecode
- Restyling FoxFace -- > FoxFace II --> Usted se encuentra aquí.
Vea también
- Aplicaciones sin barra de títulos en Visual FoxPro - Simular maximizado
- Tema principal Herramientas que cambian el entorno visual de las ventanas Vfp
- Cambiar el aspecto de un formulario en Visual FoxPro - Skinning a Form in Visual FoxPro
- Tema principal Formularios
No olvide de hacer una donación a RetailSystems, para que pueda continuar mejorando este proyecto.
Referencias
Autor del proyecto FoxFace: RetailSystems http://www.retailsystems.cz/foxfaceEn.htm
Restyling a FoxFace II -- >: Camf.