28 de septiembre de 2016

Una forma de localizar un form y ponerlo en primer plano mediante código

He averiguado una forma bastante interesante que me permite localizar un form abierto y ponerlo en primer lugar. Tengo una aplicación que ya es bastante grande y no quería usar el consabido 'DO FORM xxxx NAME xVar LINKED' pues no quiero ocupar más espacio en memoria de lo necesario.

VFP tiene en el objeto '_Screen' una matriz que hace referencia a cada uno de los forms abiertos, te tal forma que se puede acceder a dicha matriz. Basándome en esto escribí el siguiente código:

LOCAL lix,lcObjeto,lcTextp
lix = 0
lcObjeto = "Objeto"
DO WHILE !EMPTY(lcObjeto)
  lix = lix +1 
  lcObjeto = "_screen.forms(" + ALLTRIM(STR(lix)) + ")"
  IF TYPE(lcObjeto) = "O"
    lcTextp = &lcObjeto..CAPTION
    IF lcTextp = "Archivo de facturas de compras"
      &lcObjeto..ALWAYSONTOP = .T.
      &lcObjeto..ALWAYSONTOP = .F.
      &lcObjeto..ACTIVATE
      &lcObjeto..pagfrm1.page1.SETFOCUS
    ENDIF
  ELSE
    lcObjeto = ""
  ENDIF
ENDDO

La variable lcObjeto es la que nos va dar acceso al formulario, inicialmente le pongo cualquier valor para que se ejecute el 'DO WHILE ...'. Con cada pasada el 'DO WHILE ...', le incremento la variable 'lix' que es la que nos sirve para indicar cual es el formulario deseado. Pasamos a la variable 'lcTextp' el Caption de cada Form de la matriz y cuando localizamos el que queremos, directamente le cambiamos la propiedad AlwaysOnTop = .T., de esta forma pasa a primer plano, y luego lo ponemos a su valor verdadero. De todas formas por si acaso en el evento 'Activate' del Form tambien tengo puesto el AlwaysOnTop = .F. por si acaso.

Espero que se sirva a alguien, creo que como idea no está mal.

Saludos

Rafael Ramírez

21 de septiembre de 2016

Resolución de SECONDS()

Artículo original: Resolution of SECONDS()
http://www.foxpert.com/knowlbits_200705_5.htm
Autor: Christof Wollenhaupt
Traducido por: Ana María Bisbé York


En Win 9.x, SECONDS() tiene resolución de 1 ms. En los sistemas basados en NT, SECONDS() cambia cada 10 ms, como se puede ver en el programa siguiente:

For t=1 to 100
  ? Seconds()
endfor

En NT se puede cambiar la resolución para SECONDS() utilizando la función API timeBeginPeriod:

Declare long timeBeginPeriod in WinMM.dll long
timeBeginPeriod(1)

Ahora SECONDS() incrementa cada milisegundo:

For t=1 to 100
  ? Seconds()
Endfor

14 de septiembre de 2016

Saber por Api, si podemos Abrir Un Archivo de Forma Exclusiva

Esta Api, nos permite saber si un archivo lo podemos abrir de manera Exclusiva

Si Devuelve .T., esta bloqueado por otra aplicacion, util para saber si esta en uso.

? EstaBloqueado("c:\atisaappreg01.dbf")

Function EstaBloqueado(cArchivo)
 Declare Long _lopen In "kernel32" as lOpen String lpPathName, Long iReadWrite
 Declare Long _lclose In "kernel32" as lClose Long hFile
 Local hFile As Long
 hFile = -1
 hFile = lOpen(cArchivo, 0x10)
 Result = hFile = -1
 lClose (hFile)
 Return Result
Endfunc

Jorge Mota

7 de septiembre de 2016

FONTMETRIC(), TXTWIDTH() y DPI pantallas de Windows

Artículo original: FONTMETRIC(), TXTWIDTH(), and screen DPI in Windows http://www.spacefold.com/colin/posts/2005/12-01FONTMETRICandScreenD.html
Autor: Colin Nicholls
Traducido por: Ana María Bisbé York


Si está tratando de dar tamaño a objetos en un formulario VFP que se correspondan a una fuente específica, tiene que tener en cuenta también la configuración actual de DPI ( Dots Per Inch - Puntos por pulgada) de la pantalla. Considere calcular el tamaño de un objeto Rectángulo que rodee un trozo de texto dado. Conoce las propiedades fontname, fontsize y la cadena de texto; pero no conoce las dimensiones. No hay problemas, puede decir, solo necesito utilizar FONTMETRIC() y TXTWIDTH() para calcular el tamaño del texto en pixeles:

iAvgCharWidth = FONTMETRIC(6, cFontName, cFontSize, "" )
iTextWidth = TXTWIDTH( cString, cFontName, cFontSize, "" ) * iAvgCharWidth

... y diría ... ahora puedo calcular adecuadamente el tamaño de mi rectángulo

No tan rápido. ¿Qué tal si su monitor de Windows estuviera configurado en 120 DPI? El texto se crearía de tamaño diferente. Debe tener esto en cuenta:

*---------------------------------
* Determina la configuración DPI de la pantalla:
*---------------------------------
#DEFINE LOGPIXELSX 88
DECLARE INTEGER GetDeviceCaps IN WIN32API INTEGER HDC, INTEGER ITEM
DECLARE INTEGER GetDC IN WIN32API INTEGER HWND
*DECLARE INTEGER DeleteDC in WIN32API integer HDC
DECLARE INTEGER ReleaseDC IN WIN32API INTEGER HWND, INTEGER HDC
LOCAL hdc, screenDPI
hdc = GetDC(0)
THIS.screenDPI = GetDeviceCaps( m.hdc, LOGPIXELSX )
ReleaseDC( 0, m.hdc )
IF iScreenDPI <> 96
  iTextWidth = INT( (iTextWidth * iScreenDPI)/96 )
ENDIF

Estuve peleándome con este tema recientemente, ocupándome de un bug reportado por alguien que decía que los textos del título del Pageframe se truncaban, si su entorno estaba configurado como 120DPI + "Fuentes grandes"

Bueno, esta mañana leí un post del prestigioso Charles Petzold (http://www.charlespetzold.com/blog/blog.xml#0511250723) sobre Unidades independientes de dispositivo Device Independent Units (DIU) que de alguna manera (y más) explica por qué tenemos que hacerlo de esta forma, porque creo que Visual FoxPro en realidad emplea pixeles reales en lugar de DIU. Este post merece ser leído.