Índice
general |
He
notado que en muchas oportunidades me consultan una y
otra vez lo mismo, por lo que decidí abrir este sector
donde a medida que el tiempo me lo permita iré
publicando las preguntas mas frecuentes que me realizan
los programadores.
Los textos de color verde indican la respuesta.
(14-Abr-2003)
Agrandar la
letra usando PCL 5
>Bien resulta que
esta impresora ya ha dado todo lo que podía y mas y
ahora
>he comprado un HP cuya única emulación es "PCL
5" he mirado de adaptar el
>programa a este lenguaje pero me encuentro con lo
siguiente.
>
Si,
PCL es correcto.
>En IBM PROP. podía crear caracteres mas grandes con
solo una instrucción de
>escape y bajo PCL no encuentro esta secuencia.
>
Es
muy simple, debes buscar en mi página:
http://www.mundoprogramacion.com/Clipper/pcl.htm
>Por lo que la pregunta es obvia ¿conoces la forma de
conseguir que los
>caracteres se puedan hacer mas grandes ?
Por
las dudas que no comprendas como se utilizan, te adjunto
un ejemplo mas
claro.
>En el manual que tengo de IBM esta posibilidad se
llama "ENLARGED"
>
Haaaaggg
el manual, no entiendo porque no ponen los códigos PCL
allí.
Archivo ejemprn.prg (- de 1 Kb)
(08-Abr-2003)
Un buen
ejemplo de como enlazar .PRG's
>amigo, estoy
programando, pero todo lo tengo que concentar en un solo
>archivo (fuente), Pues si los trabajo por modulos, al
compilar, me manda
>Error, recuerdo que hay un comando para hacerlos
llamar internamente cada
>uno de los modulos
>por ejemplo:
>
>mi programa se llama cotización.prg, pero en ese
archivo, hay un menu
>principal, que llama al segundo o tercer modolu, pero
es lo que no recuerdo
>como hacerlo, si es con "DO", me puede
ayudar amigo, y al momento de Linkar
>solo llamar al principal, y los demás en automatico
se compilan
Me imagino.
Bueno, te adjunto un ejemplo en 4 archivos, espero lo
entiendas.
Lo compilas así:
Clipper menu
blinker fi menu
y listo.
Tienes el programa principal : MENU.PRG
Dos programas que son llamados PROG1.PRG y PROG2.PRG
y el archivo de funciones Funcs.prg
Archivo prgs.zip (3 Kb)
(07-Abr-2003)
Encriptar
bases de datos con Clipper puro.
>mi pregunta es si
hay la posibilidad
>de encriptar los archivos en dbf y como hacerlo.
>
Hay
dos maneras de hacerlo, una fácil pero cara y un poquito
mas laboriosa
aunque gratis, y con la ventaja de tener el fuente del
encriptor, ¿Cuál
supones que yo prefiera?.
La fácil es con librerías de terceros como la
DriverSix, donde te olvidas
del tema ya que la encripción/desencripción se realiza
de manera desatendida
y el programador solo debe abrir las bases de datos en
forma encriptada y
olvidarse del tema.
Estas librerías son pagas y muy caras por cierto.
Lo que hago es utilizar una rutina de
encripción/desencripción que yo mismo
creé. La misma encripta datos de cualquier tipo con
claves de cualquier tipo
y devuelve un valor de la misma longitud.
Cript(xDatos, xClave)
Encripta una variable de cualquier tipo ya sea numérica,
caracter, de fecha
o lógica y devuelve los datos del mismo tipo y largo que
la variable
original, ideal para encriptar bases de datos.
xDatos = Datos a encrptar puede ser numérica, lógica,
caracter o fecha.
xClave = Clave que puede ser numérica, lógica, caracter
o fecha.
Devuelve un valor encriptado del mismo tipo y ancho que
el original.
Ejemplo:
Cript("Esto es una prueba", 1479)
===> Una serie de caracteres ilegibles
Cript("Esto es una prueba",
"JAQUECA")
===> Una serie de caracteres ilegibles
Cript(1677, "CLAVE")
===> 8402
Cript(.T., 1479)
===> .F.
Cript(.T., 1478)
===> .T.
DeCript(xDatos, xClave)
Desencripta los datos encriptados por la función Cript()
xDatos = Datos a desencrptar puede ser numérica,
lógica, caracter o fecha.
xClave = Clave que puede ser numérica, lógica, caracter
o fecha.
Devuelve el valor original desencriptado.
Y los uso de la siguiente manera:
Ha la hora de grabar datos en una base :
[...]
Replace Base->Campo With Cript(xDato, xClave)
[...]
En un TBrow:
oTBrow:AddColumn(TbColumnNew("Nombre" ,;
{|| deCript(Base->Dato, xClave) }))
Y de la misma manera debes encriptar los datos antes de
guardarlos y
desencriptarlos al mostrarlos.
Te adjunto un archivo con las rutinas, espero haberte
ayudado.
Archivo encdec.prg (3 Kb)
(04-Abr-2003)
Pintar
registros condicionalmente con la función DbEdit()
>Maestro, existe
alguna forma en que el dbEdit se sombree a nivel de todo
el registro, no solo por campo de registro?
>
>Es decir, cuando cambie de registro, el dbEdit debe
de seleccionar o sombrear siempre TODO el registro
actual.
Sabes
hace algunos años hice la misma pregunta a varios
programadores Clipper que se encontraban en una
exposición a la que asistí.
La respuesta unánime fue : "NO".
No me convenció y le busqué la vuelta al asunto y así
fue que la encontré. Es una chapuza pero ayuda mucho
porque si bien prefiero los objetos TBrow, la función
DBEdit es mucho menos laboriosa.
Te adjunto un ejemplo donde aparecen pintados ciertos
registros de distintos campos según condiciones, por
ejemplo saldos negativos y pagos en efectivo.
Archivo Ejemdbe.ZIP (2 Kb)
(27-Mar-2003)
Leer
datos desde un lector de códigos de barras.
>necesito agregar en
un sistema de facturación de mi propiedad la lectura de
codigos barra mediante alguna pistola u otro lector de
codigos de barra. ya baje el que imprime lo que da una
ventaja, pero, como obtengo la lectura para que la
reconzca mi sistema.
>
>Espero puedas responder a mi inquietud.
>
No
entiendo por que pero recibo esta consulta muy a menudo,
está muy bien que pregunten si no conocen la respuesta,
lo que no entiendo es porque piensan que hay que hacer
algo en especial para leer la información proveniente
desde el lector de códigos de barra.
El tema es así, un lector de códigos de barra deposita
el código leído directamente en el buffer de teclado,
lo cual sería equivalente a escribir en el teclado el
código manualmente.
En pocas palabras, si tu lees con el lector un código de
barras que sea : 123456789 sería lo mismo que escribir
directamente en el teclado la secuencia numérica
132456789.
La única diferencia es que el lector seguramente lo
hará algo mas rápido.
:-)
Lo que si debes hacer es adaptar tu sistema de
facturación para que cuando se presione una tecla
numérica se abra un "Read" y lea la secuencia,
de dar <Enter> al final se encarga también el
lector, el cual algunas veces, dependiendo de la
marca" hay que configurarlo para que lo haga, esto
viene muy bien explicado en el manual del usuario.
Ejemplo de rutina para que efectúe el "Read":
Inkey(0)
[...]
Case LastKey() >= 48 .And. LastKey() <= 57
Keyb(Chr(LastKey())
@... Get CodBar Pict [999999999999999]
Read
[...]
Lo que hago es cargar en el buffer la primer tecla
presionada para que el "Read" continúe
cargando el resto del código.
(26-Mar-2003)
La
función DbEval()
>Necesito aprender a
utilizar DBEVAL() con ejemplos prácticos. Me ayudas?
Pero
por supuesto, este es el tipo de consultas que contesto
con mucho gusto.
Ok, ejemplos prácticos... veamos, la verdad es que los
manuales y guías que tengo no tienen ejemplos prácticos
sobre esta función, ni mucho menos la NG's (Norton
Guides), es un horror el ejemplo que ahí proponen.
Bueno, voy a explicarte la función por partes, espero
que lo puedas comprender, si te pierdes me lo dices y te
explico mejor algún punto.
Partamos de la funcionalidad, básicamente lo que hace es
ejecutar un "bloque de código", que puede ser
una función tuya, el incremento de una variable, etc.,
evaluando para cada registro se cumplan ciertas
condiciones.
¿La compliqué mucho verdad?
Bueno, vamos a ver cada uno de los parámetros en un
ejemplo por separado para que lo entiendas.
La sintaxis sería así:
DbEval( {|| Bloque de código, <Condición
"For">, <Condición
"While">, <nNext>, <Número de
Registro>, <lRest>)
Como podrás observar exceptuando el bloque de código
todos los demás parámetros son opcionales, con lo
cual podemos hacer mas simples los ejemplos.
Partiremos por un ejemplo donde solo se use el Bloque de
código, como no usamos condiciones lo que vamos a hacer
es contar la cantidad de registros de una base de datos.
En este ejemplo el bloque de código será
"nCount++" lo que sería igual a nCount =
nCount + 1, o sea que se incremente la variable nCount en
uno cada vez que se ejecuta el bloque, como está libre
de condiciones será en cada registro.
Ejemplo (1):
LOCAL nCount := 0
Use EJEMCLI.DBF
DbEval( {|| nCount++}, , , , , )
? "Total de Clientes :", nCount
Respuesta ==> Cantidad de registros en la base de
datos
Nota importante: dbEval() se ajusta a los filtros
preestablecidos como ser:
Set Dele (on/off)
Set Filter to
Y otros que afecten a la base de datos.
Ahora veamos un ejemplo con una condición
"For"
El resultado será la cantidad de clientes cuyo saldo sea
menor a cero.
LOCAL nCount := 0
dbUseArea(.F., , "EJEMCLI.DBF")
DbEval( {|| nCount++}, {|| Saldo < 0} , , , , )
? "Total de Clientes morosos :", nCount
Respuesta ==> Cantidad de registros en la base de
datos que cumplan con la condición Saldo < 0.
Ahora veamos un ejemplo con una condición
"While"
LOCAL nCount := 0
dbUseArea(.F., , "EJEMCLI.DBF")
DbEval( {|| Contador(nCount)}, {|| Saldo < 0}
,{||LastKey() # 27 }, , , )
? "Total de Clientes morosos :", nCount
********************
Func Contador(nCount)
********************
Inkey()
Retu nCount++
Respuesta ==> Cantidad de registros en la base de
datos que cumplan con la condición Saldo < 0 hasta
que se toque la tecla Escape (lastkey() = 27) ó termine
la base lo primero que suceda.
El parámetro nNext lo que hace ejecutar el código de
bloque sobre una cantidad de registros determinada, en el
siguiente ejemplo dará como resultado la cantidad de
registros dentro de los siguientes 150 que cumplan con la
condición Saldo < 0 hasta que se toque la tecla
Escape (lastkey() = 27)
LOCAL nCount := 0
dbUseArea(.F., , "EJEMCLI.DBF")
DbEval( {|| Contador(nCount)}, {|| Saldo < 0}
,{||LastKey() # 27 }, 150, , )
? "Total de Clientes morosos :", nCount
********************
Func Contador(nCount)
********************
Inkey()
Retu nCount++
El parámetro correspondiente al número de registro hace
que el código de bloque se ejecute solo sobre el
registro mencionado, no voy a poner un ejemplo porque
considero es demasiado simple y no hace falta.
Y Por último el parámetro lRest es un valor lógico que
indica si la evaluación será desde el primer registro
en el caso que sea .F. ó desde el registro actual .T.
El siguiente ejemplo muestra la cantidad de cantidad de
registros en la base de datos que cumplan con la
condición Saldo < 0 a partir del registro 150
LOCAL nCount := 0
dbUseArea(.F., , "EJEMCLI.DBF")
Goto 150
DbEval( {|| Contador(nCount)}, {|| Saldo < 0} , , , ,
.T.)
? "Total de Clientes morosos :", nCount
(22-Mar-2003)
El
Comando Get con el parámetro "when".
>Se supone que el @
... get Variable message "Hola"
>
>tiene que mostrarte el mensaje al final de la
pantalla, esta con SET MESSAGE TO 23 center pero no sale
nada, acaso hay que setear otra cosa ??
No,
el commando "message" solo sirve para usar con
el comando "Prompt", no con "Say" o
"Get".
Te adjunto un ejemplo que realizé exclusivamente para
responder a tu pregunta, en el hay 4 "Get's" y
un mensaje en la línea 23 que cambia cada vez que
accedes a un campo.
Archivo ejemread.prg (977 bytes)
(19-Mar-2003)
Manejo de errores desde Clipper.
>quisiera saber cual
es la manera de controlar los errores por ejemplo
>use tabla exclusive && en
este momento se genera un error y me manda el mensaje
>neterror() && el neterror me
manda el mensaje pero antes ya se genero un error
>
Esto es
muy simple, debes utilizar la función ErrorBlock() para
controlar los errores que desees.
Por ejemplo, el error correspondiente a hacer un USE en
exclusivo de una base de datos ya abierta es el 21.
Un ejemplo de programa sería:
Local
bErrorHandler // Defino como local la variable
bErrorHandler bLastHandler :=
ErrorBlock(bErrorHandler)
// Antes
de asignar mi manejador de errores grabo el actual en la
variable bLastHandler ErrorBlock( {|e| SysError( E
)} )
// Antes del comando USE para controlar los errores desde
mi función Syserror() use tabla exclusive // Abro
la tabla
? neterr() // Muestro si hay error
ErrorBlock(bLastHandler) // Devuelvo el control de
errores al manejador original.
Y la
función Syserror() debería ser mas o menos así:
FUNCTION
SYSERROR( e )
If e:genCode = 21
//21 es el código para este error, en el
archivo de cabecera ERROR.CH encontraras los códigos
para cada error.
NetErr(.t.) // Asigno NetErr = .T. (verdadero)
Retu .F. // Devuelvo el control al programa.
EndI
Return (.F.)
>quisisera saber cual es la forma para que clipper no
mande los mensajes de error y yo los pueda codificar.
Usando
ErrorBlock() puedes asignar funciones para controlar tu
mismo los errores, grabarlos en un archivo .LOG,
reintentar una impresión hasta que la impresora esté
lista o se presione una tecla, y muchas otras cosas mas.
(18-Mar-2003)
Imprimir
en Red desde Clipper
>perdona que me
dirija a ti directamente, he estado mirando la web y no
he visto lo que busco.
Es que esta sección es para eso, así que procede con tu
pregunta.
>Me gustaría saber si es posible imprimir en RED, con
clipper a una impresora USB bajo Windows.
>
>Vamos lo que quiero es saber si es posible imprimir
bajo windows, a una impresora en red y que además es
USB. Todo esto usando clipper, claro.
>
Bien,
tu pregunta se ha hecho tan común en estos últimos
tiempos que publicaré mi respuesta en mi página.
Imprimir en Red desde Windows en cualquier impresora es
muy fácil.
Primero debes instalar la impresora en la máquina
adecuada con sus correspondientes "Drivers" no
importa si esta es USB, paralela ó IR (Transmisión de
datos por infrarrojo).
Luego en cada una de las PC's donde vas a correr el
programa debes seguir los siguientes pasos:
Hacer "Click" en el botón de Inicio,
configuración, Impresoras.
"Doble Click" en "Agregar Impresora".
Hacer "Click" en el botón
"Siguiente", Seleccionar impresora en Red y
luego "Click" en el botón
"Siguiente" nuevamente.
Hacer "Click" en el botón "Examinar"
y buscar la PC que contiene la impresora,
"Click" en la impresora y aceptar, nos habrá
traído la dirección UNC en el cuadro de texto, algo
así como : \\Facturación\HP4100
Hacer "Click" en el botón
"Siguiente", Seleccionar "deseo que los
programas DOS impriman en esta impresora"
Luego hacemos click en el botón siguiente hasta
terminar.
Eso es todo, incluso si deseamos que nuestro programa
dirija la salida de impresión a dos ó mas impresoras
distintas solo tenemos que repetir los pasos para agregar
otra impresora y luego en las propiedades de cada una de
las impresoras en la solapa "General" hacemos
"Click" en capturar puerto.
Windows 95, 98 y Me nos proveen de 9 puertos virtuales
por lo que podemos asignar hasta 9 impresoras distintas.
Luego en nuestro programa utilizamos el comando:
Set Printer to <cPuerto>
Donde cPuerto será LPT1 para la impresora que asignamos
a ese puerto, LPT2 para siguiente y así...
(18-Mar-2003)
Error
interno 9002 (Internal error 9002)
>Hola!
>Tengo un problema. Compilo un programa con Clipper
5.2e y lo Linkeo con
>Blinker 3.0 sin problemas.
>Cuando lo ejecuto no entra al programa y me da el
siguiente error:
>
>RDDREGISTE (0) Internal Error 9002
>
>Por qué se produce? Cómo lo soluciono? HELP!!!
Si
leemos el manual de Clipper nos dice que un error interno
9002 se produce en tiempo de ejecución cuando el sistema
no puede detectar la RDD para el manejo de bases de datos
e índices usados por la aplicación.
Esto en la teoría puede ser cierto, no obstante a la
práctica, los años me enseñaron que este poco
descriptivo error corresponde a diferentes cosas que paso
a detallar:
En primer lugar es probable que se esté utilizando una
biblioteca u objeto que no sean compatibles con la
versión de Clipper con la que se ha compilado el
programa.
Otra posibilidad es que el Linkeditor (Bliker en este
caso) no reconozca la biblioteca que contiene el
manejador de bases de datos (RDD).
También es posible que no sea apropiado el orden de
inclusión de los objetos y/o bibliotecas en el
"Script" de Linkeditado.
Y por último que algún .OBJ se encuentre corrupto.
¿Soluciones?
Empecemos por el principio, primero hay que verificar si
todas las versiones de bibliotecas y objetos son
compatibles con el compilador y linkeditor actual, luego
si hay un "Script" de linkeditado verificar el
orden en que son llamados los objetos y/o bibliotecas y
por último, si esto está bien, proceder a borrar y a
regenerar cada uno de los .OBJ que conforman al programa.
(14-Mar-2003)
Leer datos
desde COM1, COM2, COM3 ó COM4.
>Estoy haciendo
un programa y necesito leer del puerto com1 o com2 el
peso en KGS que me marca la bascula.
>Cuales son los comandos con lo cual puedo hacerlo en
Clipper.
Bien,
he tenido que realizar este tipo de comunicaciones con
distintos dispositivos en varias oportunidades, antes,
con Clipper Summer '87 he tenido que recurrir a un
programa hecho en C#, ya que no existía ninguna
biblioteca o función que lo permitiera.
¿Sabes lo que sería "Clipper Summer '87" sin
la existencia de C?
Sería lipper Summer '87.
:-) Un poco de humor no viene mal, ¿no?
Bueno, continuando con el tema, Clipper 5 trae unas
funciones especiales para manejar la comunicación
mediante los puertos Com, se encuentran en la librería
Clipper Tools, (CT y CTP53)
Igualmente el tema es bastante complicado ya que el
programa debe interpretar los valores que el dispositivo
transmite al puerto.
En la dirección
http://www.clipx.net/ng/tools1-3/ng3261e.php (inglés)
están perfectamente explicados estos comandos.
Los comandos son:
COM_OPEN(), COM_INIT() y COM_READ()
COM_OPEN()
Abre el puerto he inicializa el Buffer.
Sintaxis
COM_OPEN(<nComPort>,<nBufferIn>,<nBufferOut>,
[<lTrapMode>]) --> lStatus
Argumentos:
<nComPort> Designa el número de puerto
"Com" a ser leído, este puede ser 1, 2, 3 ó
4.
<nBufferIn> Define el tamaño del buffer de
entrada, hasta 64535 Bytes (64 Kb), si se omite el valor
será 100 Bytes.
<nBufferOut> Define el tamaño del buffer de
salida, hasta 64535 Bytes (64 Kb), si se omite el valor
será 100 Bytes.
<lTrapMode> Si el valor es .T. (verdadero) el
puerto solo disparará una interrupción cuando recibe
datos, y estos no son el resultado de una falla en la
transmisión, si se omite el valor será .F. (Falso)
Devuelve .T. (Verdadero) si se abrió el puerto con
éxito.
COM_INIT()
Inicializa los parámetros del puerto Com.
Sintaxis
COM_INIT(<nComPort>,[<nBaudRate>],[<cParity>],
[<nDataLength>],[<nStopBits>]) -->
lInitialized
Argumentos
<nComPort> Designa el número de puerto
"Com" a ser leído, este puede ser 1, 2, 3 ó
4.
<nBaudRate> Determina 300, 600, 1200, 2400, 4800,
9600 ó 19200 baudios, si se omite se tomaran 300
baudios, yo particularmente uso 1200.
<cParity> Determina la paridad : (E)ven, (O)dd,
(M)ark, (S)pace, or (N)one. si se omite se tomara
"N".
<nDataLength> Largo de datos, 7 u 8 Bits, el valor
por default es 8.
<nStopBits> Bits de parada, si se omite el valor
será 1.
Devuelve : .T. si se inicializa Ok.
COM_READ()
Lee una cadena de caracteres desde el buffer de
recepción.
Sintaxis:
COM_READ(<nComPort>,[<nLargo>],[<lNoBorrar>])
--> cCadena
Argumentos:
<nComPort> Designa el número de puerto
"Com" a ser leído, este puede ser 1, 2, 3 ó
4.
<nLargo> Determina la cantidad de caracteres a leer
desde el buffer, si no incluyes este parámetro serán
leídos todos los caracteres.
<lNoBorrar> .T. (Verdadero) Hace que no se borre la
cadena leída en el buffer, si no se incluye se
borrarán.
Devuelve una cadena de caracteres correspondientes al
buffer de recepción.
Ejemplo:
cInput := COM_READ(1, 10) // Lee Diez caracteres desde el
puerto 1
? cInput // Los muestra en la pantalla
Es conveniente cerrar el puerto luego de usarlo mediante Com_Close(nComPort)
(12-Mar-2003)
(DOS Error
4) En Windows 2000/ME/NT.
>Tengo una
aplicación hecha con alguna versión de clipper, cuando
la ejecuto en una máquina con W95 ó W98 la aplicación
funciona bien, pero cuando la ejecuto en una maquina con
W2000 me manda el siguiente error:
>
>Error DBFNTX/1003 Open error:
>\sistema\datsis\ofertax1.ntx
>(DOS Error 4)
>
Ok,
Este error también sucede en Windows ME y NT.
En primer lugar un "DOS Error 4" se
produce cuando se agotaron los manejadores de archivos
disponibles, o sea que hay mas archivos abiertos de los
que se asignaron mediante el comando "Files"
en el archivo "CONFIG.SYS".
Windows XP, NT y W2K (2000) no
utilizan los archivos CONFIG.SYS y AUTOEXEC.BAT como
si lo hacen las versiones anteriores, en su lugar utilizan
CONFIG.NT y AUTOEXEC.NT ubicados en la carpeta
(directorio) "\WINDOWS\System32\", por
lo que para aumentar la cantidad de manejadores de
archivos (file handlers) es necesario incluir las
siguientes líneas:
En el archivo \WINDOWS\System32\Config.nt
la línea :
FILES=100
En el archivo \WINDOWS\System32\Autoexec.nt
la línea :
SET CLIPPER=F100
Esta última línea aveces no es suficiente con colocarla
solo en el archivo AUTOEXEC.NT, sino que es necesario
ejecutarla en cada una de las sesiones DOS que se abran,
para lo cual es conveniente hacer un .BAT que incluya
este comando y luego ejecute el programa.
Ejemplo:
SET CLIPPER=F100
MYPROG.EXE
Siendo MYPROG.EXE el programa en Clipper
a ejecutar.
(12-Mar-2003)
Windows
tarda mucho en imprimir desde Clipper.
>Estoy tratando de
imprimir en una impresora de matrix de punto, en un
sistema programado en lenguaje clipper bajo un sistema
operativo windows XP.
>El reporte tarda mucho en ser enviado a la impresora,
la unica manera que he logrado que salga rapido es
saliendome del sistema y volviendo a entrar.
>
Mucho
es como dos minutos y puedes también presionar Alt-Tab
para que salga de inmediato.
>Supongo que el buffer de impresión esta esperando
alguna instrucción
>para cerrarse.
Si,
es un error de Windows heredado desde la versión '98, no
de Clipper.
>
>Si tiene algun concocimiento sobre esto le
sabria agradecer mucho su ayuda.
>
En
Internet encontré mas de cien foros donde se comenta el
tema, personalmente probé cada una de las soluciones
allí propuestas y no puedo dar con la solución, cambié
mil cosas en los .INI de Windows, modifique mi programa
de impresión, pero nada.
Este problema me está rompiendo el coco a mi también,
te pido que si logras solucionarlo me avises.
Gracias y disculpa el no poder ayudarte.
(10-Mar-2003)
Evitar
Clipper dos veces ejecutadose.
>Te
quiero preguntar si es posible con Clipper 5.3, puro
hacer que cuando ya este abierto el sistema y te lo
vuelven a llamar se abra la ventana del sistema que ya
estaba abierto?
Bueno, la cosa es así, Clipper puro, si, pero ejecutando
una función de Windows 95', 98', ME, 2K, NT, ME
(prácticamente todos) llamada desde Clipper, para poder
mostrar la ventana.
Hay quienes dices, no los culpo, que efectuar este tipo
de llamadas no es una ejecución de Clipper puro, no los
culpo aunque yo particularmente considero que como bien
todos saben Windows es un sistema operativo y si yo
realizo un programa en Clipper el cual no incluye
librerías externas y solo hace una llamada a una
función del OS, entonces ese programa es Clipper puro.
Te adjunto un ejemplo, muy simple por cierto, pero
funcional, el cual realicé exclusivamente para ti, como
para explicarte mejor tal llamada. Para probarlo baja
todos los archivos en cualquier carpeta y trata de
ejecutarlo mas de una vez.
Archivo YA.ZIP (109 Kb)
|