*!* Cambia la resolución de la pantalla
*!* Sintaxis: ChangeRes(tnWidth, tnHeight)
*!* Valor devuelto: llRetVal
*!* Argumentos: tnWidth, tnHeight
*!* tnWidth especifica la nueva anchura de la pantalla en pixels
*!* tnHeight especifica la nueva altura de la pantalla en pixels
FUNCTION ChangeRes
LPARAMETERS tnWidth, tnHeight
LOCAL lnWidth, lnHeight, lnModeNum, lcDevMode
*!* Valores
lnModeNum = 0
lcDevMode = REPLICATE(CHR(0), 156)
lnWidth = IIF(EMPTY(tnWidth), 800, tnWidth)
lnHeight = IIF(EMPTY(tnHeight), 600, tnHeight)
*!* Instrucciones DECLARE DLL para cambiar resolución
DECLARE INTEGER EnumDisplaySettings IN Win32API STRING lpszDeviceName,;
INTEGER iModeNum, STRING @lpDevMode
DECLARE INTEGER ChangeDisplaySettings IN Win32API STRING @lpDevMode ,;
INTEGER dwFlags
*!* Bucle para obtener todos los modos disponibles
DO WHILE EnumDisplaySettings(NULL, lnModeNum, @lcDevMode) <> 0
lnModeNum = lnModeNum +1
ENDDO
*!* Configurar la structura DevMode
lcDevMode = STUFF(lcDevMode, 41, 4, LongToStr(1572864))
lcDevMode = STUFF(lcDevMode, 109, 4, LongToStr(tnWidth)) && Ancho
lcDevMode = STUFF(lcDevMode, 113, 4, LongToStr(tnHeight)) && Alto
*!* Cambiar resolucion
ChangeDisplaySettings(@lcDevMode, 1)
ENDFUNC
*!* Convierte un long integer a un 4-byte character string
*!* Sintaxis: LongToStr(lnLongVal)
*!* Valor devuelto: lcRetStr
*!* Argumentos: lnLongVal
*!* lnLongVal especifica el long integer a convertir
FUNCTION LongToStr
LPARAMETERS lnLongVal
LOCAL lnCnt, lcRetStr
lcRetStr = ''
FOR lnCnt = 24 TO 0 STEP -8
lcRetStr = CHR(INT(lnLongVal/(2^lnCnt))) + lcRetStr
lnLongVal = MOD(lnLongVal, (2^lnCnt))
NEXT
RETURN lcRetStr
ENDFUNC
23 de octubre de 2018
Cambia la resolución de la pantalla
7 de octubre de 2018
Una funcion ADIR() Extendida que devuelve los nombres de los archivos con la ruta completa
Retorna en un vector la ruta y nombre de de todos los archivos que concuerden con lo especificado en "tcWild".
*--------------------------------------------------------
* FUNCTION ADIRX() - ADIR Extendido
*--------------------------------------------------------
* Devuelve en un array "taArray" pasado por referencia
* el listado de archivos especificado en "tcWild" con
* la ruta completa. Ej: "D:\WORD\DOCUMENTO.DOC"
* PARAMETROS:
* taArray: Array pasado por referencia
* tcWild: Tipos de archivo. Ej: *.DBF
* tcRoot: Directorio donde busca los archivos
* RETORNA: Numerico = Cantidad de archivos
* USO:
* DIMENSION MiArray[1]
* ? ADIRX(@MiArray, "*.PRG", "C:\PROGRAMAS\")
*--------------------------------------------------------
FUNCTION ADIRX(taArray, tcWild, tcRoot)
IF EMPTY(tcWild)
*--- Por defecto "*.*"
tcWild = "*.*"
ENDIF
IF EMPTY(tcRoot)
*--- Por defecto directorio actual
tcRoot = SYS(5) + CURDIR()
ENDIF
tcRoot = ADDBS(tcRoot)
DIMENSION taArray[1]
lnCant = ADIR(taAux, tcRoot + tcWild)
FOR lnI = 1 TO lnCant
taArray[lnI] = tcRoot + taAux[lnI, 1]
DIMENSION taArray[ALEN(taArray) + 1]
ENDFOR
IF ALEN(taArray) > 1
DIMENSION taArray[ALEN(taArray) - 1]
RETURN ALEN(taArray)
ELSE
RETURN 0
ENDIF
ENDFUNC
Luis María Guayán
Yerba Buena, Tucumán
24 de septiembre de 2018
Como me aseguro que los formularios apuntan a las tablas correctas
Los formularios almacenan el path de las tablas definidas en el Entorno de Datos.
Por desgracia cuando se distribuye la aplicación, estos formularios pueden apuntar al directorio donde se desarrollaron. Estos paths deben ser reseteados en tiempo de ejecución para asegurarnos que apuntan a las tablas correctas.
* en el programa principal o en la de conexion determinar el directorio actual * almacenarlo en variables globalos o del objeto aplicación. gcAppPath = sys(2003) gcDBPath = alltrim(gcAppPath)+"datos" gcDBName = "mibasededatos.dbc"
Poner en el entorno de datos la propiedad AutoOpenTables = .F.
modificar la clase base del formulario (o cambialo en cada formulario) en el Metodo Load:
* apuntar todas las tablas al directorio y base de datos correcto
thisform.SetAll("Database",gcDbPath+gcDbname,"Cursor")
* abrir las tablas
thisform.dataenvironment.opentables()
NOTA: esto funciona con tablas de una base de datos, este codigo debe ser modificado si se usan tablas libres.
Pablo Roca
11 de septiembre de 2018
Vaciar el contenido de un directorio (archivos y carpetas)
Como podemos vaciar una carpeta y todo su contenido (Modificado)
*-----------------------------------------------------------------
* FUNCTION EmptyDir(tcRoot, tlNotAsk)
*-----------------------------------------------------------------
* Vacia todo el contenido (archivos y carpetas) del directorio
* "tcRoot" pasado como parámetro
* PARAMETROS:
* tcRoot = Directorio a vaciar
* tlNotAsk = .T. - No pregunta antes de vaciar el directorio
* USO:
* =EmptyDir("C:TEMP", .F.)
*-----------------------------------------------------------------
FUNCTION EmptyDir(tcRoot, tlNotAsk)
PRIVATE lnI, lnCant, laAux, lcSubDir
tcRoot = ADDBS(tcRoot)
IF NOT tlNotAsk
IF 1 <> MESSAGEBOX("¿Esta Ud. seguro de borrar " + ;
"todos los archivos y carpetas de" +CHR(13) + ;
tcRoot + "?", 1+32+256, "Atención")
RETURN
ENDIF
ENDIF
********************************
**** Agregado por Leonel Ortega ***
********************************
miComm = "attrib -r -h "+(tcRoot + "*.*")+" /S /D"
=wScript(miComm,2)
********************************
DELETE FILE (tcRoot + "*.*")
lnCant = ADIR(laAux, tcRoot + "*.", "D")
FOR lnI = 1 TO lnCant
IF "D" $ laAux[lnI, 5]
IF laAux[lnI, 1] == "." OR laAux[lnI, 1] == ".."
LOOP
ELSE
lcSubDir = ADDBS(tcRoot + laAux[lnI, 1])
=EmptyDir(lcSubDir, .T.)
RMDIR (lcSubDir)
ENDIF
ENDIF
ENDFOR
RETURN
ENDFUNC
********************************
**** Agregado por Leonel Ortega ***
********************************
FUNCTION wScript
LPARAMETER eComm, eWindowType
IF pCount()=0
WAIT WINDOW 'Faltan parametros en WScript' TIMEOUT 2
ENDIF
IF pCount()=1
eWindowType = 1
ENDIF
LOCAL loWshShell
loWshShell = CREATEOBJECT("WScript.shell")
loWshShell.RUN( eComm ,eWindowType,.T.) && el 2 es minimizado, 1 es Normal
ENDFUNC
********************************
23 de agosto de 2018
Cerrar aplicación si un usuario esta mucho tiempo sin trabajar
¿Cuantas veces nos hemos encontrado que nuestros usuarios se van a tomar un cafe o marchan a comer con la aplicación abierta?
La verdad, es que a mi esto me há dado bastantes problemas, ya que realizo las copias de seguridad al mediodia. Y día si, día también hay usuarios que dejan la aplicación abierta, con el problema de que la copia no se realiza ya que los usuarios dejan archivos abiertos.
La solución es la siguiente:
crear un timer (p.ejemplo) programado para 15-20 minutos, y el el evento timer programar los pasos necesarios para cerrar la aplicación.
para que el timer no se dispare cuando los usuarios estan trabajando hago lo siguiente:
En el evento mouse move del formulario y en el keypress de cada objeto, hago:
IF VARTYPE(gotimer_inactividad)="O"
* la cuenta atras de tiempo se inicia otra vez
gotimer_inactividad.interval = gocsapp.tiempo_espera
ENDIF
En mi caso la parte del formulario la hago solo una vez, ya que todos mis formularios son hijos de uno maestro definido como una clase base.
¿Que codigo se pone para cerrar la aplicación? Depende de lo que desees hacer, es decir puedes no querer cerrar a un usuario si esta en el medio de una grabación,... yo en mi caso les cierro la aplicación descartando cualquier cambio que hayan realizado.
¿Drastico? Si, pero despues de que los usuarios pierden su trabajo dos veces, debido a su negligencia, os aseguro que no volveran a dejar el ordenador indebidamente encendido.
NOTAS:
gotimer_inactividad - es el objeto timer creado al iniciar la aplicación gocsapp - es una clase general a todas las aplicaciones que desarrollo, tiene propiedades y metodos habituales. gocsapp.tiempo_espera - define el tiempo de espera para lanzar el timer. Es por si aumento o disminuyo el tiempo de espera para no tener que cambiarselo a todos los objetos. Normalmente ahi le pongo 900000
Pablo Roca