Boletín Pascal #39- 13-SEP-2002
Índice
1. Unas palabras del editor
2. En las noticias
- Delphi 7 está aquí!
- Anticipo del compilador Delphi para .NET
- Kylix 3 obtiene 5 estrellas de LinuxPlanet
- Eventos Borland que se se avecinan
3. Entendiendo VisualCLX
¿Que son los objetos de enganche (hook-objects) en una aplicación Qt?
4. Creando aplicaciones middleware de alto rendimiento con Indy
5. Inline Assembler en Delphi (III) - Arreglos estáticos
6. Foros / listas de correo
7. Delphi en la Red
- Componentes, librerías y aplicaciones
. Shareware/Comercial
. Freeware
- Artículos, trucos y consejos
- Tutoriales
- Otros enlaces
________________________________________________________________________
Tecno Soft Solutions. Reseller Autorizado de Symbol Technologies, líder
mundial en captura de códigos de barras. >>> http://www.tecno-symbol.com
________________________________________________________________________
1. Unas palabras del editor
Antes que nada, quisiera pedir disculpas por la demora en publicar esta
edición, pero he estado enterrado en trabajo estas últimas semanas.
Espero poder retomar una periodicidad más aceptable a partir del próximo
número.
Mi sitio web estuvo fuera de línea unos días esta semana, y antes de
eso he experimentado algunos problemas con la recepción de mensajes de
email. Si alguien ha intendado contarme en este tiempo y no ha recibido
respuesta de mi parte, le ruego que vuelva a intentarlo ahora.
En esta edición quiero agradecer a Max Kleiner por contribuir otro de
sus artículos al boletín, y me complace entregarle una licencia de
AnyShape Transpack v2.0 para Kylix, el componente de plataformas
cruzadas que facilita la creación de ventanas transparentes y de formas
extrañas, con edición WYSIWYG, vista preliminar en tiempo de diseño,
arrastre automático, verdaderos formularios "stay-on-top" y la
posibilidad de combinar regiones, provisto por MindBlast Software:
http://www.mindblastsoftware.com/?page=transpack&ref=PascalNL
A propósito, el autor del próximo artículo sobre Kylix que publiquemos
recibirá otra licencia de AnyShape Transpack v2.0 para Kylix.
También quiero agradecer a Romeo Lefter por su artículo sobre Indy, y
me complace entregarle el Delphi Information Library CD (DIL CD), un
gran recurso de información con artículos, trucos, consejos, compo-
nentes, javascripts, imágenes, update packs, y mucho más, provisto por
el UK Borland User Group: http://www.richplum.co.uk/dil/index.asp
Para la próxima edición, tenemos los siguientes premios disponibles:
* llPDFLib v1.1 - por llionsoft, Shareware ($70, $280 con fuentes)
llPDFLib en una biblioteca en puro Object Pascal para crear documentos
PDF. No usa ninguna DLL ni software externo de terceras partes para
generar ficheros PDF. La librería consiste del componente TPDFDocument
con propiedades y métodos como los del TPrinter de Delphi, pero
diseñado para generar un fichero PDF.
http://www.llion.net/
* Greatis Form Designer v3.4 - por Greatis Software, Shareware ($49.95)
Es un diseñador de formularios en tiempo de ejecución que le permite
mover y cambiar el tamaño de cualquier control de su formulario. No
necesita preparar su formulario para usar Form Designer. Simplemente
suelte el componente TFormDesigner en cualquier formulario, establezca
la propiedad Active en True y ¡disfrute! Para Delphi 4-7 y BCB 3-6.
http://www.greatis.com/formdes.htm
* Developer Information Library (DIL) CD - por UK Borland User Group
Más de 17.000 trucos, consejos, FAQs y artículos técnicos · Parches y
actualizaciones de las herramientas Borland · Más de 4.000 componentes
y herramientas · Más de 4.000 bitmaps listos para usar con otros
20.000 comprimidos · Más de 350 JavaScripts listos para usar · Juego
completo de HOWTOs de Linux · y mucho más...
http://www.richplum.co.uk/dil/index.asp
Finalmente, no quiero olvidarme de agradecer al Ing. Ernesto Cullen, ni
a Dave Murray, quienes colaboraron para hacer esta edición posible.
Espero que la disfruten.
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. En las noticias
Delphi 7 está aquí!
===================
Delphi 7 está entre nosotros, llamado Delphi 7 Studio, y viene en cuatro
ediciones:
* Delphi 7 Studio Architect ($3,499 - Upgrade desde Enterprise: $2,399)
http://www.borland.com/delphi/architect/index.html
* Delphi 7 Studio Enterprise ($2,999 - Upgrade: $1,899)
http://www.borland.com/delphi/delphi_enterprise/index.html
* Delphi 7 Studio Professional ($999 - Upgrade: $399)
http://www.borland.com/delphi/delphi_professional/index.html
* Delphi 7 Studio Personal ($99 - disponible para descarga gratuita)
http://www.borland.com/delphi/delphi_personal/index.html
La nueva edición Architect es como la edición Enterprise, pero viene con
herramientas adicionales, incluyendo el nuevo Bold para Delphi de
BoldSoft, que permite a los desarrolladores mantener menos código con
verdadero MDA, y además viene con tecnología UML, soporte integrado para
Rational Rose, ModelMaker, importación/exportación de información de
modelos desde/hacia el Bold Model Editor, y generación automática de
esquema de base de datos usando SQL. DataSnap (antes conocido como
MIDAS) es ahora libre de regalías tanto en la edición Enterprise como en
la Architect, y también se incluye en la edición Professional.
Excepto en el caso de la edición Personal, todas las ediciones de
Delphi 7 Studio incluyen el entorno Kylix 3 para Delphi (permitiendo
a los desarrolladores usar una base de código para el desarrollo
multiplataforma para Linux) y el Delphi 7 Studio Migration Kit (para
migrar aplicaciones a Microsoft .NET).
Enlaces Delphi 7:
* Página principal
http://www.borland.com/delphi/architect/index.html
* Requerimientos de sistema
http://www.borland.com/delphi/pdf/del7_sysreqs.pdf
* Preguntas frecuentes
http://www.borland.com/delphi/pdf/del7_faq.pdf
* Matriz de características
http://www.borland.com/delphi/pdf/del7_feamatrix.pdf
* Delphi 7/.NET User Group Tour 2002 - US / Canada
http://bdn.borland.com/article/0,1410,29089,00.html
Anticipo del compilador Delphi para .NET
========================================
Incluido con Delphi 7, pueden encontrar una presentación preliminar del
compilador Delphi para .NET, una utilidad en línea de órdenes llamada
"dccil.exe", que produce aplicaciones CIL (Common Intermediate Language)
que pueden correr en cualquier lugar donde el runtime de .NET esté
disponible. Esto significa que las aplicaciones Delphi ahora pueden ir
más allá de su tradicional plataforma Windows/Intel hacia otras
plataformas que tengan un runtime .NET, como las .NET Compact Framework
disponibles para Tablet PCs, teléfonos, y PDAs.
* Delphi for .NET compiler preview - Por John Kaster
Una primera mirada a las características del compilador Delphi para
.NET y la nueva sintaxis del lenguaje Delphi
http://bdn.borland.com/article/0,1410,28972,00.html
* Delphi for .NET Preview: Samples
Este sitio web provee aplicaciones de ejemplo para el compilador
preliminar Delphi for .NET. Dichas aplicaciones son producidas por
miembros de la comunidad Borland y del plantel de Borland.
http://dotnet.borland.com
* Usando Delphi como lenguaje para scripting con ASP.NET - por John
Kaster
Una vista previa del soporte para Delphi for .NET dentro de ASP.NET
http://bdn.borland.com/article/0,1410,28974,00.html
Kylix 3 obtiene 5 estrellas de LinuxPlanet
==========================================
* Kylix 3: Borland's Linux Delphi and C++ RAD is a Winner - Por Steven
J. Vaughan-Nichols
"Ahora, sin embargo, Kylix responde las necesidades de la mayoría de
los programadores Linux al soportar completamente C++ con el mismo
entorno de desarrollo. El resultado es un RAD que rápidamente debería
convertirse en el más popular entorno integrado de desarrollo (IDE)
para Linux."
http://www.linuxplanet.com/linuxplanet/reviews/4427/1/
* Taking Kylix 3 for a test drive - Por Joe Barr
"En resumen, Kylix 3 me ha permitido desarrollar esta simple
aplicación C++ GUI para X en tan sólo unos pocos días. Considerando
la escasa experiencia en C++ y desarrollo para X que poseo, y el hecho
que nunca trabajé antes con tuberías (pipes) excepto desde la línea de
órdenes, es un tiempo muy bueno. Kylix me ha demostrado que merece su
etiqueta de RAD."
http://linux.sys-con.com/read/32782.htm
Eventos Borland que se se avecinan
===================================
* Entwickler Konferenz (EKON6), Morfeldfen/Frankfurt (Alemania), 22-27
de septiembre de 2002
Deutsch - http://www.entwicklerkonferenz.de/
English - http://www.entwicklerkonferenz.com/
* BorCon Europe, Londres (Reino Unido), 28-29 de octubre de 2002
http://www.borconeurope2002.com/
* BorCon Japan, Tokyo (Japón), 19-20 de noviembre de 2002
http://www.borland.com/jp/
* BorCon France, París (Francia), 21-22 de noviembre de 2002
http://info.borland.fr/conference/2002/
________________________________________________________________________
IBAdmin 3.22 - Complete Interbase SQL tool - Una poderosa herramienta de
administración y desarrollo para manejar servidores y bases de datos
Interbase. IBAdmin provee muchas capacidades para ayudarle en el diseño
y gestión de su base de datos. Diseñe visualmente la estructura de su
BD con el "Database Designer", administre usuarios y permisos con el
"Grant Manager", o emplee el "SQL Debugger" para depurar procedimientos
almacenados y triggers. Disfrute de una edición confortable de código
con Code-Insight y Code Completion. >> http://www.sqlly.com/
________________________________________________________________________
3. Entendiendo VisualCLX
¿Que son los objetos de enganche (hook-objects) en una aplicación Qt?
Por Max Kleiner <max @ kleiner.com>
Kleiner Kommunikation http://max.kleiner.com/
Traducido por Ernesto Cullen
VisualCLX es la parte de la librería CLX que representa los componentes
visuales que normalmente residirían en la jerarquía de TWinControl en la
VCL.
El marco de trabajo VisualCLX (VisualCLX framework) es un conjunto de
clases que representan controles visuales que tienen que trabajar (en
la medida de lo posible) tanto en MS Windows como en el X de Linux.
Los controles representados por los componentes VisualCLX son
implementados por una librería de clases en C++ llamada Qt y "widgets"
(N. de T.: los "widgets" en Linux son el equivalente a los controles en
Windows), de la compañía de desarrollo noruega llamada Trolltech. Qt
también está disponible para Windows.
La clase VCL TWinControl se llama TWidgetControl
================================================
Qt es una librería de clases en C++, y debido a las diferencias entre
C++ y OP (Object Pascal), un programa OP no puede manipular directamente
widgets Qt. En cambio, VisualCLX hace uso de una librería adicional,
llamada Librería de Interfaz Qt (Qt Interface Library), escrita en C++,
como libqtintf.so, que exporta toda la funcionalidad de Qt en una forma
que es accesible al código OP.
La unidad de importación para esta librería de interfaz se llama
Qt.pas, pero esto significa que en lugar de ser declarados como clases,
los métodos de los widgets Qt son todos importados como métodos
"planos": estrictamente hablando, procedimientos y funciones comunes.
Definimos como método "plano" a un método de una clase que se declara
como una subrutina o función independiente.
No obstante, dado que del lado de C++ son realmente clases, casi todos
los métodos planos toman un parámetro adicional que es la referencia al
widget Qt. Ud. puede pensar que esto ralentizaría las aplicaciones, pero
generalmente no percibirá diferencia alguna en el comportamiento en
tiempo de ejecución.
Entonces, ¿cuál es la diferencia en lo arquitectónico? En una aplicación
OP, llamaríamos a los métodos a través de referencias de objetos, por
ejemplo:
myButton.setBounds(15, 15, 65, 35);
Al convertir este método en un método plano, la referencia al objeto se
pasa como el primer parámetro de tal manera que el código del método
conozca la instancia que debería invocar. El siguiente es un ejemplo
"es-casi-igual-a-esto" de un método plano, equivalente al método usado
antes:
QButton_SetBounds(myButton, 15, 15, 65, 35);
o en una manipulación de Qt, en Kylix:
uses Qt, QTypes;
var Btn: QButtonH;
Btn := QButton_create(Handle, PChar('Btn'));
QButton_setGeometry(Btn, 15, 15, 65, 35);
Por supuesto, normalmente Ud. no tendría necesidad de escribir código
como éste ya que QButton lo hace por Ud., pero sirve como un ejemplo
simplificado de como los componentes CLX hacen su trabajo usando la
CLXDisplayAPI.
Qué es la CLXDisplayAPI
------------------------
CLXDisplay API es el nombre oficial de la unidad Qt.pas que viene con
Kylix y también con Delphi 6 y posteriores. Actúa como una unidad de
importación para la librería de widgets Qt usada por VisualCLX.
Pero en la vida real el tema es un poco más complicado. Qt es una
librería de clases C++, y OP no puede manipular directamente clases
C++. Debido a esto, Borland escribió una librería adicional para que
intermedia entre una aplicación CLX y la librería Qt. Esta librería
extra se llama libqtintf.so (librería de interfaz Qt), y Qt.pas es en
realidad la unidad de importación para esta librería de interfaz.
TWidgetControl ---> Qt.pas ---> libintf.so ---> Qt_Widget_Classes
Entendiendo el mecanismo Señal/Ranura (Signal/Slot)
---------------------------------------------------
Un objeto de enganche o enlace (hook object) es un objeto C++ que existe
en la librería de interfaz Qt como un intermediario. De manera que si
Ud. quiere modificar la reacción de un widget como lo haría en Windows
con manejadores de eventos, las señales y ranuras juegan el siguiente
papel:
- Una señal (evento) llega desde un widget
- Una ranura (manejador de evento) responde a una señal
Como hemos aprendido, no es posible tener la ranura escrita directamente
en OP, significando que la librería de interfaz Qt define una clase de
enlace (hook class) para cada clase de widget. La clase de enlace
implementa una ranura simple para cada señal disponible en un widget,
cuyo único propósito es llamar algún código en nuestra aplicación Kylix.
Más sobre señales/ranuras y la manera en que Kylix maneja eventos
-----------------------------------------------------------------
Como hemos visto, los mensajes (funciones callback) no son la forma de
hacer las cosas en CLX; pero esto no significa que CLX no provea soporte
para mensajes, sólo que no es la manera que tiene Kylix de hacer las
cosas. Sugerimos, por ejemplo para movimientos del ratón, que deje a
Kylix responder al ratón y simplemente sobrescriba los métodos que CLX
usa para esos eventos.
Si Ud. crea un componente y necesita capturar los mensajes del ratón,
puede usar el método siguiente:
procedure MouseMove(shift: TShiftState; X, Y: integer); override;
Debemos acostumbrarnos a pensar que en Qt los desarrolladores no
responden directamente a los mensajes. En su lugar, trabajan con el
mecanismo de señales/ranuras y una función de conexión como la
siguiente:
QObject::connect(timer, SIGNAL(timeout)), SLOT(timerSlot()));
timer -> start(1000);
U otro ejemplo para irse acostumbrando:
QObject::connect(myslider, SIGNAL(sliderMoved(in)),
mylcdNumber, SLOT(display(in)));
No hay nada especial acerca de los métodos SliderMoved y Display. Son
sólo métodos ordinarios de C++ que están marcados como señales y
ranuras, tal como algunos métodos en Kylix se marcan como virtuales.
QObject es la clase base en Qt, de la misma manera que TObject es la
clase base en OP (Object Pascal). QObject tiene un método de clase
llamado Connect. Un método de clase de OP es la misma cosa que un
método estático en C++ o Java. En particular, se puede invocar un
método de clase sin crear primero una instancia (objeto) de esa clase.
¿Y dónde está el bucle de eventos en Kylix? En el siguiente método se
encuentra el bucle de eventos que yace en el centro de las aplicaciones
CLX:
procedure TApplication.HandleMessage;
Enganches nuevamente, y resumen
-------------------------------
Hecho: hemos aprendido que Qt usa un mecanismo de señales y ranuras, y
CLX usa un mecanismo de eventos. No es muy importante cómo se conectan
los dos, pero puede ser valioso en algún momento. Vaya aquí un resumen:
Qt usa un mecanismo de señales y ranuras. CLX usa un mecanismo de
eventos.
Para traducir señales y ranuras Qt a eventos CLX, el equipo de Kylix
creó un mecanismo conocido como "enganches" (hooks). Cada tipo de
objeto CLX tiene un objeto de enganche. Este objeto de enganche
convierte los eventos de señales y ranuras asociados con un objeto
particular en eventos CLX, y luego envía estos eventos al control CLX
apropiado.
En particular, hay un método CLX en TWidgetControl llamado EventFilter
que recibe la mayoría de estos eventos. Se puede encontrar más
información sobre este tema en el CD de herramientas de Kylix
(CompanionTools CD): sams_publishing/kdgch07.pdf capítulo 7 "CLX
architecture & Visual Development", o en la entrada ID #1679 en la
Code Central de Borland. A continuación, un extracto representativo:
Si tiene grandes deseos de ir más allá de la API CLX habitual, entonces
hete aquí uno de los métodos que querrá sobrescribir:
function TWidgetControl.EventFilter(Sender: QObjectH; Event: QEventH):
Boolean;
Este es el principal. EventFilter recibe la mayoría de los eventos que
envían Qt y el sistema operativo. Es suficiente abrir QControls y
mirar las más de 500 líneas que forman la implementación de este
método para enviar a cualquier programador sano a corriendo hacia la
seguridad de las API estándar de CLX.
No obstante, a algunos les gusta vivir en el límite. Ellos claman que el
aire es más tenue pero más limpio allá arriba...
function TWidgetControl.MainEventFilter(Sender: QObjectH;
Event: QEventH): Boolean; cdecl;
var
Form: TCustmForm;
begin
try
if csDesigning in ComponentState then begin
Form := GetParentForm(Self);
if (Form <> nil) and (Form.DesignerHook <> nil) and
Form.DesignerHook.IsDesignEvent(Self, Sender, Event) then
begin
Result := True;
Exit;
end;
end;
Result := EventFilter(Sender, Event);
except
Application.HandleException(Self);
Result := False;
end;
end;
__________________
Referencia: http://www.delphi3000.com/article.asp?ID=3311
________________________________________________________________________
¿Cuándo fue la última vez que votó por el Boletín Pascal? Por favor
apoye esta iniciativa votándonos en "The Programming Top 100!"
________________________________________________________________________
4. Creando aplicaciones middleware de alto rendimiento con Indy
Por Romeo Lefter <rombest @ hotmail.com>
Rombest Software http://www.vreau.com
Traducido por Ernesto Cullen y Ernesto De Spirito
"Middleware" (capa intermedia) es una de las tecnologías de moda en el
mercado hoy en día. Desafortunadamente, las herramientas listas para
usar con esta tecnología son my costosas. Esta tecnología está asociada
con bases de datos porque es intensamente utilizada en esta área, pero
no está limitada a bases de datos. Usando esta tecnología Ud. puede
crear una plétora de aplicaciones que uses clientes "livianos" (thin
clients).
Típicamente, un entorno middleware se ve como sigue:
+--------+ +----------+ +--------+
|Clientes| <<-Conexión1->> | Servidor | <<-Conexión2->> |Servidor|
| | |Middleware| | de BD |
+--------+ +----------+ +--------+
En la imagen, [Clientes] representa sus clientes livianos, [Servidor
Middleware] es su aplicación servidora y [Servidor de datos] es la
base de datos. De acuerdo a este modelo, los clientes, el servidor de
capa intermedia y el servidor de base de datos corren en máquinas
diferentes (el servidor de datos y el servidor de capa intermedia pueden
correr en la misma máquina). Conexión1 y Conexión2 son las conexiones
entre las partes.
La arquitectura de capa intermedia es la mejor manera de hacer economía
en serio. Por ejemplo, MS SQLServer necesita una licencia adicional por
cada cliente. Además, necesita algo llamado "Licencia de acceso de
cliente" (creo). Todo esto cuesta dinero. Con una sola licencia de
cliente (más la licencia de acceso de cliente) se puede construir un
servidor intermedio y después trabajar con muchos clientes, sin pagar
licencias adicionales. ¡Y esta solución funciona muy bien!
Con relación a Middleware quisiera decir aquí que no me gustan Midas,
COM, DCOM, COM+, etc. Hay varias soluciones Middleware en el mercado.
Una pequeña parte de ellas representan soluciones realmente buenas,
pero muy caras. Hay soluciones que son fáciles de usar pero, desafor-
tunadamente, más lentas.
Hablaré aquí de cómo crear una aplicación de capa intermedia gratis.
Esto es posible y, créanme, es superior en prestaciones a otros
competidores. Primero, veamos las herramientas que necesitamos para el
trabajo.
1. Indy http://www.indyproject.org
Necesitará Indy. Porque es simple de usar y muy rápido. Hay otros
paquetes comerciales en el mercado que son más veloces que Indy, pero
trabajar con ellos no es tan fácil. Para mí, Indy es uno de los mejores
paquetes de trabajo con redes del mercado.
2. KbmMemTable: http://www.onelist.com/community/memtable
Esta es la mejor tabla en memoria que hay actualmente en el mercado.
Es segura para usar en hilos independientes ("thread safe"), su
contenido (registros y estructura) puede ser salvado a disco o a una
corriente (stream), soporta transacciones, campos binarios largos
(blob) comprimidos y mucho más. Y lo mejor de todo, es gratis y con
código fuente.
=> Una breve descripción de las características de TKbmMemTable
Como dije, el modelo de hilos (threading model) de kbmMemTable es uno
de los mejores. Sólo hay que fijar unas pocas propiedades y la tabla
puede trabajar en forma segura en un entorno multihilo. La primera
propiedad es AttachedMaxCount. Es de tipo Integer y almacena el
máximo número de tablas en memoria que pueden adjuntarse a esta
tabla. El proceso de adjuntado es muy interesante. Cuando se adjunta
una tabla de memoria (llamémosla A) a otra tabla (B) todos los datos
contenidos en la tabla B estarán disponibles para la tabla A. Más que
una simple vista, la tabla A puede agregar o actualizar registros y
los resultados se reflejarán en la tabla B. En un entorno multihilo,
este es el mejor modelo. Otra característica de kbmMemTable es su
habilidad para guardar sus datos a corrientes (streams) o archivos.
Esto nos viene muy bien para lo que queremos hacer. En su última
versión, TkbmMemTable incluye dos componentes auxiliares:
kbmBinaryStreamFormat y TkbmCsvStreamFormat que nos ayudan a
establecer un "lenguaje común" para las corrientes del servidor y el
cliente. Como puede ver, SaveToStreamViaFormat y
LoadFromStreamViaFormat son los métodos más usados en nuestro
entorno.
Es tiempo ahora de discutir el protocolo. Primero, por razones de
seguridad, se necesitará una parte de autenticación. Por lo tanto,
tenemos que implementar dos comandos: Login y Logoff. El comando Login
se envía al servidor con 2 parámetros, el nombre de usuario y la
contraseña, como se muestra a continuación:
login usuario contraseña
Si el par [usuario,contraseña] se corresponde con los datos que están
guardados en el servidor, el usuario está habilitado para trabajar,
de lo contrario es desconectado. Cuando el usuario desea terminar su
sesión, envía al servidor el comando Logoff sin parámetros. En ese
momento, el servidor desconectará al cliente.
Para hacer este ejemplo simple y portable, trabajaré aquí con tablas de
Paradox, que emularán nuestro servidor de datos. También, por motivos de
portabilidad, usaré consultas (queries). En esta aplicación usaré la
tabla country.db que se puede acceder a través del alias DBDEMOS.
Los clientes que conectarán a nuestro servidor de capa intermedia serán
capaces de:
- agregar registros a esta tabla
- recuperar la tabla completa
Para agregar registros a la tabla, implementaremos un comando (Add) con
cinco parámetros: Nombre, Capital, Continente, Area, Poblacion. De esta
manera, el comando lucirá como sigue:
Add p1 p2 p3 p4 p5
Para obtener la tabla, solamente necesitamos un comando sin parámetros
(Get).
Es hora de trabajar, así que comencemos. Abra un nuevo proyecto, coloque
una tabla de memoria y un TIdTcpServer en él. La tabla de memoria será
usada para el proceso de verificación de identidad en el ingreso
(login), por lo que tenemos que crear dos campos de tipo String en ella:
User y Password. Tendrá que implementar algunos procedimientos para
agregar, borrar y actualizar usuarios. De la misma manera, en los
eventos FormCreate y FormClose tendrá que cargar/guardar los datos
persistentes para esta tabla (usando los métodos LoadFromBinaryFile/
LoadFromCsvFile y SaveToBinaryFile/SaveToCsvFile). He decidido usar una
tabla en memoria para la autenticación porque es lo mejor en velocidad y
su mecanismo multihilo funciona perfectamente. He decidido tener la
siguiente arquitectura:
En la ventana principal:
usrs: Un KbmMemTable usado para la autenticación (tabla de
usuarios)
Server: Un componente TIdTcpServer, nuestro servidor
MThread: Un componente TIdThreadMgrPool (usaré en este ejemplo un
reservorio (pool) hilado con un tamaño de 100)
Para una mayor facilidad de entendimiento, usaré CommandHandlers
habilitado en estos proyectos, por lo que tenemos que definir 4
comandos:
-Login
-Logoff
-Get
-Add
Debido que el tamaño de nuestro reservorio es de 100, la propiedad
AttachedMaxCount de AuthTable tiene que ser 100. Además, para hacerlo
más fácilmente entendible, hemos puesto todos los componentes de
interfaz con base de datos en un módulo de datos (DataModule). Así
que cree un módulo de datos y coloque algunos componentes en él, como
se detalla a continuación:
Query1: Un componente TQuery que hará interfaz con la base de
dates, en nuestro caso DBDEMOS
Session1: Un componente TSession usado para transacciones seguras
logintable: Una memTable que será adjuntada a AuthTable para
verificar si el par [usuario,contraseña] es correcto
buffertable: Otra memTable usada para intercambio de datos
Quite el módulo de datos de la lista de formularios creados automáti-
camente (en Project|Option|Forms).
Ahora daremos una mirada profunda al modelo de servidor. Como dije, el
usuario tiene que loguearse en el servidor. Cuando el usuario envía el
comando LOGIN, el servidor seguirá los siguientes pasos:
1. Crear el módulo de datos;
2. Adjuntar la logintable (del datasource) a AuthTable (esto es en
el MainForm);
3. Verificar si el par [usuario,contraseña] es válido;
4. Devolver al usuario el resultado de la autenticación:
- Si el número de parámetros es menor que 2 (o sea, si el comando
se parece a Login MyNombre), el servidor envía ('101 - Incorrecto
número de parámetros! Adiós!') y desconecta al usuario;
- Si el par [usuario,contraseña] es válido, el servidor envía un
mensaje como ('201 - Ok, ahora está en el sistema!') y el cliente
permanecerá conectado;
- Si el par [usuario,contraseña] no es válido, el servidor envía un
mensaje como ('102 - Lo siento, usuario o contraseña inválidos.
Adiós!') y desconecta al usuario.
Un poco de código será más explícito si no ha entendido lo que he dicho.
Así que, mire aquí abajo:
procedure TForm1.serverCommandHandlers0Command(ASender: TIdCommand);
var
ClientDataModule: TDatas;
loginFlag: boolean;
begin
// Comando Login
// Formato: login <<usuario>> <<contraseña>>
if ASender.Params.Count < 2 then
begin
ASender.Thread.Connection.WriteLn(
'101 - Incorrecto número de parámetros! Adiós!');
ASender.Thread.Connection.Disconnect;
end;
// Crear el módulo de datos... Su dueño será la misma conexión!
ClientDataModule:=TDatas.Create(ASender.Thread.Connection);
// Asigna un nombre único al componente TSession
ClientDataModule.Session1.SessionName := 'ClientSession' +
Inttostr(ASender.Thread.ThreadID);
ClientDataModule.logintable.AttachedTo := usrs;
ClientDataModule.logintable.Active := True;
ClientDataModule.Query1.SessionName :=
ClientDataModule.Session1.SessionName;
// Ok, ahora verificaremos si el [usuario,contraseña] es válido
if not ClientDataModule.logintable.Locate('User',
ASender.Params[0],[]) then
loginflag := false
else
if ClientDataModule.logintable.FieldByName('Password').AsString
= Asender.Params[1] then
loginFlag := true
else
loginFlag := false;
if loginFlag then
Asender.Thread.Connection.WriteLn(
'201 - Ok, ahora está en el sistema!')
else
begin
Asender.Thread.Connection.WriteLn(
'102 - Lo siento, usuario o contraseña inválidos. Adiós!');
ASender.Thread.Connection.Disconnect;
end;
end;
A primera vista puede parecer un poco "extraño" el modo en el que hemos
creado el módulo de datos (en mi proyecto se llama Datas). Como ha
observado, lo he creado usando una variable local. El problema es
"como lo accederemos en otros procedimientos". Y he aquí mi pequeña
innovación. Usar variables globales no sería práctico pues no sabemos
cuantas conexiones tendremos en un momento dado. No nos olvidemos que el
dueño del módulo de datos es la conexión. Por cada conexión activa
tendremos un módulo de datos creado. Por supuesto, está creado sólo si
el usuario está logueado. Si el usuario no está logueado, el módulo de
datos no existe. Para un mejor entendimiento, demos un vistazo al
escenario que se presenta a continuación...
El cliente se conecta al servidor usando el método Connect de
TIdTcpClient. En este momento, el cliente puede enviar cualquier comando
al servidor. Necesitamos saber si está logueado cuando envía un comando
como Get o Add al servido. Usando el modelo que he descrito, la verifi-
cación de usuarios es realmente fácil porque si por cada conexión
cliente existe in módulo de datos, esto significa que el cliente está
logueado, y si no, el cliente no está logueado.
Ahora es tiempo de implementar una función "buscadora". Esta función es
útil para encontrar si existe un módulo de datos para una conexión. Si
el módulo de datos existe, la función devolverá una referencia al mismo.
De lo contrario, devolverá Nil.
function TForm1.FindModule(connection:TIdTCPServerConnection):TDatas;
var
i: integer;
begin
Result := nil;
for i := 0 to Connection.ComponentCount-1 do
if Connection.Components[i] is TDatas then
Result := (Connection.Components[i] as TDatas);
end;
Como dijimos, estamos usando un "modelo de reservorio de hilos" para
nuestro servidor. Esto significa que el hilo no se destruye cuando el
usuario se desconecta del servidor, de modo que tenemos de destruir el
módulo de datos manualmente cada vez que un usuario se desconecta de
nuestro servidor:
procedure TForm1.serverDisconnect(AThread: TIdPeerThread);
var
AData:TDatas;
begin
AData := FindModule(AThread.Connection);
if AData <> nil then
AData.Free;
end;
Esto significa que para un comando Logoff tenemos que hacer algo como lo
que sigue:
procedure TForm1.serverCommandHandlers1Command(ASender: TIdCommand);
begin
ASender.Thread.Connection.Disconnect;
end;
Ahora ha llegado el momento de la verdadera implementación. Tenemos que
intercambiar datos entre nuestros clientes y el servidor, así que
primero implementaremos el comando Get. Para hacer este ejemplo fácil de
entender, este comando no tendrá ningún parámetro, pero usted puede
añadir parámetros que puedan usarse para filtrar o para cualquier otra
acción. Aquí abajo está la implementación del comando:
procedure TmainFrm.serverTIdCommandHandler2Command(ASender: TIdCommand);
var
AData: TDatas;
AStream: TStream;
begin
AData := FindModule(ASender.Thread.Connection);
if Adata = nil then
begin
ASender.Thread.Connection.WriteLn(
'103 - No está logueado! Adiós!');
Asender.Thread.Connection.Disconnect;
end;
// Crear la corriente (stream)
AStream := TMemoryStream.Create;
// Comenzar la consulta
AData.Query1.sql.Clear;
AData.Query1.sql.Add('select * from country');
AData.Query1.Active := true;
// Cargar los datos de la consulta en buffertable
Adata.buffertable.LoadFromDataSet(Adata.Query1,[mtcpostructure]);
// Guardar BufferTable en la corriente Astream
AData.buffertable.SaveToStreamViaFormat(Astream,
adata.kbmBinaryStreamFormat1);
// Poicionarse al comienzo de la corriente
Astream.Seek(0, soFromBeginning);
ASender.Thread.Connection.WriteLn(
'202 - Ok! La corriente está llegando!');
// Enviar la corriente AStream a la aplicación cliente
ASender.Thread.Connection.WriteStream(AStream,true,true);
// Liberar la corriente
AStream.Free;
end;
Para este comando, el cliente recibirá una corriente conteniendo todos
los datos de la tabla. Esta corriente puede ser cargada en un
TKbmMemTable y toda la tabla en el servidor será visible en el cliente.
Sin la BDE o cualquier otra "solución de conectividad" de terceros.
Dado que el comando Add se implementa de manera idéntica (tiene que leer
los parámetros y crear una consulta que inserte los parámetros en la
tabla), no voy a elaborar más en este aspecto. Además, dado que la
implementación cliente es realmente fácil, no la describiré.
Esta es toda la "tecnología". Es fácil de implementar, superior en
rendimiento y no cuesta nada. Hay, por supuesto, muchos otros aspectos
a considerar. Por ejemplo, puede usar corrientes comprimidas para
reducir el tráfico entre servidores y clientes.
Hay algunas cosas que usted debe saber antes de iniciar la creación de
su siguiente "gran servidor middleware". Antes que comience, tiene que
construir su protocolo y esto, en mi opinión, es la parte más importante
del proyecto. Un buen protocolo lo ayudará en el proceso de desarrollo.
Veamos el fragmento de código de arriba. Primero, note que hay un número
al inicio de cada cadena que se envía al cliente. En el protocolo de
ejemplo he usado un protocolo numérico combinado con un protocolo de
cadena. Antes del texto que se envía el cliente, he usado un código
numérico: 1XX representa las acciones con error y 2XX representa las
acciones exitosas. Esto le ayudará al desarrollar aplicaciones clientes.
Del lado del cliente puede crear una función de ayuda que extraiga este
código numérico y, por cada cadena recibida por su cliente sabrá si ha
ocurrido un error o si "todo está bien". Otra parte interesante es la
sincronización. Cuando un servidor envía una corriente, tiene que leer
una corriente del lado del cliente. Lo mismo con cadenas. Si espera por
una cadena y se envía una corriente, su aplicación cliente quedará
bloqueada. Por esta razón he insertado el mensaje '202 - Ok! La
corriente está llegando!'. A primera vista es innecesario, pero sólo
mire el comienzo del procedimiento. Si el cliente no está logueado, el
servidor le envía el mensaje '103 - No está logueado! Adiós!'. Cuando
un cliente envía un comando Get al servidor primero lee una cadena
porque tiene que saber si el servidor devuelve un error.
Otra cosa interesante es acerca de como se envían las corrientes. El
procedimiento WriteStream tiene 3 parámetros. El primero es la corriente
que será enviada. El segundo parámetro es un valor lógico, que si es
verdadero, la corriente se enviará desde el inicio y si es falso se
enviará desde la posición actual. El tercer parámetro también es lógico.
Si es verdadero, el tamaño de la corriente se enviará al cliente, y si
es falso, este valor no se enviará. Si el último parámetro es verdadero,
el tamaño se envía como un valor entero, antes de la corriente. Los
siguientes fragmentos de código son lo mismo:
1. => WriteStream con último parámetro False
....
i := MyStream.Size;
ASender.Thread.Connection.WriteInteger(i);
ASender.Thread.connection.WriteStream(MyStream, true, false);
....
es lo mismo que
2. => WriteStream con último parámetro True
....
ASender.Thread.Connection.WriteStream(MyStream, true, true);
....
Se adjunta una demo a este artículo, la que contiene una implementación
completa de un cliente y un servidor. ¡Disfrútenlo!
__________________
Referencia: http://www.delphi3000.com/member.asp?ID=806
________________________________________________________________________
En Delphiladero estamos interesados en alentar la producción de material
sobre Delphi escrito enteramente en español. Hay mucha gente capaz de
escribir artículos, programas y componentes excelentes, pero, por alguna
razón, no lo hacen. Este sitio puede ser el comienzo de un cambio...
http://webs.sinectis.com.ar/alvadel E-mail: <casta_pablo@hotmail.com>
________________________________________________________________________
5. Inline Assembler en Delphi (III) - Arreglos estáticos
Por Ernesto De Spirito <eds2008 @ latiumsoftware.com>
Pasando arreglos estáticos como parámetros
==========================================
Los parámetros de este tipo se pasan como punteros al primer elemento
del arreglo, independientemente de si el parámetro se pasa por valor o
por referencia (ya sea como "var" o como "const").
Dadas las siguientes declaraciones...
const
ARRAY_MAX = 5;
type
TArrayOfInt = packed array [0..ARRAY_MAX] of longint;
var
a, b: TArrayOfInt;
procedure InitializeArray(var a: TArrayOfInt);
var
i: integer;
begin
for i := 0 to ARRAY_MAX do
a[i] := i;
end;
...la llamada al procedimiento InitializeArray en ensamblador sería
así:
// En Object Pascal:
// InitializeArray(a);
// En Inline Assembler:
asm
mov eax, offset a // EAX := @a;
call InitializeArray // InitializeArray;
end;
OFFSET es un operador unario del ensablador que devuelve la dirección de
un símbolo. OFFSET no es aplicable a símbolos locales. Debemos usar el
opcode LEA (ver más abajo), que es más "universal".
Arreglos estáticos pasados por valor
------------------------------------
Si el arreglo de pasa por valor, es responsabilidad de la función
llamada la de preservar el arreglo. Cuando una función necesite cambiar
los valores de uno o más elementos de un arreglo pasado por valor,
normalmente crea una copia local y trabaja sobre la copia. El compilador
crea una copia por nosotros en el "begin" de procedimientos y funciones
en Pascal, pero en procedimientos y funciones totalmente en ensamblador
tenemos que hacerlo por nuestra cuenta. Una forma de hacerlo es de la
siguiente manera:
procedure OperateOnArrayPassedByValue(a: TArrayOfInt);
var
_a: TArrayOfInt;
asm
// Copia los elementos de "a" (parámetro) en "_a" (copia local)
push esi // Salva ESI en la pila
push edi // Salva EDI en la pila
mov esi, eax // ESI := EAX; // @a
lea edi, _a // EDI := @_a;
mov eax, edi // EAX := EDI; // @_a
mov ecx, type TArrayOfInt // ECX := sizeof(TArrayOfInt);
rep movsb // Move(ESI^, EDI^, ECX);
pop edi // Restaura EDI desde la pila
pop esi // Restaura ESI desde la pila
// Aquí va el resto de la función. Trabajaremos sobre "_a" (la
// copia local), cuyo primer elemento es ahora apuntado por EAX.
end;
Las cosas nuevas aquí son los opcodes LEA y MOVSB, el prefijo REP y el
operador TYPE, descritos a continuación.
LEA (Load Effective Address)
-----------------------------
Mueve al primer operando la dirección del segundo. Aquí comparamos LEA
con MOV:
Instrucción Traducidad como Efecto
-------------------------------------------------------------------
lea eax, localvar lea eax, [ebp-$04] EAX := @localvar;
EAX := EBP - $04;
mov eax, localvar mov eax, [ebp-$04] EAX := localvar;
EAX := (EBP - $04)^;
MOVSB (MOVe String Byte)
------------------------
Copia el byte apuntado por ESI a la ubicación apuntada por EDI, e
incrementa ESI y EDI de modo que apunten al siguiente byte. El trabajo
de MOVSB se puede representar como sigue:
ESI^ := EDI^; // Asumimos que ESI y EDI son de tipo PChar
Inc(ESI);
Inc(EDI);
Notas:
* MOVSW y MOVSD son las versiones Word (16 bits) y DWord (32 bits)
respectivamente (ESI y EDI se incrementan en 2 y 4 respectivamente).
* Los registros de decrementan si la bandera de dirección (Direction
Flag) está encendida.
REP
---
El prefijo REP es usa en operaciones de cadenas para repetir la
operación, decrementando ECX hasta que ECX sea cero. El trabajo de REP
se podría representar así:
// rep instrucción_de_cadenas
@@rep:
instrucción_de_cadenas
loop @@rep
Notas:
* REP no es un atajo para un código como el de arriba. Funciona mucho
más rápido.
* El valor de ECX no es comprobado al inicio del ciclo (si ECX es cero,
la instrucción sería repetida 2^32 veces, pero generará una AV mucho
antes de ello, tan pronto como ESI o EDI apunten a una ubicación de
memoria no válida).
TYPE
----
El operador TYPE es un operador unario evaluado en tiempo de compilación
que devuelve el tamaño en bytes del operando, el que debe ser un tipo de
datos. Por ejemplo TYPE WORD devolverá 2 y TYPE INTEGER devolverá 4.
Accediendo los elementos de un arreglo
======================================
Para acceder a un elemento a[i] necesitamos los valores de "@a[0]" e "i"
en registros (como EDX y ECX, por ejemplo), y entonces podemos usar el
direccionamiento de memoria como sigue:
lea edx, a // EDX := @a;
mov ecx, i // ECX := i;
mov ax, [edx+ecx*type integer] // AX := EDX[ECX]; // a[i];
// PWord(EDX + ECX * SizeOf(integer))^
En el ejemplo, asumimos que los elementos tienen 2 bytes (movimos el
valor de a[i] a AX, un registro de 16 bits ), que el arreglo no es
"packed" (cada elemento en realidad ocupa 4 bytes, el tamaño de un
Integer, así que ése fue el valor usado para calcular la posición del
elemento), y que el arreglo de de base cero. Por ejemplo:
var a: array [0..N] of word = (1, 2, 3, 6, ...);
+------ EDX = @a
|
v
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--
| 1 | 0 | | | 2 | 0 | | | 3 | 0 | | | 6 | 0 | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--
a[0] a[1] a[2] a[3]
[edx] [edx+04] [edx+08] [edx+12]
Si el arreglo no tiene base cero, tenemos que ajustar el valor del
índice para hacerlo base cero antes de direccionar el elemento.
Ejemplos:
// a[1..100]
:
mov ecx, i // ECX := i;
dec ecx // Dec(ECX); // Ajustar ECX
:
// a[-10..10]
:
mov ecx, i // ECX := i;
add ecx, 10 // Inc(ECX, 10); // Ajustar ECX
:
El procedimiento InitializeArray (presentado arriba) puede implementarse
en ensamblador de esta forma:
procedure InitializeArray(var a: TArrayOfInt);
asm // EAX = PByte(@a[0]);
xor ecx, ecx // ECX := 0;
@@loop:
mov [eax+ecx*type integer], ecx // PInteger(EAX+ECX*4)^ := ECX;
// ...o EAX[ECX] := ECX;
inc ecx // ECX := ECX + 1;
cmp ecx, ARRAY_MAX // if ECX <= ARRAY_MAX then
jle @@loop // goto @@loop;
end;
O de esta otra:
procedure InitializeArray(var a: TArrayOfInt);
asm // EAX = @a[0];
xor ecx, ecx // ECX := 0;
@@loop:
mov [eax], ecx // EAX^ := ECX;
inc ecx // Inc(ECX);
add eax, type integer // Inc(EAX); // Apuntar al siguiente elemento
cmp ecx, ARRAY_MAX // if ECX <= ARRAY_MAX then
jle @@loop // goto @@loop;
end;
Devolviendo valores array
=========================
Las funciones que devuelven arreglos reciben un último parámetro
adicional que es un puntero a la ubicación de memoria donde deben dejar
su valor de retorno (la memoria es asignada y liberada si es necesario
por el llamador).
Por ejemplo, consideremos la siguiente función:
function ReverseArray(const a: TArrayOfInt): TArrayOfInt;
var
i: integer;
begin
for i := 0 to ARRAY_MAX do
Result[i] := a[ARRAY_MAX-i];
end;
La función recibe dos parámetros:
1) EAX = la dirección del primer elemento del arreglo "a"
2) EDX = la dirección del primer elemento de Result
La función puede ser rescrita en ensamblador como sigue:
function ReverseArray(const a: TArrayOfInt): TArrayOfInt;
asm // EAX = @a[0]; EDX = @Result[0];
push ebx // Salvar EBX
mov ebx, eax // EBX := EAX;
xor ecx, ecx // ECX := 0;
@@loop:
mov eax, ARRAY_MAX
sub eax, ecx // EAX := ARRAY_MAX-ECX;
mov eax, [ebx+eax*type integer] // EAX := EBX[EAX];
mov [edx+ecx*type integer], eax // EDX[ECX] := EAX;
inc ecx // ECX := ECX + 1;
cmp ecx, ARRAY_MAX // if ECX <= ARRAY_MAX then
jle @@loop // goto @@loop;
pop ebx // Restaurar EBX
end;
Bien, eso es todo por ahora. En la próxima edición veremos como trabajar
con registros.
________________________________________________________________________
6. Foros / listas de correo
Para quienes son miembros de nuestros foros (grupos en Yahoo! Grupos),
me gustaría recordarles que la participación en los mismos está sujeta
a ciertas reglas, de las cuales me gustaría extractar algunas que son
comunes a todos los foros:
* El asunto de los mensajes tiene importancia capital. Por favor:
. Provee un asunto representativo en tus preguntas. Trata que sea lo
más específico posible y que incluya palabras clave que puedan
facilitar la búsqueda posterior de un determinado tema.
. Evita el uso de palabras como "duda", "problema", "socorro",
"SOS", "ayuda" (excepto que estés hablando de archivos de ayuda),
"consulta" (salvo que estés hablando de una consulta SQL), etc.
. Evita usar de signos de exclamación y escribir todo en mayúsculas.
. No modifiques la línea de asunto al responder un mensaje.
* Elimina lo más posible del mensaje original al responder, para reducir
así el tamaño de los mensajes. Como mínimo, al responder elimina las
líneas innecesarias de arriba y de abajo del mensaje original:
- Todo o parte de los encabezados. Mínimamente las líneas de:
. Destinatario (es el foro, ya lo sabemos)
. Asunto (se repite en la respuesta, ya lo sabemos)
. Fecha de envío (opcional)
- Las frases iniciales y finales como saludos, presentaciones, agrade-
cimientos, firmas ("signatures"), publicidades de los servicios de
webmail y de Yahoo!, direcciones del foro, etc.
- Los mensajes anteriores del hilo de conversación
* No envíes mensajes irrelevantes (como mensajes de agradecimiento,
o respuestas del tipo "yo lo quiero" / "yo también" cuando alguien
ofrece algo en el foro, y mucho menos mensajes fuera de tema como
cartas cadena -o "pirámide"-, alertas de virus, publicidades, etc.)
* No envíes ofrecimientos, solicitudes o apologías de cracks, warez,
seriales y otras formas de piratería informática.
* No envíes mensajes del tipo "¿Dónde puedo encontrar...?" (excepto en
el caso del foro de Componentes, que está para ese fin).
* Incluye abundante información sobre el problema que planteas (como
por ejemplo versión del producto y sistema operativo que usas, etc.)
* Todos los foristas y todos los mensajes tienen la misma prioridad,
así que por favor no envíes mensajes urgentes, con prioridad o con
su asunto todo en mayúsculas, y evita usar expresiones como "por
favor ayúdenme", "mi empleo depende de esto", "estoy desesperado",
"ya no sé que hacer", etc., así como cualquier otra forma de
intentar obtener ventaja o resaltar tu mensaje sobre los demás.
* No escribas todo en mayúsculas (parece que estuvieras gritando).
Como siempre, recordamos a los suscriptores las direcciones de nuestros
foros. Para unirse a algún foro, lo más recomendable es hacerlo desde la
web para así tener acceso a todas las áreas del foro y la configuración
de las opciones de suscripción, pero también es posible suscribirse por
email. Para suscribirse desde la web es necesario poseer un ID de Yahoo!
(si no tienes el tuyo, puedes conseguirlo gratis registrándote como
usuario de Yahoo!).
* Delphi-abierto. Programación en Delphi (todos los niveles). Si estás
en la etapa de aprendizaje o si no te agradan los foros discriminados
por niveles, este foro es para ti.
http://espanol.groups.yahoo.com/group/delphi-abierto
Suscripción:
http://espanol.groups.yahoo.com/group/delphi-abierto/join
delphi-abierto-subscribe@gruposyahoo.com
* Delphi-intermedio. Programación en Delphi (nivel intermedio). Si ya
sabes mucho de Delphi, pero todavía te falta un largo trecho para ser
un gurú (o no tanto), este foro es para ti.
http://espanol.groups.yahoo.com/group/delphi-intermedio
Suscripción:
http://espanol.groups.yahoo.com/group/delphi-intermedio/join
delphi-intermedio-subscribe@gruposyahoo.com
* Delphi-avanzado. Programación en Delphi. Sólo para gurús.
http://espanol.groups.yahoo.com/group/delphi-avanzado
Suscripción:
http://espanol.groups.yahoo.com/group/delphi-avanzado/join
delphi-avanzado-subscribe@yahoogroups.com
* GrupoKylix. Programación en Kylix.
http://espanol.groups.yahoo.com/group/GrupoKylix
Suscripción:
http://espanol.groups.yahoo.com/group/GrupoKylix/join
GrupoKylix-subscribe@yahoogroups.com
* FreePascal-es. Programación en Free Pascal (freepascal.org).
http://espanol.groups.yahoo.com/group/freepascal-es
Suscripción:
http://espanol.groups.yahoo.com/group/freepascal-es/join
freepascal-es-subscribe@yahoogroups.com
* Desarrolladores-Software. Un lugar para tratar todos aquellos temas
relacionados con el desarrollo de software y su comercialización, y
para compartir experiencias en el ámbito laboral, profesional o
comercial con otros.
http://es.groups.yahoo.com/group/desarrolladores-software
Suscripción:
http://es.groups.yahoo.com/group/desarrolladores-software/join
desarrolladores-software-subscribe@yahoogroups.com
* Componentes. Un foro para buscar/recomendar componentes de software
(componentes VCL y CLX, objetos ActiveX, librerías DLL, etc.), así
como utilidades, tutoriales, información, etc.
http://espanol.groups.yahoo.com/group/componentes
Suscripción:
http://espanol.groups.yahoo.com/group/componentes/join
componentes-subscribe@yahoogroups.com
________________________________________________________________________
7. Delphi en la Red
Por Dave Murray <irongut @ vizzavi.net>
Componentes, librerías y aplicaciones
=====================================
Freeware
--------
* Kylix 3 Open Edition available for download
It's a whopping 300+ MB download, but worth every nibble!
http://community.borland.com/article/0,1410,29010,00.html
* Explorer Drop v1.1, FREEWARE with source - by Simon Grossenbacher
TExplorerDrop component enables Drag&Drop with the Windows Explorer
for all controls inherited from TWinControl.
http://www.torry.net/vcl/system/draganddrop/swissexplorerdrop.zip
* KACDO Proffesional v1.0, FREEWARE - by Kiril Antonov
Delphi implementation of Microsoft's CDO for Win2k -a set of functions
for composing and sending mail. Works only on Win2k/XP machines. Set
of 3 powerful components: Message - Message, SMTP, NNTP, Encoding +
Decoding Component; Manager - manages IIS SMTP Folders; TreeView -
displays + modifies structure of complex messages.
http://www.torry.net/vcl/internet/email/kacdo30.zip
* TAdvFTP, FREEWARE with source - by Vadim Winebrand (KYLIX)
An advanced FTP client component which supports resumes and gives the
download rate every few seconds. Includes socks server support.
http://www.torry.net/kylix/clx/internet/itools.zip
Artículos, trucos y consejos
============================
* TJpegImage lets you transform BMPs to JPEGs - by Bob Swart
Dr Bob shares a trick for transforming BMPs to JPEGs and vice versa.
Thanks to a hidden component, it's not as hard as you might think.
http://builder.com.com/article.jhtml?id=u00220020913swa01.htm
* Using Delphi objects to store config information - by Sebastián Mayorá
This article explains how to use objects as a substitute for INI files
(and other similar techniques) to store configuration information.
http://delphi.about.com/library/bluc/text/uc090302a.htm
* Back to School with more Delphi knowledge - by Zarko Gajic
Whether you're parent, student or teacher here are the topics you need
to enhance your knowledge of Delphi programming. Go back to school in
style with the right tutorials, code samples and Delphi quizzes.
http://delphi.about.com/library/weekly/aa082702a.htm
* ModelMaker tutorials - by Anders Ohlsson
ModelMaker is included in D7 Enterprise & Architect - here are some
tutorials to get you started.
http://bdn.borland.com/article/0,1410,29006,00.html
* How to install and uninstall fonts
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=169
* How to check if a string is a number
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=170
* How to get second title bar color
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=171
* BDE error list
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=173
* How to get the CPU speed
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=174
* How to write a correct date in SQL
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=175
* How to get around TQuery.Refresh if it doesn't work - by m3Rlin
Sometimes TQuery.Refresh will not refresh as it's supposed to...
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=176
* How to read the serial number of an Audio CD - by m3Rlin
Audio CDs, like almost every computer drive/media have a serial number
too. Some programs use this number to recognize CDs.
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=177
* How to check is a character is a letter - by m3Rlin
www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=178
* How to export a StringGrid to an Excel-File?
http://www.swissdelphicenter.ch/en/showcode.php?id=379
* How to turn on/off Caps/Num/Scroll Lock?
http://www.swissdelphicenter.ch/en/showcode.php?id=926
* How to synchronize DBGrid title alignments with field alignments?
http://www.swissdelphicenter.ch/en/showcode.php?id=1074
* How to save memory with duplicate strings?
http://www.swissdelphicenter.ch/en/showcode.php?id=1110
* How to draw a gradient on a canvas with an arbitrary number of colors?
http://www.swissdelphicenter.ch/en/showcode.php?id=1162
* How to retrieve information about the TWebBrowser control?
http://www.swissdelphicenter.ch/en/showcode.php?id=1191
* How to retrieve the network card addresses?
http://www.swissdelphicenter.ch/en/showcode.php?id=1206
* How to convert C Types to Object Pascal Types?
http://www.swissdelphicenter.ch/en/showcode.php?id=1217
* How to get an inverse color value to a color?
http://www.swissdelphicenter.ch/en/showcode.php?id=1222
* How to show values in a hexadecimal representation?
http://www.swissdelphicenter.ch/en/showcode.php?id=1312
* How to show values in binary representation?
http://www.swissdelphicenter.ch/en/showcode.php?id=1313
* How to get the start command for a installed Mail-Client?
http://www.swissdelphicenter.ch/en/showcode.php?id=1320
* How to execute a document and wait for it to finish?
http://www.swissdelphicenter.ch/en/showcode.php?id=1333
* How to do bit-wise manipulation?
http://www.swissdelphicenter.ch/en/showcode.php?id=1341
* How to Draw on a Form's Caption bar?
http://www.swissdelphicenter.ch/en/showcode.php?id=1345
* How to access Paradox tables on CD or read-only drives?
http://www.swissdelphicenter.ch/en/showcode.php?id=1351
* How to define BDE aliases in code?
http://www.swissdelphicenter.ch/en/showcode.php?id=1353
* How to multiply big integer values?
http://www.swissdelphicenter.ch/en/showcode.php?id=1363
* How to calculate the logarithm for a variable base?
http://www.swissdelphicenter.ch/en/showcode.php?id=1371
* How to auto hide IDE windows when coding/designing?
http://www.swissdelphicenter.ch/en/showcode.php?id=1382
* How to get the length of wav file (in second)?
http://www.swissdelphicenter.ch/en/showcode.php?id=1383
* How to Clone the Controls Properties?
http://www.swissdelphicenter.ch/en/showcode.php?id=1392
* How to set system evrionment variable?
http://www.swissdelphicenter.ch/en/showcode.php?id=1394
* How to Set a new Index to TToolButton of a TToolbar?
http://www.swissdelphicenter.ch/en/showcode.php?id=1395
* How to include the mouse-cursor in a screen shot?
http://www.swissdelphicenter.ch/en/showcode.php?id=1396
* How to send data to another program by auto-drag&drop?
http://www.swissdelphicenter.ch/en/showcode.php?id=1398
* How to empty all StringGrid cells?
http://www.swissdelphicenter.ch/en/showcode.php?id=1399
* How to get the width and height of a Gif-File?
http://www.swissdelphicenter.ch/en/showcode.php?id=1400
* How to transition the system to the standby/ hibernate state?
http://www.swissdelphicenter.ch/en/showcode.php?id=1401
* How to know if the form is modal?
http://www.swissdelphicenter.ch/en/showcode.php?id=1402
* How to prevent copy/paste/cut in TEdit?
http://www.swissdelphicenter.ch/en/showcode.php?id=1403
* How to use regular expressions in Delphi?
http://www.swissdelphicenter.ch/en/showcode.php?id=1406
* How to save a QuickReport to stream?
http://www.swissdelphicenter.ch/en/showcode.php?id=1410
* How to build a Multi Screen Emulator?
http://www.swissdelphicenter.ch/en/showcode.php?id=1418
* How to use the DrawAnimatedRects API?
http://www.swissdelphicenter.ch/en/showcode.php?id=1419
* How to get the caret-position systemwide?
http://www.swissdelphicenter.ch/en/showcode.php?id=1420
* How to invoke the 'find' dialog in a TWebBrowser?
http://www.swissdelphicenter.ch/en/showcode.php?id=1421
* How to determine if the current session is remotely controlled?
http://www.swissdelphicenter.ch/en/showcode.php?id=1424
* How to translate a virtual-key to ASCII code?
http://www.swissdelphicenter.ch/en/showcode.php?id=1425
* How to convert a bitmap to RTF code?
http://www.swissdelphicenter.ch/en/showcode.php?id=1426
* How to export a TDBGrid to excel without OLE?
http://www.swissdelphicenter.ch/en/showcode.php?id=1427
* How to read a REG_MULTI_SZ value From the Registry?
http://www.swissdelphicenter.ch/en/showcode.php?id=1431
* How to restore the default positions of the IDE Toolbars?
http://www.swissdelphicenter.ch/en/showcode.php?id=1432
* How to retrieve all database tables with ADO?
http://www.swissdelphicenter.ch/en/showcode.php?id=1433
* How to add items to the Application's Windows System Menu?
http://www.swissdelphicenter.ch/en/showcode.php?id=1435
* How to get the number of Files in the Recycle Bin + their total size?
http://www.swissdelphicenter.ch/en/showcode.php?id=1436
* How to change Background Color in TRichEdit for selected characters?
http://www.swissdelphicenter.ch/en/showcode.php?id=1438
* How to show/hide the ActiveDesktop?
http://www.swissdelphicenter.ch/en/showcode.php?id=1439
* How to copy formated Rtf-Text from one TRichedit to an other?
http://www.swissdelphicenter.ch/en/showcode.php?id=1440
* How to use different underline styles for Text in TRichEdit?
http://www.swissdelphicenter.ch/en/showcode.php?id=1441
* How to put the TWebbrowser into Edit Mode?
http://www.swissdelphicenter.ch/en/showcode.php?id=1442
* How to set the paragraph line spacing in a TRichedit?
http://www.swissdelphicenter.ch/en/showcode.php?id=1444
* Speed up connection to Oracle 8i - by Mark Halter
http://www.delphi3000.com/articles/article_3344.asp
* How do we store Graphics/Shapes like an Object? - max kleiner
Designing a diagram editor or a graphic-tool raises the problem of
storing all the painted shapes in a file without get lost in too much
overhead.
http://www.delphi3000.com/articles/article_3348.asp
* Simulate a Web Form POST Request - by Clever Components
Discusses the automation of the upload process via HTTP protocol by
the POST method using the components from Clever Internet Suite.
http://www.delphi3000.com/articles/article_3351.asp
* Threaded Brute Forcing Class - by Stewart Moss
http://www.delphi3000.com/articles/article_3352.asp
* Simple useful Irc routines - by Stewart Moss
http://www.delphi3000.com/articles/article_3353.asp
* Generic File Importer Base Class - by Stewart Moss
Here is a useful base class to create derived classes to import data
from any flat file format you can think of.
http://www.delphi3000.com/articles/article_3354.asp
* ADO Dataset -> CSV file
How to export a ADO Dataset to a Comma Separated Values file with a
few lines of code.
http://www.delphi3000.com/articles/article_3355.asp
* Send E-Mails with Indy Components (Easy)
http://www.delphi3000.com/articles/article_3356.asp
* Show message in OnEnter event
Do you ever needed to display a message using the OnEnter event?
This example shows how to correctly display a message by using the
ShowMessage (or an equivalent function) in OnEnter event.
http://www.delphi3000.com/articles/article_3357.asp
* EventLog change notification in real-time
I needed a way to be notified in real-time when someone acceded my
computer inside an intranet. After doing some research, the solution
would pass by using the Security event log that is used when you
activate any audit option.
http://www.delphi3000.com/articles/article_3358.asp
* SQL-DMO part 1: The SQL-DMO API
This is the first part of a serie of articles about the SQL
Distributed Management Objects known as SQL-DMO API. In this first
article I'll talk about SQL-DMO, whats the purpose of it and what
you'll gain if you use it. I will also show how to install it, so
you can use it within our Delphi projects
http://www.delphi3000.com/articles/article_3359.asp
* Multi Column ListBox with Column Sorting and Resizing
This is a VCL that allows multiple columns in a list box. The columns
may be sorted (if the AllowSorting property is set to true) by
clicking on the column header title. The column headers are set up in
the Sections property. They are of type THeaderSections from the
THeader component and thus may also display images from an associated
image list. The items in the ListBox are semi-colon delimited fields.
The fields are lined up in accordance to the Section headers and may
be resized by the user at run-time.
http://www.delphi3000.com/articles/article_3360.asp
* Capture Output of a Console Application - Revised
How do you start a DOS or Console Application and capture the output
while it is running ? For example, how do you capture the output of
the FileCompare (FC) Command ?
http://www.delphi3000.com/articles/article_3361.asp
* Retrieve Multiple Recordsets from ORACLE 8i Stored Procedure
A faster and more resource efficient way to get data from the
Database server (in this case - Oracle)
http://www.delphi3000.com/articles/article_3363.asp
Tutoriales
==========
* Defining a ClientDataSet's Structure Using TFields - by Cary Jensen
This article demonstrates how to define a ClientDataSet's structure at
both design-time and runtime using TFields. How to create virtual and
nested dataset fields is also demonstrated.
http://community.borland.com/article/0,1410,29001,00.html
* Understanding ClientDataSet Indexes - by Cary Jensen
A ClientDataSet does not obtain its indexes from the data it loads.
Indexes, if you want them, must be explicitly defined. This article
shows you how to do this at design-time or runtime.
http://community.borland.com/article/0,1410,29056,00.html
* Improve application design with Prototyping, Modeling, + Storyboarding
- by Ronald Anthony Lewis
Meeting client expectations is the number-one goal of application
development. Here's how one developer uses three approaches to handle
different aspects of this critical objective.
http://builder.com.com/article.jhtml?id=u00320020909RAL01.htm
* An introduction to XML grammar - by Philip Page
Document Type Definitions (DTDs) are an optional but useful part of
XML. This article shows you how to declare a grammar in a DTD.
http://builder.com.com/article.jhtml?id=u00320020906ppg01.htm
* Unified Modeling Language simplifies software design - by Shelley Doll
UML is the industry standard for modeling software architecture. It
combines best practices, platform independence, and extensibility into
a common language for describing solutions. This overview of UML
describes why it's useful and outlines the major concepts.
http://builder.com.com/article.jhtml?id=u00420020903dol01.htm
* To be or not to be normal: That is the database question - Eric Roland
There are advantages + disadvantages to normalizing database schemas.
This article provides specific examples of when and why you should
normalize or denormalize your final database design based on
performance requirements.
http://builder.com.com/article.jhtml?id=u00320020819ero01.htm
* Transition from Logical to Physical Data Model - S Harkins + A Fuller
Moving from a logical to physical design is not as straightforward as
it appears. Use these tips to make the process as smooth as possible.
http://articles.techrepublic.com.com/5100-10878_11-1050841.html
Otros enlaces
=============
* Delphi Fireworks Component Contest
Basically, you have to make a self-contained Delphi visual component.
There are no prizes, but you will receive awe and recognition from
your peers, just for entering. Also it makes a great resume entry.
http://chuckr.freeshell.org/index.php
* ModelMaker is available for Delphi 7 Professional - by John Kaster
Borland provides a license to ModelMaker for Delphi 7 Professional.
http://community.borland.com/article/0,1410,29090,00.html
* Borland to wield tools against Microsoft - by Wylie Wong
After nearly being knocked out for good by Microsoft, software maker
Borland is back on its feet and eager for a rematch.
http://news.cnet.com/2100-1001-954958.html
* Borland has a bead on Visual Studio - By Mark Driver (from Gartner)
Borland plans to offer an alternative to Microsoft's Visual Studio
.NET development environment. Such a product could suit application
developers that want to leverage .NET and the best applications from
many vendors.
techupdate.zdnet.com/techupdate/stories/main/0,14179,2879601,00.html
* Now all we need are celebrity endorsements - by Lamont Adams
Humourous article about the possibility of celebrity endorsements in
programming. Use the official IDE of the World Cup!
http://articles.techrepublic.com.com/5100-10878_11-1050148.html
* SharpDevelop lets you jump into C# Programming for FREE! - Tony Patton
You're dying to start programming in C#, but Visual Studio .NET is
just too expensive. Help is on the way with this free .NET IDE.
http://articles.techrepublic.com.com/5100-10878_11-1050213.html
________________________________________________________________________
¡Tú puedes ayudarnos!
Por favor danos una mano y ayúdanos a llegar a los 10.000 suscriptores
en los próximos meses. Una forma en que puedes ayudarnos es enviando
este enlace a tus amigos:
http://www.latiumsoftware.com/es/pascal/index.php
boletin-pascal-subscribe@gruposyahoo.com
Otra forma es votándonos en alguno de estos rankings para darle más
visibilidad a nuestro sitio web y aumentar así el número de suscrip-
ciones al boletín:
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://www.lawebdelprogramador.com/buscar/votar.php?id=615
Por favor vota. Son sólo unos segundos para ti que REALMENTE pueden
hacer la diferencia. Necesitamos tu ayuda para poder continuar.
________________________________________________________________________
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=p39
________________________________________________________________________
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) 2002 por Ernesto De Spirito. Todos los derechos reservados
________________________________________________________________________
|