26 de abril de 2009

Utilizando _MemberData con el objeto _Screen

Por lo general no acostumbro utilizar variables públicas en mis aplicaciones. Siempre uso el objeto _SCREEN, le adiciono propiedades con valores que estarán disponibles para toda la aplicación. No obstante, al programar y usar Intellisense la presentación de las propiedades del objeto _SCREEN en el código se muestran siempre en minúsculas, lo cual me dejaba un tanto insatisfecho, dado que esto no ocurría con mis otras clases porque les añadía la propiedad _MemberData y lograba una mejor presentación en mi código.

Así que un día pensé, ¿qué pasaría si al objeto _SCREEN le agrego la propiedad _MemberData y le asigno el valor requerido?

Pues me di con la sorpresa que también funciona, y ahora con el Intellisense puedo tener en mi código una mejor presentación.




Les adjunto un pequeño código que se puede perfeccionar. Si por ejemplo, guardamos nuestras variables en una tabla junto con sus valores, usando SCAN podemos recorrerla e ir formando la cadena requerida para la propiedad _MemberData y a la vez ir agregando nuestras propiedades al objeto _SCREEN con el método AddProperty().
* Ejemplo de _MemberData en _Screen en VFP9 SP2

* Formando la propiedad _MemberData en formato XML
LOCAL cMemberData as String 
TEXT TO cMemberData NOSHOW PRETEXT 15
  <VFPData>
  <memberdata name="cconectbdsistema" type="property" display="cConectBDSistema"/>
  <memberdata name="cconnectioncatastro" type="property" display="cConnectionCatastro"/>
  <memberdata name="cconnectionrentas" type="property" display="cConnectionRentas"/>
  <memberdata name="cconnectionstring" type="property" display="cConnectionString"/>
  <memberdata name="cconnectiontramite" type="property" display="cConnectionTramite"/>
  <memberdata name="cconnectioncuentacte" type="property" display="cConnectionCuentaCte"/>
  </VFPData>
ENDTEXT 
_Screen.AddProperty("_MemberData", cMemberData)

* Agregando mis propiedades
_Screen.AddProperty("cconectbdsistema","")
_Screen.AddProperty("cconnectioncatastro","")
_Screen.AddProperty("cconnectionrentas","")
_Screen.AddProperty("cconnectionstring","")
_Screen.AddProperty("cconnectiontramite","")
_Screen.AddProperty("cconnectioncuentacte","")
Espero que les sirva.

Miguel Herbias, Lima, Perú

15 de abril de 2009

Reemplazo para SYS(2014)

Artículo original: Replacement for SYS(2014) 
http://doughennig.blogspot.com/2009/03/replacement-for-sys2014.html
Autor: Doug Hennig
Traducido por: Luis María Guayán

SYS(2014) es una pequeña gran función que ayuda a hacer sus aplicaciones portátiles. Como retorna la ruta relativa de un archivo, a una carpeta específica, se puede utilizar en un nombre de archivo absoluto (como el que retorna GETFILE()) y almacenar la ruta relativa, en lugar de la ruta absoluta.

Sin embargo, una cosa que siempre digo sobre SYS(2014), es que retorna la ruta en mayúsculas. Si se desea mostrar la ruta de acceso para el usuario, ellos preguntarán por qué la ruta está toda en en mayusculas en el programa, y diferente en el disco.

Afortunadamente, hay una simple función API de Windows que usted ae puede llamar, que hace lo mismo que SYS(2014), pero respeta las mayúsculas y minusculas. El siguiente es un ejemplo de cómo utilizar esta función:

(ACTUALIZACION: Walt Krzystek señaló que GetRelativePath retornó una cadena en blanco si las dos rutas se encuentran en unidades diferentes. Además, yo olvidé quitar los espacios al valor devuelto.)

*- Ejemplo de ambas funciones
lcFile = "C:\VFP\Desarrollo\Programa.prg" 
lcPath = "C:\VFP\Aplicaciones\"

? SYS(2014, lcFile, lcPath)
? GetRelativePath(lcFile, lcPath)

FUNCTION GetRelativePath(tcTo, tcFrom)
  #DEFINE FILE_ATTRIBUTE_DIRECTORY 0x10
  #DEFINE FILE_ATTRIBUTE_NORMAL 0x80
  #DEFINE MAX_PATH 260
  
  DECLARE INTEGER PathRelativePathTo IN shlwapi.DLL ;
    STRING @out, STRING @from, INTEGER fromattrib, ;
    STRING @to, INTEGER toattrib

  lcPath = SPACE(MAX_PATH)
  lcFrom = IIF(VARTYPE(tcFrom) = 'C', tcFrom, ;
    SYS(5) + CURDIR()) + CHR(0)
  lnFromAttrib = IIF(DIRECTORY(lcFrom), FILE_ATTRIBUTE_DIRECTORY, ;
    FILE_ATTRIBUTE_NORMAL)
  lcTo = IIF(VARTYPE(tcTo) = 'C', tcTo, ;
    SYS(5) + CURDIR()) + CHR(0)
  lnToAttrib = IIF(DIRECTORY(lcTo), FILE_ATTRIBUTE_DIRECTORY, ;
    FILE_ATTRIBUTE_NORMAL)
    
  PathRelativePathTo(@lcPath, @lcFrom, lnFromAttrib, @lcTo, lnToAttrib)

  lcPath = ALLTRIM(STRTRAN(lcPath, CHR(0), ' '))

  IF EMPTY(lcPath)
    lcPath = tcTo
  ENDIF EMPTY(lcPath)

  RETURN lcPath
ENDFUNC