Blog sobre programación en VFP, Actualizado por Jorge Mota en Guatemala ;)



Archivo de CategoríasTrucos



Desarrollo & Ideas & Trucos 13 Feb 2008 02:02 pm

Como imprimir imágenes almacenadas en tablas sin usar campo general en los reportes (VFP 9)

, , , , , , , , ,

Bueno, hasta hace poco lo que hacía al necesitar imprimir una imagen en un reporte era usar campo general para almacenarlas o sacarlas a un directorio temporal para así poder mandarlas a impresión.

Pero ahora con el campo BLOB en VFP9 podemos almacenar el contenido de una imagen y al mismo tiempo imprimirla en un reporte sin necesitar hacer conversión a un campo general.

Veamos un ejemplo

Create cursor qImagen (imagen blob)
append blank in qImagen
lcDir =FullPath(Curdir())
replace qImagen.imagen with filetostr(getfile([jpg;bmp;gif]))
cd (lcDir)
private oImg
oImg = newobject([image])
oImg.pictureVal = qImagen.imagen

Necesitamos también un reporte con un objeto Picture/OLE Bound establecido así:

Ahora corremos el reporte
report form "NuestroReporte" preview

Pero y que pasa si queremos imprimir imágenes que están almacenados en una tabla (en registros diferentes)?

Grabamos lo siguiente como GetImg.prg

*Function getImg
lParameters nId, cImgCont
oImg = newobj([image])
oImg.pictureval =cImgCont
return oImg

Creamos un reporte y le agregamos un objeto Picture/OLE Bound y le establecemos la propiedad así:
reporte_picture_val2.jpg

Ahora podemos probar la función en el reporte:

use in select([qImagen])
Create cursor qImagen (numero i,imagen blob)

append Blank in qImagen
append Blank in qImagen
append Blank in qImagen
append Blank in qImagen

lcDir =FullPath(Curdir())
lcFile = getfile([jpg;bmp;gif])
update qImagen set numero =recno(),imagen =filetostr(lcFile)
report form "MiReporte" preview

, , , , , , , , ,

Desarrollo & API & Ideas & Trucos 08 Ago 2007 01:43 pm

Obteniendo el nombre corto de una ruta o archivo

, , , , , , , ,

Hace poco me tope con la necesidad de saber la ruta corta de un archivo (o ruta DOS), al decir ruta corta me refiero a la ruta que manejaba el DOS antiguo, que a diferencia de windows cada archivo solo puede tener 8 caracteres en el nombre del archivo y 3 en la extensión. es decir

C:\Mis Archivos\Juan Pérez y Pérez.xls una aplicación DOS lo encontraría así: C:\Misarc~1\JUANPR~1.XLS.

Esta Función permite obtener ese nombre corto:

Function GetDosFileName(lcfile As String) As String
**http://fox.desdeguate.com/?p=77
**Autor: Jorge Mota
**Devuelve la ruta corta (DOS) de una ruta o un archivo.
Declare Long GetShortPathName In "kernel32" String lpszLongPath,;
String lpszShortPath, Long lBuffer
lcFileName=Replicate(Chr(0),254)
lnTotal=GetShortPathName(lcfile, @lcFileName, Len(lcFileName))
Return Substr(lcFileName,1,lnTotal)
Endfunc

Ejemplos de uso:
Archivo:
?lcfile = GetDosFileName([C:\Juan Pérez y Pérez.xls])
Directorio:
lcDir = GetDosFileName([C:\Archivos de Programa\])

Retornará una cadena vacía si el directorio o archivo no existe.

Hasta la próxima.

, , , , , , , ,

Desarrollo & Ideas & Trucos 29 Jul 2007 01:01 pm

Obteniendo la hora desde un servidor de Tiempo en internet con vfp (iTime)

, , , , , , ,

Hace algún tiempo en www.Portalfox.com se publicaron algunos artículos para poder obtener la hora de nuestro servidor, pero en algunos casos, no nos es posible tener acceso al servidor, ya que no usamos carpetas compartidas (shared) así que no podemos hacer el trabajo por medio de esos métodos.

Y como hace algún tiempo instale linux, para pruebas de servidor de mySql, en una máquina y me dí cuenta que se puede configurar como un servidor de hora, (tengo entendido que en Windows, podemos lograrlo según Microsoft para windows 2003 y para XP también pero no he tenido tiempo de probarlo), bueno el caso es que teniendo un servidor de hora me dí cuenta que podía sincronizar las estaciones XP desde el apartado que pone Hora de internet /Internet zone, al entrar a Panel de control (Control Panel) y seleccionar Hora y Fecha (date and time).

Así que me puse a investigar, de que manera podíamos obtener la hora desde un servidor de este tipo desde vfp, según el RFC 868 el servidor debe devolver un número de 32 bits, el cual debemos sumarle en segundos a la fecha 01-01-1900. a la Fecha y Hora que obtengamos de allí, debemos restarle/sumarle la diferencia horaria según en la zona que nos encontremos.

Seguir leyendo »

, , , , , , ,

Desarrollo & Trucos 18 May 2007 12:02 pm

Una interesante ayuda para Intellisense

, , , , , , ,

Bueno, en esta ocasión no les voy a presentar código propio (he estado demasiado ocupado estos ultimos días rediseñando una aplicación enorme, por eso no me han visto actualizar mucho). Esta herramienta la escribio Christof Wollenhaupt.

Básicamente nos permite tener en el intellisense las variables que declaremos en nuestro método, función, procedimiento, etc, ya sea en un prg, una clase o una forma, acá una muestra:

IntellisenseX

todo lo que necesitamos es empezar a escribir m presionar punto (m.) e IntellisenseX hará el resto.

Una nota interesante es que añade intellisense a VFP6 :) aunque no he podido probarlo por falta de esa versión.

La otra cosa por la que estoy usandolo, es por que me añade intelisense a los nombres de los campos de las tablas vfp que use el procedimiento actual, una muestra:

Intellisense X en Acción

Para iniciar IntellisenseX basta con hacer:

do isX.prg

y para quitarlo de memoria bassta con hacer:

do isX.prg with [quit]

pueden bajar desde acá http://www.foxpert.com/downloads.htm ISX, junto a varias herramientas más, vale la pena echarle un ojo al listado :)

Saludos y hasta la próxima.

, , , , , , ,

Desarrollo & API & Trucos 17 Ene 2007 02:12 pm

Administrando las declaraciones de las funciones API (iDeclare)

, , , , ,

Esta vez les presento una función que nos permite administrar nuestro código de declaración de las API, permitiendonos centrarlo en una sola tabla, y a su vez, permitirnos declarar la función una sola vez.

El ejemplo se compone de 2 funciones iDeclare y iCheckDll, que básicamente hacen lo siguiente:

  • iDeclare: Recibe como parámetro el nombre de la función que queremos declarar y revisa en la tabla iDeclare.dbf sí existe su definición, si la encuentra, invoca a iCheckDll para averiguar si ya ha sido declarada, en caso de ser afirmativo retorna .T., en caso de ser negativo, ejecutara el código para declarar nuestra función dll.
  • iCheckDLL: Esta función hace uso de aDLLS y aScan (introducidas en VFP 7) para obtener una matriz de las dll declaradas y buscar en la misma la declaración de la función que nos interesa.

Un breve ejemplo usando iDeclare sería:

=iDeclare([GetActiveWindow])
lnHandle = GetActiveWindow()

Sí no queremos usar iDeclare y poder declarar nosotros la función según necesitemos podemos hacerlo así:

If !iCheckDLL([GetActiveWindow])
	Declare Long GetActiveWindow In user32
Endif
lnHandle = GetActiveWindow()

Para descargar la función: http://fox.desdeguate.com/descargas/vfp/iDeclare.zip

Saludos y hasta la próxima :) .

, , , , ,

Desarrollo & Trucos 06 Dic 2006 08:46 am

Permitiendo al usuario rediseñar la interfaz de nuestra aplicación

¿Cuantas veces hemos deseado poder mover un poquito un control hacia algún lado, redimensionar un grid, o un botón cuando hemos viajado con el cliente y hemos llevado un exe, y la siguiente entrega que haremos, nada más será para hacer un cambio estetico menor?

Algunas veces nos pasa que el cliente nos pide que le pasemos x texto hacia arriba o que pongamos la etiqueta en la que mostramos alguna información abajo en lugar de estar arriba, es decir cambios menores en la interfaz.

Para esos problemas de amor y de cambios de interfaz inesperados llega iDesigner :P

Para obtener el resultado como en este video (requiere el codec DivX) solo debe arrastrar una instancia de la clase _design_gral al formulario y en algún botón, método, evento o donde prefiera :) colocar el siguiente código:

thisform._design_gral.agregar_mod()

Donde _Design_Gral es el nombre de la instancia de la clase que agregó a su formulario.

La clase cuenta con algunas propiedades que deberá establecer:

  • cConfiguracion: Archivo en el que se almacenan las propiedades que establezca de cada objeto/formulario (puede grabar la información de varios formularios y sus objetos en la misma tabla, o puede usar uno por formulario).
  • cExluir: Listado de las clases base que no deseamos agregar el comportamiento de la clase, el valor predeterminado es “Timer”, “Line”, “Shape”, en la forma de ejemplo, esta configurada a “Timer”, “Line”, por lo que el Shape si permite ajustar el tamaño y posición.
  • lMostrarPosicion: Cuando se establece a .T. muestra una ventana con información sobre el ultimo objeto que se ajusto en tamaño/posición como Alto, Ancho, Posición X y Y, permitiendo escribir un valor para cada uno de estos, para una presición mayor en cuanto al ajuste.
  • lRecordarForm: Cuando se establece a .T. cada vez que se ejecute el formulario, recuerda la posición y tamaño del mismo.
  • nEspacio: Indical el espacio que ocuparan los indicadores de ajuste en pixeles, un valor grande puede ayudar a encontrar el ajustador, pero puede quedar debajo de otro control, si esta muy cerca del mismo, un valor pequeño puede dificultar usar el control, se recomienda que se use entre un rango de 8 y 15.

Al Llamar al Método agregar_mod() de la clase, se muestra un mensaje como este:

Mensaje de información de iDesigner

Puede modificar la clase frm_aviso para cambiar el mensaje, puede que quiera poner instrucciones sobre el uso de los controles o algún texto en especial.

Cuando la propiedad lMostrarPosicion se establece a .T. al llamar al método agregar_mod(), la clase despliega una ventana donde puede editar la posición y el tamaño del objeto:

Propiedades Objeto iDesigner

Para descargar la clase, clic acá http://fox.desdeguate.com/descargas/vfp/iDesigner.zip y el video de ejemplo para ver la clase trabajando acá.

Para los que no quieran/tengan DivX :

Bueno, eso es todo, hasta la próxima y espero les sirva :)

Trucos 23 Nov 2006 06:00 am

Obtener un listado de los links de una página web

Bueno, luego de la función para obtener una “versión de solo texto de una página web” les traigo otra función que devuelve el listado de vinculos dentro de la página web que le indiquemos como parametro.

su uso es sencillo:
Mostrandolo en la pantalla de VFP

?GetPageLinks("http://google.com")

Grabando el listado en un archivo de texto:

Strtofile(GetPageLinks("http://google.com"), "c:/google_links.txt",0)

El código de la función es este:

Function GetPageLinks(cUrl As String) As String
	Local Texto, oIE, cResul, oDoc
	oIE = Createobject("InternetExplorer.Application")
	oIE.Navigate2(cUrl)
	Texto ="Procesando página"
	Do While oIE.busy
		Wait Window Texto Nowait
	Enddo
	Wait Window Texto  Timeout 1.5
	*Para forzar a que IE termine de cargar la página
	oDoc = oIE.Document
	Texto = Type("oDoc.body")
	lntotal = oDoc.links.Length
	cResul =[]
	For lnCiclo  = 0 To oDoc.links.Length-1
		elemento =oDoc.links.Item(lnCiclo).toString()+Chr(13)+Chr(10)
		cResul = cResul + elemento
	Endfor
	Wait Clear
	oDoc = .Null.
	Release oDoc
	oIE.Quit
	Release oIE
	Return cResul
Endfunc

Saludos y hasta la próxima

Trucos 22 Nov 2006 06:00 am

Obtener una versión “solo texto” de una página web

Bueno, en esta ocasión les presento una función que permite obtener el texto de una página web, sin el html de la misma, no tiene formato.

El uso es sencillo, el siguiente ejemplo muestra en la pantalla de VFP, la versión solo texto de “Google”.

?GetPageasTxt("http://google.com")

Otro Ejemplo, sería grabarlo a un archivo de texto:

=Strtofile(GetPageasTxt("http://google.com"), "c:/google.txt",0)

El código de función a continuación:

Function GetPageasTxt(cUrl As String) As String
	Local Texto, oIE, cResult, oDoc
	oIE = Createobject("InternetExplorer.Application")
	oIE.Navigate2("about:blank")
	oIE.Navigate2(cUrl)
	Texto ="Procesando página"
	Do While oIE.busy
		Wait Window Texto Nowait
	Enddo
	Wait Window Texto  Timeout 1.5
	*^para forzar a que IE termine de cargar la página
	oDoc = oIE.Document
	Texto = Type("oDoc.body")
	= oDoc.body.innerText()
	cResult = oDoc.body.innerText()
	Wait Clear
	oDoc = .Null.
	Release oDoc
	oIE.Quit
	Release oIE
	Return cResult
Endfunc

Como mención sobre su código, solo basta decir que usa Internet Explorer, para obtener la versión solo texto del mismo, y en mi máquina es necesario tener el Wait Window Texto timeout 1.5 debido a que de lo contrario devuelve una cadena vacía.

Saludos y hasta la próxima.

Trucos 08 Sep 2006 02:06 pm

Ayudando un poco a Intellisense

Para algunas personas es mucho más cómodo crear clases en prg, mientras que para otros es más cómodo hacerlo en el diseñador de clases (visualmente).

Yo normalmente acostumbro a crear mis clases en prgs independientes, si necesito crear subclases dentro del mismo archivo de clases, entonces uso un VCX, de lo contrario un prg.

He notado que cuando diseñamos en prgs nuestras clases, intellisense no es capaz de ver las propiedades que nosotros agreguemos, ni nuestros métodos, como pueden ver en esta imagen:

un truco que funciona bien, es asignar variables al objeto, tal como se ve acá:


Seguir leyendo »