19 de noviembre de 2020

Iconos Unicode en botones de Visual FoxPro

Articulo original: Unicode button icons in Visual FoxPro
http://vfpimaging.blogspot.com/2020/11/unicode-button-icons-in-visual-foxpro.html
Autor: Cesar Ch.
Traducido por: Luis María Guayán


Una gran dificultad que tienen los foxeros es actualizar sus interfaces de usuario. Dado que perdimos el soporte de MS, necesitamos hacer casi todos los cambios en la interfaz de usuario (UI) por nuestra cuenta. La interfaz de usuario de Windows 10 actual se basa en iconos monocromáticos, los de la familia SEGOE UI, SEGOE UI SYMBOL y SEGOE MDL2 ASSETS. Estas son fuentes de True Type, que traen toneladas de íconos, los que vemos por todas partes en Windows 10.

Desafortunadamente, no podemos acceder a esos iconos directamente en VFP, porque usan un rango mayor al CHR(255) admitido por VFP. Aún tenemos algunas opciones:

  1. Utilizar un ActiveX que admita Unicodes
  2. Utilizar "Real Window buttons", que admiten Unicodes - https://github.com/VFPX/Win32API/blob/master/samples/sample_274.md
  3. Obtener ayuda de GDI+ - gdiplus.dll y dibujarlos nosotros.

La tercera opción es muy buena, pero exige mucho, mucho trabajo. Afortunadamente, hice casi todo el trabajo pesado anteriormente en 2005, en la clase GradObjects, que originalmente se creó para hacer fondos y botones degradados en nuestros formularios. Recreó cada botón del formulario y lo redibujó en un archivo de imagen, lo que permite efectos de degradado, de paso del mouse y de deshabilitado.

Teniendo esto, solo necesito adaptarlo, dejando atrás los degradados ya casi abandonados, agregando soporte a unicodes y algunas adaptaciones para los efectos del mouse.

Aquí hay una versión actualizada de la muy buena y antigua clase GRADOBJECTS, que estaba destinada a generar botones y fondos degradados para nuestros formularios en 2005, en los tiempos de WinXP. Sigue siendo el mismo GradObjects, pero con algunas propiedades y características nuevas.

El uso es realmente muy simple:

  • Abra el proyecto GradObjects
  • Cree un formulario, agregue algunos botones
  • Lance una instancia de Gradobjects en el formulario
  • Establezca la propiedad FontName del botón en "SEGOE MDL2 ASSETS" o cualquier otra que desee.
  • Establezca la propiedad Caption del botón para aceptar unicodes, introduciendo los unicodes entre las etiquetas <UC> </UC>, por ejemplo:
    • Griego <UC> 03b5 03b9 03c1 03ae 03bd 03b7 </UC> - Esto muestra la palabra "Paz" en caracteres griegos, en cualquier fuente regular, como Arial, Tahoma, Segoe UI, etc.
    • Para obtener el icono de la impresora de SEGOE MDL2 ASSETS, establezca la fuente del botón y agregue lo siguiente a la propiedad Caption: "<UC> E749 </UC> "

Las propiedades predeterminadas de "GradObjects" le brindarán un aspecto degradado, pero todo lo que necesita es cambiar solo 5:

  • BackColor1: Numérico, el RGB del color de fondo
  • BackColor2: Configúrelo en .F. (Falso), porque no necesitamos gradientes aquí, ¿verdad?
  • CaptionForeColor: Numérico, el RGB del color de fondo
  • GradientMode: 0 - ¡No necesitamos degradados!
  • SelBackColor: Numérico, el RGB del color de fondo cuando se enfoca el botón o se pasa el mouse sobre él
  • SelForeColor: Numérico, el RGB del color de primer plano cuando se enfoca el botón o se pasa el mouse sobre él

¡Eso es todo!

Los Unicodes se pueden obtener directamente a través de CharMap.EXE o en toda la web. Aquí hay un excelente punto de partida: https://docs.microsoft.com/en-us/windows/uwp/design/style/segoe-ui-symbol-font

Para obtener información más detallada, consulte la publicación original de GradObjects:

El objeto "GradObjects" transformará todos los CommandButtons, Graphical OptionButtons del mismo objeto principal. Utilice contenedores, si necesita efectos diferentes (o ninguno) para algunos controles individuales en sus formularios.

Empiece a jugar con el formulario de muestra "TESTUNICODEBTNS.SCX"

Descarga Botones Unicode


17 de noviembre de 2020

Códigos QR con FoxBarcodeQR v.2.10

Actualización del 28/02/2021: Se libera una nueva versión v.2.10 de FoxBarcodeQR


FoxBarcodeQR es una clase libre que ofrece una solución alternativa para todos los desarrolladores de la comunidad de Visual FoxPro que solicitaron soporte para Códigos QR a la clase FoxBarcode

Ambas clases forman parte del proyecto VFPx:

FoxBarcodeQR utiliza las librerías:

Características de las librerías externas


BarCodeLibrary.dll 

  • Genera códigos QR  funcionales, pero sólo se puede establecer el tamaño y el tipo de la imagen generada. 
  • No tiene ajustes para el nivel de corrección de errores, colores y/o margenes.
  • No soporta cadenas de mas de 255 caracteres.

La librería BarCodeLibrary.dll contiene solo 3 funciones:

  • LibraryVersion: Retorna una cadena con la versión de la librería.
  • SetConfiguration: Método para establecer el tamaño y el tipo de archivo de imagen a generar.
  • GenerateFile: Método responsable de generar la imagen del código de barras QR.

QRCodeLib.dll  (versión 0.1b - www.validacfd.com)

  • Genera códigos QR funcionales con un mayor control de configuración.
  • Soporta cadenas de mas de 255 caracteres.

La librería BarCodeLib.dll contiene los métodos:

  • QRCodeLibVer: Retorna una cadena con la versión de la librería.
  • FastQRCode: Genera la imagen del código de barras QR con el texto a codificar.
  • FullQRCode: Igual que el método anterior, pero con mayor control en la generación de la imagen del código QR.
La API de Google genera códigos QR  a través de una llamada POST a una URL:
  • Requiere conexión a internet.
  • Soporta cadenas de mas de 255 caracteres.

Métodos de FoxBarcodeQR

FoxBarcodeQR encapsula las funciones de las librerías BarCodeLibrary.dllQRCodeLib.dll y la API de Google, en métodos propios de la clase para compatibilidad con las versiones anteriores y poder seleccionar la librería a utilizar .

Los métodos de la clase FoxBarcodeQR son: 

  • QRBarcodeImage() que utiliza la librería BarCodeLibrary.dll y que recibe los siguientes parámetros:
    • tcText: Texto para codificar
    • tcFile: Nombre del archivo de imagen que desea generar. Si no se especifica ninguno, se genera un nombre de archivo aleatorio en la carpeta de archivos temporales de Windows.
    • tnSize: El tamaño de la imagen generada. Recibe un número entero entre 2 y 12
      • 2 = 66 x 66 (en píxeles)
      • 3 = 99 x 99
      • 4 = 132 x 132
      • 5 = 165 x 165
      • 6 = 198 x 198
      • 7 = 231 x 231
      • 8 = 264 x 264
      • 9 = 297 x 297
      • 10 = 330 x 330
      • 11 = 363 x 363
      • 12 = 396 x 396
    •  tnType: El tipo de archivo de imagen generado. Recibe un número entero entre 0 y 2.
      • 0 = BMP
      • 1 = JPG
      • 2 = PNG

A partir de la versión 2.0 de FoxBarcodeQR, los nuevos métodos añadidos utilizan la librería QRCodeLib.dll v.01b (www.validacfd.com)

  • FullQRCodeImage() que recibe los mismos parámetros que QRBarcodeImage()
    •  tcText: Texto para codificar
    • tcFile: Nombre del archivo de imagen que desea generar. Si no se especifica ninguno, se genera un nombre de archivo aleatorio en la carpeta de archivos temporales de Windows.
    • tnSize: El ancho y alto en pixeles de la imagen generada
    • tnType: (solo por compatibilidad) La librería solo genera archivo de imagen tipo 0 = BMP

Para configurar las otras opciones se utilizan las siguientes propiedades:

    • lAutoConfigurate: .T. para seleccionar una versión de código QR más grande si la cantidad de datos lo requiere.
    • lAutoFit: Trabaja conjuntamente con lAutoConfigurate
    • nBackColor: Color del fondo del código QR
    • nBarColor: Color de las barras del código QR
    • nCorrectionLevel: Nivel de corrección  de errores :
      • 0 = Nivel L ( 7 % ) 
      • 1 = Nivel M  ( 15 % ) 
      • 2 = Nivel Q ( 25% ) 
      • 3= Nivel H ( 30% )  
    • nEncoding: Algoritmo de codificación:
      • 0 = Alfabético: Codifica caracteres alfanuméricos  (digitos 0-9;  mayúsculas A-Z;  otros nueve caracteres: Espacio $ % * + – . / : )
      • 1 = Byte = 1: Codifica valores binarios ( 8-bit data) 
      • 2 = Numérico: Codifica unicamente valores numéricos (digitos 0-9) 
      • 3 = Kanji: Codifica caracteres Kanji. Los caracteres Kanji en Código QR pueden tener valores 8140-9FFC y E040-EBBF 
      • 4 = Auto:  Selección automática del algoritmo de codificación. (Recomendado)
    • nMarginPixels: Margen en pixeles
    • nModuleWidth: Tamaño de los módulos en pixeles
    • nHeight: Alto de la imagen en pixeles
    • nWidth: Ancho de la imagen en pixeles
  • FastQRCodeImage() es igual que el método FullQRCodeImage() y solo se pasa el texto a codificar. El resto se configura automáticamente, sin ningún control del usuario. 
    •  tcText: Texto para codificar
    •  tcFile: Nombre del archivo de imagen que desea generar. Si no se especifica ninguno, se genera un nombre de archivo aleatorio en la carpeta de archivos temporales de Windows.
  • GooQRCodeImage()  recibe los mismos parámetros que los métodos anteriores para uniformar la clase:
    •  tcText: Texto para codificar
    •  tcFile: Nombre del archivo de imagen que desea generar. Si no se especifica ninguno, se genera un nombre de archivo aleatorio en la carpeta de archivos temporales de Windows.
    •  tnSize: El ancho y alto en pixeles de la imagen generada
    • tnType: (solo por compatibilidad) La API solo genera archivo de imagen tipo 2 = PNG

        Esta API nos permite ajustar algunas otras propiedades como:

    •     nCorrectionLevel: Nivel de corrección  de errores :
      • 0 = Nivel L ( 7 % ) 
      • 1 = Nivel M  ( 15 % ) 
      • 2 = Nivel Q ( 25% ) 
      • 3= Nivel H ( 30% )  
    • nMarginPixels: Margen en columnas

Todos estos métodos retornan la ruta y el nombre del archivo de la imagen generada con el código QR.

Ejemplos

En el siguiente ejemplo, se crean dos imágenes de Código QR, la primera con el método QRBarcodeImage() y la segunda con el método FullQRCodeImage():


SET PROCEDURE TO LOCFILE("FoxBarcodeQR.prg") ADITIVE
*--- Crear un objeto FoxBarcodeQR
LOCAL loFbc, lcQRImage
loFbc = CREATEOBJECT("FoxBarcodeQR")

*-- Utilizando la librería BarCodeLibrary.dll
lcQRImage1 = loFbc.QRBarcodeImage("http://vfpx.codeplex.com/wikipage?title=FoxBarcode",,6,0)

*-- Utilizando la librería QRCodeLib.dll (www.validacfd.com)
loFbc.nBackColor = RGB(0,255,255) && Yelow
loFbc.nBarColor = RGB(0,0,128) && Blue
loFbc.nCorrectionLevel = 2 && Q 25%
lcQRImage2 = loFbc.FullQRCodeImage("http://vfpx.codeplex.com/wikipage?title=FoxBarcode",,200,0)


Con BarCodeLibrary.dll

 


Con QRCodeLib.dll con mas opciones para configurar


A partir de ésta nueva versión 2.0 de FoxBarcodeQR se pueden codificar cadenas de caracteres mayores a 255 caracteres con la librería QRCodeLib.dll, y a partir de la versión 2.10 con la API de Google también. Ejemplo:

SET PROCEDURE TO LOCFILE("FoxBarcodeQR.prg") ADITIVE
*--- Crear un objeto FoxBarcodeQR
LOCAL loFbc, lcQRImage
loFbc = CREATEOBJECT("FoxBarcodeQR")

lcString = "+ .0010. -"
DO WHILE LEN(lcString) < 500
  lnI = LEN(lcString) + 10
  lcString = lcString + "+ ." + TRANSFORM(lnI, "@L 9999") + ". -"
ENDDO

*-- Utilizando la librería QRCodeLib.dll (www.validacfd.com)
lcQRImage = loFbc.FullQRCodeImage(lcString,,330)


*-- Utilizando la API de Google
lcQRImage2 = loFbc.GooQRCodeImage(lcString,,330)



Con QRCodeLib.dll

Con la API de Google


Para incluir un código de barras QR en un informe, se debe insertar un objeto Image y establecer la propiedad "ControlSource" con una llamada al método QRBarcodeImage(), FullQRCodeImage() o GooQRCodeImage(). Se recomienda ajustar "Escala de contenidos, mantener la forma" si el tamaño de la imagen difiere de la estructura.


Código QR en informes

Importante: Antes de ejecutar el informe y crear el objeto FoxBarcodeQR, se debe declarar la variable como PRIVATE de forma que ésta tenga alcance en el informe:

*--- Crear un objeto FoxBarcodeQR privado
PRIVATE poFbc
m.poFbc = CREATEOBJECT("FoxBarcodeQR")
... 
REPORT FORM FoxBarcodeQR PREVIEW


Distribución

Los únicos archivos necesarios para ser distribuidos para que FoxBarcodeQR funcione correctamente son:

Notas sobre la distribución e instalación del archivo BarCodeLibrary.dll y QRCodeLib.dll:

  • No se registran los archivos BarCodeLibrary.dll y QRCodeLib.dll. Debe estar ambos en la misma carpeta de la aplicación o en la carpeta del sistema de Windows.
  • BarCodeLibrary.dll y QRCodeLib.dll fueron probados y funcionan en Windows XP, 7, 8 y 10 (32 y 64 bits)

1 de noviembre de 2020

Cargar un número grande de archivos mediante ADIR()

La función ADIR() es una manera práctica de cargar todos los archivos (o de un subconjunto de todos los archivos) de una carpeta específica, en un Array. En la mayoría de los usos típicos de ADIR(), el número de archivos y por lo tanto el tamaño del Array, no es una cuestión a discutir.

Sin embargo, en aquellos escenarios donde el número de archivos que Ud. desea cargar es muy grande (mas de 10.000), existen estos problemas:

1) En versiones de VFP anteriores a VFP 9.0, ADIR() estaba limitado a cerca de 12.800 filas, debido al límite de 64.000 items máximos de un Array. Si la carpeta específicada contiene mas de 12.800 archivos, ADIR() genera un error.

2) VFP 9.0 elimina la limitación de 64.000 items, pero cuando usted intenta cargar y después procesar las filas del Array, el rendimiento sufre porque el Array entero se carga en memoria.

El siguiente código muestra una manera de solventar el problema usando la función SYS(2000) que carga un archivo a la vez en un cursor y a) Trabaja en cualquier versión de VFP y b) Consume muy poca memoria, porque solamente una fila del Array a la vez, se almacena en memoria.

CLEAR 
LOCAL xx
*
*  create 12,000 files with the ".TST" extension,
*  the limit when using VFP 8.0 or lower -- feel
*  free to increase this number dramatically in 
*  VFP 9 and higher
*
FOR xx = 1 TO 12000
  STRTOFILE("File " + TRANSFORM(m.xx),"File"+TRANSFORM(m.xx)+".TST",0)
ENDFOR
*
*  try it the ADIR() way
*
start = SECONDS()
CREATE CURSOR FileList (FileName C(60), ;
                        FileSize I, ;
                        LastModD D, ;
                        LastModT C(8), ;
                        FileAttr C(10))
LOCAL laDir[1]
ADIR(laDir,"*.TST")
INSERT INTO FileList FROM ARRAY laDir
end = SECONDS()
? end-start, RECCOUNT("FileList")
USE IN FileList
*
*  try it the SYS(2000) way
*
start = SECONDS()
CREATE CURSOR FileList (FileName C(60), ;
                        FileSize I, ;
                        LastModD D, ;
                        LastModT C(8), ;
                        FileAttr C(10))
LOCAL lcFile
lcFile = SYS(2000,"*.TST")
DO WHILE NOT EMPTY(m.lcFile)
    ADIR(laFile, m.lcFile)
    INSERT INTO FileList FROM ARRAY laFile
    lcFile = SYS(2000,"*.TST",1)
ENDDO
end = SECONDS()
? end-start, RECCOUNT("FileList")
USE IN FileList
ERASE *.TST
RETURN

VFP Tips & Tricks - Drew Speedie