3 de octubre de 2019

Colocar menús popup

Colocar menús popup

Artículo original: Positioning popup menus
http://www.foxpert.com/knowlbits_200801_2.htm
Autor: Christof Wollenhaupt
Traducido por: Ana María Bisbé York


No soy un gran fan de los menús contextuales (clic derecho del ratón). En muchas aplicaciones se implementan de forma incorrecta y no se pueden invocar con la tecla de menú contextual o la combinación estándar Shift+10. Para muchos desarrolladores, a veces parecen como un depósito para descargas. En lugar de pensar en cómo incorporar una nueva característica en la justa medida, simplemente agregan la función al menú contextual de un formulario. En esos casos, los menús contextuales son difíciles de descubrir para el usuario final. Teniendo que hacer clic en cada píxel y descubrir si hay alguna característica oculta, solamente está genial para los juegos; pero realmente no es apropiado para una aplicación productiva.

Existen usos para el menú contextual. Hay que tener en mente, que el nombre "acceso directo" es el hecho de que los menús originales sean una vía rápida para las características de acceso con un ratón, que estarían también disponible en el menú o en los botones. Las características que están solamente disponibles a través de menú contextual o de menús popups de múltiples niveles, y cuando se abre una ventana en algún otro lugar en la pantalla, difícilmente entran dentro de esa categoría.

Regresamos al tema. Existen muchas ocasiones en las que tiene sentido brindar menos opciones utilizando funcionalidades en un formulario. Por ejemplo, una característica útil para un control TextBox, es abrir una ventana examinador con una búsqueda web. Para esta funcionalidad utilizo un pequeño botón en el control TextBox que muestra una flecha hacia abajo ("u" en fuente Marlett). Este botón abre un pequeño popup, justo debajo del botón, como se ve en Microsoft Office.

Colocar menús popup produce código que utiliza MCOL() y MROW() para colocar los menús según la posición del ratón. Esto trabaja bien sin que haga clic en ningún lugar del título de la ventana. En este caso, las dos funciones devuelven -1 moviendo el popup a algún lugar fuera de esta ventana.

Cuando intenta mover el popup a algún lugar, se da cuenta enseguida que tiene una posición dada en Fóxeles en lugar de píxeles. Los Fóxeles son para Visual FoxPro lo que los Twips son para Visual Basic. Un Fóxel depende del tamaño de la fuente actual del formulario. En otras palabras, cambiar la propiedad ThisForm.FontName o cualquiera otra propiedad de fuente hará que cambie las medidas a Fóxeles.

La propiedad ScaleMode, que se utiliza raramente, permite especificar las coordenadas del formulario en Fóxeles o píxeles. Como nota al margen, un formulario con medidas Fóxeles es una buena forma de romper lo genérico de la tercera parte de los componentes. Muchos desarrolladores no trabajan mucho con las posiciones que tienen lugares decimales y añaden píxeles a las propiedades Left, Top, Width y Height sin verificar la escala antes.

Entonces, para ubicar un control popup justo debajo o arriba de un botón de comandos, puede cambiar las medidas, leer la posición del botón en Fóxeles y devolver el valor a píxeles. Esto trabaja bien para botones que estén colocados en el formulario directamente. Con controles anidados, sin embargo, tiene que utilizar OBJTOCLIENT(), una función que ignora completamente la propiedad ScaleMode. Para solucionar esto, agrego un botón derecho invisible en el formulario.

Local lnRow, lnColumn
If Vartype(Thisform.PosHelp) != "O"
  Thisform.AddObject("PosHelp", "Commandbutton")
EndIf
Thisform.PosHelp.Move( ;
  Objtoclient(This,2), ;
  Objtoclient(This,1) + This.Height ;
  )
Thisform.ScaleMode = 0
lnRow = Thisform.PosHelp.Top
lnColumn = Thisform.PosHelp.Left
Thisform.ScaleMode = 3

Con la posición en Fóxeles puedo ahora definir un menú popup como este:

DEFINE POPUP shortcut ;
  SHORTCUT RELATIVE ;
  From m.lnRow, m.lnColumn ;
  Font Thisform.FontName, This.FontSize
Define bar 1 of Shortcut Prompt "Elemento 1"
Define bar 2 of Shortcut Prompt "Elemento 2"
Define bar 3 of Shortcut Prompt "Elemento 3"
Activate Popup Shortcut

Si es que sorprende sobre la cláusula FONT que utilicé aquí, explico. Algunos clientes insisten en un control redimensionar para el formulario. Esto es, cuando un formulario se redimensiona, el contenido se alargara. Con esta cláusula el menú popup tiene el mismo tamaño que todo lo demás en el formulario.


21 de septiembre de 2019

Almacenar objetos grandes en la base de datos

Ejemplo de como subir archivos en una base de datos, en este caso PostgreSQL.

Muchas veces nos encontramos con la necesidad de guardar archivos en el servidor para disponibilidad de los usuarios de nuestra aplicación.

La acostumbrada ruta aleatoria del archivo en una base de datos y su posterior copiado en el mismo muchas veces no sera aplicable mas aun cuando nuestra base de datos se encuentra en un servidor remoto donde no disponemos de accesos a sus recursos

Aquí es cuando surge la necesidad de cambiar la estrategia de almacenamiento de estos objetos grandes en campos de la base de datos el ejemplo utiliza un campo tipo text equivalente a un campo memo de una dbf.

Lo primero es convertir nuestro archivo a base 64 para poder almacenarlo y lo hacemos con las siguientes lineas :

nfile = GETFILE()
** convertimos a base 64
wbase64 = strconv(filetostr(nfile),13)
** almacenamos en la base de datos
sqlexec(1,"insert into sistema.multimedia (objeto,nombre) values (? wbase64,?justfname(nfile))","rta")
** para descargar el archivo usaramos la siguiente sintaxis
sqlexec(1,"select * from sistema.multimedia where ide=1","rta")
_rutarchivo = SYS(5) + "\" + ALLTRIM(rta.nombre)
sele rta
strtofile(STRCONV(rta.objeto,14),_rutarchivo)
** y lo podemos abrir con el programa asociado
oShell = CreateObject("WScript.Shell")
oShell.Run(_rutarchivo,2,.f.)

mgx

13 de agosto de 2019

Solucionar el problema del relleno de VarChar

Solucionar el problema del relleno de VarChar

Autor: Mike Lewis
Texto original: Solving the "padded VarChar" problem (http://www.ml-consult.co.uk/foxst-36.htm)
Traducido por: Ana María Bisbé York


¿Cómo evitar los espacios no deseados en las tablas en Bases de datos?

Si utiliza vistas remotas para actualizar datos en bases de datos remotas, probablemente haya sufrido el problema del relleno en campos VarChar.

Cuando Visual FoxPro lee datos remotos (como puede ser SQL Server u Oracle) a una vista remota, convierte cualquier columna VarChar en un campo caracteres. Cada campo se rellena con espacios para llenar el mayor ancho. Si luego utiliza esa vista remota para actualizar el servidor, los espacios agregados se envían de regreso. El servidor almacena espacios en blanco extras en las tablas, lo que impide aprovecharse de los beneficios de datos VarChar.

En VFP 7.0 y antes, no había mucho que se pudiera hacer. De hecho, esta era una de las razones por las que los desarrolladores evitaran el uso de vistas remotas al actualizar datos, prefiriendo en su lugar utilizar comandos UPDATE y DELETE directamente vía SQL pass-through. VFP 8.0 proporciona un tratamiento alternativo con el CursorAdapter. Al agregar la función Trim en la propiedad ConversionFunc del CursorAdapter, puede eliminar los espacios extras. Pero el paso de vistas remotas a CursorAdapters podría involucrar bastante trabajo.

Una mejor solución

VFP 9.0 ofrece una solución mucho mejor. A diferencia de versiones anteriores, la versión 9.0 soporta el tipo de dato VarChar en vistas remotas. Si ambos campos, los de Vistas remotas y los del servidor son VarChar, los datos no se van a rellenar con espacios, entonces, no surgirá el problema.

Sin embargo, esto no ocurre automáticamente. De forma predeterminada, cualquier columna VarChar en el servidor se va a corresponder con un campo de caracteres en las vistas, como en versiones anteriores. Para poder aprovechar las ventajas del nuevo tipo de dato VarChar, hay que cambiar explícitamente el tipo de dato en la vista.
Si está comenzando una aplicación nueva y no tiene creadas sus vistas remotas, está de suerte. Todo lo que necesita hacer es ejecutar el siguiente comando antes de crear las vistas:

CURSORSETPROP("MapVarChar", .T., 0) 

Esto dice a VFP que haga corresponder columnas VarChar con campos VarChar del servidor. Al pasar 0 como tercer parámetro, se estipula que esta configuración se aplica a todas las vistas creadas en la sesión actual. Esto sólo afecta a las nuevas vistas que se creen, cualquier vista creada antes, no se verá afectada. Esta configuración no es persistente, asegúrese de ejecutar el comando anterior antes de crear vistas en la sesión actual.

Hacerlo retrospectivamente

Si ha creado sus vistas remotas, será necesario alterar el tipo de dato cada uno de los campos relevantes. Una vía de hacerlo es desde dentro del diseñador de vistas. Desde el menú Consultas, abra la ventana View SQL (Ver SQL). Verá la sentencia SQL que define la vista, seguida de una serie de llamadas DBSETPROP(). Este va a incluir, por cada uno de los campos de la vista, una línea de código que establece el tipo de dato del campo. Por ejemplo:

DBSetProp(ThisView+".company","Field","DataType","C(40)")

El C(40) en este ejemplo indica un campo de caracteres con ancho fijo, igual a 40. Para convertirlo en un campo VarChar, simplemente cambie la C por una V. Repita este proceso para todos los campos que quiere que se correspondan con VarChar, luego guarde la vista y cierre el diseñador. Los cambios serán efectivos la próxima vez que se abra la vista.

Alternativamente, puede utilizar la ventana comandos para hacer este trabajo. En este caso escriba un comando similar al del ejemplo anterior; pero con el nombre de la vista precediendo al nombre de la columna, en lugar de ThisView. Nuevamente cambie el tipo de datos de C a V:

DBSetProp("Customer.company","Field","DataType","V(40)")

Repita este proceso para cada campo que desee corresponder en cada uno de las vistas remotas. Como antes, los cambios van a tener efecto, la próxima vez que se abra la vista.

Mike Lewis Consultants Ltd. Febrero 2005