Boletín Pascal #13 - 24-DEC-2000
INDICE
1. UNAS PALABRAS DEL EDITOR
2. FORMAS NO RECTANGULARES - Parte I
3. APLICACIONES OPENGL CON DELPHI 5.0 - PRIMEROS PASOS
4. ABRIENDO UNA BASE DE DATOS DE MICROSOFT ACCESS (.MDB) CON DELPHI
- ADO
- BDE
- BDE + ODBC
5. LISTANDO LAS TABLAS Y CONSULTAS EN UNA BASE DE DATOS
6. ENLACES
________________________________________________________________________
1. UNAS PALABRAS DEL EDITOR
En este número Alirio Gavidia nos mostrará con dos ejemplos cuán fácil
es hacer formularios no rectangulares.
Leopold Minikus, de Minais - Individual Cad Software, nos presenta su
juego de componentes OpenGL para ayudarlo a construir aplicaciones 3D
con Delphi 5. Puede descargar gratuitamente la colección de componentes
MNOgl del sitio de minais: http://www.minais.at El archivo viene con
proyectos de ejemplo (incluyendo el que se describe en el artículo).
Si necesita ayuda o tiene preguntas acerca de los artículos presentados
en este boletín, puede enviarlas a nuestro foro/lista de correo. Sus
problemas y dudas pueden ser los problemas y dudas de otros miembros del
foro que también se beneficiarán de leer las preguntas y respuestas.
Para suscribirse, simplemente envíe un email en blanco a:
delphi-intermedio-subscribe@gruposyahoo.com
Este foro / lista de correo es un servicio gratuito provisto por Yahoo!
Grupos ( http://espanol.groups.yahoo.com ) y no hacen "spam", aunque
incluyen una pequeña publicidad en cada mensaje (de la cual aclaro que
yo veo ni un centavo). Si desea más información, por favor visite:
http://www.latiumsoftware.com/es/forums.html
Saludos,
Ernesto De Spirito
eds2008 @ latiumsoftware.com
________________________________________________________________________
JfControls Lib. Multilenguaje. Multiapariencia. Skins. Privilegios. Más
de 40 componentes integrados y personalizables. Múltiples problemas de
programación resueltos. Administración centralizada de recursos. Para
Delphi 3-2006 y C++ Builder 3-6. http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________
2. FORMAS NO RECTANGULARES - Parte I
Copyright (c) 2000 Alirio Gavidia <alirio@gavidia.org>
Para ver más de mis artículos visite:
Programación Orientada en Delphi
http://www.gavidia.org/pod/
Introducción.
=============
El presente ensayo pretende demostrar las posibilidades de usos de las
formas no rectangulares bajo Windows. El uso es simple pero las
posibilidades parecen ser interesantes. Adicionalmente, en particular en
esta primera parte, se hará uso de dos elementos importantes: "Canvas"
(lienzo) y "Timer" (temporizador).
El primer ejemplo.
==================
En el artículo anterior (ver "POST-IT". VENTANAS AJUSTABLES SIN BORDE NI
TITULO en http://www.latiumsoftware.com/es/pascal/0010.php ) hice
referencia a la posibilidad de crear un reloj analógico redondo como lo
hace el "PowerToys" de Windows. Hacer un formulario redondo es simple y
se limita a llamar a dos procedimientos. El reloj debe además dibujar
agujas (lo que requiere cierto cálculo matemático) y actualizarse unas
60 veces por minuto (para ello el "TTimer").
Nota: Reloj Analógico por contraposición a Digital. El término NO es
correcto porque el reloj que aquí creamos aún cuando tenga agujas es
digital. Para que el reloj imitara un comportamiento realmente
analógico tendría que tener un movimiento continuo, el que aquí
creamos se mueve de segundo en segundo por lo que tiene un número de
estados definidos y finitos eso lo califica de digital. Parece ser
que el término más adecuado es "reloj de agujas".
Sin título.
===========
El reloj se basa en un formulario simple sin borde; con ello se elimina
la barra de título, que resulta en un estorbo al tener un formulario
redondo. Este genera adicionalmente el problema de traslado del
formulario. Por este motivo la operación de arrastre debe ser atendida
desde el área cliente del formulario. Para resolver este inconveniente
hay varios métodos. Opto por el aplicado en el artículo anterior (uso
del wm_Syscommand $f012):
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
ReleaseCapture;
Perform(wm_Syscommand, $f012, 0)
end;
Otra técnica es responder al "Wm_NcHitTest" y retornar como resultado
"htCaption". Esto simplemente es comunicarle a Windows que se hizo clic
sobre el área de título. Me parece que hay al menos otra técnica más
pero no es objetivo de este ensayo.
El "timer".
===========
En el formulario se incluye un control "TTimer". Este control dispara un
evento de manera aproximada cada cierto intervalo (por la propiedad
"interval" dada en milisegundos). Esta bien documentado su uso en
Delphi, pero debo agregar algo: no es exacto.
El evento asociado al timer ejecuta tres acciones: eliminar agujas de
posición anterior, tomar la hora del sistema y colocar agujas en una
nueva posición.
El "Canvas".
============
El "Canvas" provee capacidades gráficas para controles gráficos y
formularios. Brinda posibilidades para dibujar líneas, elipses,
polígonos, textos y otros. Su manejo es simple y práctico.
Hacemos uso de los siguientes elementos del "Canvas":
* "Pen", para establecer color y modo de trazado de línea.
* "MoveTo", para establecer el punto inicial de trazado de una línea.
* "LineTo", para trazar una línea desde la última posición a la nueva.
* "Rectangle", para trazar un rectángulo según los parámetros
especificados.
Es de notar particularmente la propiedad "Canvas.Pen.Mode" que nos
permite utilizar valores como "pmXor" o "pmCopy" (entre muchos otros).
Nota: El uso del "Xor" como operador lógico tiene una propiedad
interesante y es que aplicada dos veces se obtiene el valor
original, esto es: "x xor y" resulta en "z" si a "z" se le aplica
"xor y" nuevamente resulta en "x". Esto es muy útil para cifrados
simples donde queremos aplicar una clave para cifrar y la misma
clave y el mismo algoritmo para descifrar. También es muy útil para
casos donde queremos dibujar algo y luego borrarlo porque para
borrarlo sólo se requiere volver a dibujar aplicando "xor" entre el
fondo y el pixel a dibujar.
El evento "Paint" del formulario ciertamente hace uso de la propiedad
"Mode" y "Color" de la plumilla obteniendo un curioso efecto. El
resultado, al menos para mi, no fue el esperado, sin embargo fue
agradable. Todo ello parece ser consecuencia de la manera en que se
crea un rectángulo, el mismo es rellenado y luego se trazan los bordes
superior e izquierdo, que bajo el operador "Xor" generan un color
blanco, la imagen resultante genera un efecto 3D. Sugiero al lector
comentar las lineas de "Mode" y "Color" para obtener sus propias
conclusiones.
Como comentario adicional "Pen.Color" sólo afecta al borde del
rectángulo. El relleno es definido por la propiedad "Brush" del "Canvas"
la cual, en este caso, permanece con su valor por defecto.
procedure TForm1.FormPaint(Sender: TObject);
Var
X1, Y1, i : integer;
Angle : double;
begin
Canvas.Pen.Mode := pmXor;
Canvas.Pen.Color := clBtnFace;
for i:=1 to 12 do
begin
Angle := i * 2 * Pi / 12;
X1 := trunc(X0 + Len * Sin(Angle));
Y1 := trunc(Y0 - Len * Cos(Angle));
Canvas.Rectangle(X1-4,Y1-4,X1+4,Y1+4)
end;
Canvas.Pen.Mode := pmCopy;
Canvas.Pen.Color := clBlack;
end;
De aritmética.
==============
El sistema de coordenadas tiene el punto cero en la esquina superior
izquierda. Para determinar la posición de la aguja necesitamos el centro
y el extremo. El centro es la mitad del ancho y la altura. Para la
longitud de las agujas tomamos una fracción del mínimo entre el ancho y
la altura.
Conocido el centro y largo de la aguja sólo resta conocer la posición de
su extremo, para ello se determina el ángulo. Aquí terminamos recurriendo
a la trigonometría. El ángulo es determinado con cero en el 12, 90
grados a las 3, 180 grados a las 6 hasta 360 a las 12. El seno del
referido ángulo nos da la apertura en la coordenada "X", el coseno la
apertura en la coordenada "Y". Como nota adicional el sistema de
coordenadas en el eje "Y" esta invertido con respecto a los sistemas
trigonométricos usuales. Todos los ángulos deben ser expresados como
Radianes para efectos de la función seno y coseno. El procedimiento
"DrawWatchHand" efectúa los cálculos (también en "FormPaint")
procedure Tform1.DrawWatchHand;
:
:
// Now draw Second
Canvas.MoveTo(X0, Y0);
Angle := S * 2 * Pi / 60;
X1 := trunc(X0 + 9*Len * Sin(Angle)/10);
Y1 := trunc(Y0 - 9*Len * Cos(Angle)/10);
Canvas.LineTo(X1, Y1);
:
:
Nótese que cada aguja utiliza una proporción del valor de Len. Así los
segundos son 9/10 de Len, los minutos 3/4 y las horas 1/2.
Redondo.
========
Hasta ahora se ha utilizado el "Canvas" para dibujar, se ha eliminado el
título y sustituido su funcionalidad, se ha efectuado cierta aritmética
y se ha hecho uso de un "timer". El punto central que da título a este
artículo es crear una forma no rectangular. Bien esto es tremendamente
simple y se resuelve con dos llamadas a Windows en el "FormCreate" del
formulario principal:
hRegion := CreateEllipticRgnIndirect(R);
SetWindowRgn(handle, hRegion, true);
"CreateEllipticRgnIndirect" es una versión de "CreateEllipticRgn" con
los parámetros (un rectángulo) empaquetados en una sola estructura. Esta
rutina retorna un "handle" (manejador) a una región elíptica circuns-
crita al rectángulo dado. Si se quiere se pueden definir regiones no
circulares usando "CreatePolygonRgn" para polígonos, "CreateRectRgn"
para rectángulos (sin sentido en el caso que nos atañe, pero es
posible), "CreateRoundRectRgn" para rectángulos de esquina redondeadas,
o "CombineRgn" para combinar los resultados de otras regiones.
"SetWindowRgn" define el área en la cual es visible una ventana. Es
interesante que bajo este concepto la ventana rectangular sigue
existiendo y sólo hemos definido algo así como un agujero por donde
verla.
Un "Bug", un segundo ejemplo.
=============================
Mi primer intento de forma no rectangular fue hace un par de años en
Delphi 3. Fue una travesura motivado a que conozco personas que detestan
terriblemente a las cucarachas (y aquí en el trópico las hay espectacu-
lares). Así que creé una cucaracha que se pasea por el escritorio de
Windows. La forma de la misma es elíptica y yo fundamentalmente creé
unos dibujos para distintos ángulos (cuatro: dos verticales y dos
horizontales). El resultado es algo tosco pero disfruté al crear este
"bicho". Sé sobradamente que hay mejores maneras de hacer esto pero
viene al caso por el tema de este artículo.
Lo siguiente.
=============
Bien, esto abre posibilidades de uso interesantes (como ya antes
mencioné). Creo que la que más adecuada parece ser la de "Skins" como
los de algunas aplicaciones. Para referencia están "Winamp",
"NeoPlanet", "Windows Media Player" (versión nueva). La técnica que
permite formas no rectangulares es aplicable a botones y otros
controles.
Bibliografía:
* Delphi Developer's Handbook,
Marco Cantù, Tim Gooch, John F. Lam
SYBEX
ISBN: 0-7821-1987-5
1.998
* La Biblia de Delphi 5
Marco Cantù
ANAYA
ISBN: 84-415-0994-8
2.000
--------------------------
El código fuente que acompaña este artículo puede descargarse desde:
http://www.latiumsoftware.com/es/file.php?id=p13
________________________________________________________________________
3. APLICACIONES OPENGL CON DELPHI 5.0 - PRIMEROS PASOS
Copyright (c) 2000 Leopold Minikus <info@minais.at>
Traducido por Ernesto De Spirito
Cuando usa la colección de componentes MNOgl de minais tiene dos formas
diferentes de construir aplicaciones de ese tipo.
Primero quiero describir la forma fácil:
Antes que nada asegúrese de instalar el archivo de paquete MNOgl
mnogl.bpl bajo Delphi (Menú Component - Install packages - botón Add -
buscar MNOgl.bpl y darle Open). El resultado es que tendrá una nueva
carpeta de componentes llamada MNOgl dentro de la cual encontrará un
montón de componentes útiles para diseñar un aplicación OpenGL.
Permítanos comenzar con un nuevo proyecto. Selecciones un componente
TMNOglControl y suéltelo sobre el formulario. Cambie el tamaño del
control como quiera o permita alinearlo. Luego seleccione un componente
TMNOglCanvas y suéltelo en el formulario. Asigne el MNOglControl1 a la
propiedad llamada WinControl. Ahora se generará un contexto de
renderizado (el MNOglControl cambia a color de fondo negro).
Permítanos ahora ver como podemos dibujar una caja en este lienzo
(canvas). Tome un componente TMNOglScene de la carpeta MNOgl y suéltelo
en el formulario. Asigne MNOglCanvas1 a la propiedad MNOglCanvas. Ahora
permítanos elegir un componente TMNOglBox y soltarlo en el formulario.
Asigne MNOglScene1 a la propiedad Scene. Ahora puede ver la forma en
modo de diseño. Intente cambiar el tamaño de la cada cambiando las
propiedades Length (largo), Width (ancho) y Height (altura).
Si desea tener su figura centrada entonces establezca la propiedad
TransformBy a (-Length/2, -Width/2, -Height/2).
Segundo quiero describir la forma cuando no desea instalar el paquete
MNOgl:
Permítanos comenzar con un nuevo proyecto. Modifique la lista uses y
agregue las unidades _mnoglcanvas, _mnogltools a su lista, por ejemplo:
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, _mnoglcanvas, _mnogltools;
Agregue las siguientes variables a su formulario:
TForm1 = class(TForm)
...
private
{ Private declarations }
MNOglControl1: TMNOglControl;
MNOglCanvas1: TMNOglCanvas;
MNOglScene1: TMNOglScene;
MNOglBox1: TMNOglBox;
public
{ Public declarations }
end;
Luego entre al método FormShow y crearemos los componentes que necesi-
tamos:
procedure TForm1.FormShow(Sender: TObject);
begin
// Crea el WinControl para el contexto de renderizado de OpenGL
// donde se "ejecutarán" sus formas
MNOglControl1 := TMNOglControl.Create(Self);
MNOglControl1.Align := alClient;
MNOglControl1.Parent := Self;
// Crea el MNOglCanvas
MNOglCanvas1 := TMNOglCanvas.Create(Self);
// Asigna el WinControl --> y se crea el contexto de renderizado
MNOglCanvas1.WinControl := MNOglControl1;
// Crea la escena (OpenGL la llama DisplayList)
MNOglScene1 := TMNOglScene.Create(Self);
// y le dice a la escena en que Canvas se ejecutará
MNOglScene1.MnOglCanvas := MNOglCanvas1;
// Crea la caja
MNOglBox1 := TMNOglBox.Create(Self);
// y le dice a la caja a que escena pertenecerá
MNOglBox1.Scene := MNOglScene1;
// Cambia las propiedades de la caja
with MNOglBox1 do begin
Length := 4;
Width := 3;
Height := 2;
end;
end;
Si quiere que la escena rote entonces sólo agregue un TMNOglNav (un
navegador) a su formulario y establezca la propiedad MNOglCanvas a
MNOglCanvas1. Cuando ejecute su programa puede presionar el botón
izquierdo del ratón en el componente MNOglNav y mover el ratón. Con
doble-clic se restablecerá la vista.
________________________________________________________________________
4. ABRIENDO UNA BASE DE DATOS DE MICROSOFT ACCESS (.MDB) CON DELPHI
ADO
===
Si tiene Delphi 5 Enterprise o Delphi 5 Profesional con ADO Express,
entonces puede usar una ADOTable y en la propiedad ConnectionString del
control ADOConnection asociado puede usar el editor de propiedades para
construir la cadena de conexión correcta. Por ejemplo:
Provider=Microsoft.Jet.OLEDB.4.0;
User ID=Admin;
Password=Password;
Data Source=D:\Path\dbname.mdb;
Mode=ReadWrite;
Extended Properties="";
Persist Security Info=False;
Jet OLEDB:System database="";
Jet OLEDB:Registry Path="";
Jet OLEDB:Database Password="";
Jet OLEDB:Engine Type=5;
Jet OLEDB:Database Locking Mode=1;
Jet OLEDB:Global Partial Bulk Ops=2;
Jet OLEDB:Global Bulk Transactions=1;
Jet OLEDB:New Database Password="";
Jet OLEDB:Create System Database=False;
Jet OLEDB:Encrypt Database=False;
Jet OLEDB:Don't Copy Locale on Compact=False;
Jet OLEDB:Compact Without Replica Repair=True;
Jet OLEDB:SFP=False
NOTA: Va todo junto en la misma línea.
Esta cadena de conexión abrirá la base de datos D:\Path\dbname.mdb
usando el controlador ADO para bases de datos Access
(Microsoft.Jet.OLEDB.4.0). El nombre de usuario sería Admin sin
contraseña (los valores por omisión cuando se crea una base de datos
Access). Si ha establecido una contraseña para su base de datos, deberá
proveerla en la propiedad Jet OLEDB:Database Password. Si ha establecido
seguridad, entonces debe indicar su archivo .MDW o .MDA de grupos de
trabajo en la propiedad Jet OLEDB:System database.
BDE
===
Si como la mayoría de nosotros, usted no tiene ADO, puede usar la BDE
que provee un controlador nativo (MSACCESS). En un componente Database,
establezca las siguientes propiedades:
DatabaseName = cualquier_nombre (o nombre_de_alias)
DriverName = MSACCESS
LoginPrompt = False
Params = PATH=d:\camino
DATABASE NAME=d:\camino\nomarch.mdb
TRACE MODE=0
LANGDRIVER=Access General
USER NAME=su_nombre_usuario
PASSWORD=su_contraseña
OPEN/MODE=READ/WRITE
SQLPASSTHRU MODE=NOT SHARED
El valor de la propiedad DatabaseName de un objeto Database es el que
debe usar en la propiedad DatabaseName de los componentes Table y Query
que representen tablas y consultas en esa base de datos (esta es la
forma de "vincularlos" al objeto Database).
BDE + ODBC
==========
En el caso de bases de datos Access, la BDE provee un controlador
nativo, pero hay muchos formatos de bases de datos para los cuales no
hay un controlador BDE, aunque tal vez pueda encontrar un controlador
ODBC. ODBC ofrece lo que yo llamaría "accesso de compatibilidad" (para
aplicaciones con apenas mínimos requerimientos de acceso a base de
datos, o aplicaciones que sólo necesitan realizar operaciones de
importación/exportación), aunque algunas veces es todo lo que tenemos...
He aquí un ejemplo de cómo usar un controlador ODBC con la BDE para
abrir una base de datos Access:
* Cree un DSN (Data Source Name = Nombre de Origen de Datos) para su
base de datos (usando la applet ODBC Data Sources del Panel de Control
de Windows).
1) Haga clic en la solapa "System DSN" o "User DSN"
2) Haga clic en el botón "Add..." (Agregar)
3) Seleccione el controlador "Microsoft Access Driver (*.mdb)" y
presione ENTER. Aparecerá el diálogo "ODBC Microsoft Access Setup".
4) Provea un nombre en el cuadro de texto "Data Source Name" (sin
espacios ni caracteres especiales).
5) Haga clic en "Select..." (seleccionar) para especificar su base de
datos .MDB.
6) Si ha establecido un esquema de seguridad tiene que seleccionar el
botón de radio "Database" en el cuadro "System Database" y hacer
clic en el botón "System database..." para especificar su archivo
de grupos de trabajo .MDW o .MDA.
7) Haga clic en el botón "Advanced..." (avanzado) para establecer el
nombre de usuario y la contraseña predeterminada. Esto es para
acceso de baja seguridad porque cualquiera con acceso a su equipo
puede ver las propiedades del DSN. Si necesita una seguridad más
alta debe proveer el nombre de usuario y la contraseña al abrir la
base de datos (vea más abajo).
8) Finalmente haga clic en el botón "OK" para guardar su DSN.
* En Delphi establezca las propiedades del componente TDatabase:
1) Establezca DatabaseName con el nombre que le dio al DSN.
2) Si desea que el usuario provea un nombre de login y una contraseña,
entonces deje LoginPrompt en True.
3) Si no le gusta el cuadro de diálogo de login estándar (o si quiere
proveer el nombre y la contraseña por código), puede establecer
LoginPrompt en False y usar su propio cuadro de diálogo (o un
nombre nombre de usuario y contraseña que tenga guardados en su
aplicación) y establezca la propiedad Params con los datos del
login:
USER NAME=su_nombre_de_usuario
PASSWORD=su_contraseña
* Asocie sus componentes TTable o TQuery con el componente TDatabase
mencionado arriba simplemente proveyendo el mismo nombre de DSN en su
propiedad DatabaseName correspondiende.
________________________________________________________________________
5. LISTANDO LAS TABLAS Y CONSULTAS EN UNA BASE DE DATOS
Si necesita conocer los nombres de todas las tablas y/o consultas
(vistas) en una base de datos abierta con la BDE, puede usar
DbiOpenTableList para crear un cursor* con todos los nombres de tablas y
consultas, y luego puede leerlo llamando a DbiGetNextRecord como se
muestra en el ejemplo de abajo que guarda los nombres en un cuadro de
lista (ListBox), indicando si corresponden a una tabla o a una
consulta.
(*) Un cursor, para quienes no están al día en la terminología de
las bases de datos, es una "tabla lógica". Por ejemplo cuando
abrimos una tabla o consulta, lo que obtenemos es un cursor, es
decir, un conjunto de datos distribuidos en filas o en columnas,
independientemente que esos datos provengan de una tabla física,
de parte de una tabla, de muchas tablas o de cualquier otra fuente
de datos.
Para probar el ejemplo, simplemente coloque un ListBox y un Button
(botón) en un formulario, y genere el manejador del evento OnClick del
botón:
uses db, dbtables, bde; // No se olvide de incluir la unidad BDE!
procedure TForm1.Button1Click(Sender: TObject);
var
db1: TDatabase;
hCursor: hDBICur; // Cursor con los nombres de tablas y
// consultas
ListDesc: TBLBaseDesc; // Registro del cursor
begin
ListBox1.Clear;
db1 := nil;
try
db1 := TDatabase.Create(nil);
// Establezca las propiedades necesarias para abrir su base de
// datos
db1.DatabaseName := 'Access_ODBC_Test';
db1.LoginPrompt := False;
db1.Connected := True;
// Generar el cursor con los nombres de tablas y consultas
Check(DbiOpenTableList(db1.Handle, False, False, '*', hCursor));
// Moverse por los registros del cursor para obtener los nombres
while (DbiGetNextRecord(hCursor, dbiNOLOCK, @ListDesc, nil)
= dbiErr_None) do
if ListDesc.bView then // ¿Es una consulta?
ListBox1.Items.Add(ListDesc.szName + ' (Consulta)')
else
ListBox1.Items.Add(ListDesc.szName + ' (Tabla)');
// Cerrar el cursor
dbiCloseCursor(hCursor);
db1.Connected := False;
except
db1.Free;
raise;
end;
db1.Free;
end;
En lugar de una variable de tipo TDatabase creada para el propósito,
puede usar un control TDatabase colocado en un formulario, o la
propiedad Database de un control TTable o TQuery.
________________________________________________________________________
6. ENLACES
EN INGLES
=========
* Top 100 Borland - Resources for Borland Developers
http://www.top100borland.com
EN ESPAÑOL
==========
* Creación de controles Delphi y ActiveX con Delphi 3.0
Un artículo para principiantes en la creación de componentes
http://www.hispan.com/eltaller/ControlDelphi.html
________________________________________________________________________
Si no has recibido el archivo con el código fuente completo de los
ejemplos que se presentan en este boletín, puedes descargarlo de la
siguiente dirección: http://www.latiumsoftware.com/es/file.php?id=p13
________________________________________________________________________
Página principal: http://www.latiumsoftware.com/es/pascal/index.php
Página del grupo: http://espanol.groups.yahoo.com/group/boletin-pascal/
Para suscribirse / apuntarse: boletin-pascal-subscribe@gruposyahoo.com
Para cancelar / removerse: boletin-pascal-unsubscribe@gruposyahoo.com
Para reportar problemas con la suscripción: eds2008 @ latiumsoftware.com
________________________________________________________________________
Este boletín se provee "TAL Y COMO ESTA", sin garantía de ninguna clase.
Su uso implica la aceptación de nuestros términos de licencia y de la
ausencia de garantía que puedes leer en nuestro sitio web. Allí también
encontrarás una nota sobre marcas registradas. Te animamos a que redis-
tribuyas este boletín, siempre y cuando lo hagas en forma completa
(incluyendo la información de copyright), sin modificaciones y de manera
gratuita. Los artículos son copyright de sus respectivos autores y se
reproducen aquí con el permiso de los mismos.
________________________________________________________________________
Latium Software http://www.latiumsoftware.com/es/index.php
Copyright (c) 2000 por Ernesto De Spirito. Todos los derechos reservados
________________________________________________________________________
|