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