7 de febrero de 2008

El namespace My en Sedna

Introducción

El namespace My, igual al introducido en Visual Studio 2005, está ahora disponible en Sedna. Las clases My crean un envoltorio a algunas funciones SYS(), funciones de la API de Windows, y métodos y propiedades de Windows Script Host, haciendo que sean mas fáciles de entender y poder escribir menos líneas de código. Todo esto ayudado por IntelliSense incluido en el namespace My.

Un buen ejemplo de esto, es el método Play que ejecuta un archivo de audio, que de la forma tradicional, con la API de Windows debíamos declarar la función y luego ejecutarla:

declare integer sndPlaySound in WinMM.dll ;
  string lpszSoundName, integer uFlags

sndPlaySound('Ding.wav', 0)

Ahora con Sedna podemos escribir solamente:

My.Computer.Audio.Play('Ding.wav')

Esta nueva clase está muy bien documentada en el archivo de ayuda My.chm incluido en la descarga de Sedna. Obviamente esta ayuda está en inglés, por lo que este artículo intentará ser una breve ayuda para la comunidad de habla hispana.

¿Cómo empezar?

Una vez descargado e instalado el complemento Sedna (ver los artículos anteriores "Sedna disponible para descarga" y "Sedna ya esta oficialmente en VFPx"), se debe registrar My con IntelliSense ejecutando la aplicación My.app, que se encuentra en la carpeta Sedna\My en el directorio de instalación de Visual FoxPro 9.0.

En el editor de código escribimos LOCAL My AS y seleccionamos el tipo My de la lista de tipos como se muestra a continuación:



Automáticamente se completará con el siguiente código:



Ahora escribiendo My. aparecerá la lista de los cinco namespaces disponibles en My:



My.App

Este namespace proporciona métodos y propiedades de la aplicación.

Por ejemplo para ejecutar un archivo específico con la aplicación asociada, utilizamos el método Execute:
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
lcArchivo = GETFILE('HTM')
My.App.Execute(lcArchivo)

My.App.Info contiene métodos y propiedades de una aplicación específica o de la aplicación actual.

El siguiente ejemplo muestra información de la aplicación VFP9.EXE utilizando el método GetApplicationInformation:
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
lcArchivo = HOME() + 'vfp9.exe'
My.App.Info.GetApplicationInformation(lcArchivo)
MESSAGEBOX( ;
  My.App.Info.ProductName + CHR(13) + ;
  My.App.Info.Version + CHR(13) + ;
  My.App.Info.Copyright, ;
  64, My.App.Info.CompanyName )

My.Computer

Proporciona acceso a varios componentes de la computadora.

La propiedad ComputerName nos muestra el nombre de la computadora
? My.Computer.ComputerName

Con My.Computer.Audio podemos ejecutar los sonidos del sistema con el método PlaySystemSound, o ejecutar un archivo de sonido específico con el método Play:
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
My.Computer.Audio.PlaySystemSound('Stop')
My.Computer.Audio.Play('C:\Windows\Media\Ringout.wav')

Con My.Computer.Time podemos tomar la fecha y hora local, su descripción, la fecha y hora GMT (Greenwich Mean Time), o convertir de Local a GMT y viceversa:
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
? My.Computer.Clock.LocalTime
? My.Computer.Clock.TimeZoneDescription
? My.Computer.Clock.GMTTime
? My.Computer.Cloc? My.Computer.Clock.ConvertLocalToGMT(DATETIME())

Con MyComputer.FileSystem podemos tener acceso a los atributos y métodos del sistema de archivos:

Con My.Computer.FileSystem.SpecialDirectories obtenemos las rutas de las carpetas especiales del usuario actual:
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
lcArchivo = HOME() + 'vfp9.exe'
WITH My.Computer.FileSystem.SpecialDirectories
  ? .Desktop      && Escritorio
  ? .Favorites    && Favoritos
  ? .MyDocuments  && Mis Documentos
  ? .NetHood      && Entorno de red
  ? .PrintHood    && Impresoras
  ? .Programs     && Programas
  ? .StartMenu    && Menú inicio
  ? .Temp         && Carpeta temporal
ENDWITH
Podemos copiar un archivo con el método CopyFile:
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
lcFile = GETFILE()
lcCopy = ADDBS(JUSTPATH(lcFile)) + 'Copia de ' + JUSTFNAME(lcFile)
My.Computer.FileSystem.CopyFile(lcFile, lcCopy)
Podemos mover un archivo con el método MoveFile:
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
lcFile = GETFILE()
lcCopy = ADDBS(JUSTPATH(lcFile)) + 'Copia de ' + JUSTFNAME(lcFile)
My.Computer.FileSystem.MoveFile(lcFile, lcCopy)
Podemos copiar una carpeta completa con el método CopyDirectory:
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
lcDir = GETDIR()
lcDir = LEFT(lcDir, LEN(lcDir)-1)
lcCopy = 'C:\Copia de ejemplo'
My.Computer.FileSystem.CopyDirectory(lcDir, lcCopy)
Podemos mover una carpeta completa con el método MoveDirectory:
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
lcDir = GETDIR()
lcDir = LEFT(lcDir, LEN(lcDir)-1)
lcCopy = 'C:\Copia de ejemplo'
My.Computer.FileSystem.MoveDirectory(lcDir, lcCopy)
Con el método GetFileInfo podemos acceder a distintas propiedades de un archivo especificado:
LOCAL My AS My
My = NEWOBJECT('My', 'My.vcx')
lcFile = GETFILE()
WITH My.Computer.FileSystem.GetFileInfo(lcFile)
  ? 'Nombre: ' + .NAME
  ? 'Carpeta: ' + .PATH
  ? 'Tipo: ' + .TYPE
  ? 'Tamaño: ' + TRANSFORM(.SIZE)
  ? 'Creado: ' + TRANSFORM(.DateCreated)
  ? 'Accedido: ' + TRANSFORM(.DateLastAccessed)
  ? 'Modificado: ' + TRANSFORM(.DateLastModified)
ENDWITH
Con el método GetDirectoryInfo podemos acceder a distintas propiedades de una carpeta especificada:
LOCAL My AS My
My = NEWOBJECT('My', 'My.vcx')
lcDir = GETDIR()
WITH My.Computer.FileSystem.GetDirectoryInfo(lcDir)
  ? 'Nombre: ' + .NAME
  ? 'Carpeta: ' + .PATH
  ? 'Archivos: ' + TRANSFORM(.Files.Count)
  ? 'Creado: ' + TRANSFORM(.DateCreated)
  ? 'Accedido: ' + TRANSFORM(.DateLastAccessed)
  ? 'Modificado: ' + TRANSFORM(.DateLastModified)
ENDWITH
Con el método GetDriveInfo podemos acceder a distintas propiedades de la unidad de disco especificada:
LOCAL My AS My
My = NEWOBJECT('My', 'My.vcx')
WITH My.Computer.FileSystem.GetDriveInfo("C")
? 'Unidad: ' + .DriveLetter
? 'Volumen: ' + .VolumeName
? 'Sistema: ' + .FileSystem
? 'Tamaño: ' + TRANSFORM(.TotalSize / 1024) + ' KB'
? 'Libre: ' + TRANSFORM(.FreeSpace / 1024) + ' KB'
? 'Nro.Serie: ' + RIGHT(TRANSFORM(.SerialNumber, '@0'),8)
ENDWITH
Con los métodos GetShortFileName y GetLongFileName podemos obtener el nombre corto de archivo (8.3), desde un nombre largo y viceversa respectivamente:
LOCAL My AS My
My = NEWOBJECT('My', 'My.vcx')
lcFile = GETFILE()
lcCorto = My.Computer.FileSystem.GetShortFileName(lcFile)
lcLargo = My.Computer.FileSystem.GetLongFileName(lcCorto)
? lcCorto
? lcLargo

My.Computer.Network nos proporciona las propiedades y métodos para tratar con redes:

Podemos descargar una página web con el método DownloadFile:
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
IF 0 = My.Computer.Network.DownloadFile('http://www.portalfox.com/backend.php','My.xml')
  My.App.Execute('My.xml')
ELSE
  MESSAGEBOX('Error al descargar archivo,16,'Error'))
ENDIF
Podemos conectarnos a un recurso compartido con el método MapNetworkDrive:
LOCAL My AS My
My = NEWOBJECT('My', 'My.vcx')
My.Computer.Network.MapNetworkDrive('Z:','\\MiServidor\MiRecursoCompartido')
Y desconectarnos con el método RemoveNetworkDrive:
LOCAL My AS My
My = NEWOBJECT('My', 'My.vcx')
My.Computer.Network.RemoveNetworkDrive('Z:')

My.Computer.Printer nos proporciona información de las impresoras:

El método AvailablePrinters nos retorna una colección de objetos con todas las impresoras disponibles:
LOCAL My AS My
My = NEWOBJECT('My', 'My.vcx')
FOR EACH lo IN My.Computer.Printer.AvailablePrinters
  ? lo.PrinterName
ENDFOR
Las propiedades DefaultVFPPrinter y DefaultWindowsPrinter nos muestran las impresoras por omisión de Visual FoxPro y de Windows respectivamente:
LOCAL My AS My
My = NEWOBJECT('My', 'My.vcx')
? My.Computer.Printer.DefaultVFPPrinter
? My.Computer.Printer.DefaultWindowsPrinter
EL método PageSetup nos muestra el cuadro de diálogo de configuración de página:
My = NEWOBJECT('My', 'My.vcx')
IF My.Computer.Printer.PageSetup()
  REPORT FORM MiInforme TO PRINTER
ENDIF

My.Computer.Registry proporciona acceso al registro de Windows:

Podemos crear y leer un valor del registro de Windows con los métodos SetValue y GetValue:
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
IF My.Computer.Registry.SetValue('HKEY_LOCAL_MACHINE\Software\PortalFox\Ejemplo', 'Version', '1.0.0')
  MESSAGEBOX(My.Computer.Registry.GetValue('HKEY_LOCAL_MACHINE\Software\PortalFox\Ejemplo','Version'),64,'Version')
ENDIF
Podemos borrar un valor o una clave completa del registro de Windows con los métodos DeleteKeyValue y DeleteKey:
LOCAL My AS My
MMy = NEWOBJECT('My', 'my.vcx')
*-- Borrar un valor de la clave
My.Computer.Registry.DeleteKeyValue('HKEY_LOCAL_MACHINE\Software\PortalFox\Ejemplo', 'Version')
*-- Borrar la clave completa
My.Computer.Registry.DeleteKey('HKEY_LOCAL_MACHINE\Software\PortalFox\Ejemplo')
Podemos enumerar todas las claves bajo una clave específica con el método EnumetateKeys.
LOCAL My AS My
My = NEWOBJECT('My', 'My.vcx')
lo = My.Computer.Registry.EnumerateKeys('HKEY_LOCAL_MACHINE\Software\Microsoft\Windows')
FOR EACH lc IN lo
  ? lc
NEXT
Podemos enumerar todas los valores de una clave específica con el método EnumetateValueKeys.
LOCAL My AS My
My = NEWOBJECT('My', 'My.vcx')
lo = My.Computer.Registry.EnumerateKeyValues('HKEY_LOCAL_MACHINE\Software\Microsoft\VisualFoxPro\9.0\Registration')
FOR ln = 1 TO lo.Count
  ? lo.GetKey(ln) + ' = ' + lo.Item(ln)
NEXT

My.Data

Proporciona características para el manejo de datos.

El método CloseAllInstances cierra todas las copias abiertas de una tabla pasada como parámetro en todas las sesiones de datos. Esto es útil si se necesita acceso exclusivo a la tabla, como por ejemplo para modificar su estructura.
 LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
My.Data.CloseAllInstances('MiTabla')
USE MiTabla EXCLUSIVE
El método OpenCursorSnapshot toma una instantánea de todos los cursores abiertos, de manera que luego el método CloseOpenedCursors solo cierra los cursores abiertos entre la llamada de ambos métodos.
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
My.Data.OpenCursorSnapshot()
USE MiVista1 IN 0
USE MiVista2 IN 0
&& ...
My.Data.CloseOpenedCursors()
El método Goto realiza un GOTO seguro, que nos asegura que el puntero ira al registro especificado, y si el número de registro no es válido, el puntero de registro se posicionará al final del archivo EOF().
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
USE MiTabla
My.Data.GoTo(99)

My.Settings

Proporciona configuraciones específicas para nuestras aplicaciones. Estas configuraciones se guardan en un archivo .XML con un esquema igual que los archivos de configuraciones de .NET. Cuando una configuración se carga con el método Load, o se agrega con el método Add; se convierte en una propiedad dinámica del objeto My, y se puede hacer referencia a esta propiedad como es muestra a continuación:
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
My.Settings.Add('DirApp',FULLPATH(''))
? My.Settings.DirApp
Advierta que IntelliSense no esta disponible para las propiedades dinámicas, ya que estas se crean en tiempo de ejecución.

El namespace My.Setting contiene cuatro métodos que nos permiten agregar configuraciones, grabar configuraciones en un archivo, comprobar su existencia y cargar las configuraciones desde un archivo.

En el siguiente ejemplo, vamos a grabar/cargar la última posición y tamaño de un formulario cuando éste fue cerrado. Ejecute el fragmento de código de abajo, cambie la posición y tamaño del formulario, ciérrelo, y vuelva a ejecutar el código.
PUBLIC goForm AS MiForm
goForm = NEWOBJECT('MiForm')
goForm.SHOW(1)
RETURN

DEFINE CLASS MiForm AS FORM
  CAPTION = 'Mueva y cambie el tamaño del formulario'
  My = NULL
  PROCEDURE Init
    THIS.My =  NEWOBJECT('My', 'my.vcx')
    WITH THIS.My
      IF FILE(FULLPATH('MiConfig.xml'))
        .Settings.Load(FULLPATH('MiConfig.xml'))
      ENDIF
      IF .Settings.EXISTS('FormTop')
        THIS.TOP    = .Settings.FormTop
        THIS.LEFT   = .Settings.FormLeft
        THIS.HEIGHT = .Settings.FormHeight
        THIS.WIDTH  = .Settings.FormWidth
      ENDIF
    ENDWITH
  ENDPROC
  PROCEDURE Destroy
    WITH THIS.My
      .Settings.Add('FormTop', THIS.TOP)
      .Settings.Add('FormLeft', THIS.LEFT)
      .Settings.Add('FormHeight', THIS.HEIGHT)
      .Settings.Add('FormWidth', THIS.WIDTH)
      .Settings.Save(FULLPATH('MiConfig.xml'))
    ENDWITH
  ENDPROC
ENDDEFINE

My.User

Proporciona información del usuario actual con las siguientes propiedades:
LOCAL My AS My
My = NEWOBJECT('My', 'my.vcx')
? My.User.DisplayName
? My.User.UserDomain
? My.User.UserName

Para tener en cuenta

Si usa My en una aplicación, asegúrese de incluir My.vcx y My.dbf en su proyecto. Se recomienda marcar como incluida a la tabla My.dbf para que también queden incluidos los archivos My.cdx y My.fpt. Si usa el namespace My.Settings asegúrese de distribuir el archivo de configuración .XML.

Ninguna de las clases My tienen código en su método Error, con lo cual si ocurre un error en un método de My, lo atrapará el controlador de error global de su aplicación, a menos que encierre las llamadas a los métodos de My entre una estructura TRY ... CATCH ... ENDTRY.

Mejorar My

El acuerdo de licencia incluido en la descarga de Sedna, nos permite la distribución y la modificación del código fuente incluido para todos los componentes de Sedna. Nosotros podemos añadir mas funcionalidad a My, como así también crear nuestros propios namespaces o subclasear la clase My.
El Equipo Visual FoxPro de Microsoft lanzó el complemento Sedna como un proyecto de código compartido en VFPx. Este se dividió en 6 proyectos distintos. Para el caso de la librería My, la podemos encontrar en "My for VFP". Allí todos podemos colaborar para mejorar Sedna, como así también todas las clases disponibles en VFPx o VFPy. Quedan todos invitados a participar.

Hasta la próxima.

Luis María Guayán

No hay comentarios. :

Publicar un comentario