Entrar
¿No tienes cuenta? Registrarse
boletin-pascal · Boletín Pascal (Delphi/Kylix)
? ¿Ya tienes membresía? Entra a Yahoo!

Consejos

¿Sabías que...
Puedes acompañar la descripción de tu grupo con una foto.

Mensajes

  Mensajes Ayuda
Avanzado
Mensajes 1 - 20 de 20   Más nuevo  |  < Más reciente  |  Más antiguo >  |  Más antiguo
Mensajes: Ver resúmenes de mensajes   (Agrupar por tema) Ordenar por fecha v  
#20 De: "Ernesto De Spirito" <owner@...>
Fecha: Mar, 8 de Feb, 2005 8:40 pm
Asunto: Boletín Pascal #53 - 08-FEB-2005
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #53 - 08-FEB-2005

Índice

1. Unas palabras del editor
2. Análisis de rendimiento del código con puntos de interrupción sin
    interrupción (non-breaking breakpoints)
3. Presentando YAPI
4. Estableciendo el manejador de eventos predeterminado de un componente
5. Antivirus en Delphi: aRC-Anti WODE.JPG 1.0
6. Foros / listas de correo
7. Delphi en la Red
    - Componentes, librerías y aplicaciones
      · Shareware / Comercial
      · Freeware
      · Actualizaciones de productos Borland
    - Artículos, trucos y consejos
    - Tutoriales y capacitación
    - Noticias
    - Otros / Sitios misceláneos

________________________________________________________________________

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


Finalmente me encuentro al día con las publicaciones. Es un gran alivio
para mí. Les agradezco el apoyo que me han brindado todo este tiempo
manteniendo vivo el interés en esta modesta publicación. Espero que en
el 2005 podamos mantener el calendario de publicación que nos hemos
propuesto.

Los usuarios de Hotmail que no hayan podido descargar el archivo con el
código fuente que acompañó al Boletin Pascal #52 debido a una falsa
alarma de virus producida por el análisis heurístico de Trend Micro (el
antivirus que usa Hotmail), pueden descargar dicho archivo desde mi
sitio web: http://www.latiumsoftware.com/descarga/p0052.zip

Bien, es hora de agradecer a los autores que contribuyeron su material
para hacer posible esta edición: Jim McKeeth, Owen Mooney, Peter Johnson
y Furious Logic. Nos complace entregar los premios de esta edición a:

* Peter Johnson - "Estableciendo el manejador de eventos..."
   InstallAWARE 3.0 Express Edition - por MimarSinan Int. ($69.95)
   Desarrolle instaladores para Windows Installer sin necesidad de
   conocimiento previo de MSI. InstallAWARE automáticamente convierte en
   tiempo de creación un script de flujo condicional en una base de datos
   MSI que cumple con ICE, certificable con logotipo. El IDE ofrece una
   interfaz visual que genera su script de instalación por usted
   automáticamente y cuyo comportamiento puede ser completamente
   adaptado. Sigue vigente la oferta especial por tiempo limitado para
   los lectores del Boletín Pascal: 30% de descuento para todas las
   ediciones. ¡La Edición Empresarial a tan sólo $559.95!
   http://www.installaware.com/landingea.html

* Owen Mooney - "Presentando YAPI"
   KnowedgeBASE Vortex 2.9 por Delphinium Software ($49.35)
   El corazón de KnowledgeBASE es un árbol de información altamente
   expandible y con gran capacidad de búsqueda, que puede verse como
   esquema o auditado dentro de un procesador de textos incorporado.
   Incluye una base de datos para referencias guardadas.
   http://www.download.com/KnowledgeBase-Vortex/3000-2064-10342084.html

* Jim McKeeth - "Análisis de rendimiento del código..."
   YAPI Professional - por Owen Mooney ($95)
   Ofrece la más fácil y aún así poderosa capacidad de impresión desde
   Delphi. Provee configuración WYSIWYG, vista preliminar, campos
   independientes, campos enlazados a datos, texto, grids, tabs, mapas de
   bits, operación con TCanvas, posicionamiento preciso o de flujo libre,
   y todo usando sentencias "writeln" simples.
   http://free.hostdepartment.com/o/owenmooney/

Agradecimientos especiales a Delphinium Software por donar KnowledgeBASE
Vortex y a Owen Mooney por donar YAPI Professional como premios
continuos para futuras ediciones. Para la próxima edición tenemos tres
premios para asignar entre los colaboradores de artículos en inglés:
InstallAWARE 3.0 Professional Edition, KnowedgeBASE Vortex y YAPI
Professional. La edición #54 será publicada en marzo, así que si tienen
una idea para un artículo y saben inglés, ¡vayan escribiendo!

Nos enorgullece continuar ofreciendo a los lectores un descuento
especial sobre InstallAWARE 3 para Windows Installer, gracias a la
linda gente de MimarSinan International. Por un tiempo limitado, los
lectores pueden obtener un 30% de descuento siguiente este enlace:
http://www.installaware.com/landingea.html

Y ahora, ¡vayamos al código!

Saludos,

Ernesto De Spirito y Dave Murray
boltin-pascal-owner@...

________________________________________________________________________

Help & Manual 3.50 por EC Software · Shareware ($ 279) - Una herramienta
visual de  autoría de ayuda para generar archivos WinHelp (.HLP),  Adobe
PDF,  páginas HTML y los  nuevos archivos HTML HELP  (.CHM) introducidos
en Windows  98,  así como  otros formatos  de  archivo  y  documentación
impresa,  todo desde una  misma fuente.  Una herramienta  imprescindible
para cualquier desarrollador de software.  http://www.helpandmanual.com/
________________________________________________________________________


2. Análisis de rendimiento del código con puntos de interrupción sin
    interrupción (non-breaking breakpoints)

    Por Jim McKeeth <jim at mckeeth dot org>


Resumen: A veces es bueno saber cuánto tiempo toma en ejecutarse una
porción específica de código. El IDE de Borland provee un medio para
lograr esto usando puntos de interrupción que no detienen la ejecución
(non-breaking breakpoints) y el registro de eventos (event log).

Este artículo fue publicado originalmente en la Borland Developer
Network (ver Referencias) e incluye varias imágenes, las que aquí se
publican en el archivo comprimido que acompaña este número.

Ya sea porque tenga un punto en su programa que corre más lento de lo
esperado, o porque está debatiendo cuál sería la forma más rápida de
hacer algo, necesita medir el rendimiento de una porción de código. En
los viejos tiempos añadiríamos algo de código a nuestros programas para
registrar la hora de inicio y final de procesos específicos. Luego lo
removeríamos o lo comentaríamos hasta que lo necesitáramos nuevamente.
Ahora usamos analizadores de rendimiento de código ("code profilers")
que cronometran la ejecución de cada línea de nuestro código y nos
proveen con reportes detallados y gráficos. Podríamos tomarnos
semanas examinando todos los datos disponibles.

Los analizadores de aplicaciones son muy lindos, pero a veces no
disponemos de uno conveniente, o realmente no queremos lidiar con uno
por tan sólo un par de líneas de código, o puede que insertar toda la
información de depuración adicional para que funcione el analizador
produzca un cambio en el comportamiento de nuestro programa. En vez de
volver al pasado y añadir todo ese código para registrar las horas de
inicio y fin, podemos usar puntos de interrupción sin interrupción.

La mayor ventaja de esta técnica comparada con el uso de un analizador
de rendimiento tradicional es cuando tenemos un programa bastante
complejo corriendo y queremos analizar algo de código en el momento, sin
tener que reiniciar el programa y ejecutar el analizador. Se puede
focalizar este análisis muy específicamente, de modo que no causaría el
impacto en el comportamiento general de nuestro programa que causarían
otros analizadores. En los casos en los que tenga unas pocas selectas
rutinas que desee analizar, encontrará esta técnica más rápida y fácil
de acometer.

Este artículo está escrito para Delphi 7, pero las técnicas deberían
trabajar con pocos o ningún cambio en otras versiones de Delphi, así
como C++ Builder y Kylix. El código adjunto es específico para Windows,
pero estoy seguro que un programador Kylix con recursos sabría qué
APIs de Linux usar en su lugar.

Antes de enseñarles como usar los puntos de interrupción sin
interrupción para analizar el rendimiento de su código, voy a cubrir
algunas bases sobre los puntos de interrupción sin interrupción. Si ya
se siente cómodo con las características avanzadas de los puntos de
interrupción, puede saltar a la sección sobre Análisis de Rendimiento.


¿Qué son los puntos de interrupción sin interrupción?
-----------------------------------------------------

Sé que probablemente estén pensando que un punto de interrupción sin
interrupción sea una contradicción. Como veremos a continuación, en
realidad no lo es. Cary Jensen ofrece un gran artículo titulado "Usando
puntos de interrupción sin interrupción en Delphi", disponible en la
Borland Developer Network (ver Referencias). No se preocupen si no lo
han leído. Cubriré todo lo que necesitan saber aquí.

El Free Online Dictionary of Computing (Diccionario Online Libre de
Computación) define un punto de interrupción como sigue:

Punto de interrupción
Un punto en un programa que, al ser alcanzado, genera algún
comportamiento útil al proceso de depuración. Generalmente, los puntos
de interrupción se usan para detener ("pausar") la ejecución del
programa, y/o volcar los valores de algunas o todas las variables del
programa. Los puntos de interrupción pueden ser parte del programa
mismo, o pueden ser establecidos por el programador como parte de una
sesión interactiva con una herramienta de depuración para escrutinizar
la ejecución del programa.

Así que los puntos de interrupción no siempre detienen (o "pausan") la
ejecución del programa. Un mejor nombre sería puntos de interrupción sin
detención, pero independientemente de cómo los llamemos, estamos usando
puntos de interrupción que no detienen la ejecución y aún así generan un
comportamiento especial. Así que, ¿cómo obtenemos uno de esos divertidos
puntos de interrupción? En realidad es muy simple:

1. Crear un punto de interrupción de la forma habitual (yo uso F5)
2. Traer el diálogo "Source Breakpoint Properties" (habitualmente yo
    hago clic derecho sobre el punto de interrupción y selecciono
    "Breakpoint Properties..." en el menú contextual)
3. Hacer clic en el botón "Advanced >>".
4. Desmarcar la casilla de verificación "Break".
5. Hacer clic en el botón "OK".

Fig 1. Basic Breakpoint Properties

Antes de presionar el botón "Advanced" (Avanzado), el diálogo "Source
Breakpoint Properties" muestra la configuración predeterminada del punto
de interrupción. Note que especifica el nombre de archivo y el número de
línea en el que se encuentra el punto de interrupción. Están en gris en
esta vista indicando que están deshabilitados porque estamos editando
las propiedades de un punto de interrupción existente. Si estuviéramos
creando o editando un punto de interrupción desde la "Breakpoint List"
([CTRL]+[ALT]+[B] para la lista, [CTRL]+[A] y [CTRL]+[E] para crear un
punto de interrupción) entonces estos campos no estarían deshabilitados y
los podríamos especificar.

Fig 2. Advanced Breakpoint Properties

El diálogo "Breakpoint Properties" después de hacer clic en el botón
"Advanced" incluye muchas características poderosas. Por ahora estamos
interesados en la casilla "Break" (interrupción). Desmárquela y haga
clic en "OK".

Su punto de interrupción se seguirá viendo igual. No está deshabilitado
(como se indica con una línea verde y un símbolo de detención gris),
pero si corre su programa ahora ya no pausa en esa línea. Si al correr
el programa la línea cambia de color a verde oscuro, entonces su punto
de interrupción está una línea que no ejecuta código. Elija una de las
líneas con un punto azul a la izquierda y repita el proceso. Está bien,
esperaré.

Si lo hizo bien, su programa correrá sin detenerse en ese línea. En este
momento esto no es muy útil, pero al menos ya sabe cómo establecer un
punto de interrupción sin detención.


Registrando con un punto de interrupción
----------------------------------------

Ahora que tenemos nuestro punto de interrupción sin interrupción, lo que
queremos es que escriba en un registro cuando se ejecuta la línea de
código que está marcando. Vuelva al diálogo "Breakpoint Properties".
Note que va directamente a la vista avanzada pues ha hecho un cambio en
la sección "Actions" (acciones). Ahora vamos a hacer otro cambio. Vamos
a añadir texto al cuadro combinado "Log message" (registrar mensaje).
Al analizar mi código habitualmente tengo un punto de interrupción con
registro en el inicio y otro al final del bloque a analizar, y hago que
esos puntos de interrupción registren "Inicio" y "Fin" respectivamente.

Si corre su programa ahora, después de hacer este cambio, no notará
ninguna diferencia obvia. El mensaje fue registrado en el "Event Log"
(registro de eventos), el que puede ser accedido desde el menú del IDE
(View -> Debug Windows -> Event Log) o presionando [Ctrl]+[Alt]+[V].
Tenía tres puntos de interrupción establecidos en mi programa, con el
primero y el último registrando un mensaje. Así es como se ve mi Event
Log:

Fig 3. Event Log

Las líneas en rojo son las que resultan de un punto de interrupción.
Notará tres líneas "Source Breakpoint" (punto de interrupción en código
fuente) y dos "Breakpoint Message" (mensaje de punto de interrupción).
Todas las otras líneas son interesantes pero distraen un poco, así que
ocultémoslas por ahora. Simplemente haga clic derecho en la ventana de
registro y elija "Properties" (Propiedades). Esto mostrará el diálogo
"Debugger Event Log Properties" (Propiedades del Registro de Eventos del
Depurador).

Fig 4. Debugger Event Log Properties

En el grupo "Messages" (Mensajes) puede desmarcar cualquier casilla para
un mensaje que no desea ver. Simplemente desmarque todas las casillas,
incluyendo la casilla "Breakpoint messages" (mensajes de puntos de
interrupción). La casilla de mensajes de puntos de interrupción es algo
engañosa. En realidad quita las líneas de "Source Breakpoint", dejando
las líneas de mensajes de puntos de interrupción (Breakpoint Message).
También puede cambiar los colores y otra información que le guste. Yo
encuentro que el registro es más fácil de leer para analizar desmarcando
la casilla "Display process info with event" (Mostrar información de
proceso con evento). Si usa su Event Log también para otros propósitos,
recuerde volver a cambiar la configuración a la original cuando haya
terminado.

Ahora, cuando corro el programa, el Event Log se ve como se muestra en
la figura 5. Esperemos que el suyo sea similar.

Fig 5. Event Log conciso

Imagino que estará de acuerdo en que esto es mucho más conciso.

CONSEJO: En vez de usar Inicio y Fin puede encontrar más útiles otros
mensajes. Algunas sugerencias: nombre de la función llamada, número de
línea, objeto siendo accedido, nombre de la consulta ejecutada,
definición del bucle, etc.


Analizando el Rendimiento
-------------------------

Ahora que sabemos como crear entradas en nuestro de eventos, podemos
usar esa característica para analizar el rendimiento de nuestro código.
Mientras que mostrar que se entra y sale de un bloque de código es útil,
eso no es exactamente análisis de rendimiento. Lo que necesitamos es una
medida de tiempo que muestre cuánto tiempo llevó la ejecución de algún
código. Esto puede lograrse usando la característica "Eval Expression"
(evaluar expresión) del punto de interrupción. Vuelva al diálogo "Source
Breakpoint Properties". Esta vez coloque GetTickCount en el cuadro
combinado "Eval Expression".

GetTickCount es una API Win32 que devuelve un cardinal conteniendo el
número de milisegundos desde que la computadora fue iniciada por última
vez. Para la programación en Delphi, esta función se encuentra en la
unidad Windows, así que asegúrese de incluirla en su cláusula Uses.
Mientras que el número devuelto son milisegundos, la resolución en
realidad no está en milisegundos. Si tiene dos llamadas distanciadas
por un par de milisegundos, puede que devuelvan el mismo número. La
resolución puede obtenerse con la API GetSystemTimeAdjustment. Además,
puesto que se usa un cardinal (o DWORD), el valor recomenzará desde
cero cada 49,7 días. No es algo de lo que probablemente se tenga que
preocupar corriendo un sistema operativo MS Windows que haya estado
arriba tanto tiempo, pero es algo a tener en cuenta.

En mi programa añadí GetTickCount a los tres puntos de interrupción,
dejando el Incio y Fin en los dos primeros. Al ejecutar mi programa
nuevamente se genera mucha más información útil en el Event Log.

Fig 6. Event Log con GetTickCount

Las líneas coloreadas con salmón o rosa ahora muestran los resultados
de la evaluación de la expresión. Note que hay dos líneas "Breakpoint
Message", y tres líneas "Breakpoint Expression. Si pusiéramos un
mensaje en el segundo punto de interrupción, algo como "Medio", entonces
tendríamos un número para cada uno. De lo contrario, no tendríamos forma
de asociar el resultado de GetTickCount con un lugar específico del
código. Si en el diálogo "Debugger Event Log Properties" rehabilitamos
los "Breakpoint messages" para que se muestren, tendríamos también el
número de línea. Personalmente prefiero usar mensajes significativos,
incluyendo el número de línea, pero puede usar lo que mejor satisfaga
sus necesidades.

Como podemos ver por estos datos, tomó 1,5 segundos ir del primer
punto de interrupción al segundo., y cerca de 1 segundo para llegar
al tercero. Parece como que tengo algo de optimización que hacer. Si
tiene curiosidad por saber cómo arribé a esos valores, es una simple
cuestión de restar cada número al que le sigue, y dividir por 1000,
redondeando al medio segundo más cercano.

Al usar la característica "Eval Expression" del punto de interrupción,
la expresión evaluada debe estar referenciada globalmente y sólo puede
ser una función que se incluya en su código compilado. Puesto que Delphi
tiene un enlazador optimizante, quita las funciones que no tienen chance
de ser ejecutadas por el programa. GetTickCount es una de esas funciones
que siempre tiene una posibilidad de ser llamada y se incluye ya sea que
la llamemos explícitamente o no, así que siempre está allí. Si usamos
otra función, una que escribamos o una de otra librería o llamada API,
debemos asegurarnos que esté enlazada. Asimismo, cuando llamamos a un
método de un objeto que cambia el valor de un campo, esos cambios puede
que no se hayan llevado a cabo después que termina la evaluación.


Análisis de rendimiento avanzado
--------------------------------

¿Qué hay si no quisiera hacer la resta mentalmente? O tal vez realmente
desea una resolución de 1 milisegundo en su análisis. Esto implica
agregar algo de código a su programa, pero hay un truco para asegurar
que el código no sea incluido en su programa cuando lo construya sin
información de depuración.

En vez de usar GetTickCount podemos usar la rutinas de temporizador de
alto desempeño, también provistas en la API de Windows. Estas rutinas
no son tan directas de usar, así que en vez de colocar complejas Eval
Expressions le sugiero construir algunas funciones para hacer las cosas
más fáciles. Estas funciones también pueden sustraer los valores entre
llamadas.

Las API QueryPerformanceCounter y QueryPerformanceFrequency API acceden
al temporizador de alto desempeño disponible en la mayoría de los
sistemas. Desconozco sobre la situación cuando estos contadores no están
disponibles. Para más información sobre esta funciones API consulte la
MSDN o la documentación del Windows SDK incluida con Delphi. Tenga
presente que usan Int64s en vez de Cardinals, y que son precisas más
allá del milisegundo.

En el archivo ZIP que acompaña este número encontrará mi librería para
usar estas llamadas API. Es muy simple de usar; hay tres funciones:
ElapsedMS, ResetElapsed y UpTimeMS. Añada la unidad JimProfiling.pas a
se cláusula Uses y podrá usar estas funciones en sus Eval Expressions.

ElapsedMS
Muestra cuántos milisegundos transcurrieron desde la última llamada a
ElapsedMS.

ResetElapsed
Resetea el contador de tiempo.

UpTimeMS
Muestra cuántos milisegundos transcurrieron desde que se inició el
programa.

Después de correr su programa tiene algo útil, y bastante preciso, en la
ventana Event Log.

Fig 7. Event Log usando la unidad JimProfiling

Note que la segunda llamada a ElapsedMS tiene un valor menor que la
primera. Esto es porque es el tiempo desde la primer llamada. La
llamada a UpTimeMS es en realidad mayor que la suma de las dos llamadas
a ElapsedMS porque incluye el tiempo anterior a la llamada a
ResetElapsed así como la pequeña cantidad de tiempo posterior a la
segunda llamada a ElapsedMS.

CONSEJO: Si necesita una línea para poner un punto de interrupción para
llamar a ResetElapsed o alguna otra función, sólo agregue una línea
Sleep(0). Aunque esto tenga algún impacto en su programa, debería ser
mínimo. La excepción es si está tratando con múltiples hilos de
ejecución (threads), puesto que cuando llama a Sleep le transfiere la
ejecución a otro hilo.

Todo el código de esta unidad se encierra en directivas {$IFOPT D+}, de
modo que se dejará afuera cuando compile su aplicación sin información
de depuración, así que no necesita acordarse de removerla de su
cláusula Uses. Puesto que el alcance de Eval Expression es global,
puede poner la unidad en cualquier cláusula Uses de su aplicación y aún
así podrá usarla en todas las unidades a lo largo de su proyecto.


Consejos finales
----------------

Si desea conservar su análisis entre sesiones de programación, asegúrese
de usar la opción "Autosave Project Desktop" (Autoguardar Escritorio de
Proyecto). Esto guardará la ubicación de todas sus ventanas así como
cualquier punto de interrupción que tuviera. Puede habilitarla desde la
pantalla "Tools" -> "Environment Options", en la ficha "Preferences"
bajo el encabezado "Autosave Options".

Si no desea que siempre se guarden sus cambios al escritorio, puede
activar esta opción, guardar el proyecto una vez, y luego volverla a
desactivar. Eso tomará una instantánea de las cosas que no cambiarán
cuando se hagan futuros cambios. Estas configuraciones se guardan en el
archivo [proyecto].dsk, que está en formato de texto plano (tipo INI).
Puede editarlo directamente si gusta.

Recuerde que si edita este archivo, y tiene el IDE abierto y
autorguardar habilitado, entonces puede sobrescribir sus cambios.
Además, los puntos de interrupción se rastrean por número de línea, así
que si añade o quita una línea arriba de una línea con un punto de
interrupción, entonces el punto de interrupción puede moverse a una
línea incorrecta.

CONSEJO: Si especifica una condición, entonces el registro sólo se
efectuará si la condición es verdadera.

La pantalla "Breakpoint List" es otro recurso valioso. La mencioné más
arriba como otra forma más de crear puntos de interrupción. Puede ir a
esta pantalla usando el atajo de teclado [CTRL]+[ALT]+[B] o desde el
menú View -> Debug Windows -> Breakpoints.

Fig 8. Breakpoint List

Note que la columna "Action" (Acción) muestra los mensajes y expresiones
que estamos registrando. Puede tener varios grupos de puntos de
interrupción para análisis. Luego, desde el menú contextual puede
habilitar o deshabilitar un grupo entero de puntos de interrupción.
También puede usar la característica Enable / Disable Group de otro
punto de interrupción para activar o desactivar estos grupos como sea
necesario.

CONSEJO: Editar puntos de interrupción (con clic derecho o usando
[CTRL]+[E]) desde esta pantalla le permite moverlos a otras líneas o
archivos. Esto es especialmente útil si tiene acciones complejas
establecidas y no desea recrearlas. También puede establecer múltiples
puntos de interrupción sobre una misma línea usando la opción "Keep
Existing Breakpoint" (Mantener el punto de interrupción existente).


Conclusión
----------

Esta técnica de analizar su código usando el IDE estándar de Delphi y
puntos de interrupción sin interrupción le provee con tiempos de
análisis de ejecución con precisión de 1 ms, altamente confinable a
un fragmento específico del código. Mientras que esto no reemplaza
completamente la necesidad de una herramienta de análisis de código en
su caja de herramientas de programación, le provee con otra poderosa
alternativa para crear programas más rápidos en menos tiempo usando el
poderoso IDE que ya posee.


Referencias
-----------

- "Using Non-Breaking Breakpoints in Delphi" por Cary Jensen
   http://bdn.borland.com/article/0,1410,31263,00.html

- "Code Profiling with Non-Breaking Breakpoints" by Jim McKeeth
   http://bdn.borland.com/article/0,1410,31905,00.html

- "Non-Breaking Breakpoint Profiling Library 1.0" por Jim McKeeth
   http://codecentral.borland.com/codecentral/ccWeb.exe/listing?id=21280

________________________________________________________________________

Ayúdanos a conseguir más suscriptores votando por el Boletín Pascal
(Pascal Newsletter) en estos rankings:
http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________


3. Presentando YAPI

    Por Owen Mooney <owenm at scottech dot net>
        http://free.hostdepartment.com/o/owenmooney/

Yapi - ahora en la versión 2.
Ahora soy un programador "senior".

Me corté los dientes con Fortran, hice my tesis en Algol-60 (¿alguien
se acuerda de eso? - antes del Pascal) y a principio de los 90 aprendí
a odiar la API de Windows usando Borland C++ y OWL ("'Orrible Windows
Library"). Luego descubrí Delphi y es lo que usé desde entonces.

Lo único que siempre le ha faltado a Delphi, ha sido una herramienta
de impresión decente. Los QReports eran inservibles para impresión
general. Compramos un producto de terceros de Nevrona. Con dedos
temblorosos y entusiastas abrí el manual y comencé a leer. ¡Oh, cielo!
La herramienta nunca se usó. Quedó en el estante por cuatro años hasta
que la tiré a la basura el año pasado. Al final, toda mi impresión la
realicé sobre el lienzo (canvas) de TPrinter. Había escuchado que muchos
programadores Delphi habían hecho lo mismo. No he usado las nuevas
herramientas de D2005 todavía, así que no puedo comentar sobre ellas.
Probablemente no las probaré porque no necesito hacerlo.

Después de unos pocos años de fustración construí mis propias
herramientas de impresión y --si me permiten un momento de
autofelicitación-- ¡son las mejores!


Diseño - La programación
------------------------

Quería que las nuevas herramientas fueran fáciles de usar, que siguieran
el más importante principio Delphi: simplicidad. Después de algunos años
de lidiar con C++ para Windows me crucé con Delphi y dije "¡Ah - Sí! Así
es como debe ser." Quería que mis herramientas de impresión evocaran esa
reacción. No sólo deberían ser más simples que otras herramientas de
impresión, sino MUCHO más simples - ¡deberían ser fenomenales!

Comencé por principios básicos.

En los viejos tiempos programábamos reportes más o menos así:

writeln(printer,'    Mi Gran Reporte'); // Centrado
writeln(printer); // Línea vacía
writeln(printer,'La primera línea');
for i := 0 to count - 1 do begin
   writeln(printer,'El dato para la línea ',i,' ',Data[i]);
end;

Con cada writeln el cabezal de la impresora matricial cobraba vida y
recorría el ancho de la página, aportando lo suyo a la contaminación
sonora de la oficina.

Mientras la tecnología puede parecer muy cruda para los estándares de
hoy, programar este tipo de cosas era fácil. Esto es por una muy
importante razón: Un reporte muy complejo podía contener cientos de
writes y writelns, pero el flujo de código seguía el flujo general del
reporte. Esta correspondencia hacía la programación fácil tanto de
escribir como de seguir. Puede ver un reporte e imaginarse cómo estaría
codificado, y podía ver el código e imaginar el reporte.

Esta metodología se cae a pedazos con impresoras modernas y el
requerimiento de proveer una vista previa de impresión. Herramientas
como QReports y otras tienden a tener una estructura que ejecute
sentencias SQL o llame a código de evento escrito por el usuario. El
flujo de la ejecucución es controlado por el código de ellos, no por
el suyo. Todo lo que usted obtiene son algunos eventos. Si tiene un
reporte complejo, lo que obtiene es una "explosión de complejidad" a
medida que su código intenta recordar qué cosa sucede cuándo. No sé
usted, pero yo me di por vencido.

Yapi provee el mismo flujo lógico del viejo writeln. En Yapi, el
código equivalente al viejo código de arriba es:

Paper.clear;
Header.writeln('Mi Gran Reporte'); // Centrado, pero sin contar espacios
Header.writeln;
Body.writeln('La primera línea');
for i:=0 to count-1 do begin
   Body.write('El dato para la línea ');
   Body.writeattab(inttostr(i),1);
   Body.writeattab(inttostr(Data[i]),2);
end;
Paper.preview;

Ese es todo el código requerido para imprimir el equivalente a la vieja
impresión matricial, pero por supuesto con márgenes, bellas fuentes,
encabezados y pies de página, paginación automática y una muy buena
pantalla de vista preliminar.


Diseño - El formateo
--------------------

Bien, por supuesto que la gente espera control WYSIWYG sobre la
disposición de la página, fuentes, tabulaciones y otros formatos. No soy
tan tonto como para proveer otra cosa.

Yapi provee varios componentes para esto, como sigue:

El componente Paper:
Provee configuración WYSIWYG para toda la estructura del reporte. Se
configuran los márgenes y las tabulaciones, así como la orientación del
papel. Típicamente las dimensiones están en milímetros, pero también se
pueden proveer pulgadas.

El componente Paper muestra todos estos detalles en tiempo de diseño,
pero es invisible en tiempo de ejecución.

El componente Text:
Los componentes Text se usan para establecer las fuentes para los
reportes (incluyendo su color). Se usan para el grueso de la impresión.

El componente Tab:
Éstos establecen las tabulaciones. Pueden ser arrastrados a la posición,
o puede establecerse su posición (en milímetros o pulgadas). También se
provee tabulación dinámica por código.

Estos tres componentes son el conjunto básico.


Probándolo
----------

Vayamos al corazón del asunto. ¿Cómo hacer que se imprima algo y cuán
fácil es iniciarse? Bien, los pasos absolutos más simples son como
sigue:

1. Arrastre un componente Yapi Paper a su formulario
2. Arrastre un componente Yapi Text al papel
3. Agregue un botón al formulario. En su evento OnClick añada tres
    líneas de código:

YapiPaper1.clear;
YapiText1.writeln('Hola Mundo');
YapiPaper1.preview;

Eso es todo. Ejecute el programa, presione el botón y tiene una
pantalla de vista previa, y otro botón en la pantalla de vista previa
realiza la impresión. Los documentos tienen un tutorial de 5 minutos,
que hace más o menos esto. Si no puede hacer esto en 5 minutos, tiene
una promisoria carrera como tejedor de canastas.


Más componentes
---------------

Los tres componentes de arriba (disponibles como conjunto gratuito) le
permiten realizar casi cualquier generación de impresión basada en
texto. Por supuesto, la gente quiere más. Otros componentes son:

* Un componente encabezado y pie (un componente hace ambos)
* Un componente cuadrícula (grid) para hacer reporte como un stringgrid
   o un dbgrid
* Un componente imagen para hacer mapas de bits (las imágenes pueden
   determinarse en tiempo de diseño o de ejecución)
* Un componente paintbox
* Un componente db report

El componente encabezado y pie hace (por supuesto) números de página.

Producir una cuadrícula fue un problema de diseño realmente interesante.
¿Cómo programa uno una cuadrícula sin contradecir la bella filosofía de
diseño que ya tenía? La respuesta vino después de algunas cervezas (en
realidad ese es un inserto colorido para aliviar el aburrimiento de lo
que de otro modo es una seca disertación técnica). El componente de
cuadrícula de texto es como un componente de texto ordinario, pero
dibuja una caja alrededor de sí mismo. Ponga dos cajas, y sus lados
adyacentes se una para formar una línea. Ponga unos abajo de otros, y
los lados superiores e inferiores se unen en una sola línea de
cuadrícula. Ponga filas y columnas juntas y "hey presto" - ¡una
cuadrícula! Todo esto hace que las cuadrículas sean tan fáciles como
texto tabulado ordinario.

El componente imagen era también una razonablemente obvia inclusión,
pero aún quedaba un último desafío de impresión - ¿cómo trataría Yapi
con texto y gráficos arbitrarios? La respuesta vino como la Yapi
PaintBox, la que opera con TODOS los métodos existentes de TCanvas.

En este punto, algún gnomo como programador comentará: "¡Oye bobo! Si
programas yapiPaintbox como un objeto Canvas, ¿por qué no usar el canvas
de TPrinter?" La respuesta es simple: "¡Porque la yapiPaintbox también
provee vista preliminar!'

Con la V2 se incluye un db report. Esto es realmente sólo para aquellos
programadores que creen que uno debería arrastrar y soltar todo un
programa y protestar agriamente a todas y cada una de las líneas de
código que tengan que escribir. Este componente produce un reporte a
partir de una TQuery o una TTable con una sola sentencia:

yapidbreport.open

He provisto el db report como una unidad objeto separada. Esto impide
que el código de bases de datos de Delphi se enlace en programas que no
son de bases de datos.


Implementación
--------------

Bueno... ¡No fue fácil!

Con cada write o writeln, Yapi crea un "token" para representar el
elemento impreso. Almacena y luego usa esos tokens para renderizar
la página relevante en la vista previa de impresión, o en el canvas de
TPrinter. Suena fácil, ¿no?

Cada token es un objeto. Se usó herencia para generalizar el código lo
más posible.

La jerarquía de clases para los tokens relevantes es:

TyapiObject - Clase abstracta; maneja mucho del procesamiento
TyapiTextObject - Puede ser un texto o una cuadrícula de texto
TyapiGraphicObject - Puede ser una imagen o un paintbox

Cada uso de write o writeln genera un nuevo token para representar un
elemento en el reporte.

En la codificación inicial todos esos componentes se almacenaban en un
arreglo en el componente Paper, pero tenía una explosión de complejidad.
Hora de hacer trizas el código y comenzar de nuevo. Añadí una nueva
clase por cada línea y la complejidad quedó bajo control.

En esta segunda versión cada write o writeln añade un nuevo token en el
objeto de la línea actual. Además, cada writeln completa el objeto de la
línea actual y comienza una nueva. Las líneas se almacenan en un arreglo
dinámico dentro del objeto Paper.

Los componentes en sí han sido creados una forma bastante estándar. El
componente Paper hereda de TCustomPanel y opera como un contenedor de
líneas, así como una herramienta para configurar el reporte. Tab,
paintbox e image heredan del componente TGraphicControl. Tanto text como
grid-text heredan de una clase base abstracta común, que a su vez hereda
de TCustomLabel.

Estuve muy agradecido que Borland proporcionara el código fuente de la
VCL. Me arrastré bastante por él para ver cómo se hacían las cosas.


La vista previa de impresión
----------------------------

La vista preliminar de impresión es un formulario Delphi estándar. La
impresión se renderiza en un TPaintbox.

La vista previa de impresión hace lo que esperaría. Seleccionar número
de página, aumento/disminución de tamaño, selección de impresora,
selección de rango de páginas - todo eso se provee.

Además tiene un par de lindos trucos. El primero es la habilidad de
controlar líneas viudas y huérfanas. Una característica única de la
vista preliminar de Yapi es la capacidad de cambiar tabulaciones y
márgenes en tiempo de ejecución, en la ventana de vista previa. Esa
maldita línea al pie puede ser eliminada simplemente estirando el margen
inferior de la página hacia arriba. La línea desaparece y aparece en la
página siguiente.

Otro truco de la pantalla de vista previa es guardarla en un archivo.
Hay dos opciones: si la guarda en un archivo con extensión .csv, eso es
lo que obtiene. Las tabulaciones del reporte se usan para separar las
columnas del archivo csv. Si la guarda en un archivo .bmp, obtiene la
página actual como un mapa de bits. Elegí el formato de salida bmp
porque es el soportado por la VCL básica. Esto significa que no tendrá
problemas de enlazamiento.

Si necesita salida a un archivo pdf, entonces le sugiero obtener un
driver de impresión pdf.


Conclusión
----------

Sólo porque Yapi es muy fácil de usar no la confunda por una herramienta
cruda. Hay muchos trucos sutiles tras bambalinas para hacer su vida más
fácil (por ejemplo ajuste de línea, ajuste en una cuadrícula de texto y
manejo de memo.text para mencionar unos pocos).

Échele un vistazo a algunos de los reportes de muestra (por ejemplo
FishFacts.pdf) en la página web. Son ejemplos PDFs usando el driver de
impresión PDF.

La Yapi básica está disponible gratis. Tiene lo básico, pero aún así es
una herramienta útil.

Visite http://free.hostdepartment.com/o/owenmooney/

A propósito, Yapi es un acrónimo de "Yet Another Printer Interface."

________________________________________________________________________

   InstallAWARE 3.0 para Windows Installer por MimarSinan International
Oferta especial: 30% de descuento en la Enterprise Edition, sólo $559.95
  InstallAWARE es la siguiente generación en  herramientas de autoría de
  instaladores con características únicas como distribución web parcial,
  avisadores de  progreso  Flash  y  HTML,  diez  temas  de  instalación
  llamativos, diálogos de instalación completamente configurables,  y un
  lenguaje de instalación que automáticamente se convierte en archivo de
  Windows Installer.  >>> http://www.installaware.com/landingea.html <<<
________________________________________________________________________


4. Estableciendo el manejador de eventos predeterminado de un componente

    Por Peter Johnson, Copyright (c) 2004
        <delphidabbler at tiscali dot co dot uk>
        http://www.delphidabbler.com/


¿Por qué este artículo?
-----------------------

Cuando hace doble-clic en la mayoría de los componentes Delphi en tiempo
de diseño, el IDE automáticamente crea un manejador de evento vacío para
el evento predeterminado. A veces necesita que un evento diferente sea
el predeterminado. El propósito de este artículo es explicarle cómo
hacer eso (hay más información sobre este tema en el archivo de ayuda de
Delphi 7, pero el ejemplo que allí se provee es incorrecto).

Hagamos esto un poco más concreto considerando estos tres componentes:

type
   TCompA = class(TComponent)
   private
     fOnFoo: TNotifyEvent;
     fOnBar: TNotifyEvent;
     fOnClick: TNotifyEvent;
     fOnChange: TNotifyEvent;
     fOnChanged: TNotifyEvent;
     fOnCreate: TNotifyEvent;
   published
     property OnFoo: TNotifyEvent read fOnFoo write fOnFoo;
     property OnBar: TNotifyEvent read fOnBar write fOnBar;
     property OnChange: TNotifyEvent read fOnChange write fOnChange;
     property OnChanged: TNotifyEvent read fOnChanged write fOnChanged;
     property OnClick: TNotifyEvent read fOnClick write fOnClick;
     property OnCreate: TNotifyEvent read fOnCreate write fOnCreate;
   end;

   TCompB = class(TComponent)
   private
     fOnFoo: TNotifyEvent;
     fOnBar: TNotifyEvent;
     fOnChange: TNotifyEvent;
   published
     property OnFoo: TNotifyEvent read fOnFoo write fOnFoo;
     property OnBar: TNotifyEvent read fOnBar write fOnBar;
     property OnChange: TNotifyEvent read fOnChange write fOnChange;
   end;

   TCompC = class(TComponent)
   private
     fOnFoo: TNotifyEvent;
     fOnBar: TNotifyEvent;
   published
     property OnFoo: TNotifyEvent read fOnFoo write fOnFoo;
     property OnBar: TNotifyEvent read fOnBar write fOnBar;
   end;

Haciendo doble-clic en los componentes en el Delphi IDE se crean los
siguientes manejadores de evento:

     * TCompA: OnCreate
     * TCompB: OnChange
     * TCompC: OnBar

Supongamos que quisiéramos que el evento OnFoo sea el creado en todos
los casos. Veremos como hacerlo durante en el curso de este artículo.


Algo de base
------------

Antes que podamos resolver nuestro problema necesitamos examinar cómo
Delphi 7 decide cuál evento usar como predeterminado (las cosas son un
poco diferentes en Delphi 4 - tal como veremos después).

Cuando se hace doble-clic a un componente, Delphi llama al método Edit
del editor de componente registrado. El editor de componente registrado
predeterminado es TDefaultEditor y es éste editor el responsable de
crear el manejador de evento. Ahora examinemos cómo TDefaultEditor.Edit
decide cuál es el evento predeterminado.

Tras pasar por un proceso, en última instancia el método Edit llama al
método TDefaultEditor.EditProperty una vez por cada propiedad del
componente. En vez de pasar a EditProperty una referencia a la propiedad
misma, lo que se le pasa es una referencia al editor de propiedad
asociado. EditProperty chequea el nombre por cada propiedad de evento
y guarda el editor de propiedad del evento preferido. Estos eventos, en
orden de preferencia, son:

     * OnCreate
     * OnChange
     * OnChanged
     * OnClick
     * el primer evento alfabéticamente

Esto significa que si un evento OnCreate está presente, se usa como el
predeterminado. Si no está presente, se usa el evento OnChange y así.
sucesivamente. Si no está presente ninguno de los eventos de la lista,
se usa el primero por orden alfabético.


Redefiniendo el comportamiento predeterminado
---------------------------------------------

De la discusión anterior queda claro que si hemos de especificar el
evento predeterminado, tendremos que cambiar la formar en que trabaja
TDefaultEditor.EditProperty. Afortunadamente para nosotros, este método
es virtual, así que podemos derivar TDefaultEditor y redefinir
EditProperty. La nueva clase puede ser declarada muy simplemente como
sigue:

type
   TMyCompEditor = class(TDefaultEditor)
   protected
     procedure EditProperty(const PropertyEditor: IProperty;
       var Continue: Boolean); override;
   end;

La implementación es igualmente directa:

procedure TMyCompEditor.EditProperty(const PropertyEditor: IProperty;
   var Continue: Boolean);
begin
   // only call inherited method if required event name
   if CompareText(PropertyEditor.GetName, 'OnFoo') = 0 then
     inherited;
end;

Ahora examinemos cómo trabaja. Recuerde que en la clase base el
método TDefaultEditor.EditProperty es llamado una vez por cada
propiedad del componente. El método elige el evento predeterminado
entre los que le son pasados. Ahora, si TDefaultEditor.EditProperty
es llamado una sola vez, entonces el evento predeterminado será aquel
cuyo editor de propiedad sea pasado en esa única llamada.

Nuestro método redefinido trabaja asegurándose que el método heredado
sea llamado sólo una vez - para el evento que queremos que sea el
predeterminado. En nuestra clase descendiente, es el método
TMyCompEditor.EditProperty el que es llamado por cada propiedad del
componente. El método simplemente comprueba si el editor de propiedad
tiene el nombre requerido ('OnFoo') y pasa ese editor de propiedad
-y sólo ese editor de propiedad- al método heredado. ¡Y voilá - OnFoo
es el evento predeterminado!


Una solución reutilizable
-------------------------

En el código que desarrollamos en la sección previa, el nombre del
evento predeterminado es fijo, o -como se dice en la jerga- está
"cableado", término derivado del inglés "(hard-)wired".

Nuestro siguiente trabajo es generalizar la solución para hacer más
fácil de reutilizar el código. Puesto que las clases sólo se distinguen
por el nombre del evento predeterminado que seleccionan, desarrollaremos
una clase base que tienen un método abstracto que las descendientes
pueden redefinir para devolver el nombre del evento requerido.

Esta es la declaración de la clase base:

type
   TCompEditorBase = class(TDefaultEditor)
   protected
     function DefaultEventName: string; virtual; abstract;
       { override to return name of default event }
     procedure EditProperty(const PropertyEditor: IProperty;
       var Continue: Boolean); override;
       { records property editor of default event }
   end;

La implementación no debería ser sorpresa - simplemente reemplazamos
el nombre que estaba cableado en la clase anterior por una llamada al
método abstracto:

procedure TCompEditorBase.EditProperty(
   const PropertyEditor: IProperty;
   var Continue: Boolean);
begin
   if CompareText(PropertyEditor.GetName, DefaultEventName) = 0 then
     inherited;
end;

Ahora podemos implementar un editor de componente para un evento
predeterminado específico -nuesto viejo amigo OnFoo otra vez-
simplemente redefiniendo el método abstracto DefaultEventName como
sigue:

type
   TCompEditor = class(TCompEditorBase)
   protected
     function DefaultEventName: string; override;
   end;
   ...
function TCompEditor.DefaultEventName: string;
begin
   Result := 'OnFoo';
end;


Arrelgos finales
----------------

Para que estos ejemplos compilen necesitamos usar las unidades Classes,
SysUtils, DesignIntf y DesignEditors. Note que las dos últimas sólo
pueden usarse al integrar con el IDE - no pueden usarse en aplicaciones
independientes.

También necesitamos registrar el editor de componentes en el
procedimiento Register de nuestra unidad como sigue:

procedure Register;
begin
   RegisterComponentEditor(TCompA, TCompEditor);
   // etc ...
end;


Diferencias con Delphi 4
------------------------

En Delphi 4, TDefaultEditor.EditProperty tiene un prototipo diferente.
Se lo declara como:

procedure EditProperty(PropertyEditor: TPropertyEditor;
   var Continue, FreeEditor: Boolean);

Podemos tratar con esto usando compilación condicional. Asumiendo que
está definido el símbolo DELPHI6ANDUP cuando usamos Delphi 6 o superior,
podemos implementar el procedimiento TCompEditorBase.EditProperty como
sigue:

procedure TCompEditorBase.EditProperty(
   {$IFDEF DELPHI6ANDUP}
   const PropertyEditor: IProperty; var Continue: Boolean
   {$ELSE}
   PropertyEditor: TPropertyEditor; var Continue, FreeEditor: Boolean
   {$ENDIF}
);
begin
   if CompareText(PropertyEditor.GetName, DefaultEventName) = 0 then
     inherited;
end;

Adicionalmente necesitamos reemplazar las unidades DesignIntf y
DesignEditors por DsgnIntf:

uses
   Classes, SysUtils,
   {$IFDEF DELPHI6ANDUP}
   DesignIntf, DesignEditors;
   {$ELSE}
   DsgnIntf;
   {$ENDIF}


Resumen
-------

En este artículo hemos visto como cambiar el manejador de evento
predeterminado que se abre en el IDE cuando se hace doble-clic en un
componente.

Primero examinamos la manera en la que Delphi decide cuál evento usar
para este propósito y luego desarrollamos una subclase de TDefaultEditor
que puede especificar explícitamente el evento predeterminado. Luego
procedimos a generalizar la solución desarrollando una clase base
abstracta para editores de componentes que modifica el evento
predeterminado.

La discusión principal cerró con un repaso de las unidades requeridas
para compilar las nuevas clases y dimos una mirada a como registrar el
editor de componentes.

Finalmente discutimos los cambios necesarios para compilar el código
con Delphi 4.


Código demo
-----------

Si quiere experimentar con este código, el archivo ZIP adjunto que
acompaña esta edición contiene código demostrativo que implementa los
componentes de ejemplo y los editores de componentes tratados en este
artículo.

__________________

Peter Johnson es un programador hobbyista que vive en West Wales (Reino
Unido) y que "chapotea" en Delphi. Mantiene el sitio web DelphiDabbler
(http://www.delphidabbler.com/) donde publica sus artículos y sus
aplicaciones y componentes Delphi gratuitos. Una versión completa de
este artículo se encuentra disponible en:
http://www.delphidabbler.com/download.php?file=article-17-demo.zip

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


5. Antivirus en Delphi: aRC-Anti WODE.JPG 1.0


Como les había prometido hace un par de números atrás, presentamos un
nuevo aporte que nos envía Furious Login desde Lima, Perú.

En esta oportunidad se trata de un antivirus específico para el gusano
conocido popularmente como WODE.JPG o también conocido como virus de la
china (o de la japonesa). Pueden encontrarse referencias de este virus
bajo los nombres W32/Rayl.A, W32/Rayl.A.worm, Win32/Elomon.worm.48644,
W32.Seone.A, AdClicker-BD, Exploit.HTML.Mht, Worm.MSN.Elon.a o
TrojanDownloader.Win32.Delf.ed según la fuente.

El virus brotó en septiembre del año pasado, y se propagaba mediante
MSN, pero no se transmitía por el MSN, sino que mostraba al contacto de
la persona con la PC infectada un enlace para ver una imagen wode.jpg
en un sitio de Internet. Al hacer clic en el enlace no se bajaba
directamente una imagen, sino una página web que contenía la imagen...
¡y algo más! Aprovechando una vulnerabilidad conocida, la página incluía
un IFRAME desde el que se bajaba otra página, la que contenía código en
Visual Basic Script (VBS) que a su vez bajaba un archivo en formato CHM
que se ejecutaba inmediatamente en la zona de seguridad local, y a
partir de allí el resto naturalmente era historia: el archivo CHM
extraía su carga útil, un archivo ejecutable, y lo ejecutaba; a su vez
este ejecutable extraía otros dos archivos ejecutables y procedía a la
infección.

El programa Delphi que les presento aquí (se incluye en el archivo
adjunto con el código fuente correspondiente a este número) fue escrito
originalmente en C++ Builder 6.0 y fue distribuido antes que la mayoría
de los más importantes antivirus pudieran detectar y eliminar el virus.

El programa hace exactamente lo que realizan los programas de este
tipo:

   1) Detectar la presencia del virus.
   2) Terminar los procesos relacionados con el virus.
   3) Eliminar los archivos del virus.
   4) Eliminar las entradas usadas por el virus para
      ejecutarse al iniciar Windows.

Para detectar la presencia de la infección se busca entre los procesos
en ejecución para determinar si alguno de ellos corresponde al virus.
En vez de la API EnumProcesses, este programa ilustra el uso de las API
Toolhelp32Snapshot, Process32Next y CloseHandle para idéntico propósito.

Habiendo determinado que un proceso corresponde a un virus, el programa
hace uso de la API OpenProcess para obtener el handle con el cual llamar
a TerminateProcess para terminar el proceso.

   ADVERTENCIA: La aplicación MSN Messenger es también terminada de
                modo abruto. Perderá las conversaciones y datos que
                no hubiera guardado. Se recomienda que usted cierre
                manualmente el MSN Messenger antes de ejecutar este
                programa.

El programa luego busca y elimina los archivos principales y temporales
del virus, y finalmente elimina la entrada en el registro de Windows que
permite la ejecución del virus cuando Windows se inicia.

   ADVERTENCIA: Como toda aplicación que elimina archivos del disco
                duro y elimina entradas en el Registro de Windows,
                debe tomar sus recaudos antes de utilizarla.

El programa pude ser adaptado para remover otros virus y gusanos que
usan procesos de infección similares.

________________________________________________________________________

Ayúdanos a conseguir más suscriptores votando por el Boletín Pascal
(Pascal Newsletter) en estos rankings:
http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________


6. Foros / listas de correo


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@...

* 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@...

* 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

________________________________________________________________________

        KnowedgeBASE Vortex 2.9 por Delphinium Software ($49.35 US)
      KnowledgeBASE Vortex presenta un árbol de información altamente
      buscable y expandible,  que puede verse como esquema o auditado
       dentro del procesador de textos incorporado en la aplicación.
         Incluye una base de datos  para referencias almacenadas.
   http://www.download.com/KnowledgeBase-Vortex/3000-2064-10342084.html
________________________________________________________________________


7. Delphi en la Red

    Por Dave Murray <irongut at vodafone dot net>


Componentes, librerías y aplicaciones
=====================================

Freeware
--------

* Clearer v1.7 - by Mauro Venturini (with source)
   History is a great new feature of Delphi 2005. There is only a little
   drawback: after project completion getting rid of all the history
   files is a bit annoying. Clear makes this more easy. It also takes
   care of .NET local storage accumulation due to version changes.
   http://www.torry.net/tools/developers/other/Clearer1.6Clearer.zip

* Delphi Scintilla Interface Components v0.16 - Jan Pettersen (w source)
   Use the Scintilla Project Syntax Highlighting edit control with Delphi
   Define your own languages based on the lexers in the SciLexer.dll
   (Scintilla Project), with the styles and keywords needed directly from
   the Delphi designer. Tested with Delphi 7.
   http://delphisci.sourceforge.net/

* Graphics32 v1.7 - by Graphics32 Team (open source, MPL)
   Graphics32 is a library designed for fast 32-bit graphics handling on
   Delphi and Kylix. Optimized for 32-bit pixel formats, it provides fast
   operations with pixels and graphic primitives, and in most cases
   Graphics32 outperforms the standard TCanvas classes. It is almost a
   hundred times faster in per-pixel access and about 2-5 times faster in
   drawing lines.
   http://graphics32.org/

* PUses v2.2 - by Mauro Venturini (with source)
   PUses implements orderly reformatting of uses clauses, including:
   rewriting the unit/namespace names one per line and sorting them;
   optionally adding the prefix unit (generated using PrefiIt!) names.
   Supports Delphi 2005 only.
   http://www.torry.net/tools/other/ide/PUses2.0PUses.zip

* TTrimmingLabel v1.0 - by Mauro Venturini (with source)
   TTrimmingLabel is a Windows Forms label that can trim the Text string
   to adapt it to the available Width. The trimming is controlled by the
   Trimming property (of type System.Windows.Forms.StringTrimming).
   Supports Delphi 2005 only.
   http://www.torry.net/vcl/labels/enhancedlabels/TrimmingLabel.zip

* Undo/Redo for TeeChart Pro VCL v1.02 - by Ivo Ungermann (with source)
   Component for limited or unlimited undo / redo function with TChart
   (part of TeeChart Pro VCL package from Steema Software). Automatically
   traced TChart events: Zoom, Unzoom, Scroll. Other chart changes traced
   with a bit of code. Tested with TeeChart Pro 7 VCL, Delphi 5 - 7.
   http://www.torry.net/vcl/charts/charts/TChartUndoRedo.zip

* sTile v2.7 - by harmware
   A graphics program to create seamless 'tiles' which can be used as
   background images for web pages and applications. It has many filters
   and effects and is a fun little program to play with. By nature, it
   produces somewhat psychedelic images, but they can be toned down or
   muted for actual use. Samples on the web site include a brick wall.
   http://www.harmware.com/stile.htm


Actualizaciones de productos Borland
------------------------------------

* Public Beta: Delphi 8 Update 3
   This patch is designed to correct issues with .NET versioning for
   Delphi 8. This is a dcu breaking change. Version calculation for
   dcuils and dcpils has been updated to depend on symbol names rather
   than values of metadata tokens imported from .NET assemblies. This
   fixes errors that users have been experiencing with updating their
   service packs for NET 1.1 and will prevent any further issues.
   http://community.borland.com/article/0,1410,32873,00.html

* Delphi 2005 Update 1 Now Available
   This update makes Delphi 2005 rock solid!
   http://community.borland.com/article/0,1410,32875,00.html


Artículos, trucos y consejos
============================

* BDNradio: Database Features of Delphi 2005 with Ramesh Theivendran and
   Joerg Weingarten
   Read the chat log and listen to the replay of the live interview with
   Ramesh and Joerg on Delphi 2005 database features.
   http://community.borland.com/article/0,1410,32925,00.html

* BDNradio: VCL and VCL for .NET in Delphi 2005 with Seppy Bloom and
   Danny Thorpe
   Listen to the replay and read the chat room log of the live interview
   with Danny and Seppy.
   http://community.borland.com/article/0,1410,32924,00.html

* BDNradio: Unit Testing in Delphi 2005 with Mark Edington
   Listen to the replay and read the chat room log of Mark Edington's
   live chat on unit testing support in Delphi 2005.
   http://community.borland.com/article/0,1410,32920,00.html

* BDNradio: .NET data remoting in Delphi 2005 with Ramesh Theivendran
   Read the chat log and listen to the live chat with Ramesh on the easy,
   flexible, and powerful way to develop .NET data remoting applications
   in Delphi 2005.
   http://community.borland.com/article/0,1410,32917,00.html

* BDNradio: Debugging in Delphi 2005 with Chris Hesik
   Listen to the replay and read the chat room log of Chris Hesik's
   interview on debugging in Delphi 2005.
   http://community.borland.com/article/0,1410,32923,00.html

* BDNradio: Web Development in Delphi 2005 with Jim Tierney and
   Steve Trefethen
   Read the chat log and listen to the replay of this live chat with Jim
   and Steve on Delphi 2005's web development support.
   http://community.borland.com/article/0,1410,32881,00.html

* Recursions in Delphi - by Zarko Gajic
   Recursion is a very simple, yet useful and powerful programmer's tool.
   Subroutines can, and frequently do, call other subroutines, a
   subroutine that activates/calls itself is called recursive. Recursion
   is a general method of solving problems by reducing them to simpler
   problems of a similar type. Many programmers often avoid this type of
   subroutine because it can be confusing and complicated. This article
   is going to make recursion in Object Pascal simple ... I hope.
   http://delphi.about.com/od/objectpascalide/l/aa120799a.htm

* Graphical Combos - by Zarko Gajic
   Creating owner drawn Combo Boxes in Delphi. See how to code a
   graphical drop-down list; examples include a combo box of colours and
   a true-type font picker.
   http://delphi.about.com/od/vclusing/l/aa101700a.htm


Tutoriales y capacitación
=========================

* An Introduction to COM Programming with Delphi (6/6) - by Curtis Socha
   Type Library: pros and cons, 5 steps to a Type Library, a look into
   the TLB Abyss.
   http://delphi.about.com/library/weekly/aa122804a.htm

* Resource Files Made Easy - by Zarko Gajic
   Part 1 of a series of articles, explains how Delphi uses standard
   Windows-format resource files: icons, bitmaps and cursors.
   http://delphi.about.com/od/objectpascalide/l/aa113099a.htm

* Inside the EXE - by Zarko Gajic
   Part 2 of a series of articles, this article will show you how to
   store (and use) sound files, video clips, animations and any kind of
   binary files in a Delphi executable.
   http://delphi.about.com/od/objectpascalide/l/aa021301a.htm

* Web Site inside a Delphi EXE - by Zarko Gajic
   Part 3 of a series of articles, shows how HTML and associated files
   (pictures) can easily be included within a Delphi application.
   http://delphi.about.com/od/objectpascalide/l/aa113099a.htm

* Creating and Using a Resource Only DLL with Delphi - by Zarko Gajic
   Fourth article in the series about storing more than just executable
   code inside a Delphi application. This part shows how to create a
   dynamic link library containing only resources.
   http://delphi.about.com/od/objectpascalide/l/aa113099a.htm

* Localizing Delphi Applications using StringTable Resources - Z. Gajic
   Part 5 in a series of articles, while resource files enable storing
   more than just program code in an EXE file, by including stringtable
   resources to an application a Delphi developer can easily build
   multilanguage applications. Learn how.
   http://delphi.about.com/library/weekly/aa011805a.htm


Noticias
========

* Borland Going After Services Revenue
   Services are destined to play a greater part in Borland's future as
   the company assists customers around Application Lifecycle Management.
   http://www.cbronline.com/article_news.asp?
   guid=B1DA308B-4561-4A9B-83EE-F4D4EFAA07E8

* Borland Purchases Brains to Drive SDO
   Borland has made its first corporate purchase in two years, acquiring
   software process consulting specialist TeraQuest Metrics Inc. Borland
   plans to integrate TeraQuest's expertise, encapsulated in templates
   for activities such as change management, project planning and
   requirements gathering, into its ALM tools, processes and services.
   http://www.cbronline.com/article_news.asp?
   guid=C5F6EE17-B508-432B-987B-F274EC223A20

* Borland Schedules Q4 and Year End 2004 Conference Call and Webcast
   Borland today announced that its fourth quarter and year end 2004
   teleconference and simultaneous Webcast is scheduled to begin at
   2:30 p.m. Pacific Time, on Tuesday 1st February 2005.
   http://www.tmcnet.com/usubmit/2005/Jan/1106470.htm

* Firebird Database Readies SMP Release
   Firebird developers are due to do an alpha release of version 2.0 of
   the open source database later this month and have completed work on
   SMP support, which is due to be released in late spring.
   http://news.zdnet.co.uk/software/developer/0,39020387,39183292,00.htm


Otros / Sitios misceláneos
==========================

* New BDN Feature: Community Calendar
   At the BorCon 2004 closing session, one of the new BDN applications
   launched was a community calendar, code named EventCentral. Any BDN
   member can use EventCentral to post events of interest to Borland
   customers anywhere around the world. Events must be approved by a
   sysop to be publicly visible.
   http://community.borland.com/article/0,1410,32936,00.html

* CodeFez Blogs
   Blogs by Charlie Calvert, Julian Bucknall, Lino Tadros, Nick Hodges
   and Steve Teixeira. Topics include software development, Delphi and
   other Borland tools.
   http://www.codefez.com/Default.aspx?tabid=79&newsType=NewsListing

* PGD DogFight Game Programming Competition
   DelphiGamer.com recently relauched and will soon be known as "Pascal
   Game Development" or PGD for short. To coincide with the relaunch, a
   themed game programming competition has been announced.
   http://www.pgd.netstarweb.com/viewtopic.php?t=1747

________________________________________________________________________

Irongut's Delphi Pages
Dedicada a la programación con Borland Delphi y Kylix. Tenemos artículos
sobre programación, noticias Borland y Delphi, código fuente y componen-
tes para usar en sus aplicaciones y más.  http://www.paranoia.clara.net/
________________________________________________________________________


¡Tú puedes ayudarnos!


Por favor danos una mano y ayúdanos a llegar a los 20.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@...

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://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium

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/descarga/p0053.zip
________________________________________________________________________

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@...
Para cancelar / removerse:    boletin-pascal-unsubscribe@...
Para reportar problemas con la suscripción: eds2004 @ latiumsoftware.com
________________________________________________________________________

Este boletín se provee "TAL Y COMO ESTA", sin garantía de ninguna clase.
Su uso  implica la  aceptación de la licencia y  la ausencia de garantía
que puedes  leer en la página http://www.latiumsoftware.com/es/legal.php
Allí también encontrarás una nota sobre marcas registradas.  Te animamos
a que redistribuyas  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
   Irongut's Delphi Pages         http://www.paranoia.clara.net/

Copyright 2005 by Ernesto De Spirito + Dave Murray. All rights reserved.
________________________________________________________________________

#19 De: "Ernesto De Spirito" <owner@...>
Fecha: Dom, 6 de Feb, 2005 2:05 am
Asunto: Boletín Pascal #52 - 05-FEB-2005
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #52 - 05-FEB-2005

Índice

1. Unas palabras del editor
2. Cómo agregar un programa al menú "Enviar a" del Explorador
3. Principios introductorios de búsqueda indexada
4. Llenando un TStringList extrayendo los registros de una columna
5. Devolviendo clases desde una DLL
6. Detección de colisión simplificada en programación de juegos
7. Foros / listas de correo
8. Delphi en la Red
    - Componentes, librerías y aplicaciones
      · Shareware / Comercial
      · Freeware
      · Actualizaciones de productos Borland
    - Artículos, trucos y consejos
    - Tutoriales y capacitación
    - Noticias
    - Otros / Sitios misceláneos

________________________________________________________________________

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


Continúo poniéndome al día con las traducciones. Esta fue la última
edición publicada en inglés el año pasado y quisiera aprovechar la
ocasión para agradecerles su constante apoyo durante este año complicado
con sus palabras de elogio hacia esta publicación y su aliento para
continuar con este proyecto de divulgación de información sobre Delphi
en español. Por supuesto, también quisiera aprovechar para agradecer a
los autores que contribuyeron artículos o premios este año, permitiendo
con su aporte que el boletín pueda continuar, y no quiero olvidarme de
los moderadores de los foros, quienes aportan mucho de su tiempo a esa
tarea.

En este número especial tenemos cinco artículos que espero sirvan como
para compensarlos parcialmente por la discontinuidad en la publicación
del boletín. Mi agradecimiento a Peter Johnson, Jim McKeeth, Stewart
Moss, Max Kleiner y John Pears por contribuir sus artículos al boletín
y permitir su traducción al español. Me complace entregar a Stewart
Moss, Max Kleiner y John Pears los premios para esta edición:

* Stewart Moss - "Llenando un TStringList extrayendo registros..."
   InstallAWARE 3.0 Express Edition - por MimarSinan Int. ($69.95)
   Desarrolle instaladores para Windows Installer sin necesidad de
   conocimiento previo de MSI. InstallAWARE automáticamente convierte en
   tiempo de creación un script de flujo condicional en una base de datos
   MSI que cumple con ICE, certificable con logotipo. El IDE ofrece una
   interfaz visual que genera su script de instalación por usted
   automáticamente y cuyo comportamiento puede ser completamente
   adaptado. Sigue vigente la oferta especial por tiempo limitado para
   los lectores del Boletín Pascal: 30% de descuento para todas las
   ediciones. ¡La Edición Empresarial a tan sólo $559.95!
   http://www.installaware.com/landingea.html

* John Pears - "Detección de colisión simplificada..."
   KnowedgeBASE Vortex 2.9 por Delphinium Software ($49.35)
   El corazón de KnowledgeBASE es un árbol de información altamente
   expandible y con gran capacidad de búsqueda, que puede verse como
   esquema o auditado dentro de un procesador de textos incorporado.
   Incluye una base de datos para referencias guardadas.
   http://www.download.com/KnowledgeBase-Vortex/3000-2064-10342084.html

* Max Kleiner - "Devolviendo clases desde una DLL"
   KylixDriver v1.1 - por ET Kimberliteware Ltd ($39 / $69 con fuentes)
   Conjunto de herramientas para el desarrollo de drivers Linux que
   accedan al hardware de la PC, permitiendo desarrollar con Kylix
   controladores de dispositivo ISA/PCI para hardware específico.
   http://www.geocities.com/etkimberliteware/kylixdriver/index.html

Un agradecimiento especial a Delphinium Software por donar KnowledgeBASE
Vortex como premio continuo para futuras ediciones. Para la próxima
edición ya tenemos asignados tres premios: InstallAWARE 3.0 Enterprise
Edition, KnowedgeBASE Vortex y YAPI Professional.

* YAPI Professional - por Owen Mooney ($95)
   Ofrece la más fácil y aún así poderosa capacidad de impresión desde
   Delphi. Provee configuración WYSIWYG, vista preliminar, campos
   independientes, campos enlazados a datos, texto, grids, tabs, mapas de
   bits, operación con TCanvas, posicionamiento preciso o de flujo libre,
   y todo usando sentencias "writeln" simples.
   http://free.hostdepartment.com/o/owenmooney/

Disponibilidad de tiempo mediante, el calendario de publicación del
boletín en inglés para el 2005 será enero (#53), marzo (#54), julio
(#55), septiembre (#56), noviembre (#57) y fin de año (#58). Les debo
la traducción del #53 cuyo original en inglés se publicó en enero, y
con eso estaríamos al día. Se las prometo para la semana que viene.

Saludos,

Ernesto De Spirito y Dave Murray
boltin-pascal-owner@...

________________________________________________________________________

Help & Manual 3.50 por EC Software · Shareware ($ 279) - Una herramienta
visual de  autoría de ayuda para generar archivos WinHelp (.HLP),  Adobe
PDF,  páginas HTML y los  nuevos archivos HTML HELP  (.CHM) introducidos
en Windows  98,  así como  otros formatos  de  archivo  y  documentación
impresa,  todo desde una  misma fuente.  Una herramienta  imprescindible
para cualquier desarrollador de software.  http://www.helpandmanual.com/
________________________________________________________________________


2. Cómo agregar un programa al menú "Enviar a" del Explorador

    Por Peter Johnson, Copyright (c) 2003
        <delphidabbler at tiscali dot co dot uk>
        http://www.delphidabbler.com/


Por qué hacerlo
---------------

Si está escribiendo un programa de propósito general relacionado con
archivos, puede ser útil agregarlo al menú "Enviar a" del Explorador de
Windows. Por ejemplo yo coloqué el Bloc de notas de Windows en el menú
"Enviar a" para poder fácilmente ver cualquier archivo en el editor de
textos.


Cómo se hace
------------

Hay dos etapas para lograr nuestro propósito:

  1. Asegurar que nuestro programa puede recibir archivos desde el menú
     "Enviar a".
  2. Crear una entrada para nuestro programa en el menú "Enviar a".

Aunque puede crear un manejador especial para el menú "Enviar a",
tomaremos la opción simple de almacenar un atajo a nuestro programa en
el menú.


Recibiendo archivos desde el menú "Send To"
-------------------------------------------

Esto es muy fácil. Si el usuario selecciona uno o más archivos y hace
clic derecho y en el emergente selecciona Enviar a | Nuestro programa,
Windows simplemente iniciará nuestro programa y le pasará los nombres de
los archivos seleccionados en la línea de órdenes. Así que para leer los
archivos enviados desde el menú "Enviar a", simplemente necesitamos
chequear nuestros parámetros de línea de órdenes.

Podemos hacer esto en el manejador del evento FormCreate de nuestra
aplicación, como sigue:

procedure TForm1.FormCreate(Sender: TObject);
var
   I: Integer;
begin
   for I := 1 to ParamCount do
     ProcessFile(ParamStr(I));
end;

Se asume que ProcessFile procesa un archivo en la forma definida por la
aplicación (en el demo que acompaña este artículo simplemente mostramos
el nombre del archivo en un control memo).

Eso es todo en lo que respecta a manejar los archivos. Ahora demos un
vistazo a cómo crear una entrada en el menú "Enviar a".


Creando el elemento de menú en el menú "Enviar a"
-------------------------------------------------

Windows almacena los contenidos del menú "Enviar a" en una carpeta
especial. Debemos crear un acceso directo a nuestro a nuestro programa
en esa carpeta.

Primero debemos encontrar la ubicación de la carpeta "Enviar a". Cada
usuario tiene su propia copia de esta carpeta. Encontramos la ubicación
llamando a las APIs SHGetSpecialFolderLocation y SHGetPathFromIDList
(definidas en la unidad ShlObj) como sigue:

function GetSendToFolder: string;
var
   pidl: PItemIDList;
   PPath: array[0..MAX_PATH] of AnsiChar;
begin
   Result := '';
   if SHGetSpecialFolderLocation(0, CSIDL_SENDTO, pidl) = NOERROR then
   begin
     try
       if SHGetPathFromIDList(pidl, PPath) then
         Result := PPath;
     finally
       CoTaskMemFree(pidl);
     end;
   end;
end;

Primero usamos SHGetSpecialFolderLocation para obtener un PIDL
representando la carpeta requerida. Pasamos CSIDL_SENDTO a la función
para obtener el PIDL para la carpeta "Enviar a" del usuario actual. Si
tenemos éxito en obtener el PIDL luego podemos obtener el camino de la
carpeta pasando el PIDL a SHGetPathFromIDList, la que almacena el
camino solicitado en un buffer apuntado por un PChar que proveemos.
Convertimos el PChar a string y eso es lo que devolvemos desde la
función. Windows asigna memoria para el PIDL usando su asignador de
tareas. Es nuestra responsabilidad liberar el PIDL usando la función
CoTaskMemFree (definida en la unidad ActiveX).

Habiendo encontrado el camino a la carpeta "Enviar a" del usuario, ahora
podemos crear un acceso directo a nuestra aplicación en dicha carpeta.
Podemos elegir hacerlo en un programa de instalación o haciendo que sea
una opción de nuestra aplicación. Cualquiera sea nuestra elección, la
siguiente sección muestra cómo crear el acceso directo.


Creando un acceso directo
-------------------------

La siguiente función muestra cómo podemos crear un acceso directo -- no
sólo para usarlo en la carpeta "Enviar a".

function CreateShellLink(const LinkFileName, AssocFileName, Desc,
   WorkDir, Args, IconFileName: string; const IconIdx: Integer): Boolean;
var
   SL: IShellLink;    // objeto shell link
   PF: IPersistFile;  // interfaz persistente de archivo al shell link
begin
   // Se presume fallo
   Result := False;
   // Asegurar que COM esté inicializado
   CoInitialize(nil);
   try
     // Crear el objeto shell link
     if Succeeded(
       CoCreateInstance(
         CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, SL
       )
     ) then
     begin
       // Almacenar las propiedades requeridas del shell link
       SL.SetPath(PChar(AssocFileName));
       SL.SetDescription(PChar(Desc));
       SL.SetWorkingDirectory(PChar(WorkDir));
       SL.SetArguments(PChar(Args));
       if (IconFileName <> '') and (IconIdx >= 0) then
         SL.SetIconLocation(PChar(IconFileName), IconIdx);
      // Crear la interfaz persistente de archivo al shell link y
      // almacenar el archivo de enlace
       PF := SL as IPersistFile;
       Result := Succeeded(
         PF.Save(PWideChar(WideString(LinkFileName)), True)
       );
     end;
   finally
     // Finalizar COM
     CoUninitialize;
   end;
end;

La función tiene numerosos parámetros. Ellos son:

   1. LinkFileName: Camino completo del archivo de acceso directo -- en
      nuestro ejemplo usamos el camino de la carpeta "Enviar a" devuelto
      por GetSendToFolder, seguido por el nombre del archivo de acceso
      directo. Note que el menú "Enviar a" muestra el nombre de este
      archivo sin su extensión, así que asígnele un nombre descriptivo.

   2. AssocFileName: El nombre del archivo referenciado por el acceso
      directo -- aquí proveemos el camino completo del programa a ser
      iniciado desde el menú "Enviar a". ParamStr(0) almacena este
      nombre de archivo.

   3. Desc: una descripción del acceso directo -- no se muestra en el
      menú "Enviar a" así que le pasamos la cadena vacía ('').

   4. WorkDir: El directorio de trabajo del programa -- podemos proveer
      una cadena vacía ('') si no se requiere.

   5. Args: cualquier argumento de línea de órdenes que deba ser pasado
      al programa -- no usamos este parámetro en este ejemplo. Recuerde
      que el menú "Enviar a" también pasa los nombres de archivo en la
      línea de órdenes.

   6. IconFileName: especifique el archivo conteniendo el icono del
      acceso directo -- en nuestro ejemplo no especificamos este archivo,
      así que se asume que el icono está en el archivo de programa.

   7. IconIdx: el índice del icono en el archivo indicado por
      IconFileName, o -1 para que se use el icono predeterminado de ese
      archivo -- especificamos -1.

De lo anterior podemos ver que podemos llamar a CreateShellLink como
sigue:

...
CreateShellLink(
   GetSendToFolder + '\' + 'Mi elemento "Enviar a".lnk',
   ParamStr(0),
   'Mi programa de ejemplo "Enviar a"',
   ExtractFileDir(ParamStr(0)),
   '',
   '',
   -1
);
...


Resumen
-------

Hemos cubierto las bases de cómo agregar un elemento al menú "Enviar a"
y cómo manejar los archivos "enviados" a nuestro programa desde el
menú. El código presentado se puede usar como una para implementar
soporte para el menú "Enviar a" en sus programas.

Se incluye una aplicación demo en el archivo comprimido con el código
fuente que acompaña a edición del boletín. La misma ha sido probada con
Delphi 4 y Delphi 7.

__________________

Peter Johnson es un programador hobbyista que vive en West Wales (Reino
Unido) y que "chapotea" en Delphi. Mantiene el sitio web DelphiDabbler
(http://www.delphidabbler.com/) donde publica sus artículos y sus
aplicaciones y componentes Delphi gratuitos. Una versión completa de
este artículo se encuentra disponible en:
http://www.delphidabbler.com/download.php?file=article-12-demo.zip

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


3. Principios introductorios de búsqueda indexada

    Por Jim McKeeth <jim at mckeeth dot org>


Introducción
------------

Hay realmente dos grandes formas de buscar en una gran colección de
documentos de texto. El método simple sería cargar cada documento y
recorrerlo en búsqueda de los términos buscados, al cual nos referimos
como "escaneo de texto completo" (full text scan). El segundo y más
rápido método es crear un índice y buscar en el índice. Un índice es
una lista de términos encontrados en un documento o conjunto de
documentos. Cada palabra sólo aparece una vez por documento, de modo
que es más corto que el documento original.


Creando un índice
-----------------

Encontrando las palabras
------------------------

Para crear un índice debe primero analizar sintácticamente el documento.
El análisis sintáctico ("parsing") es el proceso de separar los símbolos
o elementos individuales ("tokens") en una porción de texto. Un
analizador sintáctico ("parser") es un tipo de máquina de estados. Hay
muchas rutinas existentes de parser disponibles. El libro "The Tomes of
Delphi: Algorithms and Data Structures" escrito por Julian Bucknall
contiene muchos buenos parsers. Un ejemplo puede encontrarse en
http://www.delphi3000.com/articles/article_1265.asp

Un parser simple puede recorrer una cadena de texto, comenzando por
el principio, buscando el primer caracter. Si es una letra o número,
entonces es para de una palabra, si es un espacio en blanco o un signo
de puntuación, entonces es un separador. Cada palabra se agrega a la
lista (por ejemplo un TStringList) en el orden en que se encontró en el
documento. Típicamente las palabras se convierten todas a mayúsculas o
todas a minúsculas.

Al realizar el parsing y crear el índice es muy importante considerar
qué es lo que se está indexando y cómo se usará el índice. Por ejemplo
al "parsear" archivos HTML sería deseable excluir la mayoría de los
tags (con la obvia excepción los META tags, los que son manejados de
manera especial). Otras veces puede desear sólo indexar información de
resumen del documento.


Indexando las palabras
----------------------

Ahora que hemos parseado la lista de tokens, necesitamos indexarla. El
índice más simple es una lista con cada palabra encontrada en el
documento y una  referencia al documento. Esta referencia puede ser
una URL, un nombre de documento o cualquier otro identificador único
(un GUID una clave foránea a otra tabla describiendo el documento).
Un índice más complejo puede incluir la cantidad de veces que la palabra
se encontró en el documento o un ranking según la posición en la que se
encuentra en el documento (en el título, sección de palabras clave,
primer párrafo, medio, último, etc.). Esta información adicional
almacenada con cada palabra es parte de lo que diferencia el rendimiento
(eficacia y eficiencia) de un motor de búsqueda respecto de otro.

Muchas veces ciertas palabras se dejan afuera. Estas palabras se
denominan "stop words" (palabras de detención). Se trata de palabras
comunes, palabras que no serán buscadas, o palabras que no mejorarán
el significado de una búsqueda. Ejemplos de estas palabras incluyen
"el", "uno", "una", "y", "si", "pero", palabras con números en ellas o
cualquier cosa que desee filtrar. Seleccionar las palabras a dejar
afuera es otro punto que hace diferencia en el rendimiento.

Algunos motores de búsqueda solían dejar fuera palabras como "HTML" o
"WEB" porque eran palabras muy comunes, mientras que otros incluían
todas las palabras. Otros motores de búsqueda comenzaron con una lista
de diccionario y sólo indexaban palabras en esa lista. Esto lleva a
problemas al indexar nombres, términos técnicos o cualquier otra cosa
que no se encuentre en el diccionario original.

En una oportunidad estaba creando un motor de búsqueda para una
colección de artículos de un grupo de noticias. Descubrí que en los
artículos había binarios codificados como UUEncode (similar a MIME o
Base64). Esto resultaba en mi parser encontrando palabras que tenían
cientos de caracteres de largo y en un galimatías total. Decidí
omitir cualquier palabra de más de 50 caracteres o de menos de 4.
Hacer la elección de sobre qué incluir y qué omitir es una decisión
importante, y variará en base al contenido que esté indexando.

He aquí un ejemplo de estructura de tabla para su índice:

Tabla: WordList
---------------
Document: Number (clave foránea para la tabla Documents)
Word : String[20] (si nuestra palabra más larga es de 20 caracteres)
Count : Number (cuántas veces se encuentra la palabra)

La clave primaria sería compuesta por Document y Word dado que cada
palabra se lista una vez por documento.

Tabla: Documents
----------------
Document : Number (clave primaria)
Title : string (título del documento)
Location : string (URL o camino y nombre completo)

Opcionalmente podría incluir el documento entero como un Blob en esta
tabla. También podría tener otras tablas que listen términos (de la
sección Meta del documento) o incluir autores. Nuevamente, esta elección
de diseño depende del tipo de documentos que esté indexando y del
propósito de su motor de búsqueda.


Buscando en su índice
---------------------

Una vez que están todos los índices almacenados en su base de datos,
debería poder buscar en el índice por un documento. Una sentencia SQL
simple para buscar un documento que contiene una palabra se vería así:

SELECT *
FROM WordList
WHERE Word = :v_search_term
ORDER BY Count DESC

Esto devuelve todos los documentos conteniendo el término buscado y los
ordena por la cantidad de veces que se encuentra la palabra. Si desea
usar SQL, entonces buscar por múltiples palabras involucra un JOIN por
cada término. En vez de eso, podría obtener una lista por cada término y
luego combinarlas manualmente. Aquí es donde soportaría las palabras
clave AND, OR o NOT.

Si desea permitir búsquedas de frases, entonces puede buscar por cada
palabra en la frase y luego buscar la frase en aquellos documentos en
los que se encuentren todas las palabras de la frase. La misma técnica
sería aplicable a la palabra clave NEAR. Hay otras técnicas avanzadas
para hacer esto mucho más rápido, pero van más allá del alcance de este
documento.

Una vez que se encuentran los documentos y se los rankea, muestre los
títulos de cada documento, posiblemente un sumario o el contexto de la
palabras encontradas, y provea una forma al usuario de alcanzar ese
documento.


Variaciones
-----------

Una de las cosas que Google hace un poco diferentemente es que se fija
en cuántas páginas están enlazadas. Esto funciona muy bien con la
naturaleza hiperenlazada de la web. Por ejemplo si busca por Borland,
la mayoría de las páginas que mencionan Borland tienen un enlace a
www.borland.com. Esto se asume como indicio de que www.borland.com es un
sitio muy importante acerca de Borland. Google también limita el número
de documentos encontrados que obtiene en cada dominio.

Muchos motores de búsqueda también rankean alto las páginas si la
palabra buscada aparece en la URL o el título de la página. Para el
rankeo también se fijan en las meta tags para descripción y palabras
claves. Algunos motores de búsqueda en realidad ignorarán una palabra
si aparece demasiado frecuentemente en la página. Esto guadaña los
sitios que intenta inflar artificialmente sus rankings.

Otra técnica que puede usarse es Phonetics o Soundex. Esto podría
hacerse con una tabla adicional similar a la tabla WordList, pero
almacenando el valor Soundex para las palabras en vez de las palabras
mismas.


Herramientas de búsqueda de terceros
------------------------------------

dtSearch  http://www.dtsearch.com/
--------

dtSearch provee un rango completo de productos de búsqueda. Estos
productos apuntan a todos: desde el usuario final hasta el editor de
contenidos y finalmente el desarrollador. Su Motor de Recuperación
de Texto dtSearch es el núcleo de todos sus productos y provee una API
con ejemplos en Delphi. Este producto es para crear un índice de texto
completo ("full text index") y buscar en él. Usan su propio formato de
datos. Usando su API un desarrollador puede crear una aplicación Delphi
que indexe casi cualquier documento (PDF, Office, ZIP, etc., ¡y texto
también!) y luego buscar en ese índice para encontrar documentos
concordantes.

Recientemente añadieron soporte para Linux y .NET, pero todavía no lo he
probado con Linux o Delphi para .NET.

Dependiendo del tipo de proyecto en el que trabaje, una de sus líneas
de productos puede ser apropiada. Su dtSearch Publish, por ejemplo, le
permite crear CDs / DVDs de contenido buscable rápida y fácilmente,
mientras que su dtSearch Web es ideal para construir un motor de
búsqueda web.

Rubicon  http://www.fulltextsearch.com/
-------

Tamarack Associates provee su producto de avanzada Rubicon para los
desarrolladores Delphi y C++Builder que desean búsqueda indexada sin
construir un sistema desde cero. Más allá de las bases que cubriremos
aquí, también ofrecen muchas características avanzadas y mejoras en la
velocidad.

Si visita su sitio web puede bajar una versión demo de sus herramientas
de búsqueda o probar su búsqueda en grupos de noticias en los grupos de
noticias de Borland y Microsoft. Rubicon no sólo permite la búsqueda en
documentos (viene con un parser para manejar texto, HTML y RTF), sino
que también le permite buscar datos en su base de datos. Soporta
expresiones lógicas (and, or, not, near y like) así como búsqueda por
frases completas. Está escrito enteramente en puro Delphi, y realmente
ofrece al desarrollador un nivel muy alto de control sobre el proceso.

La tecnología FastPhrase de Rubicon construye una tabla más grande que
le permite realizar búsquedas de frases sin realizar un escaneo de texto
completo al documento destino. Esto se hace almacenando no sólo la
palabra, sino también una concatenación de cada palabra y sus dos
palabras adyacentes, para un total de hasta tres entradas por palabra.

Rubicon ofrece una muy abarcativa compatibilidad con bases de datos. Las
bases de datos soportadas incluyen la BDE y dbExpress así como orígenes
ADO, Advantage, Apollo, Direct Oracle Access, DBISAM, FlashFiler,
Halcyon, Interbase Express, Interbase Objects, ODBC Express y Topaz.
Otras bases de datos son soportadas a través de la construcción de sus
propios paquetes. Al instalar Rubicon (ya sea la versión demo o la
versión completa) asegúrese de seguir las instrucciones para instalarlo
correctamente de modo que soporte su base de datos seleccionada.

Resumen
-------

Basado en mis comparaciones entre dtSearch y Rubicon, ambos se
desempeñan casi igual en el departamento de velocidad de búsqueda. La
ventaja de dtSearch es sus líneas de productos adicionales y su
interfaz más simple, pero no es tan configurable. Rubicon le brinda
acceso a cada detalle de su proyecto de búsqueda, proveyéndole con el
mismo código fuente completo en Delphi y su elección de base de datos
en vez de la base de datos cerrada y la DLL de dtSearch.


Características de búsqueda de bases de datos
---------------------------------------------

Muchas bases de datos proveen características para permitirle indexar y
buscar documentos guardados en su base de datos. Oracle ofrece un add-in
adicional para indexar documentos. MySQL de modo predeterminado provee
la capacidad de indexar documentos de textos almacenados como lo haría
con cualquier otro campo. DBISAM (un reemplazo nativo de la BDE de
Delphi sin librerías externas) ahora también provee indexado y búsqueda.


Conclusión
----------

Buscar en un índice corto y bien organizado es más rápido que buscar en
documentos completos. Crear y buscar en un índice toma más esfuerzo y
planificación al principio, pero rápidamente brinda sus frutos si el
texto se busca bastante seguido. Típicamente mientras más grande y
complejo es el índice, más efectiva es la búsqueda. Si su índice se hace
demasiado grande o demasiado complejo, entonces la velocidad de búsqueda
se degradará.

Hay herramientas de búsqueda listas para usar disponibles tanto para los
usuarios finales como para los desarrolladores. dtSearch and Rubicon son
extremadamente rápidas y útiles, pero que eso no lo detenga de diseñar
su propia herramienta, sobre todo si tiene una necesidad especializada.

Véase: http://www.dtsearch.com/dtsoftware.html#Art_of_The_Text_Query

________________________________________________________________________

   InstallAWARE 3.0 para Windows Installer por MimarSinan International
Oferta especial: 30% de descuento en la Enterprise Edition, sólo $559.95
  InstallAWARE es la siguiente generación en  herramientas de autoría de
  instaladores con características únicas como distribución web parcial,
  avisadores de  progreso  Flash  y  HTML,  diez  temas  de  instalación
  llamativos, diálogos de instalación completamente configurables,  y un
  lenguaje de instalación que automáticamente se convierte en archivo de
  Windows Installer.  >>> http://www.installaware.com/landingea.html <<<
________________________________________________________________________


4. Llenando un TStringList extrayendo los registros de una columna

    Por Stewart Moss <stewart at new-heights.co.za>
        http://www.new-heights.co.za/


Introducción
------------

A veces un programador necesita un método rápido y sucio de extraer un
conjunto de registros sobre una columna o campo específico de un dataset
en una forma conveniente.

Ejemplo de esto en mis programas es cuando necesité llenar un TListBox
o TComboBox (en un formulario modal) con valores que el usuario pueda
seleccionar para reportes u otros propósitos.

Esta clase simple es una forma segura y conveniente de hacer esto. Se
restaura el registro actual en el dataset, y el estado activo del
dataset (es decir, abierto o cerrado).

También se incluye una aplicación demo en el ZIP con el código fuente de
esta edición.


Implementación
--------------

El código simplemente obtiene un objeto TField de un nombre de campo
especificado (propiedad llamada "FieldName") perteneciente a un dataset
(propiedad llamada "Dataset") e itera a través de los registros
devolviendo cada valor en el campo, de inicio a fin.

La clase TField es conveniente porque nos permite manejar cualquier
tipo de campo basado en cualquier dataset :)

Sólo se devuelven los tipos de datos que soporten el método .AsString
(por ejemplo no los Blobs).

Una propiedad booleana de la clase (llamada "emptyNulls") permite
devolver líneas en blanco si se encuentran. Esto es útil si necesita
devolver el "desplazamiento" en el dataset del registro requerido (es
decir el correspondiente DataSet.RecNo) o si las filas en blanco son
significativas.

La salida es una propiedad de sólo lectura llamada Strings de tipo
TStringList. Esta propiedad puede usarse directamente para llenar un
TListBox o incluso Strings.SaveToFile(). La salida se basa en las
variables de formato del sistema (para fechas, etc.), así que tome sus
recaudos.

Cuando el método Refresh se dispara, la propiedad Strings se lee y la
lista debe ser refrescada. Esto sucede cuando cambia el dataset o el
nombre de campo la primera vez, pero también puede hacerlo manualmente.

La salida puede ser rellenada con cadenas de inicio y fin. Esto es útil
si necesita llenar el texto para formateo. Sin embargo estos rellenos
deben ser removidos del resultado del TListBox o TComboBox (por ejemplo
en consultas de búsqueda, etc.). Honestamente no uso esta característica
de rellenado en mis programas.

La clase tienen un método llamado "quickSearch" que le permite realizar
una búsqueda tipo lookup con cualquier valor de retorno. Esto es
simplemente un envoltorio del TDataset.Locate() del dataset actual. Por
ejemplo puede presentar todos los NombreDelCliente en una lista
desplegable y quickSearch() le permitirá localizar el IdDelCliente de
su NombreDelCliente seleccionado.


Ejemplo de uso
--------------

Esto llena el TListBox llamado SrcList en el formulario TfrmSelectData
con los nombres del stock activo obtenidos de la consulta qryPortfolio.
Luego realiza una búsqueda lookup para determinar el StockID del nombre
de stock.

procedure TFormMain.thingy;
var
   StockID, StockName : string;
   DatasetExtract : TDatasetExtract;
begin
   DatasetExtract := TDatasetExtract.Create;
   try
     // cualquier campo
     DatasetExtract.FieldName := 'StockName';
     // cualquier dataset
     DatasetExtract.DataSet := qryPortFolio;

     // crear el formulario
     with TfrmSelectData.Create(Self) do
     begin

       // añadir una copia de de la TStringlist DatabaseExtract al
       // TListBox.
       // Obtener las cadenas podría generar una excepción.
       SrcList.Items.AddStrings(DatasetExtract.Strings);

       // mostrar el formulario
       ShowModal;

       // si el usuario presionó OK
       if ModalResult = mrOK then
       begin

         // Devolver el nombre del elemento seleccionado de la lista
         StockName := SrcList.Items[SrcList.selectedindex];

         // Buscar el StockID en la consulta qryPortfolio usando la clase
         StockID := DatasetExtract.Search('StockName', StockName,
                    'StockID',[]);

         showmessage('El StockID de '+StockName+' es '+StockID);
       end;
       free;

     end;                                // with

   finally
     DatasetExtract.free;
   end;
end;


Class Code
----------

{-----------------------------------------------------------------------
  Unit Name: unitDatasetExtract2

  Modification Date: 18 December 2004
  Creation Date: 04 June 02 00:39:21
  Documentation Date: 04 June 02 00:39:21

  Release Date: 15 Jan 2003
  Version: 2.0

  Author: Stewart Moss

  Compiler version:
   Delphi 5 and Delphi 6 tested

  Purpose:
   To Extract a specific field from a dataset in a TStringList. Useful
   for populating TListBoxes that you dont want to be data aware...
   (Released originally on Delphi3000.com)

  Description:
         At the moment it only support TStringLists. It will convert
         most TField.FieldType into a string

  Notes:

  Dependancies:

  History:
   15 Jan 2003: Posted at wwww.delphi3000.com. Article number 3512.
                1122 visits by Dec 2004

           Copyright 2002, 2003, 2004 by Stewart Moss
           All rights reserved.
           You must not modify this Unit Header.
-----------------------------------------------------------------------}
unit unitDatasetExtract2;

interface

uses Classes, db{$IFDEF VER140}, Variants{$ENDIF};

type
   TDatasetExtract = class
   private
     fEmptyNulls: boolean;
     recPos: integer;
     fFieldname,
       fappend,
       fprepend: string;
     fDataset: TDataset;
     fStrings: TStringList;
     refreshed: boolean;

     function FieldToString(Field: TField): string;

     function Get_Strings: TStringList;
     procedure Set_Dataset(const Value: TDataset);
     procedure Set_Fieldname(const Value: string);

   public
     constructor create;
     destructor destroy; override;

     procedure Refresh;
     function Search(searchField, searchValue, ReturnField: string;
                                  Locateoptions: TLocateOptions): string;

   published
     // You have the option of appending and prepending any information
     // to the begining of each record.
     // Useful for creating delimited records easily (ie you can just add
     // the StringList items together) (maybe not really that useful :P )
     property append: string read fappend write fappend;
     property prepend: string read fprepend write fprepend;

     // Whether or not nulls must be translated into blank values,
     // or ignored
     property EmptyNulls: boolean read fEmptyNulls write fEmptyNulls
       default true;

     // The field name to return in the string list
     property FieldName: string read fFieldname write Set_Fieldname;

     // The dataset of the field
     property Dataset: TDataset read fDataset write Set_Dataset;

     // This is the TStringList output of the class. Reading this string
     // triggers the action of the class.
     property Strings: TStringList read Get_Strings;
   end;

implementation

uses Sysutils;                          // allow exception objects

{ TDatasetExtract }

constructor TDatasetExtract.create;
begin
   fDataset := nil;
   fStrings := TStringList.create;
   EmptyNulls := true;                   // allow null rows by default
   refreshed := false;                   // we do not have data
end;

destructor TDatasetExtract.destroy;
begin
   fStrings.free;
   inherited;
end;

procedure TDatasetExtract.Refresh;
{-----------------------------------------------------------------------
   Procedure: TDatasetExtract.Refresh

   Starts at the beginning of the record set and appends the required
   field in each consecutive record to the string list using the TField.
  ----------------------------------------------------------------------}
var
   Field             : TField;
   isactive          : boolean;
begin
   with fDataset do
   begin
     try
       // turn off any data-aware components related to current dataset
       disablecontrols;

       // save Dataset open state
       isactive := fDataset.Active;
       if not isactive then
         fDataset.open;

       // Save our current place in the dataset
       recPos := RecNo;

       // go to the start
       First;
       while not eof do
       begin
         // Get the TField object for field FieldName at
         // the current position (we don't care what type)
         Field := FieldByName(fFieldname);

         // Ok is it null?
         if not varisnull(Field.asvariant) then
           // use our "safer" .AsString
           fStrings.add(fprepend + FieldToString(Field) + fappend)
         else if EmptyNulls then
           // we are allowed to insert nulls
           fStrings.add(fprepend + fappend);
         next;
       end;                              // while not eof
     finally
       // Restore our current place in the dataset
       RecNo := recPos;

       // if the dataset was closed then close it
       if not isactive then
         fDataset.close;

       // turn on the data-aware components related to current dataset
       enablecontrols;
     end;                                // finally
   end;                                  // with fDataset
end;

function TDatasetExtract.FieldToString(Field: TField): string;
{-----------------------------------------------------------------------
   Procedure: TDatasetExtract.FieldToString
   Arguments: Field: TField
   Result:    string

  This actually reads the field from the database and swallows any
  EDatabaseErrors.
  ----------------------------------------------------------------------}
begin
   try
     result := Field.AsString;
   except
     on e: EDatabaseError do
     begin
       // nothing
     end
   else
     // re-raise the exception if it is something else
     raise;
   end;
end;

function TDatasetExtract.Get_Strings: TStringList;
begin
   result := fStrings; // always return what you have (even if exception)

   if refreshed then                     // if we have clean data
     exit;                               // then we are done

   fStrings.clear;

   if (fDataset = nil) or (fFieldname = '') then
     // uber cool error message
     raise exception.create(self.ClassName +
       ': No se proveyeron dos campos obligatorios');

   Refresh;
end;

function TDatasetExtract.Search(searchField, searchValue,
             ReturnField: string; Locateoptions: TLocateOptions): string;
{-----------------------------------------------------------------------
   Procedure: TDatasetExtract.quickSearch
   Arguments: searchField, searchValue, ReturnField : string;
               Locateoptions: TLocateOptions
   Result:    string

   Searches for a field value in a specified field name and returns the
   specified field returns '' is nothing is found.

   eg
     Ask for a customer id of 10 and return the customer name
  ----------------------------------------------------------------------}
var
   isactive          : boolean;
begin
   with fDataset do
   begin
     // turn off any data-aware components related to the current dataset
     disablecontrols;

     // save Dataset open state
     isactive := fDataset.Active;
     if not isactive then
       fDataset.open;

     try
       result := '';
       First;
       if not locate(searchField, searchValue, Locateoptions) then
         exit;

       // use our "safer" .AsString method
       result := FieldToString(FieldByName(ReturnField));
     finally
       // our current place obeys TDataset.Locate()

       // if the dataset was closed then close it
       if not isactive then
         fDataset.close;

      // turn on any data-aware components related to the current dataset
       enablecontrols;
     end;
   end;
end;

procedure TDatasetExtract.Set_Dataset(const Value: TDataset);
begin
   fDataset := Value;
   refreshed := false;                   // we are dirty again
end;

procedure TDatasetExtract.Set_Fieldname(const Value: string);
begin
   fFieldname := Value;
   refreshed := false;                   // we are dirty again
end;

end.

________________________________________________________________________

Ayúdanos a conseguir más suscriptores votando por el Boletín Pascal
(Pascal Newsletter) en estos rankings:
http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________


5. Devolviendo clases desde una DLL

    Por Max Kleiner <max@...>
    Kleiner Kommunikation Reference: http://max.kleiner.com/
    Descarga del componente: http://max.kleiner.com/download/dllplus.zip


Planteo
-------

Exportar una referencia a un objeto desde una DLL es una aproximación
hacia obtener verdadero acceso OO a una DLL. La DLL debe crear y
devolver el objeto, de modo que el cliente obtiene los métodos sin
encapsulamiento. Veamos cómo funciona este "framework" llamado DLL+...


Solución
--------

También hay un ejemplo subido con Diagramas UML (*.tif) de ModelMaker.
Siempre trabajamos con ModelMaker desde que tuvimos que rediseñar un
gran proyecto.

Primero, debemos construir una clase abstracta en una unidad separada
(ver abajo la misma con una interfaz real). Puede considerar esta unidad
como una interfaz:

unit income1;
interface
type
   IIncome = class
   public
     function GetIncome(const aNetto: Currency): Currency;
                                                       virtual; abstract;
     procedure SetRate(const aPercent, aYear: integer);
                                                       virtual; abstract;
     function queryDLLInterface(var queryList: TStringList):
                                          TStringList; virtual; abstract;
   end;

Después construimos la DLL en una nueva unidad (*.dpr) con la clase
correspondiente, la que debe implementar los métodos de la interfaz:

type
   TIncomeReal = class(IIncome)
   private
     FRate: Real;
   public
     constructor Create;
     function GetIncome(const aNetto: Currency): Currency; override;
     procedure SetRate(const aPercent, aYear: integer); override;
...

Y ahora viene la exportación. Puesto que los objetos en DLL+ se crean
llamando la función global Constructor, puede ver que devolver objetos
desde la función que los crea es aceptable por el cliente:

{-------------------------------------------------------------}
function CreateIncome: TIncomeReal; stdcall;
begin result:= TIncomeReal.Create; end;

exports CreateIncome resident;
begin {fake} end.
{-------------------------------------------------------------}

Finalmente demos un vistazo al cliente. En el manejo de objetos desde
el cliente debemos considerar quién es el propietario del objeto y es
responsable de liberarlo:

Uses income1;
   private
     IncomeRef: IIncome; //member
...

function CreateIncome:IIncome; stdcall; external('income.dll');
...
procedure TfrmIncome.FormCreate(Sender: TObject);
begin
   IncomeRef := CreateIncome;
end;

De este modo el acceso es fácil, estable y mejora la mantenibilidad
de la DLL. Debería ser obligatorio implementar una función
queryDLLInterface para reproducir la interfaz y todos los parámetros
en caso de pérdida (ver ejemplo).

procedure TfrmIncome.BitBtnOKClick(Sender: TObject);
begin
   incomeRef.SetRate(strToInt(edtZins.text), strToInt(edtJahre.text));
   cIncome:= incomeRef.GetIncome(StrToFloat(edtBetrag.Text));
   edtBetrag.text:= Format('%m',[cIncome]);
end;



Llamando una interfaz
---------------------

Ahora el cliente llama a una InterfaceReference:

private
   incomeIntRef: IIncomeInt;

procedure TfrmIncome.BitBtnOKClick(Sender: TObject);
begin
   incomeIntRef:=createIncome;
   try
     with incomeIntRef do begin
     if QueryInterface(IIncomeInt, incomeIntRef) = S_OK then begin
       SetRate(strToInt(edtZins.text), strToInt(edtJahre.text));
       cIncome:=strTofloat(edtBetrag.text);

La unidad Income1 se agranda con la interfaz:

   IIncomeInt = interface (IUnknown)
     ['{DBB42A04-E60F-41EC-870A-314D68B6913C}']
     function GetIncome(const aNetto: Currency): Currency; stdcall;
     function GetRate: Real;
     function queryDLLInterface(var queryList: TStringList):
                                                    TStringList; stdcall;
     procedure SetRate(const aPercent, aYear: integer); stdcall;
     property Rate: Real read GetRate;
   end;

La DLL ahora exporta un auténtico puntero a interfaz:

   TIncomeRealIntf = class (TInterfacedObject, IIncomeInt)
   private
     FRate: Real;
     function Power(X: Real; Y: Integer): Real;
   protected
     function GetRate: Real;
   public
     constructor Create;
     destructor destroy; override;
     function GetIncome(const aNetto: Currency): Currency; stdcall;
     function queryDLLInterface(var queryList: TStringList):
                                                    TStringList; stdcall;
     procedure SetRate(const aPercent, aYear: integer); stdcall;
     property Rate: Real read GetRate;
   end;

function CreateIncome: IIncomeInt; stdcall;
begin
   result:= TIncomeRealIntf.Create;
end;

Cuando n clases implementan una interfaz pasan un parámetro a la rutina
exportada en la DLL:

function CreateIncome(intfID: byte): IIncomeInt; stdcall;
begin
   case intfID of
   1: result:= TIncomeRealIntf.Create;
   2: result:= TIncomeRealSuper.Create;
   3: result:= TIncomeRealSuper2.Create;
   end;
end;

exports CreateIncome;

La llamada del cliente se ve así:

   incomeIntRef := createIncome(3);

________________________________________________________________________

        KnowedgeBASE Vortex 2.9 por Delphinium Software ($49.35 US)
      KnowledgeBASE Vortex presenta un árbol de información altamente
      buscable y expandible,  que puede verse como esquema o auditado
       dentro del procesador de textos incorporado en la aplicación.
         Incluye una base de datos  para referencias almacenadas.
   http://www.download.com/KnowledgeBase-Vortex/3000-2064-10342084.html
________________________________________________________________________


6. Detección de colisión simplificada en programación de juegos

    Por John Pears <j.pears@...>


Los así llamados "algoritmos simples de detección de colisión" sólo
detectan colisión entre dos rectángulos, y aún el más simple parece ser
bastante complicado. Cada sprite tiene coordenadas x e y (habitualmente
el centro del sprite) con un rectándulo usado para colocar la imagen.
A veces se usa un "rectángulo de confinamiento" (bounding rectangle)
para detección de colisiones.

Cada vez que se mueve la posición x,y del sprite, las posiciones de el
o los rectángulos deben ser recalculadas. La detección de colisión luego
comprueba los lados izquierdo, derecho, superior e inferior de los
rectángulos de AMBOS sprites para determinar si hubo colisión. Todo esto
se hace por cada sprite en cada paso del juego.

¿Qué tal mover solamente el x,y (centro) del sprite y "arreglar" los
desplazamientos izquierdo y superior?

Considérese la siguiente estructura de datos:

type
   TSpriteRec = record
   Centre : tpoint;
   OffSet : tpoint; // nunca cambia a menos que cambie image.picture
   Image : TImage;
   end;
var
   Invader : array[1..A_NUMBER] of tSpriteRec;
   Rocket : array[1..ANOTHER_NUMBER] of tSpriteRec;


Colocar el sprite sería:

   Image.Left = ( Centre.x - OffSet.x );
   Image.Top = ( Centre.y - OffSet.y );

No se necesita más código; todo está allí; trabajo terminado; los
desplazamientos (offsets) nunca cambian.

Ahora podemos escribir una simple función para detectar colisiones:

Function Collided(Spr1, Spr2 : TSpriteRec) : Boolean;
begin
   result :=
   (abs(Spr1.Centre.x-Spr2.Centre.x) < (Spr1.OffSet.x+Spr2.OffSet.x)) and
   (abs(Spr1.Centre.y-Spr2.Centre.y) < (Spr1.OffSet.y+Spr2.OffSet.y));
end;

Y nuestro código principal se convierte en:

   if Collided (Rocket[10], Invader[77]) then begin
     // algo de código
   end;

La aplicación demo incluida en al archivo con el código fuente de esta
edición del boletín un simple juego del tipo "Space Invaders". Está
escrita en Delphi 6 y no usa DirectX o DelphiX. Es sólo puro Delphi
moviendo TImages. El código no es idéntico al de los ejemplos de
arriba, pero el principio sí lo es.

En la demo prueba cambiando las siguientes constantes en U_Sprites.pas:

INVADER_COLS = 16;
INVADER_ROWS = 6;

________________________________________________________________________

Ayúdanos a conseguir más suscriptores votando por el Boletín Pascal
(Pascal Newsletter) en estos rankings:
http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________


7. Foros / listas de correo


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@...

* 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@...

* 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

________________________________________________________________________

Ayúdanos a conseguir más suscriptores votando por el Boletín Pascal
(Pascal Newsletter) en estos rankings:
http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________


8. Delphi en la Red

    Por Dave Murray <irongut at vodafone dot net>


Componentes, librerías y aplicaciones
=====================================

Shareware / Comercial
---------------------

* InstallAWARE 3.0 for Windows Installer - by MimarSinan International
   Develop setups for Windows Installer without any knowledge of MSI!
   InstallAWARE automatically converts a conditionally flowing script
   into a logo certifiable, ICE-compliant MSI database at build time.
   The IDE features a visual UI which generates your setup script for
   you automatically and you can fully customize the script behavior.
   Special limited offer: 30% off all editions, Enterprise only $559.95!
   http://www.installaware.com/landingea.html

* KnowedgeBASE Vortex 2.9 by Delphinium Software ($49.35)
   KnowledgeBASE Vortex features a highly searchable and expandable
   information tree viewed in outline or audited within a built-in
   wordprocessor. Includes a database for stored references.
   http://www.download.com/KnowledgeBase-Vortex/3000-2064-10342084.html

* YAPI Professional - by Owen Mooney ($95)
   Offers the easiest and yet powerful printing from Delphi. It provides:
   WYSIWYG setup, print preview, Non database, Database, text, Grids,
   tabs, bitmaps, TCanvas operation, precise positioning or free flow
   positioning - all using simple "writeln" statements.
   http://free.hostdepartment.com/o/owenmooney/


Freeware
--------

* CSV Parser v1.0 - by Patrick Beekmans (with source)
   Parse any CSV-file with this component. You have the ability to choose
   the desired separator. This component has three events:
   OnNewColumnHeader, OnNewRow and OnNewValue.
   http://www.torry.net/vcl/vcltools/text/PBParsers.zip

* GExperts v1.21 - by GExperts Inc. (with source)
   GExperts is a set of open source tools that increase productivity by
   adding features to the IDE. Includes: Editor Experts to find matching
   delimiters, insert unit headers, etc; IDE enhancements that add a
   Windows menu and show hidden menu items; Palette enhancements that add
   multi-line tabs or add tabs to the context menu; and much more. Now
   supports Delphi 5/6/7/8/2005 and C++Builder 6.
   http://www.gexperts.org/

* Indy v10.0.51 - by The Indy Pit Crew (with source)
   Open source suite of more than 120 protocols and Internet standards.
   Each protocol is robust with rich support, the need to add additional
   support to existing protocols is rare. Indy is easy to use because it
   uses blocking sockets; everything happens in a sequence, just like
   accessing a file. Now supports .Net.
   http://www.indyproject.org/Sockets.iwp

* PGP Components for Delphi v4.0.1 - Michael in der Wiesche (w. source)
   Provides a Delphi (2-7) direct interface to PGP 6.5.x, 7.x or 8.x. New
   in Version 4.0.1: Checking and restarting of the PGPsdkService have
   been fixed, modified and enhanced; Error handling in TPGPDecode's data
   analysis has been slightly adjusted for special cases.
   http://idw-doc.homepage.t-online.de/PGPcomp.htm

* ProDelphi v17.3 - by Helmuth J. H. Adolph
   Source code profiler for Delphi (runtime measurement). Features
   include: Cyclic storage of measurement results for long period
   measurement; Open the source in the Delphi editor by clicking a
   procedure in the viewer; Conditional compilation; Integrated into the
   Delphi IDE; Measures runtimes in DLL's; Delphi 2005 Win32 supported.
   http://www.prodelphi.de/

* ProDelphi.Net v3.0 - by Helmuth J. H. Adolph
   Source code profiler for Delphi 8 and Delphi 2005. It has the same
   features as ProDelphi except measuring functions written with the
   inline assembler (not supported for .Net platform).
   http://www.prodelphi.de/

* TscFontCombobox v1.1 - by Stefan Cruysberghs (with source)
   An advanced combobox which shows the available Windows fonts. A lot of
   features for preview, used fonts, show font types (truetype, printer,
   symbol), etc are provided. This component provides all features of the
   Microsoft and Corel font combobox.
   www.torry.net/news.php?id=26&SID=d05e863b8b4107c854fa651e2bbfdeaa

* Vector Graphics ActiveX v1.6.0 - by Stas Semenov
   A graphics component for creating technical drawings, illustrations
   and presentation, training material and business reports, charts and
   diagrams and more. Based on Layer-Class-Shape architecture that
   repeatedly reduces the size of the stored data, to increase speed of
   loading and displaying documents, and also to provide excellent speed of
   execution with documents containing around 1,000,000 shapes.
   http://www.script-debugger.com/

* XP Graph v2.1 - by JLx Soft
   A Delphi Chart component equal like that one in Windows' task manager
   with bar and history, plus additional extensions.
   http://comps.jlxsoft.com/


Actualizaciones de productos Borland
------------------------------------

* Delphi 2005: The Ultimate Delphi
   The complete development solution for Windows. With all of the Windows
   languages and SDKs you need in one environment for modern Windows
   rapid application development (RAD), Delphi 2005 takes the power of
   Delphi to the next level. With Delphi, C#, Microsoft .NET Framework
   and Win32 support for GUI, Web, database, modeling, and ALM in one
   hyperproductive RAD environment, Delphi 2005 makes Windows development
   tasks faster, better, and easier.
   http://www.borland.com/delphi/


Artículos, trucos y consejos
============================

* BDNradio: Delphi 2005 Live Chat on Interop with Chris Bensen
   In this audio replay, Chris discusses his work on ActiveX, COM, .NET
   interop, VLI and the New Component wizard.
   http://community.borland.com/article/0,1410,32858,00.html

* BDNRadio: Log from Chat with Corbin Dunn on Delphi 2005 IDE Features
   Read the chat room log for questions answered by Corbin on Delphi 2005
   IDE features, and listen to the replay.
   http://community.borland.com/article/0,1410,32850,00.html

* BDNRadio: Delphi 2005 IDE Chat with Allen Bauer
   This is a log for the live audio chat from November 24th 2004 on
   Delphi 2005 with Allen Bauer, a Borland Principal Engineer, and
   Delphi IDE architect. Allen discusses his work on Delphi 2005.
   http://community.borland.com/article/0,1410,32843,00.html

* Delphi 2005 Fixes for QualityCentral Bug Reports
   There are currently 263 QualityCentral bug reports closed with the
   release of Delphi 2005.
   http://community.borland.com/article/0,1410,32837,00.html

* Namespaces in Delphi 2005
   To make Delphi code friendlier towards other .NET languages Borland
   has changed the way Delphi 2005 produces namespaces. This article
   discusses the changes that have been made and how they affect you.
   http://community.borland.com/article/0,1410,32765,00.html

* Advanced Markup Language Generation for IntraWeb
   Describes how to use an undocumented feature in IntraWeb to create
   complex controls that require multiple tags.
   http://community.borland.com/article/0,1410,32758,00.html

* BDNradio: Chat Room Log of Live Chat with Danny Thorpe on Delphi 2005
   This is the chat log for the live audio chat from November 19th 2004
   on Delphi 2005 with Danny Thorpe, a Borland Chief Scientist and
   architect of the Delphi compilers. Danny discusses changes and
   enhancements to the Delphi Win32 and Microsoft.NET compilers, the run
   time framework and .NET support in general.
   http://community.borland.com/article/0,1410,32789,00.html

* Using XMLDoc For API Documentation And HelpInsight With Delphi 2005
   How to use Borland's XMLDoc tool to quickly and easily document your
   software and generate HelpInsight for your components.
   http://community.borland.com/article/0,1410,32770,00.html

* What's New in Delphi 2005 - by Bob Swart
   A Technical White Paper on all that's new in Delphi 2005.
   http://community.borland.com/article/0,1410,32778,00.html

* Building a custom data provider for .Text
   A case study on the porting of .Text from SQL Server to InterBase
   using Delphi for .NET.
   http://community.borland.com/article/0,1410,32419,00.html

* Borland Conference 2004 Blogs
   An impressive compilation of blog entries that were created during
   BorCon 2004. It's not as good as being there, but it's close.
   http://community.borland.com/article/0,1410,32752,00.html

* How to Check if a Document in a TWebBrowser is Located on a Local
   (or Network) Drive - by Zarko Gajic
   If you need to know the location of a document displayed in a
   TWebBrowser component, you need to get the Protocol property of the
   IHTMLLocation. Here's a function that returns true if a document in a
   WebBrowser is stored locally.
   http://delphi.about.com/od/adptips2004/a/bltip1204_5.htm

* Using the TDBGrid Component - by Zarko Gajic
   Contrary to most other Delphi data-aware controls the DBGrid component
   has many nice features and is more powerful than you would have
   thought. There are many ways to customise the output of a DBGrid...
   http://delphi.about.com/od/usedbvcl/a/tdbgrid.htm

* Retrieving All Image Links from an HTML Document - by mrbaseball34
   Here's how to obtain all image links from an HTML document using Indy.
   http://delphi.about.com/od/adptips2004/a/bltip1204_3.htm

* Making Delphi 2005 Independent from .NET - by Alvaro Garcia Pascual
   Despite what Borland says, Delphi 2005 doesn't require .NET. If you
   are a Delphi Win32 developer and don't like that Delphi 2005 comes
   polluted with .NET stuff, read this article to learn how to remove
   .Net from Delphi 2005.
   http://delphi.about.com/od/delphifornet/a/delphi2005win32.htm

* A First Look at Delphi 2005 - by Zarko Gajic
   The time has come to take a sneak peak into a new Delphi version:
   Delphi 2005. Delphi 2005 is the ultimate weapon for developers:
   Delphi, C#, Win32 and .NET in one RAD environment.
   http://delphi.about.com/od/productreviews/ss/delphi2005first.htm

* How to write a Ping utility using ICMP.dll - by Serge Perevoznyk
   Raw Sockets are subject to security checks and are accessible only to
   members of the administrator's group. Icmp.dll provides functionality
   that allows developers to write Internet ping applications on Windows
   systems without Winsock 2 support and without security problems.
   http://www.delphi-central.com/tutorials/icmp-ping.aspx

* How To Find an Item in a Tree Control Via its Label - Serge Perevoznyk
   The "tree view" control does not have a built-in method for searching
   the entire tree or for selecting an item given its label. This article
   provides code that returns the location of any item in a tree when
   given a specific label to search for.
   http://www.delphi-central.com/tutorials/FindTreeViewNode.aspx


Tutoriales y capacitación
=========================

* Installable Delphi 2005 Examples
   Download an installation for dozens of tested Delphi 2005 examples for
   use directly from the IDE. These examples include the C# and Delphi
   languages and both the Win32 and .NET platforms with text that
   introduces and explains them.
   http://community.borland.com/article/0,1410,32857,00.html

* BDNtv: C++Builder in Delphi
   In this quick preview, Troy Kitch shows integration of C++Builder
   features in Delphi 2005. Flash
   http://bdntv.borland.com/cppbuilder/CPPinDelphi8x6.html

* BDNtv: Unit testing in Delphi 2005
   This BDNtv episode shows the unit testing integration for DUnit for a
   Delphi/Win32 application in Delphi 2005. Unit testing for C#, Delphi
   for .NET, and Delphi for Win32 with both NUnit and DUnit are supported
   in Delphi 2005. Flash
   http://dotnet.borland.com/bdntv/delphi/d2005unittesting8x6.html

* GOF Behavioural Patterns with C#: Part 1 - by Barry Mossman
   This is the third article in a series upon the GOF Design patterns
   from a C# and .Net Framework perspective. It is covers some of the
   Behavioral Patterns: Chain of Responsibility, Command, Interpreter.
   http://community.borland.com/article/0,1410,32710,00.html

* GOF Behavioural Patterns with C#: Part 2 - by Barry Mossman
   This is the fourth article in a series upon the GOF Design patterns
   from a C# and .Net Framework perspective. It is a continuation of the
   Behavioral Patterns this time looking at Iterator, Mediator, Observer
   and Memento (Momento) patterns.
   http://community.borland.com/article/0,1410,32795,00.html

* Deriving a Model From an Existing Database with ECO II in Delphi 2005
   Henrik Jondell demonstrates how easy it is to create model-powered
   applications for your existing databases with ECO II. Flash
   http://dotnet.borland.com/bdntv/delphi/eco2modelderivation.html

* An Introduction to COM Programming with Delphi (1/6) - by Curtis Socha
   A brief historical rundown on COM's glorious past. Abstract methods
   vs. Interfaces. Classes and Interfaces: An interesting paradox.
   http://delphi.about.com/library/weekly/aa112304a.htm

* An Introduction to COM Programming with Delphi (2/6) - by Curtis Socha
   What is an Interface? How to implement an Interface? Describing the
   TInterfacedObject.
   http://delphi.about.com/library/weekly/aa113004a.htm

* An Introduction to COM Programming with Delphi (3/6) - by Curtis Socha
   What is the implements directive? What is the Method Resolution
   Clauses? Pseudo-Multiple Interface Inheritance. Interface properties
   and other fine tales of horror.
   http://delphi.about.com/library/weekly/aa120704a.htm

* An Introduction to COM Programming with Delphi (4/6) - by Curtis Socha
   A Com Object walk-a-bout. A Class Factory tour. Our first true COM
   Object program. Homework Assignment.
   http://delphi.about.com/library/weekly/aa121404a.htm

* An Introduction to COM Programming with Delphi (5/6) - by Curtis Socha
   Marshaling Data. Oh, the glory of leadership! Variant Reference Page.
   Using Variants and Variant Arrays.
   http://delphi.about.com/library/weekly/aa122104a.htm

* Programming a Memory Game in Delphi: Part 1 - by Delphi Central
   In this tutorial, we will see how the TDrawGrid component can be used
   to help us develop a "Memory" game. Firstly we will describe what is
   involved with the Memory game.
   http://www.delphi-central.com/tutorials/memory_game.aspx

* Programming a Memory Game in Delphi: Part 2 - by Delphi Central
   In part 1 we explained how to create the form and drawgrid at design
   time. Now we will move onto writing the actual code.
   http://www.delphi-central.com/tutorials/memory_game_2.aspx

* Programming a Memory Game in Delphi: Part 3 - by Delphi Central
   In part 1 we explained how to create the form and drawgrid at design
   time, in part 2 we started writing the actual code. In the third part
   of the tutorial we will draw the grid that the game is played on.
   http://www.delphi-central.com/tutorials/memory_game_3.aspx


Noticias
========

* Delphi 2005 Architect Review
   Delphi has grown up since it launched nearly ten years ago. The latest
   version provides support for developing Win32 and .NET applications as
   well as supporting the C# language. There are many enhancements to
   almost all areas with the main goal of increasing developer
   productivity.
   http://www.builderau.com.au/program/0,39024614,39170720,00.htm

* Global 2000 Companies Select Borland to Elevate Software Quality
   An unprecedented number of high-profile customers spanning a wide
   spectrum of industries and regions selected CaliberRM and StarTeam in
   2004 as their preferred requirements management and software
   configuration and change management solutions. Companies that selected
   CaliberRM or StarTeam this year include: British Telecom, Comcast,
   EDS, Gap, HP, Jaguar Cars, Siemens AG, Symantec and Verizon Wireless.
   http://home.businesswire.com/portal/site/google/index.jsp?
   ndmViewId=news_view&newsId=20041206005289

* BDNradio Interviews with Borland's R&D staff for Delphi 2005
   Don't miss these live interviews with Borland R&D engineers.
   http://community.borland.com/article/0,1410,32786,00.html

* Software Delivery Optimisation Enables Disciplined Approach
   At the Borland Conference 2004, Dale Fuller, President and CEO,
   presented their vision and product strategy for transforming software
   development from an unpredictable art form into a more manageable and
   repeatable business process.
   http://www.itweb.co.za/sections/business/2004/0411150801.asp

* Borland's ALM Products Receive Numerous Accolades in 2004
   Borland today announced 2004 as a banner year for its products, with
   receiving numerous industry accolades and awards from around the
   globe. Industry recognition of their innovative solutions provides the
   company with significant momentum leading into 2005 and underscores
   their ongoing focus on technical excellence and customer value.
   http://home.businesswire.com/portal/site/google/index.jsp?
   ndmViewId=news_view&newsId=20041110005673&newsLang=en

* Borland to Provide UML Support to MS Visual Studio 2005 Team System
   Borland joined Microsoft and other industry leaders in announcing
   support and future plans for Software Factories, a new industry
   approach to improve software development. As part of Borland's support
   for Software Factories, the company plans to deliver a domain-specific
   modeling solution providing UML capabilities within the Microsoft
   Visual Studio 2005 Team System.
   http://www.tmcnet.com/usubmit/2004/Oct/1087428.htm

* Borland Focuses on UML Modeling
   Borland is breaking up Together ControlCenter for UML modeling into
   separate products for developing, designing, and architecting
   applications. The move is intended to align Together with the SDO
   strategy of providing a disciplined approach to development.
   http://www.infoworld.com/article/04/10/25/HNborcontrolcenter_1.html

* IBM and Borland Upgrade Developer Tools
   IBM unveiled new Rational developer tools and Borland rolled out the
   new version of its Delphi Windows development tool. Both are
   maneuvering to infuse their platforms with business process automation
   commonly used in other areas of enterprise operations.
   http://www.computerweekly.com/articles/article.asp?liArticleID=134236

* Native Win32 and .Net Framework Support for New Delphi
   Delphi, the grand-daddy of visual programming environments, has been
   updated. Delphi 2005 works with both Win32 and .Net frameworks, and
   also supports Microsoft's C# as well as the Delphi language itself.
   http://www.pcpro.co.uk/news/64469/
   native-win32-and-net-framework-support-for-new-delphi.html


Otros / Sitios misceláneos
==========================

* The Daily WTF: Curious Perversions In Information Technology
   The Daily WTF presents scary code examples. If you are looking for a
   good laugh visit the site, I just hope your code is not there! :)
   http://thedailywtf.com/

________________________________________________________________________

Irongut's Delphi Pages
Dedicada a la programación con Borland Delphi y Kylix. Tenemos artículos
sobre programación, noticias Borland y Delphi, código fuente y componen-
tes para usar en sus aplicaciones y más.  http://www.paranoia.clara.net/
________________________________________________________________________


¡Tú puedes ayudarnos!


Por favor danos una mano y ayúdanos a llegar a los 20.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@...

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://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium

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/descarga/p0052.zip
________________________________________________________________________

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@...
Para cancelar / removerse:    boletin-pascal-unsubscribe@...
Para reportar problemas con la suscripción: eds2004 @ latiumsoftware.com
________________________________________________________________________

Este boletín se provee "TAL Y COMO ESTA", sin garantía de ninguna clase.
Su uso  implica la  aceptación de la licencia y  la ausencia de garantía
que puedes  leer en la página http://www.latiumsoftware.com/es/legal.php
Allí también encontrarás una nota sobre marcas registradas.  Te animamos
a que redistribuyas  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
   Irongut's Delphi Pages         http://www.paranoia.clara.net/

Copyright 2004 by Ernesto De Spirito + Dave Murray. All rights reserved.
________________________________________________________________________

#18 De: "Ernesto De Spirito" <owner@...>
Fecha: Mié, 2 de Feb, 2005 5:51 pm
Asunto: Boletín Pascal #51 - 02-FEB-2005
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #51 - 02-FEB-2005

Índice

1. Unas palabras del editor
2. Cómo correr una sola instancia de una aplicación (y II)
3. Dentro de las clases e interfaces de Delphi (y II)
4. Enumerando todos los recursos de una red LAN
5. Foros / listas de correo
6. Delphi en la Red
    - Componentes, librerías y aplicaciones
      · Shareware / Comercial
      · Freeware
      · Actualizaciones de productos Borland
    - Artículos, trucos y consejos
    - Tutoriales y capacitación
    - Noticias

________________________________________________________________________

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


Ha pasado un largo tiempo sin que se publique el boletín, no por falta
de voluntad, sino por falta de tiempo. Aunque muchos no lo crean, lleva
varias horas armar un número y publicarlo, y en el pasado 2004 la verdad
que me ha sido difícil encontrar esas horas, que siempre son robadas al
necesario descanso y a la familia... Bien, pues ahora que dispongo de un
poco más de tiempo (al menos temporalmente), quiero decirles que no me
he olvidado de ustedes y que en estos días estaré traduciendo las dos
ediciones que me quedan pendientes de publicación, y ojalá que durante
el 2005 podamos publicar una edición cada dos meses como nos hemos
propuesto con Dave, pero no prometo nada, ¿OK?

Si no fuera por los autores que colaboran sus artículos, este boletín no
existiría, así que vaya nuestro agradecimiento en esta ocasión a Furious
Logic, Peter Johnson y Ezra Hoch, este último acreedor del premio
disponible para este número:

* Ezra Hoch - "Dentro de las clases e interfaces de Delphi"
   Delphi SWF SDK (Standard) v1.4 - por FeatherySoft ($170)
   Librería Object Pascal para crear ficheros SWF sin usar librerías
   dinámicas externas. Características: objetos visuales (forma, botón,
   texto, forma cambiante, sprite); todos los tipos de relleno (sólido,
   gradiente, imagen); fuentes incrustadas; comandos de acciones; sonidos
   (eventos, streaming); video; cualquier transición y transformación.
   http://www.delphiflash.com/

Los premios para la próxima edición, que dicho sea de paso ya está casi
lista y se publicará próximamente, son:

* KylixDriver v1.1 - por ET Kimberliteware Ltd ($39 / $69 con fuentes)
   Conjunto de herramientas para el desarrollo de drivers Linux que
   accedan al hardware de la PC, permitiendo desarrollar con Kylix
   controladores de dispositivo ISA/PCI para hardware específico.
   http://etsoftware.tripod.com/products.html

* InstallAWARE 3.0 Express Edition - por MimarSinan Int. ($69.95)
   Desarrolle instaladores para Windows Installer sin necesidad de
   conocimiento previo de MSI. InstallAWARE automáticamente convierte en
   tiempo de construcción un script de flujo condicional en una base de
   datos MSI que cumple con ICE, certificable mediante logo. El IDE
   ofrece una interfaz visual que automáticamente genera un script de
   instalación por usted, el cual puede ser completamente adaptado.
   http://www.installaware.com/landingea.html

* KnowedgeBASE Vortex 2.9 por Delphinium Software ($49.35)
   El corazón de KnowledgeBASE es un árbol de información altamente
   expandible y con gran capacidad de búsqueda, que puede verse como
   esquema o auditado dentro de un procesador de textos incorporado.
   Incluye una base de datos para referencias guardadas.
   http://www.download.com/KnowledgeBase-Vortex/3000-2064-10342084.html

Estamos orgullosos de ofrecer a los lectores del boletín un descuento
especial para InstallAWARE 3 (30% en cualquier edición), gracias a la
colaboración de MimarSinan International. InstallAWARE 3 ha sido
desarrollado enteramente en Delphi y sirve para crear instaladores MSI
sin necesidad de conocimiento previo sobre Windows Installer. En vez de
limitarse a proveer una interfaz visual (como Wise o InstallShield),
InstallAWARE tiene su propio RAD y lenguaje de programación/scripting,
el que en tiempo de construcción es automáticamente convertido a base
de datos MSI, certificable mediante con logo. Las características
únicas incluyen distribución Web parcial, programación genuina para
Windows Installer, un poderoso editor de diálogos con controles únicos
(como contenedores Flash y HTML) y compresión 7ZIP avanzada (¡el
runtime para .NET es de 11MB en vez de 23MB!). Por un tiempo limitado,
los lectores pueden obtener un descuento de 30% en cualquier edición de
InstallAWARE 3 siguiendo los enlaces que se publican en este número del
boletín.

¿Alguien ha tenido oportunidad de usar el nuevo Delphi 2005? Recibimos
sus comentarios en <eds2004 @ latiumsoftware.com>.
Para más información sobre Delphi 2005: http://www.borland.com/delphi

Saludos,

Ernesto De Spirito y Dave Murray
boletin-pascal-owner@...

__________________

Colaboraron en esta edición: Furious Logic, Peter Johnson y Ezra Hoch

________________________________________________________________________

Help & Manual 3.50 por EC Software · Shareware ($ 279) - Una herramienta
visual de  autoría de ayuda para generar archivos WinHelp (.HLP),  Adobe
PDF,  páginas HTML y los  nuevos archivos HTML HELP  (.CHM) introducidos
en Windows  98,  así como  otros formatos  de  archivo  y  documentación
impresa,  todo desde una  misma fuente.  Una herramienta  imprescindible
para cualquier desarrollador de software.  http://www.helpandmanual.com/
________________________________________________________________________


2. Cómo correr una sola instancia de una aplicación (y II)
    Parte 2: Una solución reutilizable

    Por Peter Johnson, Copyright (c) 2003
        <delphidabbler at tiscali dot co dot uk>
        http://www.delphidabbler.com/


Visión general de una solución orientada a objetos
--------------------------------------------------

Esta sección presenta una solución al problema de correr una sola
instancia de una aplicación, solución que es orientada a objetos y
extensible.

El código principal está centralizado en una sola unidad
(USingleInst.pas) que implementa y crea un objeto singleton
(TSingleInst) que maneja la instancia única de la aplicación y se
encarga de enviar y recibir datos de parámetros. Mientras que
TSingleInst provee un nombre para la clase de ventana del formulario
principal, el método de nombre de clase de ventana puede (y debe) ser
redefinido (overridden) para proveer un nombre de clase único. También
puede proveerse una marca de agua al redefinir el método.

Se requiere alguna alteración al archivo de proyecto y al formulario
principal, pero los cambios no son tan significativos como en el
ejemplo anterior (presentado en la primera parte del artículo, publicada
en el Boletín Pascal #50) y la funcionalidad principal está aislada en
USingleInst.pas.

El procedimiento para habilitar el soporte de una sola instancia de la
aplicación en un proyecto es como sigue:

* Añadir USingleInst.pas al proyecto.
* Crear una nueva clase derivada de TSingleInst y redefinir los métodos
   que devuelven el nombre de clase de ventana y (opcionalmente) la marca
   de agua.
* Registrar la nueva clase como la clase a usar al crear un objeto
   singleton SingleInst.
* Modificar los fuentes del formulario principal y del proyecto para
   llamar al punto de entrada requerido del objeto SingleInst.

En el resto de esta sección repasaremos la unidad USingleInst, luego
daremos un vistazo a cómo derivar y registrar una nueva clase a partir
de ella y finalmente describiremos los cambios a realizar a los archivos
de código fuente del proyecto y del formulario principal.


La unidad USingleInst
---------------------

Repasaremos las partes de la unidad en orden. El código fuente de la
unidad acompaña este artículo. Esta es la sección de Interfaz de la
unidad que declara la clase y las funciones de apoyo:


unit USingleInst;

interface

uses
   Windows, Controls, Messages;

type
   TSingleInstParamHandler = procedure(const Param: string) of object;

   TSingleInstClass = class of TSingleInst;

   TSingleInst = class(TObject)
   private
     fOnProcessParam: TSingleInstParamHandler; // manejador de evento
     fEnsureRestoreMsg: UINT;  // mensaje único para pedir restauración
   protected
     function WdwClassName: string; virtual:
     function WaterMark: DWORD; virtual;
     function FindDuplicateMainWdw: HWND; virtual;
     function SendParamsToPrevInst(Wdw: HWND): Boolean; virtual;
     function SwitchToPrevInst(Wdw: HWND): Boolean;
     procedure EnsureRestore(var Msg: TMessage); dynamic;
     procedure WMCopyData(var Msg: TMessage); dynamic;
   public
     constructor Create;
     procedure CreateParams(var Params: TCreateParams);
     function HandleMessages(var Msg: TMessage): Boolean;
     function CanStartApp: Boolean;
     property OnProcessParam: TSingleInstParamHandler
       read fOnProcessParam write fOnProcessParam;
   end;

function SingleInst: TSingleInst;

procedure RegisterSingleInstClass(Cls: TSingleInstClass);


Repasemos primero las declaraciones de tipo. TSingleInstParamHandler es
el tipo del manejador de evento OnProcessParam que es invocado por cada
parámetro pasado a la aplicación en un mensaje WM_COPYDATA, mientras que
TSingleInstClass es el tipo de clase ("class of") de la clase
TSingleInst y clases derivadas.

Cubriremos los métodos de la clase en la sección de Implementación. El
otro único elemento que merece ser mencionado ahora es el campo
fEnsureRestoreMsg. El mismo se usa para almacenar el Id del mensaje
usado para solicitar a una aplicación que restaure y muestre su ventana.
El Id de mensaje es provisto por Windows y está garantizando que es
único. Desafortunadamente, el uso de ese mensaje significa que no
podemos usar el manejador de mensajes de Delphi para manejar el mensaje
y debemos recurrir a interceptar mensajes en el bucle de mensajes (ver
más abajo).

Finalmente la función SingleInst se usa para devolver una instancia del
objeto singleton TSingleInst (o descendiente) mientras que el
procedimiento RegisterSingleInstClass se usa para registrar el tipo de
la clase a ser usada para crear el objeto singleton.

Examinaremos la sección de Implementación en segmentos. He aquí el
primero:


implementation

uses
   SysUtils, Forms;

var
   // Globales almacenando singleton SingleInst y la clase de SingleInst
   gSingleInst: TSingleInst = nil;
   gSingleInstClass: TSingleInstClass = nil;

function SingleInst: TSingleInst;
begin
   if not Assigned(gSingleInst) then
   begin
     if Assigned(gSingleInstClass) then
       gSingleInst := gSingleInstClass.Create
     else
       gSingleInst := TSingleInst.Create;
   end;
   Result := gSingleInst;
end;

procedure RegisterSingleInstClass(Cls: TSingleInstClass);
begin
   gSingleInstClass := Cls;
end;


Las variables globales privadas gSingleInst y gSingleInstClass almacenan
una referencia al objeto singleton y al tipo del objeto singleton (tal
como se registra en RegisterSingleInstClass) respectivamente.

De la implementación de SingleInst se puede ver que el objeto singleton
es creado la primera vez que el objeto se referencia. Si se registró una
clase derivada, ésta se usa para crear el singleton, de lo contrario se
usa la clase base. Esto significa que cualquier clase derivada de
TSingleInst debe ser registrada antes que el objeto sea accedido por
primera vez - se recomienda que RegisterSingleInstClass sea llamada en
la sección de Initialización de la unidad donde se define la clase
derivada. Esto también explica por qué el objeto singleton no se crea en
la sección de Inicialización de esta unidad, puesto que esta sección
sería llamada antes que las de las unidades de las clases derivadas.

Yendo a la definición de la clase, primero observemos el constructor de
la clase que simplemente registra a Windows el mensaje definido por el
usuario:


constructor TSingleInst.Create;
begin
   inherited;
   fEnsureRestoreMsg :=
     RegisterWindowMessage('USINGLEINST_ENSURERESTORE');
end;


Hay varios "puntos de entrada" en la clase que deben ser llamados desde
la unidad principal o desde el archivo de proyecto. Los veremos a
continuación:


function TSingleInst.CanStartApp: Boolean;
var
   Wdw: HWND;
begin
   Wdw := FindDuplicateMainWdw;
   if Wdw = 0 then
     Result := True
   else
     Result := not SwitchToPrevInst(Wdw);
end;

procedure TSingleInst.CreateParams(var Params: TCreateParams);
begin
   inherited;
   StrPLCopy(Params.WinClassName, WdwClassName,
     SizeOf(Params.WinClassName) - 1);
end;

function TSingleInst.HandleMessages(var Msg: TMessage): Boolean;
begin
   if Msg.Msg = WM_COPYDATA then
   begin
     WMCopyData(Msg);
     Result := True;
   end
   else if Msg.Msg = fEnsureRestoreMsg then
   begin
     EnsureRestore(Msg);
     Result := True;
   end
   else
     Result := False;
end;


El primero de estos "puntos de entrada" es CanStartApp, el que se llama
desde el archivo de proyecto e indica si la aplicación debe ser iniciada
o no. Funciona de modo similar a la función CanStart de la primera parte
de este artículo (publicada en el Boletín Pascal #50).

El método CreateParams establece el nombre de clase de ventana del
formulario principal actualizando los parámetros de creación del
formulario. El formulario principal debe redefinir su
TForm.CreateParamsSingleInst.CreateParams desde dentro de ese método.

El "puntos de entrada" más complejo es el método HandleMessages, que
intercepta el mensaje WM_COPYDATA y el campo fEnsureRestoreMsg del
formulario principal y maneja el procesamiento delegándolo a WMCopyData
y EnsureRestore respectivamente (ver más abajo). Esto método devuelve
verdadero si maneja el mensaje y falso en caso contrario. El formulario
principal debe redefinir el método TForm.WndProc y desde allí llamar a
SingleInst.HandleMessages, llamando su método TForm.WndProc heredado si
el método HandleMessages devuelve falso.

Examinemos ahora los métodos de soporte protegidos. Primero tenemos dos
métodos que deben ser redefinidos en clases descendientes:


function TSingleInst.WdwClassName: string;
begin
   Result := 'SingleInst.MainWdw';
end;

function TSingleInst.WaterMark: DWORD;
begin
   Result := 0;
end;


WdwClassName simplemente devuelve el nombre a usar como el nombre de
de ventana del formulario principal. Este debería ser redefinido para
devolver algo único a la aplicación. Similarmente, Watermark devuelve
0 como el valor de marca de agua (las marcas de agua se trataron en la
primera parte de este artículo -publicada en el Boletín Pascal #50-).
Este método debería ser redefinido para devolver algún valor inusual si
se emplearán marcas de agua.

Ahora siguen los dos métodos de soporte que manejan mensajes:


procedure TSingleInst.EnsureRestore(var Msg: TMessage);
begin
   if IsIconic(Application.Handle) then
     Application.Restore;
   if Assigned(Application.MainForm) and not Application.MainForm.Visible
     then Application.MainForm.Visible := True;
   Application.BringToFront;
end;

procedure TSingleInst.WMCopyData(var Msg: TMessage);
var
   PData: PChar;
   Param: string;
begin
   if TWMCopyData(Msg).CopyDataStruct.dwData = WaterMark then
   begin
     PData := TWMCopyData(Msg).CopyDataStruct.lpData;
     while PData^ <> #0 do
     begin
       Param := StrPas(PData);
       if Assigned(fOnProcessParam) then
         fOnProcessParam(Param);
       Inc(PData, Length(Param) + 1);
     end;
     Msg.Result := 1;
   end
   else
     Msg.Result := 0;
end;


Nótese que estos métodos se basan bastante en los métodos de manejo de
mensajes tratados en la primera parte de este artículo, excepto que ya
no se implementan directamente en la unidad del formulario. El único
cambio significativo es que WMCopyData ahora invoca al evento
OnProcessParam en vez de llamar a un método fijo para procesar los
parámetros directamente.

Finalmente examinaremos los tres métodos protegidos restantes:


function TSingleInst.FindDuplicateMainWdw: HWND;
begin
   Result := FindWindow(PChar(WdwClassName), nil);
end;

function TSingleInst.SendParamsToPrevInst(Wdw: HWND): Boolean;
var
   CopyData: TCopyDataStruct;
   I: Integer;
   DataSize: Integer;
   Data: PChar;
   PData: PChar;
begin
   DataSize := 0;
   for I := 1 to ParamCount do
     Inc(DataSize, Length(ParamStr(I)) + 1);
   Inc(DataSize);
   Data := StrAlloc(DataSize);
   try
     PData := Data;
     for I := 1 to ParamCount do
     begin
       StrPCopy(PData, ParamStr(I));
       Inc(PData, Length(ParamStr(I)) + 1);
     end;
     PData^ := #0;
     CopyData.lpData := Data;
     CopyData.cbData := DataSize;
     CopyData.dwData := WaterMark;
     Result := SendMessage(Wdw, WM_COPYDATA, 0, LPARAM(@CopyData)) = 1;
   finally
     StrDispose(Data);
   end;
end;

function TSingleInst.SwitchToPrevInst(Wdw: HWND): Boolean;
begin
   Assert(Wdw <> 0);
   if ParamCount > 0 then
     Result := SendParamsToPrevInst(Wdw)
   else
     Result := True;
   if Result then
     SendMessage(Wdw, fEnsureRestoreMsg, 0, 0);
end;


Estos métodos son análogos a las rutinas equivalentes en la primera
parte de este artículo y no serán descritos nuevamente aquí.


Modificaciones al archivo de proyecto
-------------------------------------

El archivo de proyecto debe pasar por un simple cambio para usar el
objeto SingleInst a fin de determinar si iniciar o no la aplicación.
Primero debe añadirse la unidad USingleInst al proyecto y luego se debe
modificar el archivo de proyecto para envolver la creación del
formulario y el código de ejecución de la aplicación en una sentencia
condicional, como sigue:


...

begin
   if SingleInst.CanStartApp then
   begin
     Application.Initialize;
     Application.CreateForm(TForm1, Form1);
     Application.Run;
   end;
end.


Modificación al formulario principal
------------------------------------

Se necesita más trabajo en la unidad del formulario principal. Primero,
agregue las siguientes declaraciones en la sección protegida de la clase
del formulario:


   protected
     procedure WndProc(var Msg: TMessage); override;
     procedure HandleParam(const Param: string);
     procedure CreateParams(var Params: TCreateParams); override;


Ahora implemente estos métodos para llamar a SingleInst como sigue:


procedure TForm1.CreateParams(var Params: TCreateParams);
begin
   inherited;
   SingleInst.CreateParams(Params);
end;

procedure TForm1.WndProc(var Msg: TMessage);
begin
   if not SingleInst.HandleMessages(Msg) then
     inherited;
end;


El método CreateParams llama al método heredado (inherited) y luego
llama a SingleInst.CreateParams para establecer el nombre de clase de
ventana. El método redefinido WndProc llama a SingleInst.HandleMessages
para determinar si el mensaje es uno de los manejados por SingleInst (la
función devuelve verdadero si maneja el mensaje). Si el mensaje no es
manejado por SingleInst.CreateParams se llama al método WndProc heredado
para manejarlo.

También queremos manejar el evento TSingleInst.OnProcessParam para que la
aplicación sea notificada cuando se pasen parámetros con un mensaje
WM_COPYDATA. En este ejemplo agregaremos los parámetros a un cuadro de
lista. Asignamos el manejador de evento en FormCreate, donde también
procesaremos los parámetros pasados al programa la primera vez que se
inicia:


procedure TForm1.FormCreate(Sender: TObject);
var
   I: Integer;
begin
   SingleInst.OnProcessParam := HandleParam;
   for I := 1 to ParamCount do
     HandleParam(ParamStr(I));
end;

procedure TForm1.HandleParam(const Param: string);
begin
   ListBox1.Items.Add(Param);
end;


Redefiniendo TSingleInst
------------------------

Ahora veremos un ejemplo de como redefinir TSingleInst. Simplemente
proveemos una nueva marca de agua y un nuevo nombre de clase de ventana.
La unidad entera (UMySingleInst.pas) se lista abajo. El único punto a
notar es cómo se registra la nueva clase como la clase a usar para el
objeto singleton SingleInst.


unit UMySingleInst;

interface

uses
   Windows,
   USingleInst;

type
   TMySingleInst = class(TSingleInst)
   protected
     function WdwClassName: string; override;
     function WaterMark: DWORD; override;
   end;

implementation

{ TMySingleInst }

function TMySingleInst.WaterMark: DWORD;
begin
   Result := $DE1F1DAB;
end;

function TMySingleInst.WdwClassName: string;
begin
   Result := 'DelphiDabbler.SingleInst.1';
end;

initialization

RegisterSingleInstClass(TMySingleInst);

end.


Conclusión
----------

Este artículo ha demostrado como asegurar que sólo una instancia de una
aplicación se ejecute. También demuestra cómo pasar los parámetros de
línea de órdenes a la instancia que ya está en ejecución, asegurando que
su ventana se muestre prominentemente.

El método usado es detectar la presencia de la clase de ventana de la
ventana principal de la aplicación entre las ventanas del nivel más
alto. La comunicación con la instancia previa se hace por medio de
mensajes enviados a la ventana principal de la instancia. En particular,
se usa una un mensaje definido por el usuario para asegurar que la
ventana se restaure y se haga visible, y se usa el mensaje WM_COPYDATA
para enviar los parámetros de línea de órdenes cruzando las fronteras de
los procesos.

Se provee el esqueleto de algo de código fuente para una aplicación que
corre como una única instancia.

Finalmente se presentó una clase reutilizable que puede ser usada
en el desarrollo de un programa que corra una única instancia de la
aplicación.

Se incluye también una aplicación demostrativa junto con el código
fuente que acompaña esta edición.

__________________

Peter Johnson es un programador hobbyista que vive en West Wales (Reino
Unido) y que "chapotea" en Delphi. Mantiene el sitio web DelphiDabbler
(http://www.delphidabbler.com/) donde publica sus artículos y sus
aplicaciones y componentes Delphi gratuitos. Una versión completa de
este artículo se encuentra disponible en:
http://www.delphidabbler.com/articles.php?article=13

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


3. Dentro de las clases e interfaces de Delphi (y II)

    Por Ezra Hoch


La primera parte de "Dentro de las clases e interfaces de Delphi" se
publicó en el Boletín Pascal #49. Debería leerse antes de este artículo:
http://www.latiumsoftware.com/es/pascal/0049.php#4

En esta parte finalizaremos cubriendo la implementación de interfaces en
Delphi, y repasaremos unas conclusiones útiles.

Comencemos con un ejemplo en profundidad:

   type

     IInterface1 = interface
       procedure ActA;
       procedure ActB;
     end;

     IInterface2 = interface(IInterface1)
       procedure ActC;
       procedure ActD; stdcall;
     end;

     TSampleClass = Class(TInterfacedObject, IInterface1, IInterface2)
       procedure ActA;
       procedure ActB;
       procedure ActC;
       procedure ActD; stdcall;
     end;

   var
     Interface1 : IInterface1;
     Interface2 : IInterface2;
     Sample : TSampleClass;
   begin
     Sample := TSampleClass.Create;
     Interface1 := Sample;
     Interface2 := Sample;
     Interface1.ActA;
     Interface1.ActB;
     Interface2.ActA;
     Interface2.ActB;
     Interface2.ActC;
     Interface2.ActD;
   end;

En vez de ver el código compilado de este ejemplo, simplemente notaré
sus aspectos interesantes. Primero, al asignar un valor a Interface1,
esperaríamos que Delphi lo tome como la dirección apuntada por 'Sample',
más una cantidad específica ($10) y que eso sea todo. Al asignar un
valor a Interface2, esperaríamos que Delphi haga lo mismo, sólo que
sumaría ($0C) porque las interfaces se almacenan en memoria de la última
a la primera.

Pero Delphi no hace esto. Asigna tanto a Interface1 como a Interface2
la dirección apuntada por 'Sample' más $0C. Esto es porque IInterface2
hereda de IInterface1. Por lo tanto IInterface2 incluye Interface1, de
modo que cualquier llamada a Interface1 en realidad será ejecutada a
través de la lista de métodos de IInterface2.

Segundo, cuando llamamos a Interface1.ActA, se llama al cuarto método
de la lista de métodos de IInterface2 (porque IInterface2 hereda de
IInterface1 y a su vez hereda de IUnknown). Llamando a Interface1.ActB
se llama al quinto método de la lista de métodos de IInterface2.
Cuando llamamos a Interface2.ActA se llama al cuarto método de la lista
de métodos de IInterface2, al igual que Interface1.ActA. Esto es porque
IInterface2 hereda de IInterface1.

Tercero, cuando llamamos a Interface2.ActD, Delphi añade una
instrucción adicional antes de llamar al séptimo método de IInterface2.
Esto es porque hemos declarado el método con una convención diferente de
llamada (stdcall). Nótese que todos los métodos de IUnknown se definen
con la directiva stdcall.

La estructura del código de los métodos de la lista de métodos de una
interfaz siempre sigue la siguiente regla:

   Primer método
   .
   .
   Último método
   Lista de métodos de la interfaz madre

En nuestro caso, el código de los métodos de la lista de métodos de
IInterface2 es como sigue:

   ActC
   ActD
   // Lista de métodos de IInterface1
     ActA
     ActB
     // Lista de métodos de IUnknown
       QueryInterface
       _AddRef
       _Release

NOTA: La estructura de arriba es cómo se organiza el código de los
métodos en memoria, pero la primera entrada en una lista de métodos
pertenece a QueryInterface (el primer método de IUnknown), aunque
apuntará a un lugar en memoria (la implementación de ese método
QueryInterface específico de la interfaz) que está más arriba que la
implementación de los métodos propios de la interfaz. En nuestro caso,
la implementación del método QueryInterface de IInterface2 está más
arriba en memoria que la implementación del método ActB de
IInterface2, que a su vez está más arriba en memoria que la
implementación del método ActD, aunque ActD sea la séptima entrada en
la lista de métodos de IInterface2, ActB la quinta y QueryInterface la
primera.

Para entender acabadamente lo que sucede cuando Delphi llama a un
método de una interfaz, démosle un vistazo al código ensamblador de
las llamadas a los métodos de la lista de métodos de IInterface2 en el
ejemplo de arriba. El siguiente código es una copia exacta del código
compilado (excepto por los comentarios):

   // ActC
   add eax, -$0C
   call TSampleClass.ActC
   // ActD
   add dword ptr [esp + $04], -$0C
   call TSampleClass.ActD
   // ActA
   add eax, -$0C
   call TSampleClass.ActA
   // ActB
   add eax, -$0C
   call TSampleClass.ActB
   // QueryInterface
   add dword ptr [esp + $04], -$0C
   call TInterfacedObject.QueryInterface
   // _AddRef
   add dword ptr [esp + $04], -$0C
   call TInterfacedObject._AddRef
   // _Release
   add dword ptr [esp + $04], -$0C
   call TInterfacedObject._Release

Como se recordará, un método de un objeto es una función o procedimiento
ordinario que acepta como primer parámetro una instancia de la clase del
método. Como puede notar, antes de cada llamada al método real (por ej.
"TSampleClass.ActD") hay una línea de código que cambia el valor de
"eax" o de "dword ptr [esp + $04]", dependiendo de la convención de
llamada. Como puede notarse, en todos los casos se resta $0C de una
variable. Pero, ¿por qué 12 ($0C = 12)? Porque resulta que esta interfaz
(IInterface2) está en el tercer lugar después del puntero a la VMT de la
clase TSampleClass (FRefcount e IUnknown están antes). Por consiguiente,
el valor de cualquier instancia de IInterface2 de TSampleClass
(Interface2 por ejemplo) es en realidad el valor del puntero a la
instancia de la clase más 12.

Aquí hay otro ejemplo que ayudará a entender la sección de arriba. El
siguiente código continúa las definiciones del código de arriba:

   type

     IAnotherInterface = interface
       procedure ActE;
     end;

     TAnotherSample = class(TInterfacedObject, IInterface2,
                        IAnotherInterface)
       procedure ActA;
       procedure ActB;
       procedure ActC;
       procedure ActD; stdcall;
       procedure ActE;
     end;

   var
     Interface2: IInterface2;
   begin
     Interface2:= TAnotherSample.Create;
     Interface2.ActC;
   end;

Ahora comparemos la entrada para este ejemplo de IInterface2 y el
anterior:

   // IInterface2 de TAnotherSample:
   add eax, -$10
   call TAnotherSample.ActC

   // IInterface2 de TSampleClass:
   add eax, -$0C
   call TSampleClass.ActC

Hay dos cambios obvios:

a) La función real que es llamada (TAnotherSample.ActC o
    TSampleClass.ActC)
b) La cantidad por la que se modifica EAX. Nótese que al cambiar
    IInterface2 de TAnotherSample, EAX se desplaza en 16 ($10 = 16), en
    vez de ser desplazado en 12. Esto es porque en TAnotherSample,
    IInterface2 es la segunda interfaz en la estructura de la instancia
    en memoria, y por consiguiente está "más lejos" que la instancia
    misma y debe desplazarse 4 bytes adicionales.

Ahora veamos algunas cosas útiles.

Primero, si quiere chequear si dos (o más) variables de interfaz son de
la misma instancia, no puede simplemente compararlas, incluso si son del
mismo tipo. Debe "QueryInterfacearlas" (convertirlas) a un mismo tipo de
interfaz, y luego comparar. Como regla general, si desea comparar
interfaces, conviértalas a IUnknown y luego compare.

Ejemplo:

   type

     IBooA = interface
     end;

     IBooB = interface
     end;

     TBoo = class(TInterfacedObject, IBooA, IBooB)
     end;

   var
     Boo : TBoo;
     BooA : IBooA;
     BooB : IBooB;
   begin
     Boo := TBoo.create;
     BooA := Boo;
     BooB := Boo;

     // Esto no compilará
     if BooA = BooB then
     begin
       Beep;
     end;

     if Integer(BooA) = Integer(BooB) then
     begin
       // Nunca llegará aquí
       Beep;
     end;

     if IUnknown(BooA) = IUnknown(BooB) then
     begin
       // Nunca llegará aquí
       Beep;
     end;

     // La palabra "as" es la mismo que QueryInterface al actuar con
     // interfaces
     if (BooA as IUnknown) = (BooB as IUnknown) then
     begin
       // Siempre llegará aquí
       Beep;
     end;
   end;

Explicación: La primera comparación no compilará porque BooA y BooB son
de dos tipos diferentes. La segunda y la tercera comparación compilarán,
pero nunca devolverán verdadero. Esto es porque la conversión de tipos
(typecasting) no cambiará el valor de la variable que está siendo
convertida. Sólo permite al compilador compilar el código aunque haya
dos tipos diferentes involucrados. He aquí que, si BooA es diferente de
BooB, la comparación nunca devolverá verdadero, sin importar qué
conversión de tipos se les hagan.

Pero, ¿por qué BooA y BooB tienen diferentes valores si ambas fueron
asignadas con la sentencia ":= Boo;". La respuesta es simple. Recuerde
cuando dije que el valor de una variable de interfaz es en realidad el
valor de la instancia misma (en realidad es el valor del puntero a la
instancia) más un número por cada interfaz- En nuestro caso, BooA es
lo mismo a lo que apunta Boo, más 16. Y BooB es lo mismo a lo que Boo
apunta, más 12. Por eso es que BooA y BooB no son lo mismo.

La cuarta comparación sí funciona. Esto es porque si una interfaz es
del mismo tipo, entonces compararla con otra interfaz del mismo tipo
devolverá el resultado esperado (si ambas interfaces fueron adquiridas
a través de QueryInterface, no por conversión de tipos). Es así porque
si son del mismo tipo, entonces la diferencia entre ambas y la instancia
es la misma. Y si son de la misma instancia, entonces deberían ser
iguales.

Esto es, cada interfaz es igual a su instancia más un desplazamiento
Delta específico (el Delta depende de la interfaz). En otras palabras,
Interfaz = Instancia + Delta. Si Instancia es la misma para ambas
interfaces, y el Delta es el mismo (porque son del mismo tipo de
interfaz), entonces ambas interfaces serán iguales.

Nota: Esta es la forma en que Delphi trabaja, para bien o para mal.
Debería tomar esto en cuenta al escribir código para propiedades de
tipo interfaz. El siguiente código no funcionará apropiadamente:

   TSample = class
     private
       FData : IUnknown;
       procedure SetData(Value : IUnknown);
     protected
       procedure Changed; virtual; abstract;
     public
       property Data : IUnknown read FData write SetData;
   end;

   procedure TSample.SetData(Value : IUnknown);
   begin
     // Esto es incorrecto.
     if Value <> FData then
     begin
       FData := Value;
       Changed;
     end;
   end;

Puede parecer que ese código debería funcionar, pero no funcionará
cuando alguien asigna la propiedad Data con un IUnknown obtenido por
simple conversión de tipos. El código correcto debería ser:

   procedure TSample.SetData(Value : IUnknown);
   begin
     if (Value as IUnknown) <> (FData as IUnknown) then
     begin
       FData := Value;
       Changed;
     end;
   end;

Segundo, una interfaz declarada como implementada por una clase (con
excepción de las interfaces que herede de otras interfaces) significa
que cada instancia de aquella clase tomará 4 bytes más de memoria. Puede
parecer poco (y probablemente lo es) excepto en un caso. Considere el
siguiente código:

   IInterfaceA = interface
   end;

   IInterfaceB = interface
   end;

   TSampleClass1 = class(TInterfacedObject, IInterfaceA)
   end;

   TSampleClass2 = class(TSampleClass1, IInterfaceA, IInterfaceB)
   end;

Podría parecer que cada instancia de TSampleClass1 debería ocupar 16
bytes, y que cada instancia de TSampleClass2 debería ocupar 20 bytes
(4 bytes más, porque soporta una interfaz más). Este no es el caso.
Cada instancia de TSampleClass1 sí ocupa 16 bytes, pero cada instancia
de TSampleClass2 ocupa 24 bytes. Esto es porque Delphi crea una entrada
de interfaz incluso para interfaces que ya están implementadas en la
clase madre.

La solución a esto es simple. Sólo remueva la declaración de
IInterfaceA en TSampleClass2. Esto no cambiará el hecho de que
TSampleClass2 implementa IInterfaceA, porque TSampleClass2 hereda de
TSampleClass1, la que implementa IInterface1. Esto no habría sucedido
si IInterfaceB fuera un descendiente de IInterfaceA.

Esto podría sumar mucho si realiza su herencia inapropiadamente. Por
ejemplo:

   TSampleClass1 = class(TInterfacedObject, IUnknown)
   end;

   TSampleClass2 = class(TSampleClass1, IUnknown)
   end;

   TSampleClass3 = class(TSampleClass2, IUnknown)
   end;

   TSampleClass4 = class(TSampleClass3, IUnknown)
   end;

   TSampleClass5 = class(TSampleClass4, IUnknown)
   end;

Cada instancia de TSampleClass5 ocupará 32 bytes de memoria, a pesar que
no tiene datos reales (excepto por FRefCount de TInterfacedObject).

________________________________________________________________________

Ayúdanos a conseguir más suscriptores votando por el Boletín Pascal
(Pascal Newsletter) en estos rankings:
http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________


4. Enumerando todos los recursos de una red LAN


Desde Lima, Perú, Furious Logic nos envía un programa que enumera todos
los recursos de una LAN.

Como puede observarse en el código fuente del programa, que se adjunta
a esta edición, el núcleo del programa es un procedimiento (MostrarRed)
que hace uso de la API WNetEnumResource para enumerar los recursos de
la red. Antes de llamar a WNetEnumResource es necesario obtener un
handle llamando a la API WNetOpenEnum, y al final debemos liberarlo con
una llamada a la API WNetCloseEnum.

El proceso obtiene la dirección IP de un recurso con la función
GetHostByName, la que se pasa como parámetro a la función inet_ntoa
para convertirla en una cadena en formato www.xxx.yyy.zzz, que es lo
que finalmente se muestra.

En caso que un recurso sea a su vez un contenedor de recursos, el
procedimiento se llama recursivamente a sí mismo para enumerar los
recursos del contenedor, y así hasta el máximo nivel de anidamiento.

Otro aspecto a destacar es que el procedimiento corre en un hilo de
ejecución (thread) diferente del programa principal, una sana práctica
para no congelar el programa mientras dura el proceso de detección.

En el Boletín Pascal #53 presentaremos otro aporte de Furious Logic.

________________________________________________________________________


5. Foros / listas de correo


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@...

* 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@...

* 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

________________________________________________________________________

Delphi BUGS?
Catch & Log every BUG showing Unit, Class, Method, Line #.
Now with support for IntraWeb applications and Anti-Freeze feature.
http://www.eurekalog.com/bannerclick.php?id=15
________________________________________________________________________


6. Delphi en la Red

    Por Dave Murray <irongut at vodafone dot net>


Componentes, librerías y aplicaciones
=====================================


Shareware / Comercial
---------------------

* KylixDriver v1.1 - by ET Kimberliteware Ltd ($39 / $69 with source)
   KylixDriver is a RAD Kylix-oriented and integrated toolkit for PC
   hardware access. This toolkit can be efficiently used for writing
   Linux device drivers for ISA and PCI hardware.
   http://www.geocities.com/etkimberliteware/kylixdriver/index.html

* Delphi SWF SDK (Standard) v1.4 - by FeatherySoft ($170)
   Object Pascal library for creating SWF files, without using of any
   external dynamic libraries. Released features: visual objects (shape,
   button, text, morphing shape, sprite); all types of filling (solid,
   gradient, image); device and embedding fonts; action commands;
   sound (events, streaming); video; any transition and transformation.
   http://www.delphiflash.com/


Freeware
--------

* PGP Components for Delphi v4.0 - Michael in der Wiesche (with source)
   These sources provide a Delphi (2-7) direct interface to PGP requiring
   a preceding full installation of PGP 6.5.x, 7.x or 8.x. Features
   include: Encoding and decoding (encrypt/decrypt/sign/verify); Creating
   and verifying file detached signatures; Key management; Key generation
   (DH/DSS, RSA); X509 Certificate support; Keyserver functions.
   http://home.t-online.de/home/idw.doc/PGPcomp.htm

* Synapse TCP/IP Library v.34 - by Lukas Gebauer (with source)
   TCP/IP library for Delphi, Kylix and FreePascal using blocking
   sockets. Contains simple non-visual objects for easy programming of
   command line utilities, visual projects, NT services, etc. New:
   FreePascal 1.9.4 support; Experimental Delphi 8 support; Optional
   support for ICONV library; New flexible FTP directory listing parser.
   http://synapse.ararat.cz/

* TPJDropFiles + TPJFormDropFiles v4.1 - by Peter Johnson (with source)
   Two components that catch files dragged and dropped from Explorer.
   TPJFormDropFiles provides a window that can contain other controls and
   catch any files dropped anywhere on it or child controls. TPJDropFiles
   is a non-visual component that subclasses a form to catch files that
   are dropped anywhere on the form.
   http://www.delphidabbler.com/software.php?id=dropfiles

* Merkes' Tiny Hex Editor v1.5.0.10 - by Merkes Pages
   A free hex editor for binary files. Allows you to edit multiple files
   (mdi), disk sectors and virtual memory of other processes. Tiny Hex
   Editor is scriptable, lets you view data structures and has a plugin
   interface for third party extensions.
   http://www.mirkes.de/en/freeware/tinyhex.php


Actualizaciones de productos Borland
------------------------------------

* Public Beta: Delphi 7.1 Update - Database Supplemental
   This is a public beta of database runtime files that address defects
   introduced in the Delphi 7.1 update.
   http://community.borland.com/article/0,1410,32492,00.html


Artículos, trucos y consejos
============================

* Interview with Danny Thorpe about Diamondback
   Danny Thorpe talks about the next Delphi release.
   http://community.borland.com/article/0,1410,32708,00.html

* Interview with Corbin Dunn about the Diamondback IDE
   Corbin Dunn, Software Engineer, Research and Development at Borland,
   talks about the Delphi IDE.
   http://community.borland.com/article/0,1410,32719,00.html

* Borland "Diamondback" Data Services over .NET Remoting
   Details on data remoting with the BorCon preview edition of
   "Diamondback", the next version of Delphi.
   http://community.borland.com/article/0,1410,32718,00.html

* Diamondback Preview License Update
   A license update that does not require an NDA or Beta Agreement.
   http://community.borland.com/article/0,1410,32717,00.html

* BDNtv: Diamondback Preview of Data Remoting
   Demonstrates the ease of remoting data in a heterogeneous database
   environment with Diamondback. Includes setting up a local DataHub for
   SQL Server and InterBase then making it a remote server. And, creating
   a client that updates tables in both databases simply by calling one
   method of the DataHub component. Flash
   http://dotnet.borland.com/bdntv/delphi/dataremoting.html

* BDNtv: Diamondback Sneak Peek
   A sneak peek at Diamondback's new IDE features and the new Delphi
   language feature for enumeration. The multiple personality IDE,
   refactoring for both .NET and Win32, Error Insight, Help Insight, the
   History View and more are shown. The for .. in .. do (foreach)
   enumerator syntax is also revealed. Flash
   http://dotnet.borland.com/bdntv/delphi/diamondbacksneakpeek.html

* Delphi 8 and Microsoft .NET version 1.1 Service Pack 1
   Delphi 8 has trouble compiling projects after .NET 1.1 Service Pack 1
   has been installed. This article explains why and offers a workaround.
   Also affects the BorCon Diamondback preview release.
   http://community.borland.com/article/0,1410,32713,00.html

* Borland CEO Touts Software Process Management
   InfoWorld Editor-at-Large Paul Krill spoke with Dale Fuller, president
   and CEO of Borland, at the BorCon conference last week about Borland's
   tools and ALM strategies and issues such as Java vs. .Net, Web
   services, and outsourcing.
   http://www.computerworld.com.au/index.php/id;954592276;fp;16;fpid;0

* Interview: Borland Aims for Better Code
   Better collaboration tools are the only route to superior software,
   argues Borland's David Intersimone.
   http://www.computing.co.uk/analysis/1157073

* DB2 Web Service Engines on Linux with Kylix 3: Part 1 - by Bob Swart
   Demonstrates how to build a SOAP Web service engine with Kylix 3,
   exposing the data from DB2 UDB database tables to the outside world.
   www-106.ibm.com/developerworks/db2/library/techarticle/dm-0406swart/

* DB2 Web Service Engines on Linux with Kylix 3: Part 2 - by Bob Swart
   Demonstrates how to build the user interface for a SOAP Web service
   engine with Kylix 3 on Linux, exposing the data from DB2 UDB database
   tables to the outside world.
   www-106.ibm.com/developerworks/db2/library/techarticle/dm-0407swart/

* Producing Dynamic Data-Entry Forms from DB2 Tables on Linux - B. Swart
   Uses Kylix 3 and dbExpress to analyze DB2 UDB database tables, fields
   (names and types) to allow the user to select a specific table, toggle
   which fields are shown, and dynamically view the output in both a
   datagrid and individual data-aware controls.
   www-106.ibm.com/developerworks/db2/library/techarticle/dm-0407swart2/

* Use Delphi Code to Create/Drop DB2 UDB Database Tables - by Bob Swart
   Examines the design and implementation of a Delphi application you can
   use to create or delete / drop tables inside IBM DB2 databases. It
   provides several examples of sending SQL DDL to the DB2 DBMS using
   Delphi and the cross-platform dbExpress data access technologies.
   www-106.ibm.com/developerworks/db2/library/techarticle/dm-0409swart/

* Work with IBM DB2 databases and SQL in Delphi for .NET - by Bob Swart
   Using Delphi code to create/drop DB2 database tables, focuses on the
   use of SQL queries to build simple and more complex SQL SELECT queries
   to end up with master-detail relations. Also examines SQL joins in
   detail, covering examples of inner joins, left/right outer joins, and
   the differences between them.
   www-106.ibm.com/developerworks/db2/library/techarticle/dm-0409swart1/


Tutoriales y capacitación
=========================

* Free Web Seminars
   More than 10 on-demand Web seminars from Borland to help you optimize
   your software delivery.
   http://community.borland.com/article/0,1410,32698,00.html


Noticias
========

* Borland Delphi 2005 Boosts Microsoft Windows Productivity
   Borland today announced Delphi 2005, previously codenamed Diamondback.
   Delphi 2005 combines Win32, .NET, Delphi and C# support all within one
   environment, significantly advances developer and team productivity
   and integrates with Borland's leading ALM solutions.
   http://www.tmcnet.com/usubmit/2004/Oct/1081925.htm

* Software Delivery Strategy Gets Under Way at Borland
   Kicking off its Software Delivery Optimization campaign, Borland
   announced upgrades to CaliberRM requirements management and StarTeam
   configuration management software at BorCon. Also at the conference,
   the company demonstrated the next version of its Delphi IDE for
   Windows application development.
   http://sdtimes.com/news/111/story7.htm

* Borland Scheme Aims to Maximise Business Value of Software Work
   Borland aims to turn software development into a simple business
   process with its Software Delivery Optimisation programme, announced
   at the BorCon 2004 earlier this month.
   http://www.computerweekly.com/articles/article.asp?liArticleID=133397

* Borland Moving Forward with SDO
   Borland took a new direction this week, with the announcement of
   Software Delivery Optimization. SDO will see three technology concepts
   delivered around Borland's ALM tools, as the company tries to lure
   C-level executives and vice presidents of application development with
   a message that software and the business should - and can - function
   as one.
   http://www.cbronline.com/article_feature.asp?
   guid=E077757F-B5CD-415C-8CCC-F10E19F6CC11

* (Turn and Face the Strain) Software Changes
   Borland this week stood atop its soapbox preaching the evils of
   software projects gone awry, with projects beset by issues such as
   last-minute changes and differing perspectives on the potential
   success of development efforts. To stem the tide of botched projects,
   Borland pitched its Software Delivery Optimization strategy.
   http://weblog.infoworld.com/techwatch/archives/000712.html

* Borland Adds Project-Management Features To CaliberRM
   Borland announced CaliberRM 2005 this week, a product designed to help
   software project managers take some of the guesswork out of software
   development. New features include tools for estimating the cost,
   scheduling and staffing of a project before any code gets written.
   http://informationweek.com/story/showArticle.jhtml?articleID=47208433

* Business Management for Software Projects
   End users will be able to manage software projects like a business
   with Borland's Software Delivery Optimisation. It aims to enable users
   to manage software projects like a business, according to Boz Elloy,
   senior vice-president of software products.
   http://www.computerweekly.com/articles/article.asp?liArticleID=133333

* Borland challenges Visual Studio with Diamondback
   With the Diamondback release of its Delphi tool for Windows
   applications, Borland will challenge Microsoft while accommodating
   .Net, Win32 and Delphi development. Michael Swindell, Borland director
   of product management for developer tools, said with Diamondback
   Borland will compete with Microsoft's Visual Studio.
   http://www.computerweekly.com/articles/article.asp?liArticleID=133332

* Borland Touts Software Delivery Optimization
   At BorCon, Borland will reveal its software delivery optimization
   strategy, which leverages the company's ALM and developer products to
   ease software development and maintenance. The strategy ultimately
   will feature a bundle of the company's products code-named Themis, due
   out in the first half of 2005, which purports to provide a platform
   for integrated, repeatable development processes.
   http://www.javaworld.com/javaworld/jw-09-2004/jw-0913-iw-borland.html

* Borland Outlines Vision for Transforming Software Development
   Today at BorCon 2004, Dale Fuller, President and CEO of Borland,
   presented Borland's vision and product strategy for transforming
   software development from an unpredictable art form into a more
   manageable and repeatable business process. Borland's vision for
   Software Delivery Optimization builds on the technical efficiencies of
   ALM, and incorporates the business processes and management
   capabilities companies seek to ensure business-to-IT alignment, and
   the delivery of quality software, on time, within budget, for maximum
   business value.
   http://home.businesswire.com/portal/site/google/index.jsp?
   ndmViewId=news_view&newsId=20040913005322&newsLang=en

* Borland and NEC Team on Online Communications
   Borland and NEC will partner to develop adaptor software in order to
   rapidly integrate web-based applications with voice and video. This
   will target communications over IP telephony, IP video and
   conferencing over online applications.
   http://www.cbronline.com/article_news.asp?
   guid=2FE9728E-9350-49C4-BC59-2C25C62987BE

* Borland Acquires Software Project Planning Tool
   Borland has acquired of Estimate Professional, a software project
   planning and estimation tool from Software Productivity Center. This
   newly acquired tool will be embedded within the next version of the
   Borland CaliberRM requirements management solution.
   http://www.infoworld.com/article/04/08/25/HNborlestimate_1.html

* Borland Joins ECMA to Help Shape Standards for the .NET Framework
   Borland has been elected as a member of ECMA International. As a
   member of ECMA, Borland will help shape standards for the .NET
   Framework and the C# and C++ programming languages.
   http://home.businesswire.com/portal/site/google/index.jsp?
   ndmViewId=news_view&newsId=20040812005195&newsLang=en

* Borland Developer News - .NET Edition, August 2004
   Your source for Delphi and C# related news. Covering mostly .NET with
   some Win32 development.
   http://community.borland.com/article/0,1410,32491,00.html

________________________________________________________________________

Irongut's Delphi Pages
Dedicada a la programación con Borland Delphi y Kylix. Tenemos artículos
sobre programación, noticias Borland y Delphi, código fuente y componen-
tes para usar en sus aplicaciones y más.  http://www.paranoia.clara.net/
________________________________________________________________________


¡Tú puedes ayudarnos!


Por favor danos una mano y ayúdanos a llegar a los 20.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@...

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://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium

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/descarga/p0051.zip
________________________________________________________________________

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@...
Para cancelar / removerse:    boletin-pascal-unsubscribe@...
Para reportar problemas con la suscripción: eds2004 @ 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
   Irongut's Delphi Pages         http://www.paranoia.clara.net/

Copyright 2004 by Ernesto De Spirito + Dave Murray. All rights reserved.
________________________________________________________________________

#17 De: "Ernesto De Spirito" <owner@...>
Fecha: Dom, 25 de Jul, 2004 11:33 pm
Asunto: Boletín Pascal #50 - 25-JUL-2004
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #50 - 25-JUL-2004

Índice

1. Unas palabras del editor
2. Obteniendo el tipo de unidad
3. Inno Setup Review
4. Cómo correr una sola instancia de una aplicación (Parte 1)
5. Foros / listas de correo
6. Delphi en la Red
    - Componentes, librerías y aplicaciones
      · Shareware
      · Freeware
      · Actualizaciones de productos Borland
    - Artículos, trucos y consejos
    - Tutoriales y capacitación
    - Noticias
    - 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


Ha pasado casi un año desde el último número del boletín, y durante este
tiempo ambos hemos estado muy ocupados con el trabajo, la familia y
otros proyectos. Muchas veces hablamos de volver a publicar el boletín,
pero nunca lo logramos. Después de algunos mensajes de apoyo de los
suscriptores del boletín (y algo de trabajo de Dave), finalmente
estamos de regreso. El el plan es publicar una edición cada dos meses
desde ahora, provisto que consigamos las contribuciones, premios y
tiempo. :) Hablando de tiempo, la verdad que el mío es en extremo
limitado, así que aprovecho este espacio para pedir voluntarios para
traducir el boletín del inglés al español.

Como siempre, nos gustaría agradecer a los autores que contribuyeron
artículos para esta edición, Lennie De Villiers y Peter Johnson, y nos
complace entregarles los premios para esta edición a:

* Lennie De Villiers - 'Obteniendo el tipo de unidad'
   Storage Library v3.29 - por DeepSoftware.Ru ($39)
   Storage Library es una elegante solución para el manejo de la
   configuración de las aplicaciones. Soporta trabajar con archivos INI,
   Registro de Windows, archivos XML, objetos TStream. Provee encripción,
   soporte Unicode, trabajar con propiedades públicas sin programar,
   almacenar la posición de los formularios, y mucho más...
   http://www.deepsoftware.ru/rsllib/index.html

* Peter Johnson - 'Cómo correr una sola instancia de una aplicación
   (Parte 1)'
   SMExport v4.50 - por Scalabium Software ($50)
   Conjunto de componentes para fácil exportación a diferentes formatos
   de archivo: CSV/Text, MS Excel, MS Access, MS Word, HTML,
   XML, SPSS, PDF, RTF, SQL etc. Disponible para Delphi 3-7 y BCB 3-6.
   http://www.scalabium.com   (mshkolnik@...)

Esperamos contar con dos premios para los autores que contribuyan
material en inglés para el próximo número, pero no sabemos cuáles serán,
así que envíennos sus artículos y tal vez se ganen una bonita sorpresa.

Bien, eso es todo. Esperamos que disfruten esta edición.

Saludos,

Dave Murray y Ernesto De Spirito
boletin-pascal-owner@...

__________________

Colaboraron en esta edición: Lennie De Villiers, Peter Johnson

________________________________________________________________________

Help & Manual 3.50 por EC Software · Shareware ($ 279) - Una herramienta
visual de  autoría de ayuda para generar archivos WinHelp (.HLP),  Adobe
PDF,  páginas HTML y los  nuevos archivos HTML HELP  (.CHM) introducidos
en Windows  98,  así como  otros formatos  de  archivo  y  documentación
impresa,  todo desde una  misma fuente.  Una herramienta  imprescindible
para cualquier desarrollador de software.  http://www.helpandmanual.com/
________________________________________________________________________


2. Obteniendo el tipo de unidad

    Por Lennie De Villiers <Lennie at openmindconnections dot com>
        http://www.openmindconnections.com/


A veces puede querer determinar si una unidad de disco es removible,
fija, CD-ROM, disco RAM, o unidad de red. Para lograr este puede usar
la función API de Windows GetDriveType.

GETDRIVETYPE
============

Declaración:
GetDriveType(lpRootPathName : PChar);

Parámetros
    lpRootPathName

Puntero a una cadena terminada en nulo que especifica el directorio raíz
del disco del que se retornará información. Se requiere la barra
invertida al final. Si pRootPathName es NULL, la función usa la raíz del
directorio actual.

Valor de retorno
El valor de retorno especifica el tipo de unidad. Puede ser uno de los
siguientes valores:

· DRIVE_REMOVABLE
   El disco puede removerse de la unidad.

· DRIVE_FIXED
   El disco no puede removerse de la unidad.

· DRIVE_REMOTE
   La unidad es una unidad remota (de red).

· DRIVE_CDROM
   La unidad es una unidad de CD-ROM.

· DRIVE_RAMDISK
   La unidad es un disco RAM.

La función devolverá DRIVE_UNKNOWN si no se puede determinar el tipo de
unidad, o DRIVE_NO_ROOT_DIR si el camino de la raíz no es válido.

Por ejemplo:
-----------

   case GetDriveType(PChar(DriveEdit.Text + ':\')) of
    DRIVE_REMOVABLE:
      ReportLabel.Caption := 'El disco puede removerse de la unidad';
    DRIVE_FIXED:
      ReportLabel.Caption := 'El disco no puede removerse de la unidad.';
    DRIVE_REMOTE:
      ReportLabel.Caption := 'La unidad es una unidad remota (de red).';
    DRIVE_CDROM:
      ReportLabel.Caption := 'La unidad es una unidad de CD-ROM.';
    DRIVE_RAMDISK:
      ReportLabel.Caption := 'La unidad es un disco RAM.';
   else
     MessageDlg('Error: No puede determinarse el tipo de unidad el ' +
                'camino de la raíz no es válido.', mtError, [mbOk], 0);
   end;

Este ejemplo obtiene una letra de unidad de un cuadro de texto llamado
DriveEdit y lo pasa a la función GetDriveType. El código automática le
agregará los dos puntos y la barra invertida al final ( :\ ). La
sentencia CASE reportará el valor devuelto por la función GetDriveType
a una etiqueta llamada ReportLabel.

Si GetDriveType no devuelve uno de esos valores listados, o sea, si
devuelve DRIVE_UNKNOWN o DRIVE_NO_ROOT_DIR, se mostrará un mensaje de
error.

Para una referencia más completa de la función API GetDriveType WinAPI
vaya a http://msdn.microsoft.com/library/psdk/winbase/filesio_2m3p.htm

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


3. Inno Setup Review

    Por Dave Murray <irongut at vodafone dot net>
        http://www.paranoia.clara.net/


Inno Setup por Jordan Russell es un instalador gratuito para programas
Windows. Primero introducido en 1997, Inno Setup está a la altura y
hasta sobrepasa muchos instaladores comerciales en características y
estabilidad. Lo he estado usando por un par de años, así que deseaba ver
qué nuevas características había en la última versión (4.2.7
2004-06-27).

Inno Setup es un instalador basado en scripts para toda las versiones
de Windows de 32 bits. Es muy flexible y configurable, y produce
instaladores de único y compacto EXE. Hay extensiones de terceros
disponibles y soporta scripts en Pascal para mayor configuración. Sus
características clave incluyen:

   * Soporte para todas las versiones de Windows de 32 bits
   * Instalador de EXE único o múltiples discos
   * Interfaz con asistentes estándar, incluyendo el último estilo
     Windows 2000/XP
   * Tipos de instalación configurables, ej. Completa, Mínima, Avanzada
   * Capacidades completas de desinstalación
   * Compresión Zip, bzip2 y LZMA (7-Zip)
   * Comparación de información de versión, reemplazo de archivos en
     uso y conteo de archivos compartidos
   * Registro de librerías DLL, OCX y de tipos
   * Instalación de fuentes
   * Creación de atajos en cualquier lugar; incluyendo el Escritorio y
     el Inicio Rápido
   * Creación de entradas en el Registro y archivos .INI
   * Creación de instaladores multilenguaje
   * Instalación y desinstalación silenciosa
   * Ejecución de otros programas o scripts Pascal durante la
     instalación
   * Soporte de automatización COM
   * Extensiones de terceros
   * Código fuente completo disponibles (Delphi 2-5)
   * Gratuito, incluso al distribuir aplicaciones comerciales


Trabajando con Inno Setup
-------------------------

Al ejecutar Inno Setup aparece un diálogo ofreciendo crear un script en
blanco, crear un nuevo script empleando un asistente o abrir un script
existente. Hay varios ejemplos que ayudan a explicar cómo crear scripts
o realizar ciertas tareas durante la instalación. Le recomiendo usar el
asistente para crear el esquema inicial de su script.

Los asistentes preguntarán por toda la información habitual como el
nombre de la aplicación y versión, nombre de la empresa y sitio web,
directorio de la instalación, nombres de archivos y accesos directos.
También tiene algunas características más avanzadas como crear un
acceso directo de Internet para su sitio web y mostrar archivos antes
y/o después de la instalación.

Los scripts de Inno Setup se parecen mucho a ficheros INI. Cada sección
de un script controla un aspecto diferente de la instalación. Por
ejemplo la sección [Setup] contiene configuraciones globales usadas por
el instalador y el desinstalador, y la sección [Tasks] define tareas
definibles por el usuario a realizarse durante la instalación. Los
elementos dentro de las secciones pueden tomar uno o más parámetros.
Por ejemplo el elemento AppPublisherURL en la sección [Setup] toma la
dirección de su sitio web. La mayoría de los elementos pueden tener
constantes incrustadas en ellos que son traducidas a sus respectivos
valores literales dependiendo de las elecciones del usuario y la
configuración del sistema: por ejemplo {sys} se refiere al directorio
de Sistema de Windows. Hay numerosas secciones y elementos, pero no se
preocupe, la documentación es excelente.

Después que haya terminado de escribir su script, el siguiente paso es
compilarlo en un instalador completo, listo para correr. De modo prede-
terminado, se crea en un subdirectorio llamado Output dentro del
directorio conteniendo el script. También hay un compilador en línea
que puede usarse como parte de un proceso automatizado de construcción.

El paso final es probar su instalador. El instalador y desinstalador
acepta parámetros en línea de órdenes que pueden ser útiles para los
administradores de sistema y para otros programas que los llamen. Los
parámetros incluyen /SILENT, /LANG y /DIR. Ambos programas devuelven un
código de retorno que puede ser usado para determinar si la instalación
o desinstalación falló y por qué.


Nuevo en la Versión 4.0
-----------------------

La Versión 4 agregó soporte de scripts en tiempo de ejecución a Inno
Setup. El motor de scripting es RemObjects Pascal Script por Carlo Kok.
Este moderno lenguaje de scripting símil Delphi permite una sofisticada
configuración de su instalador. Las posibilidades incluyen: agregar
páginas de asistente propias en tiempo de ejecución, remoción de tipos,
componentes y/o tareas bajo ciertas condiciones definibles, instalación
de elementos basada en condiciones definibles. Se incluye un depurador
integrado de tiempo de ejecución.

También se ha agregado soporte multilenguaje y se pueden especificar
versiones regionalizadas de todos los varios archivos de información. La
sección [Languages] define los lenguajes disponibles al instalador y se
puede mostrar un diálogo Select Language (elegir lenguaje). La sección
[LangOptions] opcional se puede usar para definir configuraciones espe-
cíficas al lenguaje, como fuentes.

Se agregaron muchas otras características y mejoras a la versión 4.
Algunas de las más útiles incluyen archivos no seguros (DLLs), instala-
ción / desinstalación silenciosa, mejoras al IDE, y la división en
múltiples discos ahora soporta CDs y DVDs.


Últimas Características
-----------------------

(v4.1.3 2004-01-28)

Desde que originalmente escribí este artículo aparecieron varias
versiones menores con muchas mejoras. El instalador pasó por un cambio
de cara con palabrerío simplificado, escalamiento de fuentes e imágenes
mejorado, y soporte multimonitor mejorado. Ahora contiene información
de versión configurable y usted pues especificar su icono.

El soporte de automatización COM provee la capacidad de controlar
otras aplicaciones aplicaciones y llamar DLLs ActiveX durante la
instalación. Esto le permite configurar el IIS o el SQL Server, leer y
escribir XML, leer y escribir documentos Office y mucho más.

(v4.1.6 2004-02-19)

¡La gente detrás de Inno Setup debe haber estado trabajando día y noche
porque en las últimas pocas semanas lanzaron tres actualizaciones! El
cambio más significativo es la adición de compresión LZMA. LZMA es el
algoritmo usado por el archivador 7-Zip de Igor Pavlov. Típicamente
comprime al menos un 20% mejor que el método bzip existente.

El IDE del compilador se ha mejora con un nuevo comando Run | Terminate
(Ejecutar | Terminar) y una nueva opción Build | Low Priority During
Compile (Construir | Baja Prioridad Durante la Compilación). El IDE
también muestra un icono animado y una barra de progreso durante la
compilación y el código de retorno devuelto después de una ejecución de
prueba.

(4.2.7 2004-06-27)

Los últimos cuatro meses desde la última vez que actualicé este
artículo han visto muchas mejoras a Inno Setup. El soporte multilenguaje
ha sido enormemente mejorado. El asistente de script ahora usa
constantes de mensaje definibles de modo que ahora no tiene que traducir
frases en inglés en los scripts generados. Una nueva sección
[CustomMessages] le permite fácilmente regionalizar sus propias entradas
de descripciones y mensajes. De modo predeterminado, los lenguajes cuya
página de códigos no concuerda con la del sistema del usuario no
aparecerán en el diálogo Select Language. Además, se han agregado
traducciones oficiales en catalán, checo, holandés, francés, alemán,
noruego, polaco, portugués, ruso y esloveno.

Inno Setup ahora incluye encripción 128-bit ARCFOUR opcional. La
contraseña de desencripción puede ser provista desde la línea de órdenes
para instalaciones silenciosas. Asimismo, con la señal noencryption los
archivos individuales pueden tener la encripción apagada si fuera
necesario.

Ahora se soportan las mejoras introducidas a la applet Agregar/Quitar
Programas del Panel de Control de Windows 2000. Puede mostrar un botón
"Modificar" y un diálogo "Soporte" con comentarios, información de
contacto y un enlace a su archivo léame.

La compresión predeterminado ahora es LZMA en vez de Zip, y una nueva
pasada de optimización coprime los archivos ejecutables aún más. El
nuevo parámetro /LOG de la línea de órdenes crea un archivo de registro
en el directorio TEMP del usuario detallando el proceso de instalación
para depuración. El motor de scripting en tiempo de ejecución se basa
ahora en RemObjects Pascal Script SVN code revision 916. Han habido un
montón de otros cambios incluyendo mejoras a las páginas del asistente
y a los diálogos, y corrección de errores.


Extensiones de Terceros
-----------------------

Una de las fortalezas de Inno Setup's es la saludable comunidad de
extensiones de terceros. Éstas incluyen herramientas como iwz2iss que
convierte proyectos InstallShield en scripts Inno Setup e InnoScript
que hace lo mismo para proyectos VB.

La extensión más útil es probablemente ISTool por Bjørnar Henden, un
front-end GUI para crear y editar scripts Inno Setup. Le proporciona
fácil acceso a todas las secciones del script con diálogos a medida para
editar los elementos. Estos diálogos contienen campos para todos los
posibles parámetros con casillas de verificación para cualquier posible
señal. ISTool tiene soporte arrastrar y soltar completo, usted puede
arrastrar archivos desde el Explorador y soltarlos en un directorio en
la sección [Files]. También puede importar proyectos VB e InstallShield
y simplifica el proceso de crear versiones regionalizadas.

Recientemente, varias extensiones de terceros, incluyendo ISTool, han
sido reempaquetados como el Inno Setup QuickStart Pack. No son oficiales
o requeridas, pero a Inno Setup más fácil de usar, especialmente para
nuevos usuarios.


Soporte
-------

El soporte se provee primariamente a través de los grupos de noticias en
news.jrsoftware.org. Hay tres grupos de noticias disponibles: para
cuestiones generales de Inno Setup, para scripts Pascal de tiempo de
ejecución y para extensiones de terceros. Estos grupos de noticias están
disponibles sólo a través de su servidor de noticias o de su interfaz
web.

Hay también disponible una lista de corre para notificarlo de nuevos
lanzamientos importantes. Los anuncios de parches pequeños generalmente
no se envían a la lista de correo sino que se anuncian en el grupo de
noticias general.


Conclusión
----------

Inno Setup es una gran herramienta para empaquetar sus aplicaciones.
Los scripts son fáciles de escribir y la documentación está bien
escrita y es exhaustiva. El asistente inicial es verdaderamente muy
útil y lo uso para todos mis scripts. Inno Setup es configurable y
extensible, y puede usarse como parte de un proceso de construcción
automatizado. Al combinarlo con algunas extensiones de terceros, es
un producto difícil de superar, ¡y además el precio es muy bueno!


Referencias
-----------

· Inno Setup
   http://www.jrsoftware.org/isinfo.php

· Grupos de noticias Inno Setup
   news://news.jrsoftware.org/jrsoftware.innosetup
   news://news.jrsoftware.org/jrsoftware.innosetup.code
   news://news.jrsoftware.org/jrsoftware.innosetup.thirdparty
   http://news.jrsoftware.org/read/

· ISTool
   http://www.istool.org/

· iwz2iss
   http://strony.wp.pl/wp/mikequ/eng/iwz2iss.htm

· InnoScript
   http://www.randem.com/innoscript/innoscript.htm

· RemObjects Pascal Script
   http://www.remobjects.com/

________________________________________________________________________

¡Vota por el Boletín Pascal (Pascal Newsletter) en The Borland Top 100!
http://top100borland.com/in.php?who=20
________________________________________________________________________


4. Cómo correr una sola instancia de una aplicación
    Parte 1: Un acercamiento inicial

    Por Peter Johnson, Copyright (c) 2003
        <delphidabbler at tiscali dot co dot uk>
        http://www.delphidabbler.com/


Resumen
-------

Este artículo discute cómo asegurar que sólo una única instancia de una
aplicación pueda ejecutarse. Una aplicación esto chequeando si ya hay
una instancia corriendo, y terminando en caso afirmativo. También
veremos cómo una instancia duplicada puede pasarle sus parámetros de
línea de órdenes a la instancia en ejecución antes de terminar.


Introducción
------------

El método de evitar múltiples instancias de una aplicación usado aquí
está basado en la detección de la existencia de una aplicación con una
clase de ventana principal determinada, y el paso de la línea de órdenes
se hace mediante mensajes WM_COPYDATA (tal como lo usa mi programa
Version Information Spy en http://www.delphidabbler.com/vis). Hay otros
métodos para lograr los mismos fines -- siendo uno muy común el uso de
Mutexes y el paso de datos a través de un archivo mapeado en memoria.
Este método no se tratará aquí, pero hay otros artículos en la red que
le muestran cómo hacerlo.

Un bosquejo de la metodología es:

   buscar la ventana de nivel superior de la clase correcta
   si tal ventana existe
     activar la ventana
     pasar los datos de línea de órdenes a la ventana vía WM_COPYDATA
     terminar esta instancia de la aplicación
   de lo contrario
     iniciar esta aplicación normalmente
     procesar los parámetros de la línea de órdenes
   fin

Ahora examinaremos el proceso en detalle.


Determinando si su programa está corriendo
------------------------------------------

Usamos la API de Windows FindWindow para buscar una ventana de nivel más
alto de la clase requerida. Esta rutina puede buscar por el título de la
ventana (no confiable porque pueden cambiar mientras un programa está
corriendo), la clase de la ventana (mejor) o ambos. Optamos por chequear
el nombre de clase de la ventana, sin importar el título. No obstante
hay un problema con este enfoque -- en Delphi el nombre de clase del
formulario principal se usa de manera predeterminada como el nombre de
clase de la ventana de nivel superior. Es decir, si la clase del
formulario es TForm1, el nombre de clase del formulario también es
TForm1. Dado que es posible tener más de una aplicación Delphi corriendo
que use este nombre de clase de ventana, necesitamos darle a la ventana
principal de nuestro programa un nombre de clase que sea (muy) poco
probable que sea usado por otra aplicación. Hacemos esto reescribiendo
(overriding) el método CreateParams del formulario principal como sigue:

   procedure TForm1.CreateParams(var Params: TCreateParams);
   begin
     inherited;
     StrCopy(Params.WinClassName, cWindowClassName);
   end;

Aquí, cWindowClassName es una constante establecida a algún nombre de
clase apropiado. Para asegurarnos su unicidad podemos usar un GUID como
D9CE4126-B845-42B2-ABAE-3678FF6EC836. Sin embargo, encuentro que un
nombre basado en el nombre de la empresa, el nombre de la aplicación y
posiblemente el número principal de versión es suficientemente poco
probable que sea usado por otras aplicaciones. Un ejemplo sería
DelphiDabbler.MyApp.2.

Ahora que tenemos un nombre de clase de ventana apropiado podemos
encontrar el handle de la ventana principal de cualquier instancia
existente de nuestra aplicación usando la siguiente función:

  function DuplicateAppInstWdw: HWND;
  begin
   Result := FindWindow(cWindowClassName, nil);
  end;

La función devolverá el handle de cualquier ventana de alto nivel con el
nombre de clase dado por la constante cWindowClassName. Devolverá 0 si
no hay tal ventana, así que si la función devuelve 0, no tenemos
instancia existente y podemos correr nuestra aplicación, pero si la
función devuelve un valor distinto de cero, una instancia existente está
corriendo y debemos terminar la instancia actual.

Debemos ser muy cuidadosos respecto de dónde realizamos esta compro-
bación -- si corremos esta comprobación después de haber creado la
ventana principal de nuestra aplicación, la función siempre retornará
un manejador de ventana, y éste puede ser el manejador de nuestra propia
ventana! Por consiguiente, es importante realizar esta comprobación
antes de que la aplicación cree su formulario principal. Podemos
hacerlo realizando la comprobación en el el archivo de proyecto (.dpr),
antes de que se cree el formulario principal. El archivo de proyecto
puede ser modificado como sigue:

   function CanStart: Boolean;
   var
     Wdw: HWND;
   begin
     Wdw := DuplicateAppInstWdw;
     if Wdw = 0 then
       // no hay instancia en ejecución:
       // podemos iniciar nuestra aplicación
       Result := True
     else
       // Instancia en ejecución: Intentar pasarle la línea de órdenes
       // y terminar la instancia si tiene éxito
       // (rutina explicada después)
       Result := not SwitchToPrevInst(Wdw);
   end;

   begin
     if CanStart then
     begin
       Application.Initialize;
       Application.CreateForm(TForm1, Form1);
       Application.Run;
     end;
   end.

Nótese que la aplicación sólo se inicia si la función CanStart devuelve
verdadero, de lo contrario termina instantáneamente. CanStart devuelve
verdadero si no hay otra instancia de la aplicación (es decir, si no se
encuentra una ventana de nivel superior con el nombre de clase de
ventana). Si se encuentra una instancia previa, intentamos cambiar a
ella usando la función SwitchToPrevInst. La implementación de esta
función se explica después en este artículo. Por ahora será suficiente
con saber que la función activa la ventana principal de la instancia
previa de la aplicación e intenta pasarle cualesquiera parámetros de
línea de órdenes. La función devuelve verdadero si tiene éxito, y falso
si falla. Notar que vamos adelante e iniciamos esta instancia de la
aplicación si el intento de pasar la línea de órdenes a la instancia
previa no tiene éxito. Esta es una forma a prueba de fallos de asegurar
que la línea de órdenes se procesa.

Esto cierra la parte de cómo iniciar una sola instancia de la apli-
cación. Ahora necesitamos descubrir cómo pasar cualquier dato de línea
de órdenes a la instancia previa.


Pasando la línea de órdenes a la instancia previa
-------------------------------------------------

Cuando el programa detecta que otra instancia está ejecutándose, debe
pasar su línea de órdenes al programa en ejecución. Hacemos esto en la
rutina SendParamsToPrevInstance. Esta rutina envía los parámetros a la
ventana principal de la instancia existente de la aplicación mediante
el uso del mensaje WM_COPYDATA.


Pasando datos a otra aplicación con WM_COPYDATA
-----------------------------------------------

Este mensaje es provisto por Windows para el propósito de pasar datos a
través de límites de procesos -- es decir, para enviar datos a otras
aplicaciones. Dato que el mensaje envía datos entre espacios de direc-
ciones, debemos ser cuidadosos de adherir a las reglas que gobiernan
esta cuestión. Las reglas son:

* No podemos pasar punteros, sólo los datos reales
* La aplicación que envía debe asignar y liberar la memoria requerida
   por los datos
* La aplicación receptora no debe liberar los datos
* La aplicación receptora debe copiar los datos a almacenamiento local
   si debe accederlos después que el manejador de mensajes regresa
* Debemos usar SendMessage y no PostMessage para enviar el mensaje

El mensaje WM_COPYDATA usa una estructura del tipo TCopyDataStruct para
almacenar y describir los datos a enviar. Esta estructura tiene tres
campos:

* dwData: DWORD -- almacena un valor de 32 bits definido por el usuario
* lpData: Pointer -- apunta a un bloque de datos definido por el usuario
                      (usado si se enviará un valor de más de 32 bits)
* cbData: DWORD -- tamaño del bloque de datos definido por el usuario


Función SendParamsToPrevInstance
--------------------------------

Como se mencionó arriba, la función SendParamsToPrevInstance se usa
cuando tenemos que pasar parámetros de línea de órdenes a la instancia
previa de la aplicación. La función devuelve verdadero si la aplicación
receptora procesa el mensaje WM_COPYDATA apropiadamente, y falso si el
mensaje no es manejado o si la aplicación receptora reporta un error.
He aquí la implementación:

function SendParamsToPrevInstance(WndH: HWND): Boolean;
var
   CopyData: TCopyDataStruct; // estructura de datos WM_COPYDATA
   I: Integer;                // variable de control de ciclo
   DataSize: Integer;         // tamaño requerido por los parámetros
   Data: PChar;               // puntero a la memoria de los parámetros
   PData: PChar;              // puntero al siguiente parámetro
begin
   // Establece el paquete de datos a enviarse a la otra instancia.
   // Contiene COPIA de los parámetros: no pueden enviarse punteros con
   // WM_COPYDATA. Guardaremos cada cadena parámetro en un buffer,
   // separados por #0 y terminados por un segundo #0.
   // Ejemplo: Primero#0Segundo#0Tercero#0#0

   // Primero calcular el tamaño de los parámetros
   DataSize := 0;
   for I := 1 to ParamCount do
     Inc(DataSize, Length(ParamStr(I)) + 1);
   Inc(DataSize);  // for final #0
    // Ahora asignar memoria y copiar los parámetros en ella
   Data := StrAlloc(DataSize);
   try
     PData := Data;
     for I := 1 to ParamCount do
     begin
       // Copiar la cadena de parámetro, terminada en nulo
       StrPCopy(PData, ParamStr(I));
       Inc(PData, Length(ParamStr(I)) + 1);
     end;
     // Cierre final con #0
     PData^ := #0;
     // Establecer la estructura de copia de datos:
     // Marca de agua opcional: permite una comprobación simple de la
     // la validez del paquete en la aplicación receptora
     CopyData.lpData := Data;                // datos a ser copiados
     CopyData.cbData := DataSize;            // tamaño de los datos
     CopyData.dwData := cCopyDataWaterMark;  // marca de agua en
                                             // campo de datos

     // Enviar el mensaje de copia de datos
     // Establecer el resultado de acuerdo al resultado devuelto por
     // la otra instancia
     Result := SendMessage(WndH, WM_COPYDATA, 0, LPARAM(@CopyData)) = 1;

   finally
     // Ahora liberar la memoria usada por el paquete de datos
     StrDispose(Data);
   end;
end;

La función primero junta los parámetros de línea de órdenes en una sola
estructura de datos. Esta estructura de datos es una secuencia de
parámetros de programa separados por #0, y terminada por otro caracter
#0 (esta sintaxis es comúnmente usada en Windows para almacenar una
lista de valores de cadena). Por ejemplo, los tres parámetros 'Uno',
'Dos' y 'Tres' se almacenaría como 'Uno'#0'Dos'#0'Tres'#0#0.

Habiendo asignado la memoria requerida y almacenados los datos en ella,
establecemos TCopyDataStruct.lpData para que la apunte, y registramos
el tamaño de la estructura de datos en TCopyDataStruct.cbData.

Usamos el campo TCopyDataStruct.dwData para almacenar un valor de marca
de agua de 32 bits para validar el mensaje WM_COPYDATA. El uso de esta
marca de agua provee una comprobación de los datos y le indica a la
aplicación receptora que el mensaje y sus datos han sido enviados desde
nuestra propia aplicación. La marca de agua puede ser cualquier valor
de 32 bits -- nosotros usamos el valor almacenado en la constante
cCopyDataWaterMark.

Después de usa SendMessage para enviar el mensaje a la ventana principal
de al aplicación existente. La dirección de la estructura TCopyData se
pasa en el campo LParam del mensaje. Establecemos el resultado de la
función a verdadero si el mensaje devuelve 1, y falso en caso contrario.

Finalmente, liberamos la memoria usada por para almacenar los parámetros
de la línea de órdenes.

La aplicación receptora necesitará saber cómo extraer los datos del
mensaje WM_COPYDATA, y discutiremos esto a continuación.


Manejando WM_COPYDATA
---------------------

Asó como saber cómo enviar datos a otras instancias de sí misma, una
aplicación también necesita saber cómo manejar el mensaje WM_COPYDATA
para recibir tales datos. Hacemos esto en el formulario principal del
programa escribiendo un manejador estándar de mensajes de Delphi, que
se declara en la declaración de la clase del formulario como sigue:


   procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;


Esta es la implementación:


procedure TForm1.WMCopyData(var Msg: TWMCopyData);
var
   PData: PChar;  // camina por los datos
   Param: string; // un parámetro
begin
   // comprueba si la marca de agua es válida
   if Msg.CopyDataStruct.dwData <> cCopyDataWaterMark then
     raise Exception.Create('Datos inválidos en WM_COPYDATA');
   // extrae las cadenas de los datos
   PData := Msg.CopyDataStruct.lpData;
   while PData^ <> #0 do
   begin
     Param := StrPas(PData);
     // procesa el parámetro:
     // (escribir el método para realizar el procesamiento requerido)
     ProcessParam(Param);
     Inc(PData, Length(Param) + 1);
   end;
   // establecer el valor de retorno indicando que manejamos el mensaje
   Msg.Result := 1;
end;


El manejador de mensaje procesa los datos referenciados por la
estructura de datos TCopyDataStruct. El mensaje WM_COPYDATA tiene un
puntero al registro en su campo LParam. En vez de acceder al valor
LParam directamente y convertir el tipo, usamos el mensaje provisto
por Delphi TWMCopyData para "crackear" el registro de mensaje -- su
es campo CopyDataStruct provee fácil acceso a los datos de la
estructura.

Primero comprobamos la marca de agua almacenada en
TCopyDataStruct.dwData, generando una excepción si no es válida.
Luego obtenemos un puntero a la lista de parámetros delimitados por
#0, y caminamos por el buffer, haciendo una copia de cada parámetro
antes de pasarlo al método ProcessParam method (un lugar reservado
para cualquier procesamiento que tenga que aplicarse a cada parámetro
en turno). El bucle se detiene cuando se encuentra el caracter
terminador #0. Antes de volver, establecemos el resultado del
mensaje en 1 para indicar que el mensaje ha sido manejado.


Activando la instancia previa
-----------------------------

Cuando la instancia previa de una aplicación se activa por una nueva
instancia, su ventana puede visualizarse normalmente, maximizada,
minimizada o invisible. Puede estar parcial o totalmente oculta por
otras ventanas. Si está minimizada, invisible o total o parcialmente
oculta, no habrá retroalimentación visual para el usuario de que la
instancia previa ha sido usada en lugar de la aplicación que inició.
Hay varias diferencies decisiones de diseño que podrían tomarse respecto
de cómo manejar estas situaciones. Optaremos por asegurar que la ventana
se hace prominente cuando es activada. Si la ventana se muestra normal-
mente o está maximizada, simplemente la ponemos al frente el orden Z.
Si, por el contrario, la ventana está minimizada, la restauramos y si
está oculta la mostramos.

Cuando una aplicación se inicia y encuentra que hay una instancia
previa, a la ventana principal de la instancia previa se le envía un
mensaje propio diciéndole que se "despierte". Este mensaje se define
como

   const
     UM_ENSURERESTORED = WM_USER + 1;

Enviamos este mensaje en la rutina SwitchToPrevInst mencionada arriba.
La implementación de la rutina se mostrará después en este artículo.

La aplicación receptora deberá manejar y actuar sobre este mensaje.
Hacemos esto en el formulario principal de la aplicación, otra vez
usando un manejador de mensaje de Delphi, declarado en la clase del
formulario como:

   procedure UMEnsureRestored(var Msg: TMessage);
     message UM_ENSURERESTORED;

La implementación del manejador de mensaje es:

   procedure TForm1.UMEnsureRestored(var Msg: TMessage);
   begin
     if IsIconic(Application.Handle) then
       Application.Restore;
     if not Visible then
       Visible := True;
     Application.BringToFront;
   end;

En este manejador de mensaje verificamos si la aplicación está mini-
mizada (comprobado el estado de la ventana especial Application) y la
restauramos si es así. Luego mostramos el formulario principal si
actualmente está oculto. Finalmente traemos el formulario principal
al frente del orden Z.


Toques finales
--------------

Sólo nos resta implementar finalmente la función SwitchToPrevInst a la
que nos refiriéramos antes en este artículo. La función tiene dos
propósitos principales:

1. Asegurar que cualquier parámetro de línea de órdenes se envíe a la
    instancia previa
2. Activar la instancia previa, asegurando que su ventana principal se
    muestra

La función toma el handle de la ventana principal de la instancia previa
de la aplicación como parámetro (el que no debe ser cero). Recuerde que
debemos devolver verdadero si los parámetros son exitosamente pasados a
la instancia previa, y falso en caso de error. La implementación de
SwitchToPrevInst es como sigue:

   function SwitchToPrevInst(Wnd: HWND): Boolean;
   begin
     Assert(Wnd <> 0);
     if ParamCount > 0 then
       Result := SendParamsToPrevInstance(Wnd)
     else
       Result := True;
     if Result then
       SendMessage(Wnd, UM_ENSURERESTORED, 0, 0);
   end;

Si tenemos parámetros de línea de órdenes, intentamos enviarlos a la
instancia previa usando la rutina SendParamsToPrevInstance, devolviendo
verdadero o falso según se tuvo éxito o no. Si no hay parámetros,
nuestra función no tiene datos que enviar a la instancia previa y
devuelve verdadero. Sólo si la función tiene éxito enviamos un mensaje
UM_ENSURERESTORED a la instancia previa para hacer que muestre su
ventana principal en el frente.


Juntando todas las piezas
-------------------------

El código fuente adjunto contiene el esqueleto de un proyecto Delphi que
implementa todo el código tratado en este artículo. El proyecto contiene
tres módulos que pueden usarse como moldes para una aplicación real:

* Un archivo de proyecto incorporando las modificaciones requeridas al
   código generado por Delphi.
* Una unidad conteniendo las varias funciones usadas para manejar y
   activar la instancia única de la aplicación.
* Una unidad de formulario esqueleto conteniendo los varios manejadores
   de mensaje y otro código necesario del formulario. El formulario en
   sí no contienen componentes.


Una solución reutilizable
-------------------------

La solución al problema de arriba funciona y provee un molde para usar
en cualquier aplicación. Sin embargo el código fuente debe ser adaptado
para cada  aplicación. Podemos encontrar una solución reutilizable --
algo oriendado a objetos. Bueno, ¡en parte! En la próxima edición, la
segunda parte de este artículo le mostrará una solución orientada a
objetos que, aunque requiere alguna modificación al formulario principal
y al archivo de proyecto, al menos mueve la mayor parte del código a una
clase extensible.

__________________

Peter Johnson es un programador hobbyista que vive en West Wales (Reino
Unido) y que "chapotea" en Delphi. Mantiene el sitio web DelphiDabbler
(http://www.delphidabbler.com/) donde publica sus artículos y sus
aplicaciones y componentes Delphi gratuitos. Una versión completa de
este artículo se encuentra disponible en:
http://www.delphidabbler.com/articles.php?article=13

________________________________________________________________________

Delphi BUGS?
Catch & Log every BUG showing Unit, Class, Method, Line #.
Now with support for IntraWeb applications and Anti-Freeze feature.
http://www.eurekalog.com/bannerclick.php?id=15
________________________________________________________________________


5. Foros / listas de correo


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-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@...

* 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

________________________________________________________________________

¡Vota por el Boletín Pascal (Pascal Newsletter) en The Delphi Top 200!
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________


6. Delphi en la Red

    Por Dave Murray <irongut at vodafone dot net>


Componentes, librerías y aplicaciones
=====================================


Shareware / Comercial
---------------------

* SMExport Suite v4.50 - by Scalabium Software ($50)
   SMExport suite is a component set for easy data exporting into
   different file formats: CSV/Text, MS Excel, MS Access, MS Word, HTML,
   XML, SPSS, PDF, RTF, SQL etc. Available for Delphi 3-7 and BCB 3-6.
   http://www.scalabium.com   (mshkolnik@...)

* Storage Library v3.29 - by Deepsoftware.Ru ($39)
   Storage library - elegant way for application settings management.
   Supports working with ini files, registry, xml files, TStream objects.
   Provides encryption, unicode support, working with published
   properties without programming, saving form position and much more...
   http://www.deepsoftware.ru/rsllib/index.html

* COM Genie v1.00 - by WS&V (£10)
   A Component Object Model navigator designed to enable you to navigate
   the interfaces of a COM object in a hierarchal manner. Functions that
   return functional interface pointers can be expanded to reveal the
   contents of the relevant interface, and its functional interfaces.
   The free demo is restricted to the first 80 interfaces.
   http://web.ukonline.co.uk/alison.burgess2/


Freeware
--------

* Borland Research Project: BabelCode
   BabelCode is a C# to Delphi for .NET code conversion utility. It is
   implemented as a web service and an ASP.NET client.
   http://dotnet.borland.com/babelcode/

* CrossKylix v2.65.11 - by Simon Kissel (with source)
   Integrates the Kylix compiler into the Delphi IDE allowing compilation
   of native Linux apps. Console projects, packages and visual CLX apps
   are fully supported with compile warnings, hints and error messages.
   http://crosskylix.untergrund.net/

* Inno Setup v4.2.7 - by JR Software (with source)
   A free installer for Windows that rivals commercial installers in
   features and stability. See review in this issue for details.
   http://www.jrsoftware.org/isinfo.php

* TurboPower XML Partner v2.60 - by TurboPower (with source)
   Add the power of XML to Borland Delphi, C++ Builder and Kylix projects
   through native, easy to use VCL and CLX components. These components
   simplify the process of creating, modifying, and parsing XML data.
   http://sourceforge.net/projects/tpxmlpartner

* Form Explorer v1.0
   Herramienta que permite editar y tener una vista previa de los
   archivos de formularios del entorno Borland Delphi en formato texto,
   de una manera simple y ágil. El propósito es que el usuario pueda
   editar y tener una vista previa de sus formularios sin necesidad de
   ingresar al entorno Borland Delphi.
   http://delphiuser.iespana.es/delphiuser/projects.html

* Constructor para Borland Delphi v1.0
   Herramienta para generar código personalizado para crear cuadros de
   mensajes, selectores de carpetas y cuadros "acerca de", de una manera
   simple y ágil. El propósito es que el usuario pueda generar un código
   personalizado de acuerdo a sus necesidades de manera visual.
   http://delphiuser.iespana.es/delphiuser/projects.html


Actualizaciones de productos Borland
------------------------------------

* Delphi 7.1 Update Has Been Fixed And Is Live
   Updated to fix the persistent field issue in the original release. The
   latest version enforces data integrity without raising an exception.
   http://community.borland.com/article/0,1410,32400,00.html

* Borland Delphi 8 Janeva Integration Plugin
   Allows Delphi applications to communicate with J2EE based applications
   using Borland Janeva. CORBA integration will come in the near future.
   http://codecentral.borland.com/codecentral/ccWeb.exe/listing?id=21772

* Delphi 8 HelpKit
   Assists developers to integrate their help files with Borland's.
   http://cc.borland.com/codecentral/ccweb.exe/listing?id=21767

* Updated Delphi 8 License
   New Delphi 8 license provides additional permissions for developers of
   VCL for .NET components. Supercedes all previous Delphi 8 licenses.
   http://community.borland.com/article/0,1410,32293,00.html

* ilink32 Version 5.66 Update for C++ Customers
   Resolves an access violation when linking together large numbers of
   object files. For C++BuilderX (including Mobile) and C++Builder 6.
   http://community.borland.com/article/0,1410,32448,00.html


Artículos, trucos y consejos
============================

* Why You Can't Pass a List to an InterBase SQL Param - by Craig Stuntz
   When writing a WHERE clause in your InterBase SQL, it would sometimes
   be convenient to write WHERE FOO IN (:SomeParam) and pass a list of
   values to SomeParam. You can't do that; here's why.
   http://community.borland.com/article/0,1410,32076,00.html

* Agile Management June 2004: The S-Curve Explained - David J. Anderson
   Provides some more insight as to what causes the S-curve effect and
   how to minimize it by paying attention to a few areas at the beginning
   and end of a project.
   http://community.borland.com/article/0,1410,32411,00.html

* .NET tip: Getting the User's Home, Temp or My Documents Directory
   -  by Charlie Calvert
   How to retrieve commonly used directories when using .NET.
   http://community.borland.com/article/0,1410,32384,00.html

* A Hint About .NET WinForms Controls ToolTips - by John Kaster
   This article explains how .NET Extender Providers can be used to
   include ToolTips for .NET WinForms controls.
   http://community.borland.com/article/0,1410,32345,00.html

* Beyond Proprietary Databases: Helen Borrie on the Future of Firebird
   "It's very satisfying to learn of yet another big corporation or
   enterprise software product that has switched to Firebird, and, as the
   word gets out, it happens more often."
   http://www.linuxinsider.com/story/34399.html

* IntraWeb And ActiveForms - by Bob Swart
   How to use IntraWeb and ActiveForms together to create some innovative
   solutions for your intranet / extranet needs.
   http://www.thedelphimagazine.com/samples/1749/1749.htm

* Manage Complexity With State Machines - by Rob Bracken
   Explains state machines and how to use them to model a wide range of
   real-world problems, making code easier to debug, maintain and modify.
   http://www.thedelphimagazine.com/samples/1738/1738.htm

* Handling SQL Mail - by Jason Sweby
   Use the email facilities built into MS SQL Server to send email from
   your applications in response to database triggers, and more.
   http://www.thedelphimagazine.com/samples/1729/1729.htm

* Fun With Threads - by Steven Soroka
   Some practical tips to make threading in your apps more efficient.
   http://www.thedelphimagazine.com/samples/1712/1712.htm

* NTFS Compression And Sparse Files - by Marcel van Brakel
   Explains what the NTFS file compression and sparse files features have
   to offer and how to make use of them in your own software.
   http://www.thedelphimagazine.com/samples/1696/1696.htm

* XML Topic Maps - by Craig Murphy
   Discusses how XML topic maps provide a mechanism to intelligently
   classify information, and how to implement topic maps in your apps.
   http://www.thedelphimagazine.com/samples/1686/1686.htm

* An Introduction To Endo-Testing Using Mock Objects - by Sascha Frick
   Problems arise when applying unit testing and test driven development
   principles to complex projects. Describes how to overcome the problems
   with endo-testing and mock objects.
   http://www.thedelphimagazine.com/samples/1677/1677.htm

* All About ECO - by Malcolm Groves
   A series of blog posts on ECO.
   http://blogs.borland.com/malcolmgroves/category/83.aspx


Tutoriales y capacitación
=========================

* BDNtv: Introduction to Together for Visual Studio .NET v2.0
   Part 1 of a 4 part tutorial, this episode gives you a quick intro to
   Together for Visual Studio .NET version 2.0. (Flash)
   http://community.borland.com/article/0,1410,32395,00.html

* BDNtv: LiveSource with Together for Visual Studio .NET v2.0
   Part 2 of a 4 part tutorial, this episode gives you an intro on using
   LiveSource with Together for Visual Studio .NET version 2.0. (Flash)
   http://community.borland.com/article/0,1410,32396,00.html

* BDNtv: Audits with Together for Visual Studio .NET v2.0
   Part 3 of a 4 part tutorial, this episode gives you a quick intro on
   using audits with Together for Visual Studio .NET version 2.0. (Flash)
   http://community.borland.com/article/0,1410,32397,00.html

* BDNtv: Patterns with Together for Visual Studio .NET v2.0
   Part 4 of a 4 part tutorial, this episode gives you an intro on using
   patterns with Together for Visual Studio .NET version 2.0. (Flash)
   http://community.borland.com/article/0,1410,32399,00.html

* Building CORBA Applications with Delphi 8 and Janeva (1) - P. Glowacki
   Shows the necessary steps to build simple CORBA server and client
   applications with Borland Janeva 6.0 and Borland Delphi 8 for .NET.
   http://community.borland.com/article/0,1410,32074,00.html

* Introduction to Delphi for .NET and the New IDE - by Xavier Pacheco
   Provides an overview of Delphi for .NET, with a focus on how to use
   Delphi to develop software for business solutions. Sample chapter from
   the book 'Delphi for .NET Developer's Guide'.
   http://www.informit.com/articles/article.asp?p=174323

* Gekko Software
   Tutorial on building automation server objects using Delphi. Assumes a
   basic knowledge of Delphi and object orientation. The more experienced
   developer will find useful hints and background information.
   http://www.gekko-software.nl/Delphi/


Noticias
========

* Borland Reports Strong Sales
   Despite a tough quarter in the industry, Borland was able to nail
   several large deals including a multimillion dollar deal with British
   Telecommunications that helped push Q3 revenues up to $76.5 million.
   www.santacruzsentinel.com/archive/2004/July/23/biz/stories/02biz.htm

* Borland Solution Selected by BT to Transform Systems Engineering
   Borland's ALM solution will underpin BT's Systems Engineering
   Programme, which was set up to develop a single design and delivery
   methodology for all future IT projects across BT Group.
   http://www.tmcnet.com/usubmit/2004/Jul/1059138.htm

* Boo Hoo Hoo for Victims of XP SP2
   Quite a few applications will break under the new security-focused
   service pack. Problems in the debugger in Borland's Delphi in RC 1
   were fixed quickly, although another tester reports that multiple
   applications under SP2 cannot access the Borland Database Engine.
   http://www.eweek.com/article2/0,1759,1624962,00.asp

* Borland Developer News - .NET Edition, July 2004
   The July 2004 installment of the Borland .NET Development Newsletter.
   Contains information, news, and links for Delphi and C#Builder .NET.
   http://community.borland.com/article/0,1410,32443,00.html

* Many Ways to Skin .NET and Java Integration
   .NET and J2EE used to be web services islands but now vendors have
   begun shipping tools that bridge the two architectures. Borland's
   Janeva has a twist on the translation theme.
   http://sdtimes.com/news/106/story7.htm

* Message from Business Objects: Potential Security Vulnerability
   Notice of a security vulnerability in Crystal Reports web API. Effects
   Crystal Reports for both C#Builder and JBuilder and requires a patch.
   http://community.borland.com/article/0,1410,32402,00.html

* Interbase / Firebird Database Name Buffer Overflow Vulnerability
   A vulnerability in Firebird and Interbase can be exploited to cause a
   DoS and potentially compromise a system due to a boundary error in the
   handling of database names that can cause a buffer overflow by passing
   a long database name when connecting.
   http://secunia.com/advisories/11756/

* Borland Developer News - .NET Edition, June 2004
   The June 2004 installment of the Borland .NET Development Newsletter.
   Contains information, news, and links for Delphi and C#Builder .NET.
   http://community.borland.com/article/0,1410,32390,00.html

* Borland Teams Up With eBay and PayPal
   eBay and Borland have announced a new relationship that will provide
   Borland developers with access to tools and resources for creating web
   services applications for the eBay and PayPal platforms.
   http://community.borland.com/article/0,1410,32373,00.html

* Borland and Microsoft Arm Systems Integrators with Application
   Development and Deployment Best Practices
   Borland presented alongside Microsoft and leading systems integrators
   a road map for delivering the Visual Studio 2005 Team System. This
   will provide a set of best practices, architecture guidance and
   integrated tools designed to enable IT organizations to successfully
   build and deploy custom solutions for the Windows Server System.
   http://home.businesswire.com/portal/site/google/index.jsp?
   ndmViewId=news_view&newsId=20040524005402&newsLang=en

* Borland Brings RM to the Masses
   Requirements Management is a key discipline underlying software
   quality and success but business requirements are too often lost in
   translation before they ever become software capabilities. The best RM
   solutions address both human and technology adoption barriers.
   http://www.adtmag.com/article.asp?id=9223

* eWeek Application & Web Services Development Award
   WINNER: Microsoft Visual Studio .Net 2003.
   RUNNER-UP: Borland Enterprise Studio For Java 7.
   http://www.eweek.com/article2/0,1759,1560688,00.asp


Otros enlaces
=============

* Delphi User
   En este nuevo sitio web encontrarás dos descargas interesantes: Form
   Explorer y Constructor para Borland Delphi. Se detallan más arriba en
   la sección Freeware.
   http://delphiuser.iespana.es/delphiuser/

* Borland Blog Central
   Blogs by Borland staff.
   http://blogs.borland.com/

* Delphi 8 Documentation Available as PDF
   Registered users of Delphi 8 can now download this PDF that provides
   conceptual, procedural, and Language Guide topics. English-only.
   http://www.borland.com/products/downloads/download_delphi_net.html

* IDC Recommends Borland Janeva for Interoperability
   Developers who want to use a mixture of .NET, J2EE and CORBA should
   consider using Borland Janeva. Find out why in this PDF from IDC.
   http://www.borland.com/features/pdf/idc_interopToday_may04.pdf

* D7 Ent/D8 Arch Component Migration List
   Are you planning to move from Delphi 7 to Delphi 8? Check this chart
   to see how easy it will be for you.
   http://community.borland.com/article/0,1410,31984,00.html

* Mozilla-Delphi Project
   The Mozilla-Delphi project provides resources for working with Mozilla
   technologies in the Borland Delphi and Kylix programming environments.
   http://delphi.mozdev.org/

* Delphi Dabbler
   Delphi Pascal source code library, components, programming articles,
   tutorials and free programs.
   http://www.delphidabbler.com/

* Borland Delphi 8 (review)
   Good compatibility makes this impressive package ideal for Delphi
   users moving to .Net.
   http://www.vnunet.com/Products/Software/1154731

________________________________________________________________________

Irongut's Delphi Pages
Dedicada a la programación con Borland Delphi y Kylix. Tenemos artículos
sobre programación, noticias Borland y Delphi, código fuente y componen-
tes para usar en sus aplicaciones y más.  http://www.paranoia.clara.net/
________________________________________________________________________


¡Tú puedes ayudarnos!


Por favor danos una mano y ayúdanos a llegar a los 20.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@...

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://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium

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/descarga/p0050.zip
________________________________________________________________________

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@...
Para cancelar / removerse:    boletin-pascal-unsubscribe@...
Para reportar problemas con la suscripción: eds2004 @ 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
   Irongut's Delphi Pages         http://www.paranoia.clara.net/

Copyright 2004 by Ernesto De Spirito + Dave Murray. All rights reserved.
________________________________________________________________________

#16 De: "Ernesto De Spirito" <edspirito@...>
Fecha: Mar, 30 de Sep, 2003 4:38 am
Asunto: Boletín Pascal #49 - 30-SEP-2003
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #49 - 30-SEP-2003

Índice

1. Unas palabras del editor
2. Atributos de clase al estilo Delphi
3. Creando un Experto de Delphi
    La forma más simple de crear un Experto de Delphi
4. Dentro de las Clases e Interfaces de Delphi (I)
5. Notas de un desarrollador (III)
    Abrir un archivo con la aplicación predeterminada
6. Validando números de CBU
7. Foros / listas de correo
8. Delphi en la Red
    - Componentes, librerías y aplicaciones
      · Shareware
      · Freeware
      · Actualizaciones de Delphi y otros productos Borland
    - Artículos, trucos y consejos
    - Tutoriales y capacitación
    - Otros enlaces
    - Noticias

________________________________________________________________________

¿Necesitas alojamiento para tu sitio web? http://www.tecnosoftonline.com
________________________________________________________________________


1. Unas palabras del editor


Estoy muy contento de poder anunciar que el boletín alcanzó los 10.000
suscriptores. Muchas gracias a todos los suscriptores que hicieron esto
posible refiriendo el boletín a sus colegas, y también a los webmasters
que publicaron un enlace a nuestro sitio, permitiendo que el sitio web
sea conocido en la comunidad Delphi.

En esta edición tenemos un artículo de Demian Lessa mostrándonos cómo
implementar atributos de clase en Object Pascal, un artículo de Daniel
Wischnewski explicando cómo crear un Experto Delphi sencillo, un
artículo de Ezra Hoch revelando el funcionamiento interno de clases e
interfaces, un artículo de Alirio Gavidia sobre asociaciones de archivos
y uno breve mío mostrando cómo validar número de CBU. Gracias a los
autores por contribuir sus artículos para esta edición, y los premios
disponibles para esta edición son para:

* Demian Lessa ("Atributos de clase al estilo Delphi")
· NTTools 7 For Delphi - por i-tivity (USD 39.95)
   ¡Basta de batallar con la API de Seguridad de Windows NT! Obtenga su
   copia de NTTools 7 para Delphi 4/5/6/7 ahora y ahórrese incontables
   horas con esta colección de 40 componentes VCL escritos específica-
   mente para tratar con las funciones de Seguridad de Windows NT. Se
   incluye código fuente completo.
   http://www.i-tivity.biz/nttools.htm

* Daniel Wischnewski ("Creando un Experto de Delphi")
· LMD SearchPack 2.0 - por LMD Innovative (EUR 39)
   LMD SearchPack incluye 3 controles para integrar capacidades avanzadas
   de búsqueda de textos en su proyecto, incluyendo soporte de operadores
   AND, OR, NEAR y NOT. Viene con código fuente y extensivos ejemplos.
   http://www.ceberus.com/lmd/products/index.php3#P6

Para la próxima edición tenemos disponibles los siguientes premios para
para dos de los autores que colaboren artículos (en inglés):

* EurekaLog v4.1.1 - por Fabio Dell'Aria (Std $24, Pro $49, Ent $99)
   EurekaLog le confiere a su aplicación (GUI, consola, Web, etc.) la
   habilidad de capturar cada excepción que se produzca, generar un
   registro detallado (con unidad, clase, método y número de línea) y
   enviarlo por email. Se integra completamente en el IDE, y Ud. sólo
   tiene tiene que hacer un simple "build" para añadir EurekaLog a
   sus aplicaciones. No disminuye el rendimiento de las aplicaciones
   e incrementa el tamaño del archivo compilado en sólo un 0.5% - 4%.
   Compatible con Delphi 3 - 7 y todas las plataformas de Windows.
   http://www.eurekalog.com/bannerclick.php?id=15

* SMExport v4.30 - por Scalabium Software ($20 estándar, $35 c/fuentes)
   Conjunto de componentes VCL nativos para exportar datos de distintos
   orígenes (datasets, grids, cubos de decisión, memoria, árboles DevExp,
   etc.). Exporta a MS Excel, MS Access, MS Word, PDF, Text/CSV, HTML,
   XML, dBase, RTF, SQL, Lotus 1-2-3, QuattroPro y más.
   http://www.scalabium.com/

Bien, eso es todo por ahora. Espero que disfruten esta edición.

Saludos,

Ernesto De Spirito
boletin-pascal-owner@...

__________________

Colaboraron en esta edición: Dave Murray

________________________________________________________________________

Help & Manual 3, por EC Software · Shareware ($ 279)  -  Una herramienta
visual de  autoría de ayuda para generar archivos WinHelp (.HLP),  Adobe
PDF,  páginas HTML y los  nuevos archivos HTML HELP  (.CHM) introducidos
en Windows  98,  así como  otros formatos  de  archivo  y  documentación
impresa,  todo desde una  misma fuente.  Una herramienta  imprescindible
para cualquier desarrollador de software.  http://www.helpandmanual.com/
________________________________________________________________________


2. Atributos de clase al estilo Delphi

    Por Demian Lessa <demian @ knowhow-online.com.br>


En una reciente discusión sobre atributos de clase en el foro delphi-br
en Yahoo! Grupos, tuve la chance de aprender una nueva técnica que
permite la implementación práctica de las atributos de clase en Delphi.
Pero, ¿qué son estos atributos de clase?

Las atributos de clase son valores asociados a una clase y no sus
instancias. Es decir el valor del atributo de clase es el mismo para
todas las instancias de la clase. ¿Y para qué son útiles los atributos
de clase? Puedo sugerir dos utilidades muy obvias: conteo de instancias
de clase y asociación de una instancia objeto a una clase como un todo
(para propósitos de gestión).

Cuando uno necesita llevar la pista del número de instancias de una
clase, puede hacerlo usando una variable global a la unidad en la
sección Implementation. Esto garantiza que la variable no sea cambiada
por código fuera de la unidad, pero otras porciones del código dentro de
la unidad (incluso fuera de la clase) todavía pueden cambiar el valor de
esa variable. Encapsulando este valor en un atributo de clase se
resuelve el problema y la cuenta de instancias sólo puede ser modificada
mediante llamadas apropiadas a los métodos de la clase.

Otro uso importante de las atributos de clase se relaciona con el uso de
objetos de gestión o de apoyo. Imagínese, por ejemplo, que en vez de
contar las instancias de una clase deseamos guardar una lista de las
instancias de nuestra clase que están corriendo. Todo lo que tenemos que
hacer es definir un atributo de clase para mantener una lista de las
instancias de la clase. Este objeto lista puede ser instanciado cuando
sea necesario, y destruido por ejemplo en la sección Finalization de la
unidad. ¡Esto puede incluso utilizarse como base para un mecanismo
simple de colección de basura!

La implementación de los atributos de clase en Delphi se presenta abajo.
Los valores de los atributos de clase se ocultan dentro de la clase y
sólo se pueden cambiar con llamadas a los métodos apropiados. El truco
de cómo encapsular el valor me fue presentado por Marcelo Almeida, uno
de los moderadores del foro delphi-br en Yahoo! Grupos.

   type
     TMiClase = class
     private
       class function Attribute: PInteger;
       class function InstanceList: Pointer;
       class procedure DestroyInstanceList;
     public
       constructor Create;
       class function GetAttribute: Integer;
       class function GetInstanceList: TObjectList;
       class procedure SetAttribute(Value: Integer);
     end;

   class function TMiClase.Attribute: PInteger;
   {$J+}
   const
     placeholder: Integer = 0;
   {$J-}
   begin
     Result := @placeholder;
   end;

   class function TMiClase.InstanceList: Pointer;
   {$J+}
   const
     placeholder: TObjectList = nil;
   {$J-}
   begin
     if (TObjectList(Pointer(@placeholder)^) = nil) then
       // destruyamos nuestros objetos
       placeholder := TObjectList.Create(false);
     Result := @placeholder;
   end;

   class procedure TMiClase.DestroyInstanceList;
   begin
     if (GetInstanceList <> nil) then
     begin
       GetInstanceList.Free;
       TObjectList(InstanceList^) := nil;
     end;
   end;

   class function TMiClase.GetAttribute: Integer;
   begin
     Result := Attribute^;
   end;

   class function TMiClase.GetInstanceList: TObjectList;
   begin
     Result := TObjectList(InstanceList^);
   end;

   class procedure TMiClase.SetAttribute(Value: Integer);
   begin
     Attribute^ := Value;
   end;

   constructor TMiClase.Create;
   begin
     inherited Create;
     SetAttribute(GetAttribute + 1);
     GetInstanceList.Add(Self);
   end;

   destructor TMiClase.Destroy;
   begin
     SetAttribute(GetAttribute - 1);
     GetInstanceList.Remove(Self);
     if (GetInstanceList.Count = 0) then
       DestroyInstanceList;
     inherited Destroy;
   end;

En TMiClase, los métodos de clase Attribute e InstanceList son los
responsables de encapsular los valores de los atributos de clase. En
estos métodos se usan constantes tipadas locales (directiva $J+) para
alojar los atributos de clase. Las constantes tipadas pueden cambiar
su valor en tiempo de ejecución igual que las variables. Pero las
constantes que usamos son locales, así que, ¿cómo pueden almacenar
valores globales para la clase? La respuesta es bastante simple: no
utilizamos los valores de las constantes. Las constantes se declaran
para que el compilador reserve la memoria apropiada para sus tipos de
valores. Y, aunque declaradas como locales, la memoria que el compilador
reserva para ellas (representado por un simple puntero) no se cambia a
través de la ejecución del programa y, por lo tanto, podemos utilizar
esta memoria para implementar nuestros atributos de clase. Astuto, ¿no?
Los métodos Attribute e InstanceList devuelven punteros a la memoria
reservada por el compilador para las constantes tipadas locales. ¡Éste
es el gran truco!

En el código adjunto encontrarán los fuentes completos para TMiClase y
una pequeña aplicación mostrando el uso de los atributos de clase de
TMiClase.

________________________________________________________________________

¡Vote por el Boletín Pascal en el DPSC Top 100 Programming web sites!
(sólo cliquea "here" donde dice "Click here to vote!", y eso es todo)
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
________________________________________________________________________


3. Creando un Experto de Delphi
    La forma más simple de crear un Experto de Delphi

    Copyright © 2003 Daniel Wischnewski.
    Visite mi empresa
      http://www.gatenetwork.com
    Versión en alemán de este artículo disponible en
      http://www.delphipraxis.net/referenzen.php


Introducción
============

A veces uno desea definir algunas rutinas para hacer su vida más fácil
mientras usa Delphi. Una manera simple de hacer esto es creando un
Experto. Este primer artículo le muestra los fundamentos.

Este artículo lo introduce al mundo de los Expertos de Delphi. Los
Expertos de Delphi son DLLs que serán cargadas durante la secuencia de
inicialización de Delphi. Este artículo apareció primero en alemán en
Delphi-PRAXiS: http://www.delphipraxis.net/viewtopic.php?t=5300

   NOTA: Las técnicas mostradas en este artículo son válidas comenzando
         con Delphi 3 o 4 y son desaprobadas desde Delphi 7, aunque
         todavía siguen siendo completamente soportadas por el IDE de
         Delphi.


Instalación de un Experto para el IDE de Delphi
===============================================

Cada Experto Delphi debe ser registrado en el Registro de Windows. Para
cada versión de Delphi instalada en una máquina, así como para cada
usuario usando la máquina, el Experto Delphi debe registrarse separada-
mente.

En el Registro, el Experto Delphi debe registrarse bajo la clave:

   HKCU\Software\Borland\Delphi\X.0\Experts

donde X tiene que ser substituido por la versión apropiada de Delphi que
se soporta. Puede suceder que la clave Experts no esté instalada, y en
tal caso debe ser creada.

Bajo la clave Experts usted tiene que crear un valor de cadena para el
Experto de Delphi. El nombre debe ser único y el valor debe apuntar a la
DLL del Experto, incluyendo tanto el camino completo como el nombre del
archivo del Experto de Delphi. La vez próxima que Delphi levante, el
Experto será cargado automáticamente.


La interfaz del Experto de Delphi
=================================

A fin de que el Experto de Delphi interactúe con el IDE de Delphi tiene
que exportar una función con el nombre ExpertEntryPoint, usando los
siguientes parámetros:

   function InitExpert(
     ToolServices: TIToolServices;
     RegisterProc: TExpertRegisterProc;
     var Terminate: TExpertTerminateProc):
     Boolean; export; stdcall;

El primer parámetro, ToolServices, ofrece todas los interfaces
"documentadas" al IDE de Delphi. El segundo parámetro, RegisterProc, se
utiliza para cargar el Experto en el IDE de Delphi. El último parámetro,
Terminate, se emplea para notificar a la DLL del Experto cuando esté a
punto de ser descargada por el IDE de Delphi.

El método InitExpert devuelve True si el Experto ha sido cargado con
éxito; de lo contrario devuelve Falso o bien genera una excepción para
descargar la DLL del IDE de Delphi (véase la muestra de código para la
solución).


La clase PlugIn TIExpert
========================

Cualquier experto de Delphi debe ser derivado de la clase TIExpert que
está declarada en la unidad ExptIntf. Esta clase define algunos métodos
abstractos que deben ser implementados por cada PlugIn: GetName,
GetAuthor, GetComment, GetPage, GetGlyph (diferente para Windows y
Linux), GetStyle, GetState, GetIDString, GetMenuText y Execute. El
propósito de cada método se explica en el código fuente que se adjunta.


El más simple Experto de Delphi
===============================

Este Experto de Delphi no hará demasiado, pero sirve para mostrar la
forma básica de hacer el trabajo. Mostrará una entrada en el menú Help
(comportamiento predeterminado). Una vez que el usuario cliquea el
elemento de menú se llamará el método Execute del Experto. Se deben
respetar los siguientes puntos a fin de tener el Experto trabajando:

* El método GetState debe devolver [esEnabled]
* El método GetStyle debe devolver esStandard
* El método GetMenuText devuelve el texto a mostrar en el menú Help
* El método Execute define la acción del experto al activarse

El código fuente completo de este experto simple se encuentra adjunto.

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


4. Dentro de las Clases e Interfaces de Delphi (I)

    Por Ezra Hoch


Algunas palabras antes de comenzar:

- Primero, deseo comenzar este artículo diciendo que todo el conoci-
   miento en este artículo se deriva de ver el desensamblador de Delphi
   5. Por lo tanto todo lo escrito aquí es válido solamente para Delphi 5
   y pudo cambiar por cualquier actualización o versión diferente.

- Segundo, para entender completamente lo que se escribe en este
   artículo, usted tendrá que zambullirse en algo de código ensamblador.
   Explicaré lo que hace el código ensamblador, pero esté preparado,
   puede ser bastante complicado.

Y ahora, a la substancia. En Delphi, una instancia de una clase es un
simple puntero. Esto puede parecer extraño a algunas personas puesto
que han usamos instancias en Delphi muchas veces y nunca tuvieron que
tratarlos como punteros. Eso es correcto, pero sólo porque Borland fue
bastante amable de envolver bellamente los punteros. Estos punteros en
realidad apuntan a una estructura complicada en memoria, la que
intentaremos comprender. Primero, demos un vistazo a la definición de
una clase simple:

   TBoo1 = class
     FDataA, FDataB : Integer;
   end;

   var
     Boo1 : TBoo1;
   begin
     Boo1 := TBoo1.Create;
   end;

Ahora miremos a lo que Boo1 apunta (Boo1 es un puntero , ¿recuerda?).
Boo1 apunta a los siguientes valores, cada uno de 4 bytes de tamaño:

   Un puntero a la VMT de TBoo1
   FDataA
   FDataB

   N. de T.: VMT = Virtual Methods Table = Tabla de métodos virtuales

Ahora examinemos un descendiente de TBoo1:

   TBoo2 = class(TBoo1)
     FDataC, FDataD : Integer;
   end;

   var
     Boo2 : TBoo2;
   begin
     Boo2 := TBoo2.Create;
   end;

Boo2 apuntará a los siguientes valores en memoria:

   un puntero a la VMT de TBoo2
   FDataA
   FDataB
   FDataC
   FDataD

Nótese que los valores a los que apunta Boo2 incluyen algunos de los
valores a los que apunta Boo1. Eso es muy fácil de explicar - TBoo2
hereda de TBoo1 y por consiguiente debe incluir todos los campos que
tiene TBoo1.

Como regla general, podemos indicar que cada instancia de la clase
apunta a los siguientes valores:

   un puntero a la VMT de la clase
   una lista de los campos de la clase madre
   una lista de los campos de la clase

Ahora es tiempo de investigar las interfaces. Antes que podamos entender
completamente las interfaces debemos entender la manera en que Delphi
hace una llamada de método a una instancia de una clase. Lo que Delphi
hace realmente es llamar a la función (o procedimiento) con un parámetro
más aparte de los declarados, y ese parámetro es la misma instancia.
Veamos un ejemplo:

   TMoo = class
     FData: Integer;
     procedure Act(Value: Integer);
   end;

   procedure TMoo.Act(Value: Integer);
   begin
     if Self.FData = Value then Self.FData := FData + 1
     else Self.FData := Value;
   end;

   var
     Moo: TMoo;
   begin
     Moo := TMoo.Create;
     Moo.Act(15);
   end;

¿Cómo hace Delphi para implementar esto? Simple, 'TMoo.Act' en realidad
se compila como un procedimiento que acepta dos(!) parámetros. Uno es el
parámetro definido -'Value', de tipo entero- y el otro es una instancia
de la clase TMoo. Cada vez que Delphi llama a 'Moo.Act' efectúa un
cierto preprocesamiento de antemano, es decir, pasa la instancia de
TMoo que está haciendo la llamada. Básicamente usted podría decir que
cualquier llamada a un método de un objeto es traducida a una llamada
regular a un procedimiento o función que acepte el objeto que hace la
llamada como parámetro.

En el ejemplo anterior, 'TMoo.Act' en realidad se compila a algo como
esto:

   procedure TMoo_Act(Self: TMoo; Value: Integer);
   begin
     if Self.FData = Value then Self.FData := FData + 1
     else Self.FData := Value;
   end;

Es hora de volver a las interfaces. Considere el siguiente código:

   IKoo = interface
     function Calculate(Value: Integer): Double;
   end;

   function Evaluate(Koo: IKoo; Value: Integer): Double;
   begin
     Result := Koo.Calculate(Value);
   end;

   TKooA = class(TInterfacedObject, IKoo)
     function Calculate(Value: Integer) : Double;
   end;

   TKooB = class(TInterfacedObject, IKoo)
     procedure DoNothing;
     function Calculate(Value: Integer): Double;
  end;

Cualquier clase que soporte IKoo puede ser pasada como una variable a la
función 'Evaluate'. Cuando pasamos una instancia de TKooA a 'Evaluate'
necesitamos llamar al primer método de TKooA, pero cuando pasamos una
instancia de TKooB, necesitamos llamar al segundo método de TKooB! ¿Cómo
sabrá Delphi qué función llamar cada vez?!

Para comprender la respuesta, debemos repasar qué es realmente una
interfaz (y cómo se implementa en Delphi). Una interfaz es simplemente
una lista de métodos que una clase declara que implementa. Es decir,
cada método en el interfaz se implementa en la clase. La manera que
Delphi pone en práctica esto es como sigue:

   Cada interfaz que una clase soporta es realmente una lista de punteros
   a los métodos. Por lo tanto, cada vez que se hace una llamada a un
   método de una interfaz, la interfaz en realidad traslada esa llamada a
   uno de sus punteros a método, así dando la ocasión de actuar al objeto
   que en realidad implementa la interfaz. Explicaré esto vía el ejemplo
   de 'Koo' arriba:

   Cada vez que la función 'Evaluate' obtiene un parámetro del tipo IKoo,
   lo que realmente obtiene es una lista (con 4 elementos - IKoo hereda
   de IUnknown) de punteros a métodos. Si obtuviera una interfaz de IKoo
   que fue implementada por por TKooA, entonces el cuarto elemento en la
   lista de punteros-a-métodos apuntaría a 'TKooA.Calcualte'. Si no,
   apuntaría 'TKooB.Calcualte'. Por lo tanto, cuando se hace una llamada
   a 'IKoo.Calculate', en realidad se llamará al método al que apunta
   'IKoo.Calculate' (ya sea 'TKooA.Calculate' o 'TKooB.Calculate'). Ésta
   es la manera en que Delphi implementa las interfaces.

Y ahora veamos cómo Delphi almacena interfaces en memoria. Para cada
instancia de una clase que soporte 'N' interfaces, necesitamos 'N'
diferentes listas de punteros-a-método (una por cada interfaz). Pero
estas listas son las misma dentro del ámbito de una misma clase, por lo
tanto, para ahorrar memoria, mantenemos solamente 'N' punteros a estas
listas por cada instancia (en vez de las listas mismas).

Considere el siguiente código:

   ILooA = interface
   end;

   ILooB = interface
   end;

   TLoo = class(TInterfacedObject, ILooA, ILooB)
     FLooA, FLooB: Integer;
   end;

Así es como se vería una instancia de TLoo en memoria:

   un puntero a la VMT de TLoo
   FRefcount
   IUnknown
   FLooA
   FLooB
   ILooB
   ILooA

En general, cualquier instancia se varía así:

   un puntero a la VMT de la clase
   la estructura de la clase madre (excepto por el puntero a la VMT)
   el primer miembro de datos de la clase
   .
   .
   el último miembro de datos de la clase
   última interfaz en la lista de interfaces de la clase
   .
   .
   primera interfaz en la lista de interfaces de la clase

Como dije al comienzo de este artículo, para realmente captar la manera
en que Delphi instrumenta las clases y las interfaces debemos mirar el
código ensamblador que Delphi produce. Primero aprenderemos un poco de
ensamblador para entender el código que seguirá. En ensamblador hay una
cosa llamada 'registro'. Un registro es un lugar en la CPU que puede
alojar un valor de 32 bits. En una CPU Pentium  hay 8 registros
principales (EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP). La mayoría de las
acciones que se realizan en ensamblador se hacen sobre registros. Aquí
están algunos comandos en ensamblador:

   (Mueve el valor en un registro)
   Mov Registro, Valor

   (Mueve el valor en Registro2 a Registro1)
   Mov Registro1, Registro2

   (Mueve el valor apuntado por Registro2 a Registro1.
    Esto es lo mismo que el siguiente código: "Registro1 := Registro2^;")
   Mov Registro1, [Registro2]

   (Mueve el valor al que apunta Registro2+Valor a Registro1.
    Lo mismo que: "Registro1 := Pointer(Integer(Registro2) + Valor)^;")
   Mov Registro1, [Registro2 + Valor]

Ejemplos:

   MOV EAX, 10
   MOV EBX, EAX
   MOV EAX, [EBX + 6]

EBX tendrá el valor 10 y EAX tendrá el valor que está en la dirección
16 ($10).

Apenas para cerciorarse de que usted entendió esta parte, daré un
ejemplo de cómo Delphi asigna un valor al miembro de los datos de una
instancia.

   TGoo = class
     FDataA, FDataB: Integer;
   end;

   var
     Goo: TGoo;
   begin
     Goo := TGoo.Create;
     Goo.FDataA := 5;
     Goo.FDataB := 7;
   end;

Si abre el desensamblador de Delphi, verá el siguiente código:

   // Goo.FDataA := 5;
   mov eax, [ebp-$08]
   mov [eax + $04], $00000005
   // Goo.FDataB := 7;
   mov eax, [ebp-$08]
   mov [eax + $08], $00000007

¿Por qué el valor apuntado por "ebp-$08"? Simple, allí es donde se
almacena la variable Goo. Note que acceder a FDataA es lo mismo que
acceder a la dirección "eax+$04" y que acceder a FDataB es lo
mismo que acceder a la dirección "eax+$08". Esto es porque la
dirección a la que apunta "eax" es el puntero a la VMT de TGoo, y (como
mencioné antes) los siguientes valores en memoria son los miembros de
dato de TGoo.

Volvamos a las interfaces. Mire el siguiente código:

   IRoo = interface
   end;

   TRoo = class(TInterfacedObject, IRoo)
   end;

   var
     Roo: TRoo;
     RooIntf: IRoo;
   begin
     Roo := TRoo.Create;
     RooIntf := Roo;
     RooIntf._AddRef;
   end;

El siguiente código ensamblador no es exactamente lo que produce Delphi
pero hace lo mismo y sirve al propósito:

   // RooIntf := Roo;
   // eax contiene el valor devuelto por TRoo.Create, es decir, la
   //     variable Roo
   // ecx contiene el valor que más tarde debería ser asignado a RooIntf
   mov ecx, eax
   // Esto es lo mismo que: "ecx := ecx + $0C;"
   add ecx, $0C
   // RooIntf._AddRef
   // Empujar "ecx" en la pila de la CPU
   push ecx
   mov ecx, [ecx]
   // "call ecx" le dice a la CPU que salte a la dirección guardada como
   // un valor en "ecx"
   call ecx

Miremos el código al que nos lleva "call ecx":

   // obtener (POP) en "ecx" el valor que empujamos en la pila
   pop ecx
   // Lo mismo que: "ecx := ecx - $0c;"
   sub ecx, $0C
   // Llamar al método "_AddRef" con "ecx" como variable.
   call TInterfacedObject._AddRef(ecx)

Se impone una pequeña explicación. ¿Por qué Delphi sumó "$0C" a "ecx"?
Recuerde cómo Roo se almacena en la memoria (un indicador a la VMT,
FRefCount (de InterfacedObject), IUnknown (de TInterfacedObject), IRoo).
IRoo es el cuarto valor en la lista a la cual el "ecx" señala. Cada
valor tiene 4 bytes de largo, así que IRoo está 12 bytes (4*4) después
de "ecx", y "$0C" es 12 en notación hexadecimal. Así pues, básicamente,
sumando "$0C" a "ecx" hizo que "ecx" apunte al valor correcto, es decir,
que apunte a IRoo de Roo (una instancia de TRoo).

¿Por qué empujamos ecx en la pila? Esto es porque necesitaremos usarlo
más tarde, al llamar al verdadero método "_AddRef". Recuerde, "ecx" es
la dirección de Roo + 12.

Después de eso, movemos en "ecx" el valor al que "ecx" apunta. ¿Recuerda
cuándo dije que en vez de contener las listas de punteros-a-método
Delphi almacena sólo los punteros a los mismos (para ahorrar memoria)?
Esto es por qué "ecx" era en realidad un puntero, pero ahora contiene el
valor al cual apuntaba antes.

El siguiente comando es llamar al método al que "ecx" apunta. Ahora
observemos ese método. Es muy corto. Lo único que hace es modificar el
valor de "ecx" (después de restaurarlo de la pila) de modo que sea
igual que el valor de Roo (es decir, apunta a la variable Roo). Entonces
el método 'TInterfacedObject._AddRef' se llama con "ecx" (Roo) como
parámetro. Éste es igual que cuando he escrito que Delphi en realidad
compila un método de clase como una función o un procedimiento regular
que acepta un parámetro adicional - la instancia de la clase.

¿Para qué es bueno esto? Sumamos un valor a un indicador, luego hicimos
ese salto por la memoria, luego restamos el mismo valor del puntero y
¡finalmente llamamos a la función a la que apunta el puntero! ¿Por qué
molestarse? ¡Podríamos simplemente llamar la función sin sumar y restar
valores!

Aquí es donde el poder de la indirección entra en juego. Note que la
llamada a 'RooIntf._AddRef' no sabía que RooIntf era realmente de una
instancia de TRoo. Simplemente llamó al método que estaba allí para
llamar. La implementación de este método es donde se hizo la reasig-
nación del valor del puntero. Es decir, solamente la implementación a
la que RooIntf apunta (IRoo de TRoo) sabía cuánto fue sumado o restado
del puntero salvado en la pila. Si tuviéramos otra variable de tipo
TRoo2, que también implementara IRoo, y hubiésemos hecho la asignación
'RooIntf := variable de tipo TRoo2' y luego llamado el método
'RooIntf._AddRef', entonces se hubiera restado un valor diferente del
valor salvado en la pila, así haciendo que la llamada del método vaya al
lugar correcto en la clase TRoo2.

__________________

El autor puede ser encontrado en ezra.hoch@...

________________________________________________________________________


5. Notas de un desarrollador (III)
    Abrir un archivo con la aplicación predeterminada

    Por Alirio A. Gavidia

La presente es parte de una serie de pequeños artículos narrando expe-
riencias en el desarrollo de una aplicación.


El menú contextual o "cómo con un par de clics
convertir un archivo de un formato a otro"
==============================================

Lo que refiero aquí como Menú Contextual es la facilidad del Explorador
de Windows (y similares ventanas de Windows) de mostrarnos un menú con
el botón derecho que es diferente para cada archivo seleccionado. Para
que quede claro ejecute el Explorador busque un archivo cualquiera y
haga clic con el botón derecho. En mi caso he seleccionado un MP3 y la
primera opción del menú es "Play in Winamp". Tengo más abajo una opción
que dice "Agregar en ZIP" entre otras.

Recientemente en RentACoder solicitaron un programa para conversión de
archivos BMP/JPG y BMP/GIF. Me pareció que esto se puede combinar con el
uso de menúes contextuales (originalmente los uso en HalZip imitando
WinZip).

Del artículo anterior de esta serie tenemos como convertir archivos de
distintos formatos. Ahora vamos a concentrarnos en el manejo del menú
contextual como extensión del Explorador de Windows.


Abrir un archivo con una aplicación predeterminada
==================================================

Esto es simple comparativamente, tomando el ejemplo de Wimamp sólo
tenemos que manipular el Registro de Windows. Comencemos con REGEDIT y
vamos a HKEY_CLASSES_ROOT desde allí buscamos '.mp3'. Por lo pronto sólo
nos interesa el valor "Default" contenido. Esto programáticamente sería
así:

Registry es de tipo TRegistry, lo asumo ya creado.

   Registry.RootKey := HKEY_CLASSES_ROOT;
   if Registry.OpenKey('\.mp3',True) then
      appasoc := Registry.ReadString('');

Nota: Para leer el valor "default" o por defecto de una clave ("key")
       simplemente use el método de lectura que corresponda sobre un
       identificador en blanco.

Obtenido 'appasoc' (que debe ser 'Winamp3.File') buscamos este valor en
HKEY_CLASSES_ROOT y encontramos información interesante como la descrip-
ción del tipo dada en el valor por defecto, el icono por defecto tomado
del archivo que señalemos, y las opciones relativas al "Shell", en este
caso nos interesa "Play", dentro de Play hallamos el comando que
queremos asociar. Si siguieron todo esto usando Regedit verán que es
bastante simple.

El ejemplo anexo a este artículo ('test03') permite revisar las defini-
ciones presentes en la máquina y adicionalmente crear algunas nuevas.

En el segundo ejemplo anexo a este artículo ('gconvert') usamos la aso-
ciación a BMP, JPG, WMF, EMF, ICO y GIF para conversiones. Simplemente
creamos la entrada "Convertir a .." esto sin dañar el valor "Open" por
defecto.

"Gconvert" es casi una aplicación de consola (sin interfaz Windows) que
acepta un parámetro. El parámetro aceptado se asume como un archivo de
tipo jpg, gif, ico, wmf, emf. Para probarlo simplemente suelte un
archivo de cualquiera de estos tipos sobre el programa y... voila.
Obtendrá un archivo bmp.

Además "gconvert" opera con los parámetros /r  y /u el primero asocia
los archivos convertibles, el segundo parámetro elimina esta asociación.

Compile "gconvert" y obtenga el ejecutable correspondiente. Ciertamente
al soltar un archivo jpg o gif o de cualquiera de los tipos convertibles
obtendrá un bmp. Ejecute el archivo registro.bat para asociar los
archivos convertibles al menú de contexto, busque un archivo de los
tipos convertibles y revise el menú que despliega con el botón derecho
del ratón.


Sensitivo a contexto
====================

Ni WinZip y HalZip usan este enfoque más allá de las opciones "abrir"
e "imprimir". La razón es poder manejar múltiples archivos con una
llamada. Con el esquema dado hasta ahora si se selecciona tres archivos
"txt" y con el menú derecho se opta por "Abrir" tendremos tres
instancias del programa.

El otro problema es la interactividad de los menúes. Para ello basta ver
que WinZip y HalZip generan entradas de menú de forma dinámica. Verán
que Winzip genera un menú de tipo e-mail <nombre archivo>. Donde <nombre
archivo> cambia según el menú seleccionado.

Delphi trae un ejemplo de esto en

   ...\Borland\Delphi5\Demos\Activex\Shellext

Revísenlo si quieren. Será analizado con más propiedad próximamente en
esta serie de artículos.

Este tema será analizado más profundamente en el próximo artículo.


Alirio A. Gavidia.
desde www.gavidia.org

__________________

Próximo tema: DLL y su registro

________________________________________________________________________

¡Vote por el Boletín Pascal en el DPSC Top 100 Programming web sites!
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
________________________________________________________________________


6. Validando números de CBU

    Por Ernesto De Spirito


Las cuentas bancarias en Argentina se identifican por un número de CBU
(Clave Bancaria Uniforme), formado por 22 dígitos, divididos en dos
bloques. El primer bloque, formado por 8 dígitos, identifica al banco y
sucursal, mientras que el segundo bloque, formado por los restantes 13
dígitos, identifica la cuenta bancaria. El último dígito de cada bloque
es el dígito verificador del mismo según el algoritmo clave 10 con
ponderador 9713.

Para validar un número de CBU se deberán computar los dígitos verifica-
dores de ambos bloques y compararlos con los respectivos valores para
ver si coinciden o no. La siguiente función realiza ese trabajo:

   function CBU_Valido(const CBU: string): boolean;
   {
   Copyright (c) 2003 Ernesto De Spirito
   http://www.latiumsoftware.com/es/index.php

   Determina si un número de CBU (Clave Bancaria Uniforme)
   es válido.

   La cadena que se pasa como parámetro debe estar formada
   por 22 dígitos numéricos (no se admiten guiones, barras
   ni espacios como parte de la cadena con el CBU).
   }
   var
     i: integer;

     function Verificador(const s: string; i1, i2: integer): char;
     // Devuelve el dígito verificador para los dígitos
     // de las posiciones "i1" a "i2" de la cadena "s"
     // usando clave 10 con ponderador 9713
     const
       ponderador: array[0..3] of integer = (3,1,7,9); // 9713
     var
       i: integer;        // subíndice para recorrer la cadena
       j: integer;        // subíndice del ponderador (módulo 4)
       suma: integer;     // sumatoria de los productos parciales
       digito: integer;   // dígito verificador
     begin
       suma := 0; j := 0;
       for i := i2 downto i1 do begin
         inc(suma, (Ord(s[i])-Ord('0')) * ponderador[j mod 4]);
         inc(j);
       end;
       digito := (10 - suma mod 10) mod 10;
       Result := Chr(digito + Ord('0'));
     end;

   begin
     Result := False;
     // Comprueba la longitud de la clave
     if Length(CBU) <> 22 then exit;
     // Comprueba que esté integrada sólo por dígitos numéricos
     for i := 1 to 22 do
       if not (CBU[i] in ['0'..'9']) then exit;
     // Comprueba el primer dígito verificador
     if CBU[8]  <> Verificador(CBU, 1, 7)  then exit;
     // Comprueba el segundo dígito verificador
     if CBU[22] <> Verificador(CBU, 9, 21) then exit;
     // Pasó todas las pruebas. Es válido.
     Result := True;
   end;

Llamada de ejemplo:

   procedure TForm1.btnValidarClick(Sender: TObject);
   begin
     if CBU_Valido(edtCBU.Text) then
       ShowMessage('El CBU ingresado es válido')
     else
       ShowMessage('El CBU ingresado no es válido');
   end;

________________________________________________________________________

          ¡Vote por el Boletín Pascal en The Programming Pages!
       http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
________________________________________________________________________

   Delphi BUGS?
   Catch & Log every BUG showing Unit, Class, Method, Line #.
   Now with support for IntraWeb applications and Anti-Freeze feature.
   http://www.eurekalog.com/bannerclick.php?id=15
________________________________________________________________________


7. Foros / listas de correo


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-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@...

* 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

________________________________________________________________________

   Merlin's Delphi Forge
   Delphi and Kylix news, FAQ, downloads, links, forums and more.
   Accepting uploads and submissions.
   http://www.delphifaq.net/
________________________________________________________________________


8. Delphi en la Red

    Por Dave Murray <irongut @ vodafone.net>


Componentes, librerías y aplicaciones
=====================================


Shareware/Comercial
-------------------

* LMD SearchPack 2.0 - by LMD Innovative (EUR 39)
   LMD SearchPack includes 3 controls for integrating advanced text
   search capabilities into your projects including support of AND, OR,
   NEAR and NOT operators. Full source code and extensive demo projects
   included. http://www.ceberus.com/lmd/products/index.php3#P6

* EurekaLog v4.2 - by Fabio Dell'Aria (Std $24, Pro $49, Ent $99)
   Gives your application the ability to catch every exception, generate
   a detailed log and send it via email. Integrated with Delphi 3 - 7, a
   single rebuild adds EurekaLog to your app. NEW: save modified files on
   exception; detailed Log when the application freezes; customizable
   email for every exception; speed and stability improvements.
   http://www.eurekalog.com/bannerclick.php?id=15


Freeware
--------

* WinDowse v5.1 - by Greatis Software (free for non-commercial use)
   Unique windows analyzer, best Borland's WinSight replacement. Greatis
   WinDowse is an extremely convenient tool for obtaining necessary
   technical information about any window. Place a mouse cursor on a
   window, and WinDowse will show all parameters of the window and window
   class. Full Delphi 3-7 source code available after 100 Euro donation.
   http://www.greatis.com/windowse.htm

* Inno Setup v4.0.8 - by JR Software (with source)
   A free installer for Windows that rivals commercial installers in
   features and stability. Features include: all 32-bit Windows versions;
   create a single EXE or disk spanning; standard interface; customizable
   setup types; complete uninstall capabilities; zip / bzip2 compression;
   create shortcuts, registry + .INI entries; silent install / uninstall;
   register DLL, OCX and type libraries; install fonts; Pascal Script.
   http://www.jrsoftware.org/isinfo.php

* TPages v1.2 - by Angus Johnson (with source)
   Visual component for simple, non-data-aware reports. Features include:
   text wrapped between margins, in columns or at specific offsets;
   multiple alignment options; multi-line page headers, footers and
   column headers; angled text; bitmaps, lines, boxes and arrows; page
   numbering; prevent blocks of text spanning across pages.
   http://www.users.on.net/johnson/delphi/


Actualizaciones de Delphi y otros productos Borland
---------------------------------------------------

* Fixes for Kylix 3 Issues on Newer Distros (updated) - Andrés Colubri
   Kylix 3 (particularly C++) on newer Linux distros (eg. RedHat 8+,
   Madrake 9+, SuSE 8.2) has a number of bugs: compilation errors with
   STL, unresolved references when linking, installer and IDE hangs, etc.
   This package contains a collection of fixes to address these issues.
   http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=20136


Artículos, trucos y consejos
============================

* Come learn about Octane! Sneak peeks around the world!  - by A Ohlsson
   First Octane sighting at Entwickler Konferenz in Frankfurt, Germany.
   http://bdn.borland.com/article/0,1410,30387,00.html

* Using D7 to Consume Web Services and Transform XML - by Anders Ohlsson
   In this BDNtv episode, Anders shows how you can consume web services
   that return XML data. Anders uses Delphi 7 Enterprise to create a
   simple application that consumes an XML web service, transforms the
   result and displays custom picked data in a regular DBGrid.
   Format(s): Flash, Duration: 9:34.
   http://community.borland.com/article/0,1410,30379,00.html

* Customizing the DBNavigator
   Enhancing the TDBNavigator component with modified graphics (glyphs),
   custom button captions, and more. Exposing the OnMouseUp/Down event
   for every button.
   http://delphi.about.com/library/weekly/aa090203a.htm

* Accessing and managing MS Excel sheets with Delphi - by Zarko Gajic
   How to retrieve, display and edit Microsoft Excel spreadsheets with
   ADO (dbGO) and Delphi. This step-by-step article describes how to
   connect to Excel, retrieve sheet data, and enable editing of data
   (using the DBGrid). You'll also find a list of most common errors (and
   how to deal with them) that might pop up in the process.
   http://delphi.about.com/library/weekly/aa090903a.htm

* Delphi History: from Pascal to Octane - by Zarko Gajic
   Concise descriptions of Delphi's versions and its history, along with
   a brief list of features and notes. Find out how Delphi evolved from
   Pascal to a RAD tool that can help you solve development problems not
   only for Windows but also for Linux and .NET.
   http://delphi.about.com/cs/azindex/a/dhistory.htm

* Drop Down List Inside a DBGrid: Part 1 - by Zarko Gajic
   Here's how to place a drop down pick list into a DBGrid. Create
   visually more attractive user interfaces for editing lookup fields
   inside a DBGrid - using the PickList property of a DBGrid column.
   http://delphi.about.com/library/weekly/aa092703a.htm

* How to Darken or Lighten TColor?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1411

* How to execute a Javascript function in a Webbrowser / IE Document?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1732

* How to display the items in a listview control as a group? (WinXP)
   http://www.swissdelphicenter.ch/en/showcode.php?id=1782

* How to detect if an Application is running within VMware?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1819

* How to mix two colors using transparency coefficient?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1832

* THvHQuery for exporting query to CSV file - by Henk van Hoek
   Export a query to a Comma Separated CSV File.
   http://www.delphi3000.com/articles/article_3763.asp

* TEdit and EConvertError - by Andrew Kennaugh
   Checking TEdit for StrToFloat using OnKeyPress not OnChange.
   http://www.delphi3000.com/articles/article_3765.asp

* Inline Assembler in Delphi (I): Introduction - by Ernesto De Spirito
   Reprinted from this newsletter, Ernesto's Assembler tutorial.
   http://www.delphi3000.com/articles/article_3766.asp

* Inline Assembler in Delphi (II): ANSI strings - by Ernesto De Spirito
   http://www.delphi3000.com/articles/article_3767.asp

* Inline Assembler in Delphi (III): Static Arrays - Ernesto De Spirito
   http://www.delphi3000.com/articles/article_3768.asp

* Inline Assembler in Delphi (IV): Records - by Ernesto De Spirito
   http://www.delphi3000.com/articles/article_3769.asp

* Inline Assembler in Delphi (V): Objects - by Ernesto De Spirito
   http://www.delphi3000.com/articles/article_3770.asp

* Inline Assembler in Delphi (VI): Calling External Procedures
   - by Ernesto De Spirito
     http://www.delphi3000.com/articles/article_3771.asp

* Inline Assembler in Delphi (VII): 128-bit Integer Arithmetic
   - by Ernesto De Spirito
     http://www.delphi3000.com/articles/article_3772.asp

* Playing Sounds Thru The Built-In PC Speaker - by Ernesto De Spirito
   Using inline assembler to play sounds with the built-in PC speaker.
   http://www.delphi3000.com/article.asp?id=3773

* Determining if a Logical Drive Exists - by Ernesto De Spirito
   How to know if there is a drive assigned to a letter.
   http://www.delphi3000.com/articles/article_3774.asp

* Using TList's and Pointers in delphi (Part II) - by Stewart Moss
   Demonstration of how to create records on a TList object.
   http://www.delphi3000.com/articles/article_3775.asp

* Adding HTML Resources to DLL/EXE that IE can Reference - Matt Harrison
   Creating an RC file to store HTML and Images as resources that works
   with IE's res:// format.
   http://www.delphi3000.com/articles/article_3776.asp

* Horizontal Modularization - by Hang Liu
   This article introduces a modular approach to building large
   applications.
   http://www.delphi3000.com/articles/article_3777.asp

* Borland DataSnap vs Microsof ADO.NET - by Pablo Reyes
   A comparison between the tools provided by these technologies for
   building data aware applications.
   http://www.delphi3000.com/articles/article_3778.asp

* Simple Winsock Component for Console App - by J3N7iL Jones
   How can I create a TCP/IP internet connection in a console application
   using winsock?
   http://www.delphi3000.com/articles/article_3779.asp

* PageControl Without Border - by Tommy Andersen
   http://www.delphi3000.com/articles/article_3783.asp

* Adding new Standard Actions - by Andreas Schmidt
   http://www.delphi3000.com/articles/article_3784.asp

* Create a Sizeable Dialog - by Terrance Hui
   How to create a sizable dialog (with sizegrip) without using any 3rd
   party components.
   http://www.delphi3000.com/articles/article_3785.asp

* Selecting Files - by Teun Spaans
   In which ways can you let your user choose a file or directory?
   http://www.delphi3000.com/articles/article_3786.asp

* Debugging Tricks - by Andreas Schmidt
   How to read the content of a TStrings in the integrated debugger.
   http://www.delphi3000.com/articles/article_3787.asp


Tutoriales y capacitación
=========================

* BorCon 2003 to be be held in San Jose, California November 1-5, 2003
   http://info.borland.com/conf2003/


Otros enlaces
=============

* Public Beta: QualityCentral Java Client - by John Kaster
   Use a smart client for Borland QualityCentral from wherever you can
   run JDK 1.4.x.
   http://community.borland.com/article/0,1410,30348,00.html

* San Francisco East Bay Delphi User Group
   Our goal is to connect the Delphi developers in the Bay Area. We meet
   the 1st Wednesday of every month and have great speakers and sessions.
   We organize Delphi events with the help of eBig - the East Bay IT
   Group (www.ebig.org). The group will explore Delphi and how Borland's
   Delphi 7-8 Studio provides a migration path to Microsoft .NET for
   developers as well as Delphi and Linux (Kylix).
   http://www.ebig.org/sig/sig.aspx?SIGid=20


Noticias
========

* Altova XMLSPY to be Included in Borland Development Tools
   Special Edition of Altova XMLSPY Available in Borland Delphi Studio,
   C++ Builder, and C# Builder for the Microsoft .NET Framework.
   http://www.altova.com/press/2003-08-28_borland.pdf

________________________________________________________________________

¿Cómo calificaría al boletín? ¡Califique al Boletín Pascal en el ranking
Top 200 Delphi! · http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________


¡Tú puedes ayudarnos!


Por favor danos una mano y ayúdanos a llegar a los 20.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@...

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.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
http://news.optimax.com/topdelphi/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://www.top219.org/cgi-bin/vote.cgi?delphi&83
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
http://213.65.224.200/cgi-bin/toplist.cgi/hits?Id=80
http://www.programacion.net/votar-enlace.php?id=474
http://www.lawebdelprogramador.com/buscar/enlace.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/descarga/p0049.zip
________________________________________________________________________

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@...
Para cancelar / removerse:    boletin-pascal-unsubscribe@...
¿Problemas con tu suscripción?      boletin-pascal-owner@...
________________________________________________________________________

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) 2003 por Ernesto De Spirito. Todos los derechos reservados
________________________________________________________________________

#15 De: "Ernesto De Spirito" <edspirito@...>
Fecha: Lun, 8 de Sep, 2003 10:34 pm
Asunto: Boletín Pascal #48 - 08-SEP-2003
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #48 - 08-SEP-2003

Índice

1. Unas palabras del editor
2. Cuadros de diálogo HTML
    Usando la función API ShowHTMLDialog en la MSHTML.dll
3. Reemplazando el InplaceEditor estándar del TStringGrid
    Cómo modificar el TStringGrid para tener una lista de opciones o un
    botón con puntos suspensivos en la celda seleccionada
4. Usando los Shell Controls de Delphi
5. Inline Assembler en Delphi (X) - Sonido con el altavoz del PC
6. Foros / listas de correo
7. Delphi en la Red
    - Componentes, librerías y aplicaciones
      · Shareware
      · Freeware
      · Actualizaciones de Delphi y otros productos Borland
    - Artículos, trucos y consejos
    - Tutoriales y capacitación
    - Otros enlaces
    - Noticias

________________________________________________________________________

¿Necesitas alojamiento para tu sitio web? http://www.tecnosoftonline.com
________________________________________________________________________


1. Unas palabras del editor


Han transcurrido casi cuatro meses desde la última edición, pero ahora
me alegra poder anunciar que el boletín ha vuelto! Muchas gracias por
las palabras de aprecio y de ánimo que he recibo de los suscriptores.
Es agradable saber que el boletín no pasa desapercibido.

Hay varios artículos en español que me han enviado en este tiempo y que
ya lo iré publicando en subsiguientes ediciones. Como de costumbre, me
gustaría comenzar agradeciendo a los autores que contribuyeron artícu-
los para esta edición: Wes Turner, Werner Palmer y Dave Murray, y me
complace entregar los premios disponibles para esta edición a:

* Wes Turner ("Cuadros de diálogo HTML")
· SMImport v1.75 - por Scalabium Software ($30 standard, $50 c/fuentes)
   Conjunto de componentes VCL nativos para importar datos en un dataset
   sin librerías externas. Soporta Access (usando DAO/MS Jet), Excel (sin
   OLE/DDE), Lotus 123, QuattroPro, texto, HTML, XML incluyendo formato
   TClientDataset, Paradox, dBase y cualquier descendiente de TDataSet.
   Nuevo en la versión 1.75: Creador visual de expresiones; importación
   desde Word; importación directa desde dBase sin BDE; carga de campos
   BLOB para XML; estilo extendido para el diálogo del asistente; evento
   OnCreateStructure que permite la creación dinámica de un dataset antes
   de realizar el verdadero proceso de importación, y más.
   http://www.scalabium.com/

* Werner Palmer ("Reemplazando el InplaceEditor estándar ...")
· EurekaLog v4.1.1 - por Fabio Dell'Aria (Std $24, Pro $49, Ent $99)
   EurekaLog le confiere a su aplicación (GUI, consola, Web, etc.) la
   habilidad de capturar cada excepción que se produzca, generar un
   registro detallado (con unidad, clase, método y número de línea) y
   enviarlo por email. Se integra completamente en el IDE, y Ud. sólo
   tiene tiene que hacer un simple "build" para añadir EurekaLog a
   sus aplicaciones. No disminuye el rendimiento de las aplicaciones
   e incrementa el tamaño del archivo compilado en sólo un 0.5% - 4%.
   Compatible con Delphi 3 - 7 y todas las plataformas de Windows.
   http://www.eurekalog.com/bannerclick.php?id=15

Para la próxima edición tenemos disponibles los siguientes premios para
para dos de los autores que colaboren artículos (en inglés):

* NTTools 7 For Delphi - por i-tivity (USD 39.95)
   ¡Basta de batallar con la API de Seguridad de Windows NT! Obtenga su
   copia de NTTools 7 para Delphi 4/5/6/7 ahora y ahórrese incontables
   horas con esta colección de 40 componentes VCL escritos específica-
   mente para tratar con las funciones de Seguridad de Windows NT. Se
   incluye código fuente completo.
   http://www.i-tivity.biz/nttools.htm

* LMD SearchPack 2.0 - por LMD Innovative (EUR 39)
   LMD SearchPack incluye 3 controles para integrar capacidades avanzadas
   de búsqueda de textos en su proyecto, incluyendo soporte de operadores
   AND, OR, NEAR y NOT. Viene con código fuente y extensivos ejemplos.
   http://www.ceberus.com/lmd/products/index.php3#P6

La unidad HighResTimer.pas publicada en la última edición como parte del
artículo "Mediciones de tiempo de alta precisión" -por Michael Darling-
ha sido modificada para funcionar bajo Delphi 6 y Delphi 7 (y espero que
también bajo Delphi 8 eventualmente). Gracias a Francisco Arena por
hacernos saber del problema con la compilación condicional. La edición
actualizada está en http://www.latiumsoftware.com/download/p0047.zip

A propósito, hay una actualización al artículo "Codificar y decodificar
Base64 (MIME)" -por Daniel Wischnewski- y su respectivo código fuente,
publicado en el Boletín Pascal #40. Gracias al autor por la revisión. La
edición actualizada de ese boletín se encuentra disponible para descarga
en http://www.latiumsoftware.com/download/p0040.zip

Cambiando de tema, quisiera aprovechar este espacio para felicitar a
EC Software por su producto Help & Manual (una utilidad de autoría de
ayuda), el que ha sido seleccionado como Producto del Año en los Readers
Choice Awards 2003 de la revista Delphi Informant Magazine (que mencioné
en la edición pasada), aparte de ganar muy ampliamente su categoría
(Paquete de Autoría de Ayuda) con un abrumador 51% de los votos!
http://www.delphizine.com/opinion/2003/09/di200309jc_o/di200309jc_o.asp

Bien, eso es todo por ahora. Espero que disfruten esta edición.

Saludos,

Ernesto De Spirito
boletin-pascal-owner@...

__________________

Colaboraron en esta edición: Dave Murray

________________________________________________________________________

Help & Manual 3, por EC Software · Shareware ($ 279)  -  Una herramienta
visual de  autoría de ayuda para generar archivos WinHelp (.HLP),  Adobe
PDF,  páginas HTML y los  nuevos archivos HTML HELP  (.CHM) introducidos
en Windows  98,  así como  otros formatos  de  archivo  y  documentación
impresa,  todo desde una  misma fuente.  Una herramienta  imprescindible
para cualquier desarrollador de software.  http://www.helpandmanual.com/
________________________________________________________________________


2. Cuadros de diálogo HTML
    Usando la función API ShowHTMLDialog en la MSHTML.dll

    Por Wes Turner <splitdfile @ yahoo.com>


¿Dónde está la función ShowHTMLDialog? ¿En una unidad .PAS?
===========================================================

No. La función ShowHTMLDialog() está en la biblioteca MSHTML.dll, y
necesitará hacer

   hLib := LoadLibrary('MSHTML.DLL');

para acceder a esta DLL, y luego hacer

   ShowHTMLDialog := GetProcAddress(hLib, 'ShowHTMLDialog');

para obtener la dirección de la función.

Sólo puede usarse esta función si se encuentra instalado el Internet
Explorer (o Explorador de Internet) versión 4 o posterior.


¿Cómo es un Cuadro de Diálogo HTML?
===================================

Cuando llame a ShowHTMLDialog, Internet Explorer muestra una ventana de
navegador tipo diálogo con sólo una barra de título (sin barras de menú,
de herramientas, ni de estado). Esta ventana de navegador leerá el HTML
en un archivo y lo mostrará en la ventana de navegador. Si necesita
entrada de datos del usuario (botones, textos, botones de radio, etc.)
necesitará usar JScript o VBScript como lenguaje de codificación para
leer o cambiar estas entradas.


¿Qué código se necesita para usar un diálogo HTML?
==================================================

Dado que un diálogo HTML es una ventana del navegador Internet Explorer,
se usa COM para la comunicación entre su programa y el IE, con variants,
y las interfaces IMoniker y IHTMLDialog. La función ShowHTMLDialog
implementará estas interfaces por usted.

La función ShowHTMLDialog se define a continuación:

   function ShowHTMLDialog(
     hwndParent: Cardinal;   // Manejador del padre
     UrlMnk: IMoniker;       // IMoniker que tiene el archivo fuente HTML
     PvarArgIn: PVariantArg; // Dirección variant que contiene el PWChar
                             // enviado al diálogo
     PWCHOptions: PWChar;    // Puntero a cadena con opciones del diálogo
     PvarArgOut: PVariantArg // Dirección variant que recibe los datos
                             // puestos en IHTMLDialog::returnValue
     ): HRESULT; // El valor devuelto es un OLE HRESULT (Integer)

   Parámetros

   hwndParent - Manejador del padre del cuadro de diálogo; puede ser
     cero.

   UrlMnk - Una interfaz IMoniker conteniendo la URL de la que se cargará
     el archivo HTML para el cuadro de diálogo. El archivo puede ser un
     recurso de la aplicación.

   PvarArgIn - Puntero a un registro VariantArg que contiene los datos
     enviados al cuadro de diálogo. Los datos pasados en este VariantArg
     se colocan en la propiedad IHTMLDialog::dialogArguments del objeto
     ventana de diálogo. Se establece principalmente como VT_BSTR, con un
     PWChar para el texto que el diálogo mostrará. Este parámetro puede
     establecerse como un VariantArg vacío (VT_EMPTY).

   PWCHOptions - Opciones de ventana para el cuadro de diálogo. Este
     parámetro puede ser NIL o la dirección de un PWChar conteniendo una
     combinación de valores separados por punto y coma (;).

     POptions := 'dialogHeight:13;dialogWidth:21;resizable:no;help:no;'
               + 'center:yes'

   PvarArgOut - Puntero a un registro VariantArg que contendrá los datos
     enviados desde el cuadro de diálogo cuando se cierre. Este
     VariantArg obtiene los datos que fueron puestos en la propiedad
     IHTMLDialog::returnValue del objeto ventana de diálogo. Este pará-
     metro puede ser un VariantArg vacío.

   Valor devuelto - Devuelve S_OK si fue exitosa, o un valor de error.

El segundo parámetro de ShowHTMLDialog es de tipo IMoniker. Para colocar
datos en un IMoniker debe usar la función CreateURLMoniker en la unidad
UrlMon.pas, definida a continuación:

   function CreateURLMoniker(
     MkCtx: IMoniker; // moniker a usar como contexto de base,
                      // puede ser NIL
     szURL: PWChar;   // contiene el texto de la URL a interpretar
     out mk: IMoniker // moniker con la nueva URL creada por MkCtx y
                      // szURL.
     ): HResult; // el resultado es un OLE HRESULT (Integer)

Esta cadena URL (szURL) debe ser prefijada con "file://" para significar
una ubicación de un archivo en disco, o con "res://" para significar una
ubicación de un recurso de programa, y en el caso de un recurso debe ser
seguida por un camino y nombre de archivo, y un "/#" precediendo el
número de recurso, como ésta para un archivo:

   UrlStr := 'file://C:\Program Files\HtmlDlg1.htm';

o

   UrlStr := 'file://' + ExtractFilePath(ParamStr(0)) + 'HtmlDlg1.htm';

y como ésta para un recurso:

   UrlStr := 'res://MyProgram.exe/#101';

o

   UrlStr := 'res://' + ExtractFileName(ParamStr(0)) + '/#101';
      ====>  el #101 se define en su archivo .rc de creación de recursos

El tercer y el quinto parámetro de ShowHTMLDialog son de tipo
PVariantArg, esto es, un Variant que Delphi no "decodifica" automáti-
camente por usted, así que tendrá que leer o escribir este variant
usted mismo con el tipo de datos variant .vt (VarArgs.vt) y luego usar
ese "tipo" de datos cuando use los datos del Variant.


Código de ejemplo para un diálogo HTML
======================================

Aquí va un código de clic de botón que mostrará cun cuadro de diálogo
HTML. No comprobé la versión de Internet Explorer puesto que no usé
DHTML u objetos COM disponibles en versiones superiores (5, 6, 7 , 8) de
IE. El código usa un archivo HTML en disco (HtmlDlg1.htm), en la carpeta
de la aplicación. Una cadena de texto (VarArgs.bstrVal) se envía al
diálogo con el título del diálogo, una cadena de texto de información, y
elementos de texto para colocar en el cuadro combinado. El código para
la página web HtmlDlg1.htm se encuentra más abajo en este artículo.

   uses ActiveX, ComObj, UrlMon;

   procedure TForm1.button_FileHtmlDlgClick(Sender: TObject);
   type
     TShowHTMLDialog = function(hwndParent: Cardinal;
       UrlMnk: IMoniker; PvarArgIn: PVariantArg;
       PWCHOptions: PWChar; PvarArgOut: PVariantArg): HRESULT; stdcall;
   var
     hLib2: Integer;
     ShowHTMLDialog: TShowHTMLDialog;
     URLMoniker: IMoniker;
     VarArgs, VarReturn: TVariantArg;
     ArugStr, UrlStr, Return: String;
     POptions: PWChar;
   begin
     Return := 'ERROR, la versión de IE es anterior a la 4 o no soporta '
             + 'diálogos HTML';
     hLib2 := LoadLibrary('MSHTML.DLL');
     if hLib2 <> 0 then
     try
       ShowHTMLDialog := GetProcAddress(hLib2, 'ShowHTMLDialog');
       if Assigned(ShowHTMLDialog) then
         begin
         // Se usa PvarArgIn para pasar datos al diálogo HTML. El variant
         // VarArgs se usará aquí como un PWChar, usando "^" como deli-
         // mitador para las siete subcadenas que se envían al diálogo
         ArugStr := 'Título diálogo HTML^Este es texto de información '
                  + 'pasado al diálogo<br>Ingrese su nombre abajo^'
                  + 'Pequeña^Mediana^Grande^Mi talla^Talla universal';
         // La primer subcadena es el título del diálogo, y la siguiente
         // subcadena es el texto (y HTML) que será escrito al HTML con
         // document.write(ArgArray[1]) en JScript. Note que usé tags
         // HTML en este texto. Esto le permite adaptar el diálogo en
         // base a datos de su programa. Las restantes subcadenas se
         // colocan el combo box
         VarArgs.vt := VT_BSTR;
         VarArgs.bstrVal := StringToOleStr(ArugStr);

         // UrlStr se prefija con  file://  para significar un archivo en
         // disco. Use  res://  para significar un recurso
         UrlStr := 'file://'+ExtractFilePath(ParamStr(0))+'HtmlDlg1.htm';
         // URLMoniker se establece con la URL del archivo HTML que se
         // usará como origen del cuadro de diálogo. Puede ser un archivo
         // un archivo en disco, un recurso de programa, o una dirección
         // de un archivo en Internet. Si no se encuentra el archivo HTML
         // se muestra un cuadro de diálogo en blanco
         OLECheck(CreateURLMoniker(nil, StringToOleStr(UrlStr),
           URLMoniker));

         POptions := 'dialogHeight:17;dialogWidth:23;resizable:no;'
                   + 'help:no;center:yes';
         // Se puede omitir POptions (poniéndola en Nil), pero le permite
         // establecer algunas opciones del diálogo, como ancho y altura
         VariantInit(OleVariant(VarReturn));
         // VariantInit establece el VarReturn.vt a VT_EMPTY
         if ShowHTMLDialog(Handle, URLMoniker, @VarArgs, POptions,
            @VarReturn) = S_OK then
         begin
           // El método window.returnValue de JScript automáticamente
           // establecerá VarReturn.vt al tipo de datos que se le asigne.
           // Yo sólo usé dos tipos de datos para window.returnValue: una
           // cadena de texto JScript (VT_BSTR  - OLE wide string) y un
           // entero (VT_I4), así que cualquier otro tipo de datos
           // variant indicará un error.
           if VarReturn.vt = VT_BSTR then
           begin
             Return := VarReturn.bstrVal;
             // Usé un "^" para delimitar VarReturn.bstrVal, pero el
             // primer caracter es el número del botón de radio, que
             // es menor que 9, así que no lo delimité, pues siempre
             // será un solo caracter (Return[1])
             Return := 'Se pulsó Aceptar'#10'Radio es '+Return[1]+#10
                     + 'Combo es '+Copy(Return,2,Pos('^',Return)-2)
                     + #10'Texto es '
                     + Copy(Return,Pos('^',Return)+1, 512);
           end else
             if VarReturn.vt = VT_I4 then
               Return := 'No se pulsó Aceptar'#10'VarReturn es '
                       + IntToStr(VarReturn.lVal)
             else
               Return := 'ERROR: El tipo de datos Variant no es entero '
                       + 'o cadena OLE';
         end else
           Return := 'ShowHTMLDialog FALLÓ';
       end;
     finally
       FreeLibrary(hLib2);
     end;
     ShowMessage(Return);
   end;


Código HTML para el diálogo de arriba
=====================================

Abajo se encuentra el código HTML para la página web "HtmlDlg1.htm", a
mostrarse en el cuadro de diálogo HTML creado por el código Delphi de
arriba. Para obtener funcionalidad de su cuadro de diálogo (presión de
botones, ingreso de textos, selección de combos) necesitará usar un
lenguaje de HTML script. Si no sabe HTML o algún lenguaje de HTML
scripting (JScript, JavaScript, VBscript), entonces los cuadros de
diálogo HTML no son para usted.

La propiedad window.dialogArguments es su acceso a los datos pasados por
el cuadro de diálogo. Habitualmente pasará al cuadro de diálogo una
cadena Wide String o un entero en su parámetro VarArgs. Si desea más de
un elemento de dato en su variant, puede usar una cadena delimitada y
luego el método Split:

   ArgArray = window.dialogArguments.split("^");

Split usará su único parámetro como el caracter delimitador, para
dividir la cadena en un arreglo. Recíprocamente, si necesita devolver
más de un dato desde el cuadro de diálogo, nuevamente puede usar una
cadena delimitada, como he hecho aquí:

   <html id=dlg1 style="width: 25.9em; height: 22em">
   <!-- Si NO usa PWCHOptions en la llamada a ShowHTMLDialog, puede poner
        el ancho y altura de la ventana arriba -->
   <head>
   <title>Diálogo HTML de prueba</title>

   <script language="JScript">
   var RBnum = 0;

   var ArgArray = new Array();
   // obtener los argumentos del diálogo en un arreglo con .split y el
   // delimitador
   ArgArray = window.dialogArguments.split("^");

   // La comprobación de ArgArray de abajo no es necesaria, pero le
   // permite tener un cuadro de diálogo predeterminado en caso de
   // llamar a ShowHTMLDialog con un PvarArgIn vacío
   if (ArgArray.length==0) {ArgArray[0]="Título del diálogo";}
   if (ArgArray.length==1) {ArgArray[1]="No <b>Información </b> Texto";}
   if (ArgArray.length==2) {ArgArray[2]="Ninguno";}

   // la primer cadena del arreglo es el título
   document.title = ArgArray[0];
   // establece el valor de retorno predeterminado
   window.returnValue = 0;

   function StartUp()
   {
   // limpia las opciones en Combo1
   Combo1.options.length = 0;

   // Agrega las cadenas de ArgArray a las opciones del Combo1
   var index;
   index = 2;
   // Comienza con un índice de 2 porque las primeras dos cadenas
   // eran el título y la información
   while(index < ArgArray.length)
      {
      var tempOption = new Option(ArgArray[index]);
      Combo1.options[Combo1.options.length] = tempOption;
      index++;
      }

   // Establece la primera opción del Combo1 como la seleccionada
   Combo1.options[0].selected = true;
   }

   function OkClick()
   {
   // Este valor de retorno significa que se presionó el botón Aceptar
   window.returnValue = RBnum+Combo1.options[Combo1.selectedIndex].text+
                        "^"+Edit1.value;
   // Dado que window.returnValue es un variant, no puede obtener texto,
   // números ni objetos
   // El entero RBnum se convierte automáticamente a texto
   // Cierra la ventana de diálogo
   window.close();
   }

   function CancelClick()
   {
   // El valor de retorno -1 significa que se presionó el botón Cancelar
   window.returnValue = -1;
   window.close();
   }

   function RadioClick(num)
   {
   RBnum = num;
   // Seleccionar y deseleccionar los botones de radio
   RB1.checked = (num == 0);
   RB2.checked = (num == 1);
   RB3.checked = (num == 2);
   }

   </script>
   </head>
   <body onload="StartUp()" BGCOLOR="#A0E2F2" TEXT="Black">
   <center>
   <font size="5"><b>Un Cuadro de Diálogo HTML</b></font>
   <!-- Usé tamaños de fuente fijos porque IE puede tener su fuente
   predeterminada como grande o pequeña, arruinando su tamaño, pero
   usted puede usar hojas de estilo para definir fuentes, colores y
   bordes -->
   <font size="3">
   <br><script language="JScript">
   // Una operación útil - document.write( )
   // La segunda cadena del arrglo es el texto informativo que se
   // escribe aquí
   document.write(ArgArray[1])
   </script>
   <br><input type=text name="Edit1" value="Sin nombre" size="24"
    title="Escriba su nombre aquí"><p>
   <table border="2" cellpadding="8" cellspacing="0">
   <tr>
    <td><font size="3"><input type=radio name="RB1" checked=1
      onClick="RadioClick(0)">Sr.<br>
     <input type=radio name="RB2" onClick="RadioClick(1)">Sra.<br>
     <input type=radio name="RB3" onClick="RadioClick(2)">Srta.</font>
    </td>
    <td><font size="3">Elija su talla - <select
     name="Combo1"></select></font>
    </td>
   </tr>
   </table>
   <P><input type=button value="Aceptar" id="OkBut" onClick="OkClick()"
    title="Presione aquí para usar las entradas de arriba">
   <input type=button value="Cancel" id="CancelBut"
    onClick="CancelClick()">
   </font>
   </center>
   </body>
   </html>

Hay siete subcadenas en el parámetro VarArgs de ShowHTMLDialog. La
primera se usa como el título del diálogo, la segunda es el texto
informativo escrito en la página HTML con JScript, y las subcadenas
restantes se añaden al cuadro combinado (combo box). Para cuadros de
diálogo HTML más avanzados también es posible establecer un enlace
IDispatch entre el cuadro de diálogo y su programa, de modo que el
cuadro de diálogo pueda llamar a código en su programa Delphi a través
de IDispatch.


Usando un recurso para su archivo HTML
======================================

Puede usarse el mismo código de arriba para un archivo HTML como recurso
de un programa, excepto que UrlStr debe cambiarse a

   UrlStr := 'res://' + ExtractFileName(ParamStr(0)+'/#101');
   OLECheck(CreateURLMoniker(nil, StringToOleStr(UrlStr), URLMoniker));

y debe añadirse un recurso a su programa donde se necesitará definir el
recurso HTML como número 23 y definir la llamada a ese recurso con un
número, como este para HtmDlg.rc:

   #define RT_HTML 23
   #define Dlg1 101

   Dlg1 RT_HTML "HtmlDlg1.htm"

Necesitará definir el RT_HTML como el número 23 (puede usar cualquier
otra designación aparte de RT_HTML, pero ese es el nombre MS), y luego
darle a sus archivos HTML un número como 101.

Si tiene un navegador o muestra páginas web en su programa, puede
considerar usar diálogos HTML.

__________________

Visite el sitio web de Wes Turner si desea aprender cómo hacer programas
a pura API sin la unidad Forms: http://www.angelfire.com/hi5/delphizeus/
Allí encontrará numerosos ejemplos de programación Windows básica.

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


3. Reemplazando el InplaceEditor estándar del TStringGrid
    Cómo modificar el TStringGrid para tener una lista de opciones o un
    botón con puntos suspensivos en la celda seleccionada

    Por Werner Palmer <werner.pamler @ infineon.com>


El TStringGrid es un componente Delphi ampliamente utilizado. Se puede
ingresar texto directamente en las celdas de la cuadrícula, pero a veces
es deseable usar editor "in-situ" alternativos, como un cuadro combinado
para elegir entre una lista de valores, o un diálogo de usuario llamado
cuando al pulsar el botón "[...]" en la correspondiente celda de la
cuadrícula. Mientras que éste es un comportamiento estándar para un
TDBGrid, no está disponible para la no enlazada a datos TStringGrid. Se
pueden encontrar algunas soluciones por toda la web, pero sin embargo,
la funcionalidad básica ya ha sido implementada en el ancestro de
cualquier cuadrícula, TCustomGrid. Trabajo con Delphi 6, y esto puede no
ser cierto para versiones anteriores.

El correspondiente editor in-situ que tiene todas las características
mencionadas puede encontrarse en la unidad Grids como TInplaceEditList.
Puede ser accedido derivando un nuevo componente desde TStringGrid, el
que aquí llamaremos TNewStringGrid. En este nuevo componente, el método
"CreateEditor" será reemplazado para usar TInplaceEditList como editor
in-situ (en vez del estándar TInplaceEdit). La nueva StringGrid también
hereda el método "GetEditStyle" que decide cuáles celdas usarán el nuevo
editor in-situ.

En la implementación de TNewStringGrid creamos un nuevo evento
"OnGetEditStyle" que llama al método GetEditStyle. El manejador del
evento recibe las coordenadas de la celda y devuelve el estilo del
editor (esSimple, esPickList o esEllipsis, tal como se define en
Grids.pas).

Adicionalmente para el estilo de editor esPicklist, tenemos que escribir
un manejador de evento para el evento "OnGetPickListItems" para pasarle
la lista de opciones (un TStringList) a la nueva StringGrid. Para el
estilo de editor esEllipsis, necesitaremos un manejador de evento para
el evento "OnEditButtonClicked" que se dispara cuando el usuario pulsa
el botón "[...]"; este manejador de evento por ejemplo podría abrir un
cuadro de diálogo complejo solicitando entrada del usuario y debería
llenar la celda con el correspondiente texto ingresado.

No se olvide de activar la opción goEditing de la StringGrid, o de otro
modo no podrá editar los datos de la cuadrícula.

Se adjunta la unidad NewStringGrid y un proyecto de ejemplo.

________________________________________________________________________

¡Vote por el Boletín Pascal en el DPSC Top 100 Programming web sites!
(sólo cliquea "here" donde dice "Click here to vote!", y eso es todo)
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
________________________________________________________________________


4. Usando los Shell Controls de Delphi

    Por Dave Murray <irongut @ vodafone.net>


Desde Delphi 6 en adelante, Borland provee Shell Controls, incluyendo
TShellTreeView y TShellListView, que imitan la funcionalidad del Explo-
rador de Windows, pero están escondidos en la página Samples (muestras)
de la Paleta de Componentes, no tienen documentación y hasta su código
fuente puede ser difícil de hallar (está en Delphi\Demos\ShellControls).
Puede perdonársele si piensa que son una ocurrencia tardía que no se
espera que usted use.

Recientemente quise construir mi propio cliente FTP porque no me gustan
ninguno de los gratuitos que evalué y pensé "tengo Indy, así que ¿cuán
difícil puede ser?" Probé la demo de TIdFTP, el componente Indy cliente
FTP, y la conexión de red parecía bastante fácil así que comencé a
pensar acerca del diseño. Quería algo simple y me decidí por una vista
del sistema de archivos local sobre una vista del sistema de archivos
remoto, con la barra de herramientas principal entre ambas vistas. Cada
vista contendría un TreeView y un ListView con unos pocos botones para
una navegación simple al estilo Explorador. También quería arrastrar y
soltar (drag and drop) entre los controles y con el Explorador. A esta
altura comencé a buscar componentes para implementar el lado local y
descubrí los Shell Controls de Borland. Decidí que esa clase de
disposición era algo que podía reutilizar, así que comencé a trabajar en
un marco genérico.

Así que, ¿cómo trabajan? Bien, alguna funcionalidad es fácil de
implementar pero en otras formas estos controles pueden ser difíciles
de usar y prestarse a confusiones. La mayoría de los métodos que uno
esperaría encontrar o no existen o devuelven parámetros de dudoso valor.
Frecuentemente son del tipo equivocado para otras llamadas que usted
quiera hacer. Lo que deberían haber sido un par de horas de programación
fácil rápidamente se transformaron en varias noches de lectura de código
fuente, experimentación y tirarse de los pelos. En algún punto de este
proceso decidí convertirlo en un artículo, así podría compartir mi dolor
con ustedes. ;)

Comencemos por lo fácil. Conecté mi TShellTreeView a un TShellListView y
comencé con la barra de herramientas. El primer botón que quería era uno
que subiera un nivel en el árbol de directorios y después de un poco de
mirar me di cuenta que el método TShellListView.Back haría esto por mí.
La mayoría de los otros botones que quería eran más difíciles, así que
volveré a ellos luego, pero un botón Vistas para el TShellListView
fue fácil. Simplemente creé un menú desplegable para mi botón que
estableciera TShellListView.ViewStyles. En este punto tenía un simple
administrador de archivos que que proveía características básicas de
navegación y el menú contextual estándar del Explorador de Windows.

Consideré añadir un TShellComboBox sobre la lista de archivos. Quería
que ajustara su tamaño con el marco como los otros controles, pero no
tiene una propiedad Align. Intenté usando Anchors pero no pude obtener
el efecto que quería, así que deseché la idea.

Ahora vamos a la parte más complicada. Los shell controls no proveen
métodos para ayudarnos a manipular archivos, así que necesitamos usar la
API de Windows. La función SHFileOperation() puede realizar las opera-
ciones de Copiar, Mover, Eliminar y Renombrar, así que escribí el
siguiente envoltorio para hacerla fácil de usar.

   function TconExplorerFrame.FileOperation(const source, dest : string;
     op, flags : Integer) : boolean;
   // Copia, mueve, elimina o renombra archivos y carpetas via WinAPI
   var
     Structure : TSHFileOpStruct;
     src, dst : string;
     OpResult : integer;
   begin
     // Inicializa la estructura de operación de archivo
     FillChar(Structure, SizeOf (Structure), #0);
     src := source + #0#0;
     dst := dest + #0#0;
     Structure.Wnd := 0;
     Structure.wFunc := op;
     Structure.pFrom := PChar(src);
     Structure.pTo := PChar(dst);
     Structure.fFlags := flags;
     case op of
       // Establece el título de un simple diálogo de progreso
       FO_COPY : Structure.lpszProgressTitle := 'Copiando...';
       FO_DELETE : Structure.lpszProgressTitle := 'Eliminando...';
       FO_MOVE : Structure.lpszProgressTitle := 'Moviendo...';
       FO_RENAME : Structure.lpszProgressTitle := 'Renombrando...';
       end; // case op of..
     OpResult := 1;
     try
       // realiza la operación
       OpResult := SHFileOperation(Structure);
     finally
       // reporta éxito / fracaso
       result := (OpResult = 0);
       end; // try..finally
   end; // function TconExplorerFrame.FileOperation

Esta función devuelve True si la operación fue exitosa, y muestra un
diálogo de progreso si es necesario. Fíjese en SHFILEOPSTRUCT en la
ayuda de WinAPI para ver los posibles valores y señales. Aún no me
decido si necesitaré acceso a esta función desde fuera de mi marco, así
que por el momento es un método privado, pero puedo cambiar esto en el
futuro.

Un botón Eliminar fue simple; todo lo que que tuve que hacer fue
determinar qué archivo o carpeta estaba seleccionado y eliminarlo
usando FileOperation().

Mientras hacía un botón Refrescar decidí escribir una función genérica
que podría ser llamada desde otros métodos y que refrescaría ambos
controles. TShellTreeView.Refresh toma un nodo como parámetro, pero
¿qué nodo pasarle? Intenté pasándole la carpeta actual, pero no siempre
funcionó (esto también parece ser un problema en el Explorador). Luego
probé pasándole el nodo raíz y esto funcionó apropiadamente. El control
TShellListView parpadea cuando refrescamos el TShellTreeView al que está
conectado, así que primero lo desconecto. Vea el procedimiento
TconExplorerFrame.Refresh en el fuente.

Al crear una nueva carpeta debemos darle un nombre único. La forma usual
de hacerlo es llamarla 'Nueva carpeta' y agregar un número al nombre si
esa carpeta ya existe. Escribí una función GetNewFolderName() que
devuelve el nombre único que necesitaba usando un bucle While y la
función DirectoryExists() de la unidad SysUtils.pas. Mi botón Crear
Carpeta llama a esta función y luego usa CreateDir() de SysUtils.pas.

Quería proveer un botón Propiedades pero los Shell Controls no tienen
ningún método útil. Como presionar Alt+Enter en un TShellListView
funciona, me metí en ShellCtrls.pas y revisé el código fuente. Inicial-
mente parecía simple, todo lo que tenía que hacer era llamar a
DoContextMenuVerb. O no, porque DoContextMenuVerb no es un método de
TShellListView sino un procedimiento privado de ShellCtrls.pas. En esta
etapa decidí que el plagio era el camino más fácil y lo copié en la
unidad de mi marco.

Hacer doble-clic a archivos en un TShellListView no funciona (en Win2k
por lo menos), pero elegir Abrir en el menú contextual sí. Revisando el
fuente tiene un método DblClick que llama a ShellExecute(). Entonces
noté TShellFolder.ExecuteDefault. Como un TShellFolder puede ser un
archivo o una carpeta y podemos obtener el elemento seleccionado como
un TShellFolder llamando a TShellListView.SelectedFolder, escribir un
evento OnDblClick fue fácil. Esto también asegura que doble-clic no
intente abrir el archivo sino que realice la acción predeterminada de su
menú contextual, que es lo que hace el Explorador. En el código fuente
vea TconExplorerFrame.shlllstvwFilesDblClick.

A esta altura tenía todo lo que quería, excepto arrastrar y soltar.
Nunca había programado arrastrar y soltar antes, así que tuve que hacer
algo de lectura antes de poner manos a la obra. Idealmente me hubiera
gustado poder cambiar el cursor si el usuario pulsaba Ctrl, como hace el
Explorador. Esto significaría usar un TDragControlObject para proveer
una imagen de arrastrar, así que decidí mantener las cosas simples por
ahora y descartar ese efecto.

Comencé con arrastrando desde mi TShellListView a mi TShellTreeView. Los
métodos y propiedades necesarias (con sus tipos de retorno correctos)
parecen no existir hasta que uno se da cuenta que la propiedad
SelectedFolder puede devolver tanto archivos como carpetas. Escribí un
evento OnDragOver para el TShellTreeView de modo que acepte elementos
del TShellListView comencé con su evento OnDragDrop. Rápidamente me
encontré conque no podía acceder al archivo arrastrado desde este
evento, así que decidí almacenarlo en una variable global a mi marco
durante el evento TShellListView.OnStartDrag y luego limpiarla en el
evento TShellListView.OnEndDrag. Tuve problemas también con la carpeta
destino, TTShellTreeView.GetNodeAt y TTShellTreeView.DropTarget
devuelven un TTreeNode pero para obtener el camino para una operación de
archivos quería un TShellFolder así que selecciono el DropTarget para
recuperar el SelectedFolder (un TShellFolder) y luego vuelvo a selec-
cionar la carpeta que estaba seleccionada previamente. Esto hace que el
TShellListView parpadee horriblemente (hasta puede verse el cambiar de
directorio), así que probé usando TShellListView.Items.BeginUpdate y
EndUpdate pero no resultó, de modo que tuve que desconectarlo del
TShellTreeView, realizar las operaciones seleccionadas y luego volver
a conectarlo. Es desagradable y no me gusta, pero funciona. El evento
OnDragDrop no provee información acerca del teclado y deseaba una
operación de Copia si el usuario está presionando Ctrl al terminar de
arrastrar. Usé la función GetKeyState() de la Jedi Code Library
(JCLSysInfo.pas) para esto.

Una vez funcionando el arrastre desde mi TShellListView modifiqué mis
eventos OnDragOver y OnDragDrop para también aceptar una carpeta
arrastrada desde mi TShellTreeView y le agregué al mismo los eventos
OnStartDrag y OnEndDrag. Estos seis eventos proveen todas las caracte-
rísticas requeridas para soltar un archivo en el TShellTreeView desde
dentro del marco. Para mantenerlo simple, sólo permito al usuario
seleccionar y arrastrar de a un elemento por vez.

El Explorador le permite arrastrar una carpeta desde el árbol hasta la
lista de archivos, y arrastrar archivos a carpetas dentro de la lista.
Pero arrastrar una carpeta de un TShellTreeView selecciona y muestra esa
carpeta y en cualquier caso TShellListView.DropTarget siempre devuelve
Nil! Debido a esto no pude encontrar ninguna forma de implementar esas
características. :(

Habiendo hecho lo que pude para proveer arrastrar y soltar dentro de mi
marco, ahora quería hacerlo trabajar con el Explorador. Para aceptar un
archivo soltado desde el Explorador usamos mensajes de Windows y no
estaba seguro de si eso afectaría mis eventos de arrastrar y soltar,
pero me complació descubrir que no. No obstante, tuve algunos problemas
en hacerlo funcionar apropiadamente. Debemos llamar a DragAcceptFiles()
con el manejador (handle) del control que aceptará archivos para
decirle a Windows que le envía el mensaje de soltar archivos, pero
TFrame no tiene un evento OnCreate y no podemos referirnos a sus
componentes o a él mismo en la sección de inicialización. Hubiera
querido que mi marco estuviera totalmente encapsulado pero tuve que
resignarme a llamar a DragAcceptFiles() en el evento OnCreate del
formulario que lo contiene. Inicialmente quería pasarle el manejador
(handle) de mi TShellListView de modo que los archivos sólo pudieran
soltarse allí, pero necesitaría un mensaje WMDROPFILES para el
TShellListView, por lo que terminé aceptando archivos desde cualquier
parte del marco pasándole su manejador (handle). Una vez que resolví
estos problemas, el resto fue fácil.

El procedimiento TconExplorerFrame.WMDROPFILES maneja el mensaje de
soltar. Usa la API DragQueryFile() para determinar la cantidad de
elementos siendo soltados y luego la usa de nuevo para obtener el
camino completo de un elemento a medida que itera por la lista. Windows
automáticamente nos provee con un cursor de Copia y presionar Ctrl o
Shift no tiene efecto, de modo que copio los elementos a la carpeta
actualmente mostrada en mi TShellListView.

También quería poder arrastrar archivos al Explorador u otras instancias
de mi programa de prueba, pero no pude encontrar ningún artículo o truco
que explique cómo hacerlo. Hubiera esperado que habilitar arrastrar
desde el Explorador pudiera darme una de esas características como un
efecto colateral o ayudarme a descubrir cómo hacerlo, pero no fue así.
Pienso que tal vez necesitaría construir mi propio descendiente de
TCustomShellListView que fuera "drag-enabled" con el shell, pero no sé
por dónde comenzar.

Así que este es el fin de mi exploración con los Borland Shell Controls.
Si alguien sabe como arrastrar de Delphi a otras aplicaciones o puede
sugerir otras mejoras a mi marco, por favor contácteme. Los fuentes de
mi marco y el programa de prueba están en el archivo adjunto; siéntanse
libres de usarlos en sus propios programas.

________________________________________________________________________

          ¡Vote por el Boletín Pascal en The Programming Pages!
       http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
________________________________________________________________________


5. Inline Assembler en Delphi (X) - Sonido con el altavoz del PC


Las instrucciones ensamblador IN y OUT nos permiten leer y escribir un
puerto de E/S respectivamente.

Para leer un puerto:

   in acumulador, puerto

IN lee un byte, palabra o doble-palabra (8, 16 o 32 bits) del puerto
especificado, y almacena el resultado en el registro acumulador, es
decir en AL, AX, o EAX para un puerto byte, palabra o doble-palabra
respectivamente. El número de puerto puede ser una constante byte
(0..255) o el registro DX (para así tener acceso a todos los puertos
de E/S).

Para escribir en un puerto:

   out puerto, acumulador

OUT escribe en el puerto especificado el byte, palabra o doble-palabra
que está en el registro acumulador (AL, AX, o EAX ). De nuevo, el número
de puerto puede ser una constante byte en el registro DX.

NOTA: Puesto que IN y OUT implican acceso directo al hardware y dado que
       Windows NT/2000/XP no permite eso para aplicaciones de usuario,
       entonces esas instrucciones no funcionarán (generarán una excep-
       ción) bajo esos sistemas operativos (a menos que corran en modo
       protegido en el anillo 0, también conocido como modo kernel).

Aquí veremos un ejemplo de uso de ensamblador para leer y escribir
puertos de E/S con el fin de programar los chips Contador/Temporizador
8253/8254 e Interfaz Periférica Programable 8255 (PPI) en la placa madre
para hacer que el altavoz del PC ejecute un sonido.

Los pasos para ejecutar un sonido usando esos chips son los siguientes:

1) Preparar el 8253/8254 para recibir la frecuencia. Esto se hace
     escribiendo el valor $B6 en el Registro de Control del Temporizador
    (puerto $43).

2) Escribir la frecuencia del sonido en el Registro de Frecuencia del
    8253/8254 (puerto $42). En realidad, no es la frecuencia en Hertz lo
    que debemos escribir en el registro, sino el resultado de dividir
    1331000 por esa frecuencia. Primero se escribe el byte de orden más
    bajo del resultado, y después el byte de orden más alto.

3) Activar el altavoz y hacer que use el Temporizador 8253/8254. Esto
    se hace encendiendo los primeros dos bits del Puerto B del PPI 8255
    (puerto $61).

4) Apagar el altavoz cuando el sonido deba detenerse. Esto se hace
    apagando el segundo bit del Puerto B del PPI 8255 (puerto $61).

La siguiente función en ensamblador nativo implementa los pasos listados
arriba:

   procedure SpeakerSound(Frecuencia: word; Duracion: longint);
   // Copyright (c) 2003 Ernesto De Spirito
   // Visite: http://www.latiumsoftware.com
   // Ejecuta un tono por el altavoz del PC usando los chips
   // Contador/Temporizador 8253/8254 e Interfaz Periférica
   // Programable 8255 (PPI) en la placa madre de la PC.
   // NOTA: Este código no funcionará bajo Windows NT/2000/XP.
   asm
     push edx          // Empujar Duracion en la pila (para Sleep)
     mov cx, ax        // CX := Frecuencia;
     // Preparar el 8253/8254 para recibir los datos de la frecuencia
     mov al, $B6       // Función: Esperar datos de la frecuencia
     out $43, al       // Escribir en el Timer Control Register
     // Calcular los datos de la frecuencia
     mov dx, $14       // DX:AX = $144F38
     mov ax, $4F38     //       = 1331000
     div cx            // AX := 1331000 / Frecuencia;
     // Enviar los datos de la frecuencia al chip 8253/8254
     out $42, al       // Escribir el byte de orden bajo
     mov al, ah        // AL := Byte de orden alto de AX
     out $42, al       // Escribir el byte de orden alto
     // Decirle al PPI 8255 que comience el sonido
     in al, $61        // Leer el Puerto B del PPI 8255
     or al, $03        // Encender los bits 0 y 1:
                       // bit 0 --> usar el 8253/8254
                       // bit 1 --> activar el altavoz
     out $61, al       // Escribir al Puerto B del PPI 8255
     // Esperar
     call Sleep        // Sleep(Duracion); // requiere la unidad Windows
     // Decirle al PPI 8255 que detenga el sonido
     in al, $61        // Leer el Puerto B del PPI 8255
     and al, NOT 2     // Limpiar el bit 1 (desactivar el altavoz)
     out $61, al       // Escribir al Puerto B del PPI 8255
   end;

Llamada de ejemplo:

   procedure TForm1.Button1Click(Sender: TObject);
   var
     i: integer;
   begin
     Randomize;
     for i := 1 to 3 do
       SpeakerSound(Random(900)+100, 200);
   end;

NOTA: El uso del altavoz incorporado del PC para producir sonidos es
       OBSELETO. En su lugar, las aplicaciones deberían usar sonidos
       MIDI o WAVE.

________________________________________________________________________

¿Errores Delphi?  Capture y registre cada error mostrando unidad, clase,
método y número de línea. http://www.eurekalog.com/bannerclick.php?id=15
________________________________________________________________________


6. Foros / listas de correo


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-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@...

* 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

________________________________________________________________________

   Merlin's Delphi Forge
   Delphi and Kylix news, FAQ, downloads, links, forums and more.
   Accepting uploads and submissions.
   http://www.delphifaq.net/
________________________________________________________________________


7. Delphi en la Red

    Por Dave Murray <irongut @ vodafone.net>


Componentes, librerías y aplicaciones
=====================================


Shareware/Comercial
-------------------

* InterBase 7.1 Trial - por Borland
   http://community.borland.com/article/0,1410,30157,00.html

* Versión de prueba de C#Builder Enterprise disponible para descarga
   http://bdn.borland.com/article/0,1410,30278,00.html

* Edición personal de C#Builder 1.0 disponible para descarga. Esta
   edición está limitada a desarrollo gratuito no comercial.
   http://bdn.borland.com/article/0,1410,30203,00.html


Freeware
--------

* TurboPower OfficePartner v1.64b - by TurboPower (with source)
   OfficePartner is the easy way to integrate your project with Microsoft
   Office. With OfficePartner you can access COM services in Office with
   easy to use VCL components.
   http://sourceforge.net/projects/tpofficepartner/

* KeyNote v1.6.1, by Marek Jedlinsky - Free (MPL 1.1) with source
   Keynote is a flexible, multi-featured tabbed notebook, based on
   Windows standard RichEdit control. It's always accessible with a
   single keypress, even if you work in another application. The basic
   idea in KeyNote is that you can include many separate notes within a
   single file. Features include strong data encryption, styles, macros,
   plugins, and templates. Delphi source code available.
   http://www.tranglos.com/free/keynote.html

* DScriptVCL - by DelphiScript (freeware, source code available for $49)
   Give Winamp's look & feel and GUI quality to your applications with
   DScriptVCL, a set of visual components for Delphi 5/6/7. DScriptVCL
   includes Main Forms, Menus, Panels, Leds, Numeric Displays, Progress
   Bars, Buttons, Checkboxes and many more other graphical components.
   http://www.delphiscript.com/dscriptvcl/

* WinAmpDll - by Ivan Spiridonov (with source)
   A DLL Project which shows how to create WinAmp General Purpose Plugins
   for WinAmp.
   http://www.torry.net/vcl/mmedia/other/wagppdll.zip

* Keyboard Macro Manager v1.0 - by Daniel Cunningham
   Delphi IDE Enhancement for saving / restoring keyboard macros.
   http://www.torry.net/vcl/experts/ide/keymac.zip

* TssSimpleIPC v1.0 - by Sunisoft (with source)
   TssSimpleIPC is a component for Interprocess Communications.
   Properties: IPCName - specifies the name of IPC, communications will
   be valid between the components in different process with same name.
   Events: OnTextMsgRecieved - occurs when another component in different
   process with same name sent some text message; OnBinMsgRecieved -
   occurs when another component in different process with same name has
   sent a binary message. Methods: SendTextMessage - send text message;
   SendBinMessage - send binary message.
   http://www.torry.net/vcl/internet/irc/simpleipc.zip

* QTest v1.9 - by Michael Johnson (with source)
   Delphi friendly way to create test cases for test-centric coding (ala,
   extreme programming). Update includes logging capability, more detail,
   and some expansion of the methods of testing.
   http://www.bigattichouse.com/qtest.php

* QSetup Installation Suite 4.0.0.4 (28-AUG-2003) - by Pantaray Research
   Highly effective and powerful setup program featuring a user-friendly
   and intuitive user interface designed to let you create high quality
   sophisticated installation delivery with minimum effort and no script
   programming. QSetup is FREE for independent software developers.
   http://www.pantaray.com/


Actualizaciones de Delphi y otros productos Borland
---------------------------------------------------

* Fixes for Kylix 3 issues on newer distros (updated) - Andrés Colubri
   Kylix 3 (particularly the C++ part) on newer Linux distributions (eg.
   RedHat 8 & 9, Madrake 9 & 9.1, SuSE 8.2) has a number of problems:
   compilation errors with STL, unresolved references when linking,
   installer and IDE hangs, etc. This package contains a collection of
   fixes that (hopefully) addresses these problems.
   http://codecentral.borland.com/codecentral/ccweb

* First Update Pack for C#Builder available to registered users
   http://bdn.borland.com/article/0,1410,30287,00.html


Artículos, trucos y consejos
============================

* InterBase 7.1 Trial Technical Specifications - Sriram Balasubramanian
   Capabilities of the InterBase 7.1 Trial version.
   http://community.borland.com/article/0,1410,30151,00.html

* The Coad Letter 110: Announcing UML 2.0 - by Randy Miller
   The UML 2.0 Specification has been approved by the OMG. The final
   editing process is going on and the specification is set to be
   released to the public by the end of the year. Here is what is new.
   http://community.borland.com/article/0,1410,30144,00.html

* What's New in UML 2? The Use Case Diagram - by Randy Miller
   This article examines a new element of the use case diagram in UML 2.0
   including multiplicities and conditions on "extends" relationships.
   http://community.borland.com/article/0,1410,30166,00.html

* Business Rules - by Randy Miller
   This article looks at business rules in a modeling and development
   environment.
   http://community.borland.com/article/0,1410,30158,00.html

* InterBase Community Tools and Solutions - by Aaron Ruddick
   Third party tools and solutions for InterBase.
   http://community.borland.com/article/0,1410,30126,00.html

* Interview with Steve McConnell - by Clay Shannon
   Steve McConnell, the author of several important programming books
   including "Code Complete", "Rapid Development", "Software Project
   Survival Guide", and "After the Gold Rush" answers questions about his
   current projects.
   http://community.borland.com/article/0,1410,29921,00.html

* Get Your Delphi Apps off to a Fast Start - by Clay Shannon
   Explains how and why you should create a template project. This can
   save you a lot of time whenever you begin a new Delphi project, as the
   normal "setup work" you do will already be done - setting properties,
   adding forms and units, etc.
   http://community.borland.com/article/0,1410,29907,00.html

* Interview with Lino Tadros - by Clay Shannon
   Lino Tadros talks about creating the first ActiveX control ever
   written with Delphi, a practical joke he played on some of his
   employees, why he eschews the newsgroups lately, who he impersonates,
   and the new magazine he is writing for.
   http://community.borland.com/article/0,1410,30085,00.html

* Simple Programming Tip #2 - by Charlie Calvert
   A discussion of benefits to be derived from using testing tools such
   as JUnit, DUnit, NUnit or CppUnit. The heart of the argument is that
   such tools encourage programmers to create highly modular, reusable
   classes that are easy to maintain.
   http://community.borland.com/article/0,1410,30049,00.html

* Are We Not Geeks? - by Clay Shannon
   Why is programming the least understood of all professions? There is
   a conspiracy to defame us! Hollywood and Madison Avenue don't want us
   to come out from behind our cubicle walls. A tongue-in-cheek take on
   how programmes are viewed.
   http://community.borland.com/article/0,1410,29920,00.html

* Interview with Chad "Kudzu" Hower - by Clay Shannon
   Chad "Kudzu" Hower, prime mover behind Indy and IntraWeb, talks about
   the future of Delphi, what he thinks of .NET, how to bring about world
   peace, why he rarely reads computer books, and other things.
   http://community.borland.com/article/0,1410,30038,00.html

* Disseminating Your Software - by Clay Shannon
   The difference between deployment and dissemination of software is
   discussed, as is the relative merits of hosting your own software or
   outsourcing that chore. DIY vs. outsourcing is also examined relative
   to the processing of payments.
   http://community.borland.com/article/0,1410,29931,00.html

* InterBase 7.1 DataType to ADO.NET C# Type mappings - by Borland
   Developer Support Staff
   InterBase SQL datatypes and C# Object Type mappings using the
   InterBase Borland Data Provider (BDP).
   http://community.borland.com/article/0,1410,30108,00.html

* Distributed Information Systems, From A to Z: Part I - Serge Dosyukov
   This article is a first in a series discussing several aspects of
   building distributed information systems using Delphi 7 and Indy.
   http://community.borland.com/article/0,1410,30025,00.html

* Interview with Ray Lischner - by Clay Shannon
   Ray Lischner talks about his books, how he backed into programming,
   his keyboard deafness, the extent of his multilingualism, C#, his
   predictions for a post-.NET Borland and what he's working on.
   http://community.borland.com/article/0,1410,30013,00.html

* Life cycle of a Database Application - by Oleg Meeting
   Analyses a database project's life pattern and concludes some useful
   recommendations for developers.
   http://community.borland.com/article/0,1410,28994,00.html

* This Old Pipe - by Randall Nagy
   Few appreciate how much modern computing relies upon pipes and
   streams. This article reviews how to apply these elegant IPC
   mechanisms to your console and GUI applications.
   http://community.borland.com/article/0,1410,29772,00.html

* Using XMLBroker with IntraWeb - by Guinther Pauli
   This article will explain how to use the XMLBroker in a IntraWeb
   application, caching data and updates in browser. And finally, how to
   solve this updates to database server.
   http://community.borland.com/article/0,1410,29860,00.html

* Advanced Dynamic Packages - by Vino Rodrigues
   Topics covered include: Calling Custom Class Methods, Calling Standard
   Functions and Procedures, Obtaining Package Information and Obtaining
   Knowledge of Class Names.
   http://community.borland.com/article/0,1410,29119,00.html

* Creating Custom Windows Event Logs - by Dennis Passmore
   Explains what is involved in creating custom event logs and why they
   will come in handy to monitor your applications.
   http://www.thedelphimagazine.com/samples/1655/1655.htm

* Adding Regular Expression Filtering to ShellListView - George Merriman
   How to add regular expression (filename) filtering to the Delphi file
   explorer application.
   http://delphi.about.com/library/weekly/aa052503a.htm

* Shell Controls: Delphi's Hidden Gems - by George Merriman
   How to create a reasonable Delphi facsimile of the Windows Explorer,
   all without writing a single line of code.
   http://delphi.about.com/library/weekly/aa052503a.htm

* Records in Delphi: Part 1 - by Zarko Gajic
   Learn about records, Delphi's Pascal data structure that can mix any
   of Delphi's built in types including any types you have created.
   http://delphi.about.com/library/weekly/aa062700a.htm

* Records in Delphi: Part 2 - by Kevin S. Gallagher
   Why and when to use variant records and creating an array of records.
   http://delphi.about.com/library/weekly/aa070803a.htm

* TNumEdit - by Michael Klaus
   TNumEdit is a TEdit descendant that only accepts numerical input. You
   can adjust whether to accept positive or negative numbers, integers or
   decimals. You can also limit the input by using MinValue and MaxValue.
   http://delphi.about.com/library/weekly/aa070603a.htm

* About Delphi Programming *Current Headlines* - by Zarko Gajic
   Put About Delphi Programming *Current Headlines* on your web site for
   FREE! Get the *Current Headlines* without leaving the Delphi IDE using
   the free Delphi IDE add-on.
   http://delphi.about.com/library/blsticker.htm

* How to execute a Javascript function in a Webbrowser/ IE Document?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1732

* How to display the items in a listview control display as a group (XP)?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1782

* How to know when a form is activated or deactivated?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1775

* How to Determine if you are running inside Virtual PC?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1756

* How to implement a Linked List Memory Table?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1758

* How to get the server (router) and client IP address of your dial-up
   connection? - by Sunish Issac
   There are quite a lot of articles on retrieving IP addresses for LAN
   interfaces. Here's one for dialup using RAS(Remote Access Services).
   http://www.delphi3000.com/articles/article_3683.asp

* Changing the z-order of controls - by Daniel Wischnewski
   Move your control step-by-step.
   http://www.delphi3000.com/articles/article_3684.asp

* RAVE Export Device for EMF, WMF and Bitmaps - by Julian Ziersch
   How to implement a generic RAVE render device.
   http://www.delphi3000.com/articles/article_3685.asp

* How To Use MSAccess In Delphi (using BDE Components) - by Ameenudeen M
   Methods to access data in MS Access Database from Delphi Application
   using standard BDE Components.
   http://www.delphi3000.com/articles/article_3687.asp

* Handle OleExceptions - by Andreas Schmidt
   A EOleException has more information than the default handler shows.
   http://www.delphi3000.com/articles/article_3694.asp

* DialogUnits To Pixels - by Jean Claude Servaye
   How to convert dialogs units in pixels if the dialog do not use the
   system font.
   http://www.delphi3000.com/articles/article_3695.asp

* Check for exe files and DLLs - by Peter Johnson
   This article looks at how we examine a file to check if it is a DOS or
   Windows executable and, if so, whether it is a program file or a DLL.
   http://www.delphi3000.com/articles/article_3696.asp

* TreeView+ComboBox - by Eugine Veselov
   How to create a combobox which has a popup treeview.
   http://www.delphi3000.com/articles/article_3699.asp

* Converting ASCII to Paradox - by gourari noureddine
   Exports delimited file to a Paradox table.
   http://www.delphi3000.com/articles/article_3700.asp

* Dynamic ODBC DSN create and ADV MS-SQL Login - by Mike Heydon
   This class adds dynamic ODBC Alias/DSN generation at run-time. Also
   featured is two login modes, one that lets the programmer handle
   returned errors and another that stays in a loop with error messages
   that allows retry and Alias/DSN user setup. There are also properties
   that set and retrieve ODBC Alias/DSN driver and dsn settings such as
   CPTimeout, Version etc.
   http://www.delphi3000.com/articles/article_3702.asp

* Advanced exception handler to find the exception source file name,
   call stack and all other related information - by Clever Components
   This article describes how to replace the standard Delphi exception
   handlers with advanced ones in order to get more control over all
   errors occuring during run-time execution. It is possible to collect
   very detailed information about all occured exceptions and save this
   information for later use without any interference with end-user.
   http://www.delphi3000.com/articles/article_3703.asp

* Using TList's and Pointers in Delphi - by Stewart Moss
   A small demonstration that shows how to use the TList helper object
   and how to use pointers. It creates a list of Pointers to Integers but
   they could be a list of pointers to any record or class type.
   http://www.delphi3000.com/articles/article_3705.asp

* Component to Monitor Clipboard - by Enrique Ortuño
   http://www.delphi3000.com/articles/article_3708.asp

* Direct File Access with a StringGrid - by Max Kleiner
   From time to time we need to populate a StringGrid from a file and
   save it to a file in a well defined structure like a record. Here's a
   way to handle this with a contol class.
   http://www.delphi3000.com/articles/article_3709.asp

* Converting a floating point value to an integer value - by Jim Carter
   Real to Integer typecasting.
   http://www.delphi3000.com/articles/article_3712.asp

* Methods for Cutting and Pasting SQL Select Order by Clause - A. Wijoyo
   Most of data access components don't have method for sorting in memory
   records. So the only way for sorting records is add an order by clause
   to the query and reopen it. These method make this task easier to do.
   http://www.delphi3000.com/articles/article_3715.asp

* Inline-editing with a TTreeView - by Omer Can
   http://www.delphi3000.com/articles/article_3720.asp

* TTreeView descendant showing LAN hierarchy - by Eugine Veselov
   This component shows your LAN resources represented as a tree.
   http://www.delphi3000.com/articles/article_3721.asp


White Papers / Casos de estudio
-------------------------------

* Case Study: Smart Restaurant Solutions
   See how Smart Restaurant Solutions took advantage of Delphi 7 Studio
   to deliver a Web Services-based solution to keep ahead of the
   competition.
   www.borland.com/products/case_studies/delphi_smart_restaurant.html


Tutoriales y capacitación
=========================

* BorCon 2003 to be be held in San Jose, California November 1-5, 2003
   http://info.borland.com/conf2003/

* Borland Web Seminars
   The Borland Web Seminar Series is designed to address the latest in
   development, deployment, and integration technologies.
   http://info.borland.com/web_seminar/

   Available Web Seminars include:
   - Delivering high-performance applications for the Microsoft .NET
     Framework
   - Simplifying Integration of the Microsoft .NET Framework with
     J2EE/CORBA
   - Driving Alignment of IT Initiatives with Business Goals
   - Why Upgrade to JBuilder 9
   - Accelerating Productivity with Agile Modeling
   - Introduction to the Borland Embedded Databases
   - Performance Management for J2EE Systems

* Writing MS SQL Server Extended Stored Procedures with Delphi
   By Berend de Boer
   Presents a framework which makes writing Microsoft SQL Server Extended
   Stored Procedures a breeze with four sample xp's (Extended Stored
   Procedures) shown and discussed.
   http://www.berenddeboer.net/article/1293.zip
   Source code: http://www.berenddeboer.net/article/1293_C.zip

* Integrating with Outlook - By Berend de Boer
   This article explores the possibilities of using Microsoft Outlook as
   an extension of your program, or vice versa, your program as an
   extension of Outlook. The article gives you a good idea of Outlook's
   object model. You'll be able to integrate straight into Outlook itself
   by extending Outlook's menu and toolbars. After reading this article
   you should be able to program and control Outlook, sending mail and
   reading contacts. Also you should have a good start in writing
   Exchange Extensions.
   http://www.berenddeboer.net/article/1292.zip
   Source code: http://www.berenddeboer.net/article/1292_C.zip


Otros enlaces
=============

* i-griegavcl
   Sitio dedicado a la programación de componentes (VCL) Delphi con
   código fuente.
   http://www.i-griegavcl.com/

* TodoProgramacion
   Página dedicada a la programación en general. Aquí podrá encontrar
   documentación, código fuente, programas, foros, noticias, cursos
   on-line y muchas cosas más.
   http://www.todoprogramacion.miarroba.com

* AjpdSoft
   Programas gratuitos con código fuente, y trucos para Delphi.
   http://www.ajpdsoft.com

* Borland Partner CDs are online - by John Kaster
   The partner CD submissions for Borland's latest IDE products are
   available for download.
   http://community.borland.com/article/0,1410,29797,00.html

* Delphi-PRAXiS
   Delphi community for German speaking programmers.
   http://www.delphipraxis.net


Noticias
========

* Borland Upgrades Embedded Database - by Paul Krill
   Borland Software introduced InterBase 7.1, a cross-platform embeddable
   database that adds support for Windows Server 2003.
   http://www.infoworld.com/article/03/06/17/HNinterbase_1.html?platforms

* BorCon 2003 to be be held in San Jose, California November 1-5, 2003
   http://info.borland.com/conf2003/

   Other Borland conferences around the world:

   - EKon 7 - 7th German/Borland Developers Conference - Frankfurt -
     September 21-26, 2003
     http://www.entwicklerkonferenz.de
     http://www.entwicklerkonferenz.com/

   - Borland Conference Europe - Amsterdam - November 10-12, 2003
     http://www.europeanborlandconference.com/

   - Borland Conference France - Paris - December 10-11, 2003
     http://info.borland.fr/conference/2003/

* Open Letter to the Borland C++ Developer Community - by J.P. LeBlanc
   Learn about the future of the Borland C++ product line...
   http://bdn.borland.com/article/0,1410,30279,00.html

________________________________________________________________________

          ¡Vote por el Boletín Pascal en The Programming Pages!
       http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
________________________________________________________________________


¡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@...

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.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
http://news.optimax.com/topdelphi/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://www.top219.org/cgi-bin/vote.cgi?delphi&83
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
http://213.65.224.200/cgi-bin/toplist.cgi/hits?Id=80
http://www.programacion.net/votar-enlace.php?id=474
http://www.lawebdelprogramador.com/buscar/enlace.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/descarga/p0048.zip
________________________________________________________________________

Página del grupo:  http://espanol.groups.yahoo.com/group/boletin-pascal/
Para suscribirse / apuntarse:   boletin-pascal-subscribe@...
Para cancelar / removerse:    boletin-pascal-unsubscribe@...
¿Problemas con tu suscripción?      boletin-pascal-owner@...
________________________________________________________________________

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) 2003 por Ernesto De Spirito. Todos los derechos reservados
________________________________________________________________________

#14 De: "Ernesto De Spirito" <edspirito@...>
Fecha: Mar, 27 de May, 2003 6:42 am
Asunto: Boletín Pascal #47 - 27-MAY-2003
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #47 - 27-MAY-2003

Índice

1. Unas palabras del editor
2. Lineamientos sobre el rendimiento de Interbase (y II)
    - Configuración de Interbase
       · Backup / Restore (respaldo/restauración) regulares
       · Clase de Prioridad de Interbase
       · Desactivar la escritura asincrónica
       · Deshabilite la recolección de basura (garbage collection)
       · El parámetro Lock hash slots
       · Tamaño de página de la base de datos
       · Parámetros de memoria de trabajo (Working Set)
       · Caché de la base de datos
    - Consideraciones para el desarrollo
       · Siempre trabaje con la menor cantidad de datos posible
       · No mantenga las transacciones abiertas más tiempo del necesario
       · Sistemas grandes, montones de tráfico, mantenga sus tablas de
         búsqueda (lookup) en el cliente
       · Programe directamente a la API de Interbase
       · Utilice una conexión remota
       · Llene completamente y pruebe su sistema durante el desarrollo
       · Prepare y parametrice sus consultas
       · Componentes VCL
       · Piense en lo que está haciendo
       · Algo será lento
       · Use el cliente
       · Vea lo que su aplicación realmente hace en lugar de lo que Ud.
          piensa que hace
       · Utilice componentes de acceso nativo
       · Buscando registros
    - Otras formas de mejorar el rendimiento
       · Actualice Interbase
       · Bases de datos de sólo lectura
3. Usando Cabinet.dll para crear sus propios archivos de gabinete (.CAB)
4. Detectando clics-derechos en la barra de título de sus formularios
    Cómo impedir que se muestre el menú contextual de la barra de título
5. Notas de un desarrollador (II)
    Convertir archivos gráficos de distinto tipo
6. Mediciones de tiempo de alta precisión
    Utilizando QueryPerformanceCounter para obtener tiempos de alta
    resolución
7. Inline Assembler en Delphi (IX) - Aritmética entera de 128 bits (3)
8. Foros / listas de correo
9. Delphi en la Red
    - Componentes, librerías y aplicaciones
      · Shareware
      · Freeware
      · Actualizaciones de Delphi
    - Artículos, trucos y consejos
    - Tutoriales
    - Otros enlaces
    - Noticias

________________________________________________________________________


1. Unas palabras del editor


Como de costumbre, debo pedir disculpas por la demora en la publicación
de este número. Ya saben cómo es...

En el código del artículo "Enumerando las conexiones de red" publicado
en la edición pasada, la memoria asignada por la llamada a GlobalAlloc
no era liberada por GlobalFree porque el puntero era modificado en el
camino puesto que se lo usó para iterar a través de los elementos de la
enumeración. Debería usarse un puntero auxiliar para ese propósito,
preservando así el valor asignado por GlobalAlloc. Gracias a Wim van
Nifterick por descubrir este error, y ya que estamos, vaya un agrade-
cimiento especial a Bill Boulton por ayudarme con la compatibilidad para
Delphi 3, y otro para Ernesto Cullen por la traducción del artículo
sobre rendimiento de Interbase.

Ahora toca el turno de agradecer a los autores que contribuyeron
artículos para esta edición: Peter Mc Leod, Vimil Saju, James Clements,
Alirio A. Gavidia y Michael Darling, y me complace entregarles los
premios para esta edición a:

* Vimil Saju (Usando Cabinet.dll para crear sus propios archivos de...)
· SDL Component Suite 7.0 - por Software Development Lohninger ($99)
   La SDL Component Suite provee un amplio rango de componentes para la
   ciencia y la ingeniería, por ejemplo matemáticas, estadísticas,
   química, diagramas, visualización de datos, transformadas de Fourier
   (FFT), ploteos 3D, mapas geográficos, ajuste de curvas, etc.
   Disponible para Delphi 3-7 y BCB 4-6.
   http://www.lohninger.com/sdlindex.html

* James Clements (Detectando clics-derechos en la barra de título de...)
· NTTools 7 For Delphi - por i-tivity (USD 39.95)
   ¡Basta de batallar con la API de Seguridad de Windows NT! Obtenga su
   copia de NTTools 7 para Delphi 4/5/6/7 ahora y ahórrese incontables
   horas con esta colección de 40 componentes VCL escritos específica-
   mente para tratar con las funciones de Seguridad de Windows NT. Se
   incluye código fuente completo.
   http://www.i-tivity.biz/nttools.htm

Para la próxima edición tenemos disponibles los siguientes premios para
para dos de los autores que colaboren artículos (en inglés):

* SMImport v1.75 - por Scalabium Software ($30 standard, $50 c/fuentes)
   Conjunto de componentes VCL nativos para importar datos en un dataset
   sin librerías externas. Soporta Access (usando DAO/MS Jet), Excel (sin
   OLE/DDE), Lotus 123, QuattroPro, texto, HTML, XML incluyendo formato
   TClientDataset, Paradox, dBase y cualquier descendiente de TDataSet.
   Nuevo en la versión 1.75: Creador visual de expresiones; importación
   desde Word; importación directa desde dBase sin BDE; carga de campos
   BLOB para XML; estilo extendido para el diálogo del asistente; evento
   OnCreateStructure que permite la creación dinámica de un dataset antes
   de realizar el verdadero proceso de importación, y más.
   http://www.scalabium.com/

* EurekaLog v4.1.1 - por Fabio Dell'Aria (Std $24, Pro $49, Ent $99)
   EurekaLog le confiere a su aplicación (GUI, consola, Web, etc.) la
   abilidad de capturar cada excepción que se produzca, generar un
   registro detallado (con unidad, clase, método y número de línea) y
   enviarlo por email. Se integra completamente en el IDE, y Ud. sólo
   tiene tiene que hacer un simple "build" para añadir EurekaLog a
   sus aplicaciones. No disminuye el rendimiento de las aplicaciones
   e incrementa el tamaño del archivo compilado en sólo un 0.5% - 4%.
   Compatible con Delphi 3 - 7 y todas las plataformas de Windows.
   http://www.eurekalog.com/bannerclick.php?id=15

La revista Delphi Informant Magazine está conduciendo su tradicional
encuesta anual para sus Readers Choice Awards. Por favor tómense un
momento para seleccionar sus herramientas Delphi favoritas:
http://www.delphizine.com/ballot2003/

Espero que disfruten esta edición.

Saludos,

Ernesto De Spirito
boletin-pascal-owner@...

__________________

Colaboraron en esta edición: Ernesto Cullen, Dave Murray y Bill Boulton.

________________________________________________________________________

           ¡Vote por el Boletín Pascal en The Programming Pages!
     http://www.programmingpages.com/topsite.asp?r=latium&Language=29
________________________________________________________________________


2. Lineamientos sobre el rendimiento de Interbase (y II)

    Por Peter Mc Leod <PeterMcLeod@...>

        Traducido por Ernesto Cullen


Configuración de Interbase
==========================

Backup / Restore (respaldo/restauración) regulares
--------------------------------------------------

Su base de datos brinda una ventaja competitiva a sus clientes debido a
la información que contiene. Realizar respaldos regulares es esencial
para asegurar la integridad de los datos a sus clientes. La restauración
también es importante porque optimiza la base de datos al

- reconstruir índices,
- eliminar versiones obsoletas de los registros (recolección de basura),
- defragmentar páginas de la base de datos,
- reescribir tablas de la base de datos en forma contigua, y
- recalcular estadísticas de la base de datos.

Una buena herramienta para realizar respaldos y restauraciones es
IBBackup, que está disponible en www.ibphoenix.com

Nota: se sugiere que se haga una copia del original antes de restaurar
la base de datos. Esto es debido a que la restauración realiza una
verificación de integridad en su base de datos, acción que utiliza
intensamente el procesador. Esencialmente esto significa que puede ser
posible tener un respaldo erróneo que no puede ser restaurado. Durante
el respaldo no se realiza esta comprobación ya que la idea es asegurar
los datos sin impactar en el rendimiento del sistema.


Clase de Prioridad de Interbase
-------------------------------

La clase de prioridad de Interbase debería ser fijada en High (versión
superserver bajo Windows) para asegurar que Interbase pueda demandar
más recursos del sistema. Esto puede hacerse desde IBConsole en la
versión de Windows. O edite el archivo ibconfig y fije
SERVER_PRIORITY_CLASS a dos (elimine el símbolo '#' para que la línea
no se tome como un comentario, de otra manera se aplicará el valor por
defecto).


Desactivar la escritura asincrónica
-----------------------------------

Bajo Windows NT, Interbase por defecto tiene habilitada la escritura
forzada. Esto significa que las operaciones de escritura de Interbase
van directamente a la base de datos y no a través del caché del sistema
operativo, y eso es más lento. En sistemas Linux ocurre la inversa.
Esto puede resultar en una diferencia de rendimiento de más del 300% en
algunas operaciones.

El problema es que si Ud. deshabilita la escritura asincrónica bajo
Windows, y el sistema operativo se cae mientras Interbase está
escribiendo al disco, corre el riesgo de perder datos y corromper la
base de datos. Como Linux es inherentemente más estable esto no es un
riesgo tan importante. Si Ud. quiere deshabilitar la escritura
asincrónica asegúrese de hacer muchos respaldos de la base de datos y
de tener una buena UPS en el servidor (debería hacer muchos respaldos
y tener una buena UPS igualmente) y escriba lo siguiente en una consola
de DOS:

   GFIX -WRITE ASYNC/SYNC MYDATABASE.GDB


Deshabilite la recolección de basura (garbage collection)
---------------------------------------------------------

Interbase realiza por defecto una limpieza (sweep) en la base de datos
para recolectar versiones viejas de los registros cuando se acumulan
demasiados, más allá de un cierto umbral. Desafortunadamente, esto puede
impactar severamente en el rendimiento de los procesos clientes que
provocaron que se alcance el umbral. Para deshabilitar la recolección
automática de residuos, debe ejecutar el siguiente comando gfix sobre
su base de datos:

   gfix -h 0

Nota: las acciones de respaldo y restauración realizarán la recolección
de residuos en la base de datos. Esto es otra razón por la que la base
de datos debería ser respaldada regularmente, tan frecuentemente como
sea práctico.


El parámetro Lock hash slots
----------------------------

El parámetro 'Ranuras hash de bloqueos' (Lock hash slots) se usa para
determinar el tamaño de la tabla de hash utilizada para encontrar
bloqueos en un objeto particular de la base de datos (esto es cierto en
todos los sistemas excepto VAX/VMS). El número debería ser un número
primo para ayudar al algoritmo de hashing a producir una buena
distribución. Usualmente una primera indicación de que existe un
problema con el tamaño de la configuración Lock Hash Slots es un
detrimento del rendimiento en el servidor Interbase (donde hay muchos
usuarios y páginas de caché grandes). Para determinar si este es el
problema, genere una impresión de la tabla de bloqueos (mientras el
sistema está siendo usado activamente) y examine el largo promedio de
[la clave de] hash. Si es mayor que 10, Hay un problema. Para calcular
un nuevo valor para el parámetro Lock Hash Slot multiplique la longitud
promedio por el número actual de ranuras y divida el resultado por
nueve. Ajuste este resultado hacia arriba según sea necesario para
conseguir un número primo, pero uno que esté entre 101 y 2048 (estos
son los límites para este parámetro). Para cambiar el parámetro edite
el archivo ibconfig y cambie el valor, recordando eliminar el '#' al
principio de la línea LOCK_HASH_SLOTS para que el valor tenga efecto.
Personalmente, fijo este valor en 501 para la mayoría de las
instalaciones de Interbase que uso. Si realiza esto en la arquitectura
Super Server, debería incrementar el tamaño de la tabla de bloqueos en
forma acorde.


Tamaño de página de la base de datos
------------------------------------

El tamaño de página de la base de datos determina la cantidad de datos
que serán extraídos en un acceso lógico a la base de datos. Interbase
tiene un tamaño de página por defecto de 1KB, con valores posibles de
2KB, 4KB, y 8KB. Para bases de datos pequeñas (menos de 4 GB), fije el
tamaño de página en 4096 (4K) bytes, para bases de datos muy grandes el
valor debería ser 8192 (8K). Algunas pruebas de rendimiento de bases de
datos indican que un cambio de tamaño de página de 1K a 4K puede
incrementar el rendimiento en alrededor de un 20%.

Al tener un tamaño de página de 4KB, la E/S de la base de datos se
corresponde con el tamaño por defecto de la E/S del sistema operativo,
resultando en una mayor eficiencia y rendimiento. Otras ventajas de un
tamaño mayor de página incluyen:

. Menor fragmentación de registros ya que se pueden almacenar más
   registros en una página.
. Menos páginas devueltas por una consulta dada (ya que los registros
   se almacenarán más frecuentemente en forma contigua)
. Los índices B-tree son menos profundos
. Las entradas/salidas son más contiguas

Los tamaños de página expresados arriba son lineamientos solamente; se
recomienda que realice algunas pruebas, para determinar el tamaño más
aplicable a su sistema.

Para que el cambio de tamaño de página tenga efecto se debe realizar un
respaldo y restauración de la base de datos.


Parámetros de memoria de trabajo (Working Set)
----------------------------------------------

Los parámetros de configuración de memoria de trabajo sólo son
aplicables a Interbase corriendo bajo Windows (usando la arquitectura
Super Server). Estos parámetros determinan la cantidad de memoria RAM
que será dedicada al proceso de Interbase. El tamaño mínimo (minimum
process working set) define la cantidad mínima de memoria RAM física
que será garantizada para el proceso Interbase. El tamaño máximo
(maximum working set) define la cantidad de memoria a partir de la
cual Interbase comenzará a usar el caché del sistema. Yo recomiendo que
el tamaño mínimo sea determinado tomando lo necesario para las páginas
de caché de la base de datos (Database Cache Pages) y agregando tres MB.
Al dejar el máximo tamaño en cero se permite al sistema determinar el
punto a partir del cual Interbase necesita intercambios a disco. El
tamaño máximo debería ser siempre más alto (o cero) que el caché de la
base de datos, de otra manera el sistema continuamente paginará a disco
para todas las operaciones.


Caché de la base de datos
-------------------------

El caché de la base de datos (Database Cache) es el número de páginas
de la base de datos que son mantenidas en la RAM del servidor. Alguna
experimentación en la asignación del caché de la base de datos (en
ibconfig) a un valor entre 256 y 10.000 produce incrementos del
rendimiento hasta un cierto punto. Después de este punto se nota un
decaimiento en el rendimiento.

También es una buena idea fijar el caché para la base de datos usando
GFIX con el siguiente comando:

   Gfix -buffers 10000 -user sysdba -password masterkey mydatabase.gdb

Si Ud. tiene una base de datos pequeña debería usar las estadísticas
para ver la cantidad de páginas en su base de datos. No debería fijar
el Cache de la base de datos a un número mayor que la cantidad de
páginas de la base de datos, ya que cualquier página de disco ocupará
solo una página en el caché.


Consideraciones para el desarrollo
==================================

Siempre trabaje con la menor cantidad de datos posible
------------------------------------------------------

El tráfico de red es un factor mayor en el rendimiento percibido de su
aplicación. Si Ud. tiene 100.000 registros y hace algo como "Select *
from myTable" estará moviendo todos los registros. El uso de filtros
para devolver solamente un subconjunto de los datos ayuda a reducir
esto. Si es posible evite el uso de grillas que muestren una gran
cantidad de registros. Utilice SQLMonitor (o su equivalente) para
controlar sus comandos SQL y ver que pasa REALMENTE cuando corre su
aplicación.


No mantenga las transacciones abiertas más tiempo del necesario
---------------------------------------------------------------

Mantener una transacción abierta puede bloquear registros en una base
de datos. Mantener las transacciones abiertas por un largo período de
tiempo también incrementa la cantidad de memoria que Interbase requiere
para mantener la información de esas transacciones. En lugar de comenzar
una transaccion tan pronto como una pantalla de ingreso se abra y
aceptarla (commit) cuando el usuario presione 'Grabar', es mejor obtener
una copia de los datos y comenzar y terminar la transacción cuando se
presiona el botón de grabación. Algunas técnicas facilitan esta aproxi-
mación, por ejemplo los Conjuntos de Datos Clientes (ClientDatasets).
Estas técnicas tienen las ventajas de:

. Reducir el tráfico en la red
. Reducir el riesgo de bloqueos en la base de datos
. Reducir la vida de una transacción
. Reducir la cantidad de memoria que Interbase requiere para mantener
   esas transacciones


Sistemas grandes, montones de tráfico, mantenga
sus tablas de búsqueda (lookup) en el cliente
-----------------------------------------------

Si Ud. tiene algunos datos que no cambian (como los estados, provincias
o países), entonces tiene la oportunidad de mantener una copia de esta
información en un ClientDataset en la máquina cliente (en lugar de
recuperar los detalles desde el servidor). De esta manera, se puede
simular un encuentro en el lado del cliente usando un campo calculado.
Esto le permite reducir el número de extracciones (fetches) que necesita
hacer sobre la base de datos, y reduce el tráfico en la red.


Programe directamente a la API de Interbase
-------------------------------------------

Si la velocidad es una necesidad absoluta entonces un programa escrito
en C con SQL embebido tendrá mejor rendimiento que una aplicación
cliente corriendo a través de varias capas intermedias (como la BDE,
etc). Este tipo de aplicación se programa directamente usando la API en
gds32.dll, lo que produce una mejora en velocidad.


Utilice una conexión remota
---------------------------

Cuando desarrolle su aplicación no utilice una cadena de conexión local
al conectar a su base de datos (c:\ruta\basededatos.gdb), ya que esto
utilizará archivos mapeados en memoria para comunicarse con su base de
datos. En algunas versiones de Interbase el uso de cadenas de conexión
locales y remotas simultáneamente puede causar una corrupción física de
la base de datos. Use una cadena de conexión remota, con lo que podrá
obtener una mejor indicación del rendimiento actual del sistema
(nombreservidor:c:\ruta\basededatos.gdb) y le permitirá señalar
problemas más temprano. Mejor todavía, desarrolle su aplicación
conectando a una base de datos en otra máquina a través de una red.


Llene completamente y pruebe su sistema durante el desarrollo
-------------------------------------------------------------

Frecuentemente los desarrolladores usan un sistema reducido durante el
proceso de desarrollo y prueba en sus máquinas de desarrollo. La
desventaja de esto es que el recuperar solamente unos pocos registros
(o incluso unos pocos cientos de registros) localmente es muy rápido.
La realidad es que seguramente se estará desarrollando un sistema
cliente-servidor que tiene que correr a través de una red, y puede
tener miles o incluso millones de transacciones. Para probar su sistema,
ejecútelo a través de una red, asegúrese de tener la base de datos
apropiadamente llena (yo recomendaría introducir alrededor de 1/3 más
registros de los que alguien pudiera tener en su sistema). Preferible-
mente realice sus pruebas en el peor harware y entorno de red en el que
podría correr su sistema.


Prepare y parametrice sus consultas
-----------------------------------

Siempre que sea posible, escriba sentencias SQL que puedan ser parame-
trizadas y prepare la consulta antes de ejecutarla (solamente necesita
ser preparada una vez ya que permanecerá preparada hasta que explíci-
tamente se 'desprepare' o cambie el contenido de la propiedad SQL. Las
sentencias/consultas preparadas y parametrizadas son más veloces que las
parametrizadas pero no preparadas.


Componentes VCL
---------------

El componente TQuery fue designado para su uso en aplicaciones cliente/
servidor, y debería ser utilizado siempre en reemplazo del componente
TTable el cual es para desarrollos de bases de datos locales. Cuando
utilice TQuery, permita al servidor manejar las actualizaciones,
borrados y conflictos fijando RequestLive en False. No utilice Locate
o RecordCount ya que éstas piden todos los registros del servidor
(fetchall). Use una cláusula Where para hacer que el servidor realice
el filtrado de los datos por Ud.


Piense en lo que está haciendo
------------------------------

Cuando diseñe un sistema recuerde que el hecho que Interbase le permita
hacer algo no significa que sea una buena idea. Todas las acciones
tienen una consecuencia. Piense acerca de cómo está diseñando y desarro-
llando su sistema y en las ramificaciones que lo afectarán a Ud, la red
y los clientes. Recuerde que es posible que alguien más tenga que
mantener este sistema.


Algo será lento
---------------

Cuando desarrolle un sistema si tiene que realizar la misma tarea una y
otra vez, digamos un millón de veces, este proceso será lento no importa
qué tan veloz sea su cliente y su servidor. Si éste es el caso, vea si
su filosofía de diseño le permite diseñar este tipo de proceso fuera del
sistema. En algunos casos esto no será posible, en cuyos casos puede
tener la necesidad de emplear un sistema donde este tipo de procesa-
miento se realice fuera del uso normal de los clientes.


Use el cliente
--------------

En un sistema cliente-servidor, Ud. no tiene que enviar todo al servidor
para su proceso. Puede distribuir la carga realizando una parte del
trabajo en la máquina del cliente. Si Ud. almacena los detalles de los
cálculos entonces obtendrá ventajas en la reducción de tráfico en la
red, transacciones más cortas y en no cargar al servidor con cada
proceso individual. Un ejemplo puede ser el calcular el costo para cada
elemento de una orden de compra y el total de la orden de compra en el
cliente.


Vea lo que su aplicación realmente hace
en lugar de lo que Ud. piensa que hace
---------------------------------------

Herramientas como el Monitor SQL le permiten ver internamente la forma
en que su aplicación recupera datos desde Interbase. Estas herramientas
son invaluables porque permiten ver datos como los siguientes:

. Conexión/desconexión
. Transacciones
. Ejecución de sentencias
. Operaciones de las sentencias

Los varios componentes VCL se comportan de diferente manera. Usando un
monitor SQL tiene la oportunidad de investigar qué está pasando detrás
de escena con estos componentes, y también qué sucede cuando hace
cambios de diseño a su aplicación.

Otras herramientas que deberían estar en su arsenal de desarrollo de
aplicaciones:

· Interbase Performance Monitor (monitor de rendimiento de Interbase)
    de Craig Stuntz (requiere Interbase 7.0 o superior)
· Interbase Plan Analyser (analizador de planes de Interbase) de Craig
    Stuntz
· Sleuth QA Suite de TurboPower Software (le permite ajustar el
    rendimiento de su aplicación Delphi/C++ Builder)


Utilice componentes de acceso nativo
------------------------------------

La BDE está ahora discontinuada y no será soportada más por Borland.
Componentes como IBX, FibPlus, IBObjects proveen un incremento en el
rendimiento de alrededor de un 40%, en comparación con la BDE. Estos
componentes también proveen acceso a más características internas de
Interbase. El uso de tales componentes, no obstante, lo enlaza a la
plataforma Interbase. Si esto es un problema, entonces los componentes
DBX pueden proveerle la habilidad de conectar a Interbase y otras
bases de datos, consiguiendo todavía un buen rendimiento (no tan bueno
como el de IBX etc, pero ciertamente ni cerca de lento como la BDE).


Buscando registros
------------------

Soundex es un método de indexación que fue desarrollado por el
departamento de censos de U.S., para agrupar nombres que sonaran
imilares. Como un ejemplo, realizar una búsqueda del nombre "smith" en
300.000 registros puede llegar a tomar alrededor de 2.95 segundos en
completarse, mientras que con soundex podría alcanzar el resultado en
alrededor de 0.77 segundos. Claro que el resultado incluiría el nombre
"smith" y otros que sonaran como "smith". Para ver un buen artículo
sobre creación y uso de una función soundex refiérase a "Implementing
a Soundex Function" de John Midwinter en http://www.ibphoenix.com.


Otras formas de mejorar el rendimiento
======================================


Actualice Interbase
-------------------

Cada nueva versión de Interbase (o Firebird) implementa mejoras que
incrementan el rendimiento del RDBMS, o incrementa la flexibilidad del
programador a través de extensiones de lenguaje. El incremento de
rendimiento y funcionalidad le permitirán construir mejores sistemas
cliente-servidor. Debido a las mejoras recientes en estos productos,
cualquiera que esté usando una versión de Interbase anterior a la
versión 7.0 debería considerar la actualización. Si esto no es una
opción, entonces considere actualizar a la última versión de Firebird.


Bases de datos de sólo lectura
------------------------------

Una base de datos normalmente dejará algún espacio libre en sus páginas
(alrededor de un 25%) para dar lugar a nuevas versiones de los
registros. En una base de datos donde el propósito primario es ver
datos, esto significa que es necesario recuperar más páginas para ver
los datos. En estas bases de datos de sólo lectura se pueden llenar las
páginas completamente para que los datos sean contiguos y se necesiten
enos páginas para recuperar los datos, usando el siguiente comando gbak:

   GBAK -C -USE_ALL_SPACE backup.gbk mydatabase.gdb

________________________________________________________________________

¿Errores en las aplicaciones? Capture y registre cada error detallando
unidad, clase, método y número de línea donde se produce, y envíe los
datos por email. Ahora con soporte para compilador en línea de comandos
y aplicaciones IntraWeb. http://www.eurekalog.com/bannerclick.php?id=15
________________________________________________________________________


3. Usando Cabinet.dll para crear sus propios archivos de gabinete (.CAB)

    Por Vimil Saju vimil@...


He desarrollado un componente que le permite a uno comprimir ficheros
en un archivo de gabinete (archivo .CAB). Este componente requiere la
librería cabinet.dll, que usualmente reside en la carpeta del sistema.
El componente consiste de dos unidades. La primera unidad contiene todas
las estructuras requeridas por el componente.

He actualizado la uCabinet. Ahora puede agregar archivos usando como-
dines. La compresión ahora tiene lugar en un hilo separado, así que su
programa no se congelará. He corregido el error en OnStatusEvent y ahora
muestra el progreso correctamente. También añadí una función para
cancelar, la que puede ser llamada durante el proceso de compresión
para cancelarlo. Ahora puede especificar el directorio en el que quiere
descomprimir el archivo usando la función AddFile.

También añadí capacidad de descompresión, aunque aún no está perfec-
cionada. El compresor y el decompresor corren en hilos separados para
que la aplicación no se congele. Usted también puede obtener la lista de
ficheros existentes en un gabinete sin extraerlos. Se han removido
muchos errores. Ahora hay dos componentes: TCabCompressor y
TCabDecompressor.

Para elegir un fichero individual para descomprimir tiene primero que
seleccionarlo llamando a la función CabDecompressor1.Files[0].Select.
Para seleccionar todos los ficheros puede llamar la función
CabDecompressor1.SelectAllFiles y para seleccionar ficheros usando
comodines use la función CabDecompressor1.SelectFilesByWildCard.

El evento BeforeCopyFile en la clase TCabDecompressor ha sido actua-
lizado para incluir un parámetro Overwrite que indica si el fichero
siendo descomprimido sobrescribirá un fichero existente o no.

Se adjuntan las dos unidades junto con un programa demostrativo en el
archivo Zip.

__________________

La última versión de este artículo y su código fuente puede encontrarse
en Delphi3000.com: http://www.delphi3000.com/articles/article_1820.asp

________________________________________________________________________

TsiLang Components Suite. Un juego completo de componentes profesionales
para crear  rápidamente aplicaciones  multilingües  elegantes,  útiles y
amistosas con el usuario. >>>> http://www.sicomponents.com/tsilang1.html
________________________________________________________________________


4. Detectando clics-derechos en la barra de título de sus formularios
    Cómo impedir que se muestre el menú contextual de la barra de título

    Por James Clements <essexboy @ bigfoot.com>


¿Cómo detecto un clic con el botón derecho del ratón y/o cómo mato el
menú de mi barra de título?

Este es un problema relativamente simple. Sólo necesita conocer el
mensaje de Windows correcto que debe capturar. He aquí cómo hacerlo:

Declaración:

   procedure WMNCRButtonDown(var Msg : TWMNCRButtonDown);
     message WM_NCRBUTTONDOWN;

Definición:

   procedure TMainFrm.WMNCRButtonDown(var Msg : TWMNCRButtonDown);
   begin
     if (Msg.HitTest = htCaption) then
     begin
       // su código aquí
       // la siguiente línea mata el menú
       Msg.HitTest := 0;
     end
     else
       inherited;
   end;

Información adicional:

   * NC viene de "no cliente" (non-client)
   * Se puede usar WMNCLButtonDown o WMNCMButtonDown para el botón
     izquierdo o el botón del medio respectivamente
   * No se genera ningún mensaje WM_NCRBUTTONUP sino sólo un mensaje
     WM_RBUTTONUP cuando se suelta el botón del ratón

Esto ha sido probado con Delphi 5 en Windows 2000, 95, 98 y NT 4.0.
Debería funcionar bien con otra versiones de Delphi, pero éstas no han
sido probadas.

________________________________________________________________________

Resource Builder 2.0.  Una poderosa herramienta  para crear scripts RC y
archivos de  recursos para sus  aplicaciones. Incluye potentes  editores
de imágnes y soporte JPEG. >>>>>> http://www.sicomponents.com/rbldr.html
________________________________________________________________________


5. Notas de un desarrollador (II)

    Por Alirio A. Gavidia


La presente es parte de una serie de pequeños artículos narrando expe-
riencias en el desarrollo de una aplicación.


Convertir archivos gráficos de distinto tipo
============================================

Continúo la tónica del artículo anterior. Si no lo recuerdan, es simple.
Entre otras cosas, en el referido artículo, se incluyó una rutina que
siempre levantaba un archivo de nombre "fondo.bmp" y lo presentaba como
fondo en un control de tipo "TToolBar". Ahora nos planteamos como hacer
con otros tipos de formatos gráficos.

En particular, al desarrollar "CC Cyber Café", yo opté por tomar
distintos formatos y convertirlos en "BMP". Esto ya lo había hecho para
otro pequeño proyecto. La imagen convertida se guarda como "BMP" y luego
se actualiza el control afectado. Más abajo es presentada la rutina
donde el parámetro "FileName" es el nombre del archivo gráfico a
convertir. Se asume que la extensión es JPG, JPEG, GIF, ICO, WMF, EMF o
BMP, si es otra cosa debe lanzar una excepción.

Las rutinas para convertir GIF y JPG son análogas y se fundamentan en
abrir el archivo en la clase correspondiente y asignarlo a un objeto
TBitmap para luego salvarlo. En particular hablamos de "TJpegImage" en
la unidad "jpeg" y "TGIFImage" en la unidad "RxGif" (otro aporte de las
Rx) luego se detalla un poco más esto. Ambas clases descienden de
TGraphic, y por ello se las puede asignar a "TBitmap".

Nótese que el caso de "TIcon" es diferente. "TIcon" es dibujado en el
objeto "TBitmap".

WMF, EMF son dos formatos "Windows Metafile" (y "Extended Windows
Metafile") se manipulan igual que los iconos.

   procedure SetToolBarWallPaper(FileName: String);
   Var
     bmp : TBitMap;
     jpg : TJpegImage;
     gif : TGIFImage;
     ico : TIcon;
     wmf : TMetaFile;
     ext : String;
   begin
     if FileExists(FileName) then
      begin
        ext := upperCase(ExtractFileExt(Filename));
        bmp := TBitMap.Create;
        if (Ext='.JPG') or (Ext='.JPEG') then
         begin
          jpg := TJpegImage.Create;      // Recuerde: uses jpeg
          jpg.LoadFromFile(Filename);
          bmp.Assign(jpg);
          bmp.SaveToFile(IncludeTrailingBackslash(ExtractFilePath(
            Application.ExeName))+'fondo.bmp');
          jpg.free;
         end
        else if (Ext='.GIF')  then
         begin
          gif := TGIFImage.Create;      // Recuerde: uses RxGif
          gif.LoadFromFile(Filename);
          bmp.Assign(gif);
          bmp.SaveToFile(IncludeTrailingBackslash(ExtractFilePath(
            Application.ExeName))+'fondo.bmp');
          gif.Free
         end
        else if (Ext='.ICO')  then
         begin
          ico := TICON.Create;
          ico.LoadFromFile(Filename);
          bmp.Height := ico.Height;
          bmp.Width := ico.Width;
          bmp.Canvas.Draw(0,0,ico);

          bmp.SaveToFile(IncludeTrailingBackslash(ExtractFilePath(
            Application.ExeName))+'fondo.bmp');
          ico.Free
         end
        else  if (Ext='.WMF') or (Ext='.EMF') then
         begin
          wmf := Tmetafile.Create;
          wmf.LoadFromFile(Filename);
          bmp.Height := wmf.Height;
          bmp.Width := wmf.Width;
          bmp.Canvas.Draw(0,0,wmf);
          bmp.SaveToFile(IncludeTrailingBackslash(ExtractFilePath(
            Application.ExeName))+'fondo.bmp');
          wmf.Free
         end
        else
         begin
          bmp.LoadFromFile(Filename);
          bmp.SaveToFile(IncludeTrailingBackslash(ExtractFilePath(
            Application.ExeName))+'fondo.bmp');
         end;
        fondo.Assign(bmp);
        bmp.free;
      end;
   end;

Bien, he retomado el ejemplo del artículo anterior y he incluído esta
nueva rutina.

Delphi (al menos desde la versión 3) trae consigo la unidad jpeg.
Respecto a GIF yo uso la de las Rx (que ocupan bastante espacio). Sin
embargo hay otras disponibles.

Actualmente estoy trabajando con los archivos "PNG" o "Portable Networt
Graphics". Si bien no los incluyo en este ejemplo los tomaré en cuenta
para una futura versión. El formato "PNG" tiene características real-
mente interesantes.

"BMP" (Bitmap). Es el formato básico. Cada imagen tiene un ancho y un
alto. Supongamos 32 x 32. Esto implica que son 1024 puntos. Si cada
punto puede tener 256 colores hablamos de un archivo de 1024 bytes. Es
simple y lineal casi un arreglo pero con las dimensiones primero.
Existe una variación con compresión RLE (Run-Length Encoding según creo
recordar).

"ICO" (Iconos). Tiene una funcionalidad agregada que es la de tener un
color transparente y uno inverso. Esto permite hacer iconos que no
luzcan cuandrados como los BMP. En BMP se puede definir un color trans-
parente pero esto es un truco de librería no del formato. En el "ICO"
esto es implícito del formato.

Los formatos "GIF" y "JPG" agregan compresión. En consecuencia ya no es
lineal la cuenta de numero de puntos por colores -> espacio en disco.
"JPG" tiene compresión con distintos niveles de pérdida. GIF es un
formato comercial que pertenece a CompuServe quien reclama y cobra por
derechos; así que si ustedes hacen dinero con GIF tienen que salir a
pagar (para más información revisen la documentación de las RX respecto
al formato "GIF"). El formato JPG comprime tomando en cuenta gradientes
(degradados) de colores y por eso es muy bueno al comprimir fotos; pero
cuando la imagen es plana (sin degradados) GIF lo supera al no dejar
pérdida. En otras palabras, para fotos mejor usar JPG y para iconos y
mapas de bits sin degradados usar GIF. GIF aporta dos características
adicionales que no tiene JPEG (o JPG que es lo mismo): Soporte a color
transparente y animación. Del color transparente hablo en el siguiente
párrafo. De la animación será otro día. Sin embargo las RX traen un buen
ejemplo de ello. Yo lo he usado para los banners publicitarios de
"HalZip" y "CC Cyber Cafe".

Hoy (18 de Marzo) comencé a trabajar con PNG. Es un formato genial.
Primero porque nos olvidamos de deberle dinero a nadie por derechos. ¡Es
libre! Segundo, tiene transparencia real gradual. Es posible hacer un
archivo de imagen PNG semi-traslúcido. Por lo demás, se porta igual que
una imagen GIF (sin la animación hasta donde he visto).

En otro artículo hablaré más de PNG. Por lo pronto gracias.

Alirio A. Gavidia
desde www.gavidia.org

__________________

Próximo tema: Más conversión de imagenes y el menú contextual o cómo con
               un par de clics convertir algo.

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


6. Mediciones de tiempo de alta precisión
    Utilizando QueryPerformanceCounter para obtener tiempos de alta
    resolución

    Por Michael Darling <michael.darling @ which.net>


Las funciones estándar Time y Now, e incluso el TTimer, tienen una
precisión aproximada de 55 milisegundos pues usan el reloj interno de
la PC. Para mediciones de tiempo más precisas Windows provee un contador
de alta precisión que se accede a través de QueryPerformanceCounter y
QueryPerformanceFrequency. Esta clase implementa una interfaz Delphi a
esos métodos.

La unidad adjunta implementa un objeto HighResTimer para simplificar el
uso de las funciones QueryPerformanceCounter y QueryPerformanceFrequency
de la API de Windows para un contador de alta resolución. Ésta puede ser
extendida para proveer funcionalidad WriteToFile, LogToDB, etc.

Simplemente añada la unidad a su cláusula Uses y luego cree una
instancia de THighResTimer donde la necesite.

Note: La unidad contiene IFDEFs para manejar el cambio de TLargeInteger
       en las versiones 3, 4 y 5+ de Delphi.

Una vez creado el HighResTimer sólo necesita ser comenzado antes de
realizar una acción y luego detenido una vez que la acción ha sido
realizada. El tiempo obtenido puede recuperarse como TDateTime llamando
a la propiedad Time o como un entero llamando a la propiedad Ticks.

Ejemplo:

   var
     MyHighResTimer: THighResTimer;
     i, j: Integer;
   begin
     MyHighResTimer := THighResTimer.Create;
     try
       MyHighResTimer.Start;
       for i := 0 to 1000 do
       begin
         j := i;
       end;
       MyHighResTimer.Stop;
       ShowMessage(Format('La operación tomó:'#13'Tiempo: %8.8f segundos'
         + #13'Ticks:%d', [MyHighResTimer.Time, MyHighResTimer.Ticks]));
     finally
       MyHighResTimer.Free;
     end;
   end;

________________________________________________________________________

* LMD StoragePack - por LMD Innovative - Shareware (EUR 59)
   Ocho componentes para salvar/restaurar datos de configuración (o sea,
   en tiempo de diseño, a través del diálogo de selección de propiedades)
   en/desde el Registro de Windows o archivos Ini, XML o binarios, siendo
   fácil cambiar entre estos formatos. Se incluye código fuente completo
   y un proyecto demo. http://www.ceberus.com/lmd/products/index.php3#P9
________________________________________________________________________


7. Inline Assembler en Delphi (VIII) - Aritmética entera de 128 bits (3)

    Por Ernesto De Spirito <edspirito@...>


En esta tercera y última parte de la serie sobre enteros de 128 bits
(a los que nos hemos referido como enteros grandes, enteros gigantes o
enteros enormes) veremos finalmente la verdadera aritmética, con las
cuatro operaciones fundamentales (suma, resta, multiplicación y
división).

Antes de entrar en ello me gustaría decir que los procediminetos y fun-
ciones presentados en las dos partes precedentes han sido corregidos y
más optimizados, pero todavía no he podido probarlos tanto como me
hubiera gustado. Si alguien encuentra algún error o quisiera realizar
algún comentario sobre el código fuente, por favor sírvase enviarme un
email.


Suma (adición)
==============

¿Cómo sumamos dos números, cada uno compuesto por cuatro enteros de 32
bits? Bien, pues en realidad es bastante fácil. Simplemente los sumamos
de la misma manera en que sumaríamos dos números de cuatro dígitos
decimales (como por ejemplo 3597 y 0015), excepto que aquí cada dígito
puede tener como 4 millardos (2^32) de valores diferentes en vez de sólo
diez. El algoritmo sería como sigue:

   function AddWithCarry(x: Longint; y: Longint;
                         var Carry: Boolean): Longint; forward;

   function HugeAdd(x: Hugeint; y: Hugeint): Hugeint;
   // Result := x + y;
   var
     Acarreo: Boolean;
   begin
     Acarreo := False;
     Result[0] := AddWithCarry(x[0], y[0], Acarreo);
     Result[1] := AddWithCarry(x[1], y[1], Acarreo);
     Result[2] := AddWithCarry(x[2], y[2], Acarreo);
     Result[3] := AddWithCarry(x[3], y[3], Acarreo);
   end;

AddWithCarry (SumaConAcarreo) es una función ficticia que devuelve un
entero con los 32 bits más bajos del resultado de la suma de los dos
argumentos, más 1 si Carry (acarreo, el tercer parámetro) es True.
También almacena True o False en el Carry (pasado por referencia)
dependiendo de si la suma generó un acarreo o no (o si el acarreo fue
1 o 0, si quieren verlo de esa manera). En realidad, esta función no
tiene que ser ficticia:

   function AddWithCarry(x: Longint; y: Longint;
                         var Carry: Boolean): integer;
   // MultiplyWithCarry = SumarConAcarreo
   asm
     // if Carry then CF := 1 else CF := 0;
     test byte ptr [ecx], -1   // Efecto colateral: CF := 0;
     jz @@NoCarry
     stc                       // CF := 1;
   @@NoCarry:
     // Result := x + y + CF;  CF := AcarreoGenerado;
     adc eax, edx
     // Carry := CF;
     setc byte ptr [ecx]
   end;

Sería más eficiente codificar HugeAdd enteramente en ensamblador:

   function HugeAdd(x: Hugeint; y: Hugeint): Hugeint;
   // Result := x + y;
   // Parámetros: EAX = @x; EDX = @y; ECX = @Result
   asm
     push esi

     mov esi, [eax+_0_]     // ESI := x[0];
     add esi, [edx+_0_]     // ESI := ESI + y[0];
     mov [ecx+_0_], esi     // Result[0] := ESI;

     mov esi, [eax+_1_]     // ESI := x[1];
     adc esi, [edx+_1_]     // ESI := ESI + y[1] + Carry;
     mov [ecx+_1_], esi     // Result[1] := ESI;

     mov esi, [eax+_2_]     // ESI := x[2];
     adc esi, [edx+_2_]     // ESI := ESI + y[2] + Carry;
     mov [ecx+_2_], esi     // Result[2] := ESI;

     mov esi, [eax+_3_]     // ESI := x[3];
     adc esi, [edx+_3_]     // ESI := ESI + y[3] + Carry;
     mov [ecx+_3_], esi     // Result[3] := ESI;

     pop esi
   end;


Resta (sustracción)
===================

La resta funciona bastante como la suma, pero en vez de generar un
acarreo, la operación genera un préstamo ("borrow", también representado
por la señal de acarreo o "Carry Flag") si el minuendo (primer operando)
es menor que el sustraendo (segundo operando):

   function SubtractWithBorrow(x: Longint; y: Longint;
                               var Borrow: Boolean): Longint; forward;

   function HugeSub(x: Hugeint; y: Hugeint): Hugeint;
   // Result := x - y;
   var
     Prestamo: Boolean;
   begin
     Prestamo := False;
     Result[0] := SubtractWithBorrow(x[0], y[0], Prestamo);
     Result[1] := SubtractWithBorrow(x[1], y[1], Prestamo);
     Result[2] := SubtractWithBorrow(x[2], y[2], Prestamo);
     Result[3] := SubtractWithBorrow(x[3], y[3], Prestamo);
   end;

   function SubtractWithBorrow(x: Longint; y: Longint;
                               var Borrow: Boolean): Longint;
   // SubtractWithBorrow = RestarConPrestamo
   asm
     // if Borrow then CF := 1 else CF := 0;
     test byte ptr [ecx], -1   // Efecto colateral: CF := 0;
     jz @@NoBorrow
     stc                       // CF := 1;
   @@NoBorrow:
     // Result := x - y - CF;  CF := PréstamoNecesitado;
     sbb eax, edx
     // Borrow := CF;
     setc byte ptr [ecx]
   end;

Deberían estar listos para escribir una versión en puro ensamblador
de HugeSub, puesto que es igual que HugeAdd, salvo que tienen que
reemplazar ADD y ADC por SUB y SBB respectivamente.


Número opuesto
==============

Dado un número, estas implementaciones de HugeNeg devuelven su número
opuesto (complemento a dos):

   function HugeNeg(x: Hugeint): Hugeint;
   begin
     // Result := (Not x) + 1;
     Result := HugeAdd(HugeNot(x), IntToHuge(1));
   end;

   function HugeNeg(x: Hugeint): Hugeint;
   begin
     // Result := 0 - x;
     Result := HugeSub(IntToHuge(0), x);
   end;

La segunda es la más simple y rápida pues involucra una sola operación,
y ahora que sabemos cómo restar, podemos implementarla en ensamblador:

   function HugeNeg(x: Hugeint): Hugeint;
   // Result := -x;
   // Parámetros: EAX = @x; EDX = @Result
   asm
     // Result := 0 - x;
     push esi
     xor esi, esi
     mov ecx, [eax+_0_]     // x[0]
     sub esi, ecx           // 0 - x[0]
     mov ecx, 0
     mov [edx+_0_], esi     // Result[0]
     mov esi, [eax+_1_]     // x[1]
     sbb ecx, esi           // 0 - x[1] - Préstamo
     mov esi, 0
     mov [edx+_1_], ecx     // Result[1]
     mov ecx, [eax+_2_]     // x[2]
     sbb esi, ecx           // 0 - x[2] - Préstamo
     mov ecx, 0
     mov [edx+_2_], esi     // Result[2]
     mov esi, [eax+_3_]     // x[3]
     sbb ecx, esi           // 0 - x[3] - Préstamo
     mov [edx+_3_], ecx     // Result[3]
     pop esi
   end;


Multiplicación
==============

Una forma de multiplicar números es por medio de un bucle aditivo:

   function HugeMul(x: Hugeint; y: Hugeint): Hugeint;
   begin
     SetZero(Result);
     while not HugeIsZero(y) do begin
       Result := HugeAdd(Result, x);
       HugeSub(y, 1)
     end;
   end;

Computacionalmente hablando, este algoritmo es bastante pobre. Por
ejemplo, si el valor de "y" fuera 4 millones, ¡el ciclo se repetiría
4 millones de veces! Como sea, la idea todavía sería buena si pudiéramos
acelerar el proceso de algún modo. Juguemos un poco con el álgebra:

   x * y = x * (y[3]*2^96 + y[2]*2^64 + y[1]*2^32 + y[0]*2^0)
         = (x*y[3])*2^96 + (x*y[2])*2^64 + (x*y[1])*2^32 + (x*y[0])*2^0

Ahora hemos reducido el problema de multiplicar dos números Hugeint al
de multiplicar un número Hugeint por un entero de 32 bits. Multiplicamos
el primer operando por los cuatro enteros que componen el segundo
operando y luego corremos los resultados parciales 0, 32, 64 y 96 bits
(para multiplicarlos por 2^0, 2^32, 2^64 y 2^96) respectivamente, y
finalmente sumamos esos valores para obtener el resultado final.

   function HugeMulInt(x: Hugeint; y: Longint): Hugeint; forward;

   function HugeMul(x: Hugeint; y: Hugeint): Hugeint;
   begin
     Result := HugeShl(HugeMulInt(x, y[3]), 96)
             + HugeShl(HugeMulInt(x, y[2]), 64)
             + HugeShl(HugeMulInt(x, y[1]), 32)
             +         HugeMulInt(x, y[0]);
   end;

Esa es exactamente la forma en la que multiplicamos números decimales
cuando ralizamos los cálculos en un papel, excepto que aquí la base es
2^32 en vez de 10. Ahora veamos cómo multiplicar un Hugeint por un
entero:

   function MultiplyWithCarry(x: Longint; y: Longint;
                              var Carry: Longint): Longint; forward;

   function HugeMulInt(x: Hugeint; y: Longint): Hugeint;
   // Result := x * y;
   var
     Acarreo: Longint;
   begin
     Acarreo := 0;
     Result[0] := MultiplyWithCarry(x[0], y, Acarreo);
     Result[1] := MultiplyWithCarry(x[1], y, Acarreo);
     Result[2] := MultiplyWithCarry(x[2], y, Acarreo);
     Result[3] := MultiplyWithCarry(x[3], y, Acarreo);
   end;

   function MultiplyWithCarry(x: Longint; y: Longint;
                              var Carry: Longint): integer;
   // MultiplyWithCarry = MultiplicarConAcarreo
   // Result := LoDWord(x * y + Carry);
   // Carry  := HiDWord(x * y + Carry);
   asm
     // EDX:EAX := EAX * EDX;  // x * y
     mul edx
     // Inc(EDX:EAX, Carry);
     add eax, [ecx]
     adc edx, 0
     // Carry := EDX;          // 32 bits de orden más alto del resultado
     mov [ecx], edx;
   end;

MultiplyWithCarry es bastante similar a AddWithCarry, pero realiza una
multiplicación en vez de una suma, y genera un acarreo de 32 bits en
vez de uno de un solo bit (la multiplicación de dos valores de 32 bits
genera un resultado de 64 bits, mientras que la suma de dos valores de
32 bits genera un resultado de 33 bits).

MultiplyWithCarry primero realiza una multiplicación sin signo de "x"
(EAX) por "y" (EDX), usando la instrucción MUL. El resultado es un
entero sin signo de 64 bits en EDX:EAX, al que la función le suma el
acarreo pasado por parámetro (Carry). La función devuelve los 32 bits
más bajos del resultado final (ubicados en EAX), y los 32 bits más altos
(EDX) constituyen el acarreo para la siguiente multiplicación, los que
son almacenados en el parámetro Carry (pasado por referencia).

En el código fuente que se adjunta podrán encontrar una implementación
de HugeMul y HugeMulInt. Por razones de simplicidad, en los ejemplos de
arriba se consideraron números sin signo, pero en las implementaciones
en ensamblador se consideraron números con signo. Además, la versión de
HugeMul que se adjunta no llama a HugeMulInt o HugeShl sino que ha sido
altamente optimizada.

En vez de considerar un entero gigante como la sumatoria de cuatro
enteros de 32 bits multiplicados por cuatro potencias de 2^32, podemos
considerarlos como la sumatoria de 128 enteros de un bit multiplicados
por 128 potencias de 2:

   bit127 * 2^127 + bit126 * 2^126 + ... + bit1 * 2^1 + bit0 * 2^0

Puesto que cada bit puede ser sólo 0 o 1, el algoritmo de arriba puede
simplificarse enormemente:

   function HugeMul(x: Hugeint; y: Hugeint): Hugeint;
   // Result := x * y;
   var
     i: Longint;
   begin
     SetZero(Result);
     for i := 0 to 127 do
       if BitTest(y, i) then
         Result := HugeAdd(Result, HugeShl(x, i));
   end;

La idea es sumar diferentes potencias de 2 de "x", dependiendo estas
potencias de los bits que estén encendidos (que sean 1) en "y". Por
ejemplo, si "y" fuera 20, los 5 y 3 estarían encendidos (20 en decimal
es 10100 en binario), así que sólo se realizarían dos sumas, y el
resultado sería HugeShl(x, 3) más HugeShl(x, 5).

Este algoritmo puede ser codificado bastante eficientemente en
ensamblador, pero aún así el primer algoritmo trabajará más rápido. La
razón por la que muestro este segundo algoritmo es que hará más fácil
entender el algoritmo que usaremos para la división.


División
========

Veamos primero el caso de una división de un Hugeint por un entero de
32 bits, que debería ser fácil de entender:

   function DivideWithRemainder(x: Longint; y: Longint;
                                var Remainder: Longint): Longint; forward;

   function HugeDivInt(x: Hugeint; y: Longint): Hugeint;
   // Result := x div y;
   var
     Resto: Longint;
   begin
     Resto := 0;
     Result[0] := DivideWithRemainder(x[3], y, Resto);
     Result[1] := DivideWithRemainder(x[2], y, Resto);
     Result[2] := DivideWithRemainder(x[1], y, Resto);
     Result[3] := DivideWithRemainder(x[0], y, Resto);
     asm
       mov edx, Resto
     end;
   end;

   function DivideWithRemainder(x: Longint; y: Longint;
                                var Remainder: Longint): Longint;
   // DivideWithRemainder = DividirConResto
   // Result    := Remainder:x div y;
   // Remainder := Remainder:x mod y;
   asm
     push esi
     mov esi, edx         // y
     mov edx, [ecx]       // Remainder
     // EAX := EDX:EAX div ESI;
     // EDX := EDX:EAX mod ESI;
     div esi
     // Remainder := EDX;
     mov [ecx], edx;
     pop esi
   end;

HugeDivInt deja el resto de la división en EDX, para que pueda usarse en
una función que devuelva el resto de la división:

   function HugeModInt(dividend: Hugeint; divisor: Longint): Longint;
   // Result := dividend mod divisor;
   // Parámetros: EAX = @dividend; EDX = @divisor;
   asm
     sub esp, TYPE(Hugeint) // Hace lugar en la pila para el Hugeint
     mov ecx, esp           // que alojará el resultado de la división
     call HugeDivInt        // Realiza la división y deja el resto en EDX
     add esp, TYPE(Hugeint) // Restaura el puntero de pila
     mov eax, edx           // Result := Resto; // fue dejado en EDX
   end;

Para el caso de dos enteros gigantes, podemos pensar en un algoritmo
como el que uno usaría para dividir dos números de cuatro dígitos con
lápiz y papel, pero resulta bastante complejo, además que en realidad
no es tan rápido pues implica divisiones, multiplicaciones y restas, y
a veces tenemos idas y vueltas. ¿Hay otro algoritmo posible? Sí lo hay:

   function HugeDiv(dividend: Hugeint; divisor: Hugeint): Hugeint;
   // Result := dividend div divisor;
   begin
     if HugeIsZero(divisor) then
       raise EDivByZero.CreateRes(@sDivByZero);
     Result := 0;
     while HugeCmp(dividend, divisor) >= 0 do begin
       dividend := HugeSub(dividend, divisor);
       Result := HugeAdd(Result, IntToHuge(1));
     end;
   end;

Por supuesto, este algoritmo resulta pesadamente lento (si dividimos 12
millones por 3, el ciclo se ejecutará 4 millones de veces), pero podemos
acelerar las cosas un poco restando del dividendo el divisor multipli-
cado por diferentes potencias de dos, de mayor a menor, estableciendo el
bit correspondiente en el resultado cada vez que realicemos una resta
(el bit en la posición de la potencia de dos que fue usada). Es lo
inverso a lo que hicimos en el caso de la multiplicación que mostramos
arriba. El proceso de división sería reducido entonces a 128 restas
cuanto mucho.

En el siguiente ejemplo, el dividendo es 20 (10100 en binario) y el
divisor is 3 (11 en binario):

    10100 - 11 * 2^2 = 10100 - 1100  = 1000      Result := 100
     1000 - 11 * 2^1 =  1000 -  110  = 10        Result := 110

Inicialmente, 11 (en binario) * 2^2 (100 en binario) es el valor más
grande que es menor o igual que el dividendo, así que restamos ese
valor del dividendo y encendemos el bit 2 del resultado porque restamos
el divisor multiplicado por dos elevado a la 2. Hasta aquí, el resto es
8 (1000 en binario), y 11 * 2^1 es el valor más alto que resulta menor
o igual que este resto, así que restamos ese valor y encendemos el bit
1 del resultado porque restamos el divisor multiplicado por dos elevado
a la 1. El resto es 2 (10 en binario), y como el divisor es mayor que
ese valor, la división se detiene allí. El resto de la operación
entonces sería 2 (10 en binario) y como los bits 2 y 1 del resultado
fueron encendidos, entonces el resultado será 110 en binario, es decir,
6 en decimal.

   function HugeDiv(dividend: Hugeint; divisor: Hugeint): Hugeint;
   var
     _r_: Hugeint;  // resto
     _d_: Hugeint;  // divisor
     _q_: Hugeint;  // cociente
     BitPosR, BitPosD, count: integer;
   begin
     _r_ := dividend;
     _d_ := divisor;
     HugeSetZero(_q_);
     BitPosD := HugeBitScanReverse(_d_);
     if BitPosD = -1 then RaiseDivByZero;
     BitPosR := HugeBitScanReverse(_r_);
     count := BitPosD - BitPosR;
     if count > 0 then
       _d_ := HugeShl(_d_, count);
     repeat
       if HugeCmp(_d_, _r_) <= 0 then begin
         _r_ := HugeSub(_r_, _d_);
         HugeBitSet(_q_, count);
       end;
       _d_ := HugeShr(_d_, 1);
       dec(count);
     until count < 0;
     Result := _q_;
     asm
       lea edx, _r_
     end;
   end;

HugeBitScanReverse es una función que devuelve la posición del primer
bit igual a 1, realizando la búsqueda desde el bit 127 hasta el bit 0.
Si todos los bits son 0, el resultado es -1. Usamos HugeBitScanReverse
para determinar la primer potencia de dos por la que deberíamos multi-
plicar el divisor para comenzar la iteración.

La implementación en ensamblador de HugeDiv, que encontrarán adjunta,
soporta números con signo. Es sólo una primera aproximación, y puede ser
altamente optimizada.

La función deja la dirección del resto en EDX de modo que pueda usarse
por una función que deba devolver el módulo o resto de la división:

   function HugeMod(dividend: Hugeint; divisor: Hugeint): Hugeint;
   // Result := dividend Mod divisor;
   // Parámetros: EAX = @dividend; EDX = @divisor; ECX = @Result
   asm
     push ecx              // @Result
     call HugeDiv          // EDX := @remainder;
     pop eax               // EAX := @Result;
     call HugeMov          // EAX^ := EDX^;
   end;

________________________________________________________________________

¡Vota por el Boletín Pascal en el DPSC Top 100 Programming web sites!
(sólo cliquea "here" donde dice "Click here to vote!", y eso es todo)
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
________________________________________________________________________


8. Foros / listas de correo


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-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@...

* 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

________________________________________________________________________

   Merlin's Delphi Forge
   Delphi and Kylix news, FAQ, downloads, links, forums and more.
   Accepting uploads and submissions.
   http://www.delphifaq.net/
________________________________________________________________________


9. Delphi en la Red

    Por Dave Murray <irongut @ vodafone.net>


Componentes, librerías y aplicaciones
=====================================


Shareware/Comercial
-------------------

* SMImport v1.75 - por Scalabium Software ($30 standard, $50 c/fuentes)
   Conjunto de componentes VCL nativos para importar datos en un dataset
   sin librerías externas. Soporta Access (usando DAO/MS Jet), Excel (sin
   OLE/DDE), Lotus 123, QuattroPro, texto, HTML, XML incluyendo formato
   TClientDataset, Paradox, dBase y cualquier descendiente de TDataSet.
   Nuevo en la versión 1.75: Creador visual de expresiones; importación
   desde Word; importación directa desde dBase sin BDE; carga de campos
   BLOB para XML; estilo extendido para el diálogo del asistente; evento
   OnCreateStructure que permite la creación dinámica de un dataset antes
   de realizar el verdadero proceso de importación, y más.
   http://www.scalabium.com/

* SMExport v4.30 - por Scalabium Software ($20 standard, $35 c/fuentes)
   Conjunto de componentes VCL nativos para exportar datos de distintos
   orígenes (datasets, grids, cubos de decisión, memoria, árboles DevExp,
   etc.). Exporta a MS Excel, MS Access, MS Word, PDF, Text/CSV, HTML,
   XML, dBase, RTF, SQL, Lotus 1-2-3, QuattroPro y más.
   http://www.scalabium.com/

* Storage Library v3.24 - por DeepSoftware.Ru ($39)
   Storage Library es una elegante solución para el manejo de la
   configuración de las aplicaciones. Soporta trabajar con archivos INI,
   Registro de Windows, archivos XML files, objetos TStream. Provee
   encripción, soporte Unicode, trabajar con propiedades públicas sin
   programar, almacenar la posición de los formularios, y mucho más...
   http://www.deepsoftware.ru/rsllib/index.html

* Delphi Knowledge Base v1.5 ($29)
   Una colección única de trucos y artículos Delphi donde los programa-
   dores pueden encontrar ideas, soluciones y compartir su experiencia.
   La nueva versión incluye búsqueda rápida de artículos, interfaz plana
   integrada, señaladores, nuevas características de filtrado, agrupa-
   miento y ordenamiento de artículos, interfaz multilenguaje (incluyendo
   español), herramienta de actualización de artículos mejorada y más.
   http://www.baltsoft.com/product_dkb.htm

* EurekaLog v4.1.1 - por Fabio Dell'Aria (Std $24, Pro $49, Ent $99)
   EurekaLog le confiere a su aplicación (GUI, consola, Web, etc.) la
   abilidad de capturar cada excepción que se produzca, generar un
   registro detallado (con unidad, clase, método y número de línea) y
   enviarlo por email. Se integra completamente en el IDE, y Ud. sólo
   tiene tiene que hacer un simple "build" para añadir EurekaLog a
   sus aplicaciones. No disminuye el rendimiento de las aplicaciones
   e incrementa el tamaño del archivo compilado en sólo un 0.5% - 4%.
   Compatible con Delphi 3 - 7 y todas las plataformas de Windows.
   http://www.eurekalog.com/bannerclick.php?id=15


Freeware
--------

* IBUtils v0.9.2.4 - by Ales Kahanek
   IBUtils is designed to simplify database design for Interbase and
   Firebird databases by showing the links between the tables in your
   database visually, like some CASE tools do. It does not allow database
   editing, it is a read-only tool. The model is saved to INI-like files
   or can be exported as an image to a JPG or BMP file. Uses IBObjects.
   http://www.alikiwi.com/ibutils/ibutils.htm

* Key Objects Library v1.72 - by Delphree (with source)
   Based on experience aquired on eXtreme Class Library project. Main
   purpose is to create smaller programs using Delphi environment.
   http://delphree.clexpert.com/pages/app_KOL.htm

* GPU 0.788b - by Delphree (with source)
   GPU is a Gnutella client for sharing files and CPU-resources. The
   objective is to develop a robust framework for distributed computing
   on a peer-to-peer grid.
   http://delphree.clexpert.com/pages/app_GPU.htm

* TurboPower SysTools for Kylix v1.01 - by TurboPower (source) (KYLIX)
   A library of utility routines and algorithms for Borland Kylix. Among
   other things, it supports 1-Dimensional bar codes, date time and
   string routines, sorting, a regular expression engine and a run-time
   math expression analyzer.
   https://sourceforge.net/projects/tpsystoolskylix/


Actualizaciones de Delphi
-------------------------

* Patch: glibc update for Kylix 3 C++ package loading - by John Kaster
   Linux distributions using glibc 2.2.x will probably encounter issues
   loading the database and SOAP packages for the Kylix 3 IDE for C++.
   This patch resolves that issue.
   http://community.borland.com/article/0,1410,29968,00.html


Artículos, trucos y consejos
============================

* Sip from the Firehose: It all starts with Define! - by David I
   In the recent BDN 2003 Survey, David I asked members a question about
   what drives their development processes and decisions. In this article
   he reports the results.
   http://community.borland.com/article/0,1410,30043,00.html

* Interview with Jeff Duntemann - by Clay Shannon
   Jeff Duntemann tells about his experiences working for Borland,
   writing and editing for Coriolis and Visual Developer, a rigged
   programming contest he participated in vs. Bill Gates, what he does
   everywhere, and what he's been up to lately.
   http://community.borland.com/article/0,1410,30012,00.html

* Interview with Steve Teixeira - by Clay Shannon
   Interview with Steve Teixeira, co-author of the classic "Delphi X
   Developer's Guide". Among other things, Steve tells about his days at
   Borland, how the above tome came about, and "geek" practical jokes.
   http://community.borland.com/article/0,1410,29925,00.html

* Using Semaphores in Delphi Part 2: The Connection Pool - Cary Jensen
   Semaphores are used to coordinate multiple threads and processes. The
   ability of semaphore to provide multiple threads with simultaneous
   access to a shared resource is highlighted by the TFixedConnectionPool
   class described in this article.
   http://community.borland.com/delphi/0,1419,1,00.html

* Binary Serialization with the .NET Framework and Delphi for .NET
   - by Marcel van Brakel
   This article explains binary serialization, complete with Delphi for
   .NET and C# source code.
   http://community.borland.com/article/0,1410,29787,00.html

* Simple Programming Tip #1 - by Charlie Calvert
   This article describes the first of several simple programming tips.
   The discussion and code in this article is generic and applies equally
   to C++, C#, Delphi or Java. The tip for this article is: Avoid writing
   code that does anything substantial inside a visual container, instead
   write code inside separate classes designed for a single purpose.
   http://community.borland.com/article/0,1410,30011,00.html

* MessageBox on top of "stay on top" forms - by Zarko Gajic
   This tip causes "stay on top" forms to allow a MessageBox to appear on
   top. After the message box is closed, the topmost forms are restored
   so that they continue to float to the top.
   http://delphi.about.com/cs/adptips2003/index.htm

* Mouse moving the contents of a ScrollBox - by Zarko Gajic
   How to move a TImage object in a ScrollBox with the mouse, like a drag
   and drop operation - without the scroll bars.
   http://delphi.about.com/library/weekly/aa050603a.htm

* Sorting records in Delphi DBGrid - by Zarko Gajic
   How to sort records in Delphi DbGrid by clicking on the column title.
   How to change the appearance of the selected column title to reflect
   the sort order. How to change the cursor when moving over the DBGrid
   column titles.
   http://delphi.about.com/library/weekly/aa042203a.htm

* Choosing a ZIP Library for Delphi - by Mark Steinberg
   Describes the pros and cons of several ZIP libraries - VCLZip, ZipTv,
   ZipForge, Abbrevia and Delphi Zip.
   http://www.delphifaq.net/modules.php?name=FAQ&op=view&id=219

* How to encrypt/decrypt files using NTFS API - by m3rlin
   http://www.delphifaq.net/modules.php?name=FAQ&op=view&id=220

* Coding DB2 SQL for Performance: The Basics - by Craig S. Mullins
   Poorly coded SQL and application code can cause performance problems.
   This article is intended to give the basics of good SQL programming to
   application developers, particularly for those who are using Borland
   Kylix and Delphi RAD tools.
   http://www7b.software.ibm.com/dmdd/library/techarticle/0210mullins/
   0210mullins.html

* Create a Reusable Component to Connect Delphi 7 to DB2 with dbExpress
   - by Bob Swart
   How to use IBM DB2 as the backend database for applications written
   with Delphi 7 and dbExpress. Specifically, how to connect the seven
   dbExpress components to DB2 and use them to build visual forms on top
   of database tables.
   http://www7b.software.ibm.com/dmdd/library/techarticle/0210swart/
   0210swart.html

* Display and Modify DB2 Master-Detail Data in Delphi 7 Apps - Bob Swart
   A typical real world application will involve combining and displaying
   data from multiple tables in a usable format for reviewing and
   editing. This article shows how to add data and create relationships,
   manipulate the data from a Delphi application and get ready to move
   the entire package to Linux with Kylix.
   http://www7b.software.ibm.com/dmdd/library/techarticle/0211swart/
   0211swart.html

* The Big Switch: Moving from Windows to Linux with Kylix 3 - Bob Swart
   One of the great things about using tools and databases such as Delphi
   IBM DB2 is that moving between platforms is only a matter of a few
   changes and a recompile. This article shows how to take the big jump
   and move a Delphi 7 application running on Windows to a Linux (Intel)
   application using Kylix 3.
   http://www7b.software.ibm.com/dmdd/library/techarticle/0211swart/
   0211swart2.html

* Build DB2 and Delphi 7 Internet Applications with WebSnap - Bob Swart
   With Delphi 7 WebSnap technology, you can quickly take data from an
   IBM DB2 database and move it to a Web-based application in a snap.
   http://www7b.software.ibm.com/dmdd/library/techarticle/0211swart/
   0211swart3.html

* Create Distributed DB2 and Delphi Web Apps with DataSnap - Bob Swart
   Enter the world of distributed applications, where you split your
   application into two different tiers: a thin client and a database
   server tier. This article focuses on the server side, as well as the
   communication between the client and the middleware server.
   http://www7b.software.ibm.com/dmdd/library/techarticle/0212swart/
   0212swart.html

* DB2 and Delphi 7: SOAP and Database Web Services - by Bob Swart
   Creating a distributed application based on SOAP as the communication
   protocol, where the server (DB2) will be turned into a cross-platform
   Web Service. As a consequence, you can compile both the server and the
   client with Delphi 7 and Kylix 3 and deploy them on either Windows or
   Linux; this is a true cross-platform solution.
   http://www7b.software.ibm.com/dmdd/library/techarticle/0212swart1/
   0212swart1.html

* Data Entry Input Validation With Delphi and Kylix - by Bob Swart
   How to build data entry forms on top of IBM DB2 Universal Database as
   database tables and records, and how to perform data entry validation
   using Delphi Studio and Kylix. Uses dbExpress and DB2 PE v8.1.
   http://www7b.software.ibm.com/dmdd/library/techarticle/0303swart/
   0303swart.html

* Drill Into DB2 Tables for Decision Support Using Delphi - by Bob Swart
   How to build decision-support functionality by drilling into IBM DB2
   tables using the Decision Cube component of Delphi. Uses dbExpress to
   connect to the DB2 UDB Personal Edition v7.x database.
   http://www7b.software.ibm.com/dmdd/library/techarticle/0304swart/
   0304swart.html

* DB2 + SOAP: Database Web Services Follow-up with DataSnap - Bob Swart
   This extended DataSnap SOAP example covers deployment issues and some
   login and authentication details that help increase security for the
   DB2 backend database.
   http://www7b.software.ibm.com/dmdd/library/techarticle/0305swart/
   0305swart.html

* Building a Web Service in Delphi with a DB2 Backend - by Marco Cantù
   To help you get started with Web services this article shows you a
   practical SOAP Web service example built with Delphi and a test client
   that serves up data from an IBM DB2 Universal Database backend.
   http://www7b.software.ibm.com/dmdd/library/techarticle/0212cantu/
   0212cantu.html

* Check Efficiency of Oracle Caching with this Report - Donald Burleson
   One of the most important areas of Oracle tuning is the management of
   the RAM data buffers. Not only is it useful to know the contents of
   Oracle data buffers, it's also interesting to watch them move about in
   the list. Try this report to check up on your caching effectiveness.
   http://builder.com.com/article.jhtml?id=u00320030422brl01.htm

* Ensure data integrity with proper database design - by Susan Harkins
   Data is the backbone of application development, so data accuracy is
   imperative. Take advantage of referential integrity to protect your
   database from invalid data.
   http://builder.com.com/article.jhtml?id=u00320030507ssh01.htm

* How to List all files in a directory?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1725

* How to export a TStringGrid to a MS Word table?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1726

* How to export an Excel Table to a TStringgrid?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1728

* How to trap mouse events outside of my application?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1729

* How to fill in MS Word Form Fields?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1731

* How to read a BlobStream with TADOQuery from an AccessDB?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1744

* User list on Windows NT - by Serhiy Perevoznyk
   http://www.delphi3000.com/articles/article_3637.asp

* Do you want TWAIN? - by Maarten de Haan
   Delphi Scanner Support Framework as a component.
   http://www.delphi3000.com/articles/article_3638.asp

* How to convert a Grid's Surfer to a Grid's Arcview - by Camila Pinilla
   This code is useful to load a raster Grd file from surfer to ArcView
   when you want to interpolate data by using Sufer and then loading the
   grid by using Raster Arcview.
   http://www.delphi3000.com/articles/article_3639.asp

* Component to calculate a Regression Multiple of set data - C Pinilla
   This code was used in a mathematical model to calculate a Regression
   Multiple in many points of a computational mesh.
   http://www.delphi3000.com/articles/article_3640.asp

* An easy procedure to draw a Vector Field - by Camila Pinilla
   Useful if you have to draw a velocity field in a two dimensional mesh.
   http://www.delphi3000.com/articles/article_3641.asp

* Choosing a ZIP Library for Delphi - by Mark Steinberg
   http://www.delphi3000.com/articles/article_3644.asp

* How to create a dynamic PopUpMenu - by Christoph Otto
   Have you ever wanted to Create a PopupMenu at a Position you wanted?
   E.g. from a button going up. Here's how using TrackPopupMenuEx.
   http://www.delphi3000.com/articles/article_3647.asp

* Secure compression component - by Ronald Douson
   A discussion on chosing a component for compressing files with strong
   encryption.
   http://www.delphi3000.com/articles/article_3648.asp

* Fast Sine and Cosine Calculations - by John Pears
   How to really speed up sine and cosine calculations (in degrees).
   http://www.delphi3000.com/articles/article_3649.asp

* Understanding pointers: for the amateurs - by Martin Strand
   Written for all the beginners out there.
   http://www.delphi3000.com/articles/article_3650.asp

* WebSnap III: use of Adapter instead of Html Transparent Tags
   - by Eber Irigoyen
   The use of adapters to manage content in your web pages. Perhaps
   easier to use than html transparent tags?
   http://www.delphi3000.com/articles/article_3651.asp

* TreeView control DragDrop Operation helper functions - by Wei Bao
   Make Treeview dragdrop operation programming simpler: automatic expand
   and collapse, move with children nodes, disable drop to child and
   self, auto scroll while the cursor near top or bottom of the control.
   http://www.delphi3000.com/articles/article_3652.asp

* INI to XML- by Jim McKeeth
   INI was the old way to store settings (outside the registry), now
   everything is XML. This routine will convert an INI file into an XML
   node of a document.
   http://www.delphi3000.com/articles/article_3654.asp

* Moving items in a TListBox using the mouse - by Christophe Geers
   A quick example on how to move items in a TListBox using the mouse.
   http://www.delphi3000.com/articles/article_3655.asp

* A lot of DLLs with forms, Load dynamically into a PageControl of a
   Main-Form - by Manfred Suesens
   How to put DLL-Forms as Parent to a MainForm-PageControl-TabSheet.
   http://www.delphi3000.com/articles/article_3656.asp

* Internet Explorer Automation - by Teun Spaans
   How to integrate IE into your application.
   http://www.delphi3000.com/articles/article_3657.asp

* Next or Prev working Day - by Andreas Schmidt
   How to calculate the next/prev working day starting from a given date.
   http://www.delphi3000.com/articles/article_3658.asp

* Creating a Delphi-Expert (Part I) - by Daniel Wischnewski
   The simplest way of creating a Delphi-Expert.
   http://www.delphi3000.com/articles/article_3661.asp

* Create "Wait.." panel in design time - Miquel Taule
   Quick way to create a panel message.
   http://www.delphi3000.com/articles/article_3666.asp

* Reading + Writing System-Wide Environment Variables - Richard Winston
   How do you set an environment variable that will apply outside the
   process that set the variable or those spawned by it?
   http://www.delphi3000.com/articles/article_3669.asp

* Automatically start a service after using /Install or /Uninstall
   switch - by Brian Gochnauer
   Have you ever wished that the service would also start after
   installing the service not just install itself.
   http://www.delphi3000.com/articles/article_3671.asp

* Captions in the DBNavigator - by Victor Dalvi
   http://www.delphi3000.com/articles/article_3672.asp

* Users Take Open Source Databases for a Spin - by John Cox
   A growing number of companies are finding that open source databases
   are reaching a state where they can become the latest addition to
   their inventory of open source tools.
   http://www.nwfusion.com/news/2003/0428specialfocus.html

* The Art of Enbugging - by Andy Hunt and Dave Thomas
   An article from IEEE Software about reducing the errors in your code
   through decoupling techniques.
   http://www.pragmaticprogrammer.com/articles/jan_03_enbug.pdf


White papers
------------

* Cross-platform Development with Borland RAD Tools - by Borland
   Traditionally, developers create and maintain separate programs for
   Windows and Linux platforms. Borland makes it possible to target both
   platforms with a single application. This white paper gives you an
   overview of what you can do including multi-tier apps, Web apps, and
   integration with Web services.
   http://bdn.borland.com/article/images/29139/
   xplatform_with_borland_rad_tools.pdf

* Database Application Development Using Borland Kylix and DB2 UDB v7.2
   - by Paul Yip (IBM) and Ramesh Theivendran (Borland)
   Kylix is a RAD tool that provides a thin, cross-platform, database-
   independent, disconnected data-access model that can be used to
   quickly develop database applications for Linux and Windows platforms.
   By combining Kylix and DB2, you can write applications once and deploy
   them to run natively on both Linux and Windows without code changes.
   http://www-3.ibm.com/software/data/pubs/papers/kylix/kylix.pdf


Tutoriales
==========


* A Beginner's Guide to Delphi: Chapter 13 - by Zarko Gajic
   It's time to learn how to let Delphi help you code faster: start using
   code templates, code insight, code completion, shortcut keys, etc.
   http://delphi.about.com/library/weekly/aa020202a.htm

* Creating Simple User Object Property Dialogs - by Brian Frost
   A neat way of creating simple user object property dialogs that avoids
   spending ages wiring up controls to object properties.
   http://www.thedelphimagazine.com/samples/1614/1614.htm

* Fun With OpenGL - by Dave Jewell
   Insights into the OpenGL graphics library and what it can do for your
   applications, demonstrating that it's not as difficult as you might
   think and it isn't all chocolate teapots, either!
   http://www.thedelphimagazine.com/samples/1445/1445.htm

* Relational Databases: Defining Relationships Between Database Tables
   - by Susan Harkins
   Database normalization is the cornerstone of database theory. Once a
   database is normalized, relationships between the data in multiple
   tables must be established.
   http://builder.com.com/article.jhtml?id=u00320030430ssh01.htm

* How to Program the Lego Mindstorms Robotic Kit - by Geert Barandat
   Tutorial of the Lego® Mindstorms® robotics kit and how to program it
   with Delphi. Topics include an introduction to ActiveX, PC-RCX
   interfacing and building autonomous robots.
   http://www.barandat.be/mindstorms/


Otros enlaces
=============

* The Quick Reference Site
   The ultimate resource for free IT Quick Reference Cards and e-books.
   http://www.digilife.be/quickreferences/indexe.html

* Delphi Informant Magazine Readers Choice Awards 2003
   Each year, Delphi Informant Magazine recognizes outstanding products
   and vendors in the Delphi add-on market. Please take a moment to
   select your favorite Delphi tools. This is your chance to voice your
   opinions regarding the tools and products you use in your everyday
   development efforts.
   http://www.delphizine.com/ballot2003/


Noticias
========

* Borland Janeva
   Janeva provides seamless, high-performance interoperability between
   the Microsoft .NET Framework applications and the J2EE and CORBA
   infrastructures, allowing .NET client- or server-based applications
   to access J2EE and CORBA server-side components through the highly
   scalable and secure Internet Inter-ORB Protocol (IIOP). Janeva is
   tightly integrated with popular development environments for the
   Microsoft .NET Framework, including Microsoft Visual Studio for .NET
   and Borland C#Builder. Janeva helps accelerate the application
   lifecycle at a low total cost of ownership: implementation requires
   no expertise with J2EE or CORBA technologies, no change to back-end
   systems, and no additional hardware or software investments.
   http://www.borland.com/janeva/

   Janeva in the news:
   - http://www.oreillynet.com/pub/wlg/3167
   - http://news.com.com/2100-1012_3-999698.html
   - http://zdnet.com.com/2100-1104_2-999698.html
   - http://www.businessweek.com/technology/cnet/stories/999698.htm
   - http://www.nytimes.com/cnet/CNET_2100-1012_3-999698.html

* Borland C#Builder
   The first independent development environment for the .NET Framework.
   C#Builder offers a design-driven approach to development that
   increases team productivity. C#Builder provides interoperability
   between .NET, J2EE and CORBA, so you can integrate different software
   systems. It also provides native support for major databases.
   http://www.borland.com/csharpbuilder/

* C# Builder box screen shots - by Anders Ohlsson
   A first look at the screen shots that are on the product boxes for
   Borland's new C# Builder (formerly Project Sidewinder).
   http://community.borland.com/article/0,1410,30021,00.html

* Borland Makes .Net 'Life Cycle' Play - by Martin LaMonica
   Borland Software will take on software giant Microsoft with a suite
   of .Net development tools targeted at companies that program with both
   .Net and Java.
   http://news.com.com/2100-1012-997684.htm

* Borland: Building Bridges Between Java and .Net - by ZDNet
   ZDNet Video interviews Dale Fuller, President and CEO, Borland.
   http://zdnet.com.com/1601-2-997475.html

________________________________________________________________________

           ¡Vote por el Boletín Pascal en The Programming Pages!
     http://www.programmingpages.com/topsite.asp?r=latium&Language=29
________________________________________________________________________


¡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@...

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.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
http://news.optimax.com/topdelphi/links.exe/click?id=70C517ECAE6E
http://www.top219.org/cgi-bin/vote.cgi?delphi&83
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
http://213.65.224.200/cgi-bin/toplist.cgi/hits?Id=80
http://www.programacion.net/votar-enlace.php?id=474
http://www.lawebdelprogramador.com/buscar/enlace.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/descarga/p0047.zip
________________________________________________________________________

Página del grupo:  http://espanol.groups.yahoo.com/group/boletin-pascal/
Para suscribirse / apuntarse:   boletin-pascal-subscribe@...
Para cancelar / removerse:    boletin-pascal-unsubscribe@...
¿Problemas con tu suscripción?      boletin-pascal-owner@...
________________________________________________________________________

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) 2003 por Ernesto De Spirito. Todos los derechos reservados
________________________________________________________________________

#13 De: "Ernesto De Spirito" <edspirito@...>
Fecha: Mié, 23 de Abr, 2003 4:43 pm
Asunto: Boletín Pascal #46 - 23-ABR-2003
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #46 - 23-ABR-2003

Índice

1. Unas palabras del editor
2. Lineamientos sobre el rendimiento de Interbase (I)
    - Desarrollo de la base de datos
       · Normalice su base de datos
       · Claves primarias
       · Claves externas
       · Use índices en columnas de relación
       · SQL
       · Subconsultas correlacionadas
       · Combinaciones externas (Outer join)
       · Procedimientos almacenados
       · No utilice campos Char o Varchar largos
       · BLOBs
       · Utilice procesamiento cliente/servidor
       · Plan de consultas
       · RDB$DB_KEY
     - Lineamientos para el servidor
       · Utilice un servidor dedicado
       · Utilice Linux como sistema operativo del servidor
       · Si Ud. tiene que usar Windows
       · Use máquinas de un solo procesador con Interbase
       · Utilice un disco rígido dedicado
       · Discos veloces
       · Utilice una dirección IP estática en el servidor
       · Utilice TCP/IP como protocolo de red
       · No utilice salvapantallas
       · Ingreso al servidor a través de consola
       · Utilice la misma versión del cliente de Interbase que su servidor
       · Superando restricciones de entrada/salida de disco
       · Protección de archivos de Windows
3. Incluyendo componentes en una StatusBar
4. Notas de un desarrollador (I)
    Rx TSpeedBar y TToolBar - Menú movible
5. Enumerando las conexiones de red
    Detectando las conexiones de red actuales
6. Buscando archivos en Delphi
7. Inline Assembler en Delphi (VIII) - Aritmética entera de 128 bits (2)
8. Foros / listas de correo
9. Delphi en la Red
    - Componentes, librerías y aplicaciones
      · Shareware
      · Freeware
      · Actualizaciones de Delphi
    - Artículos, trucos y consejos
    - Tutoriales
    - Otros enlaces
    - Noticias

________________________________________________________________________


1. Unas palabras del editor


Perdón por la demora en la publicación de este número. Como es habitual,
quisiera comenzar agradeciendo a los autores que colaboraron artículos
para esta edición: Peter Mc Leod, Alex Schlecht, Alirio A. Gavidia, Igor
Siticov y Charl Linssen. Me complace entregarles los premios para esta
edición a los dos primeros:

* Peter Mc Leod (Lineamientos sobre el rendimiento de Interbase)
· 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/

* Alex Schlecht (Incluyendo componentes en una StatusBar)
· LMD StoragePack - por LMD Innovative - Shareware (EUR 59)
   Ocho componentes para salvar/restaurar datos de configuración (o sea,
   en tiempo de diseño, a través del diálogo de selección de propiedades)
   en/desde el Registro de Windows o archivos Ini, XML o binarios, siendo
   fácil cambiar entre estos formatos. Se incluye código fuente completo
   y un proyecto demo. http://www.ceberus.com/lmd/products/index.php3#P9

También quiero hacer un agradecimiento especial al Ing. Ernesto Cullen
por la traducción del artículo Lineamientos sobre el rendimiento de
Interbase, cuya segunda parte se publicará en el próximo número, para el
cual tenemos disponibles los siguientes premios para dos de los autores
que colaboren artículos (en inglés):

* SDL Component Suite 7.0 - por Software Development Lohninger ($99)
   La SDL Component Suite provee un amplio rango de componentes para la
   ciencia y la ingeniería, por ejemplo matemáticas, estadísticas,
   química, diagramas, visualización de datos, transformadas de Fourier
   (FFT), ploteos 3D, mapas geográficos, ajuste de curvas, etc.
   Disponible para Delphi 3-7 y BCB 4-6.
   http://www.lohninger.com/sdlindex.html

* NTTools 7 For Delphi - por i-tivity (USD 39.95)
   ¡Basta de batallar con la API de Seguridad de Windows NT! Obtenga su
   copia de NTTools 7 para Delphi 4/5/6/7 ahora y ahórrese incontables
   horas con esta colección de 40 componentes VCL escritos específica-
   mente para tratar con las funciones de Seguridad de Windows NT. Se
   incluye código fuente completo.
   http://www.i-tivity.biz/nttools.htm

En las noticias, Borland está preparando la próxima versión de Delphi,
nombre clave Octane, planeada para ser lanzada a fines de este año.
Esta nueva versión continuará soportando la VCL y CLX, permitiendo a
los desarrolladores construir aplicaciones Win32 tradicionales, pero el
lenguaje Delphi tendrá soporte completo para .Net y además incluirá una
versión 100% .Net de un gran subconjunto de la VCL, permitiendo así a
los desarrolladores construir también aplicaciones para la plataforma
.Net usando el mismo IDE, y con las habilidades y el conocimiento sobre
Delphi que ya poseen. Para más información:

- Open Letter to the Delphi Community - por Simon Thornhill
   http://bdn.borland.com/article/0,1410,29951,00.html

- Octane and Delphi Q&A - por Anders Ohlsso
   http://bdn.borland.com/article/0,1410,29952,00.html

Espero que disfruten esta edición.

Saludos,

Ernesto De Spirito
boletin-pascal-owner@...

__________________

Colaboraron en esta edición: Ernesto Cullen y Dave Murray

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


2. Lineamientos sobre el rendimiento de Interbase (I)

    Por Peter Mc Leod <PeterMcLeod@...>

        Traducido por Ernesto Cullen


Este documento intenta plasmar varios lineamientos sobre cómo obtener el
mejor rendimiento de Interbase. Antes de comenzar con los aspectos que
yo recomendaría al diseñar una base de datos para alcanzar las
necesidades de sus clientes, querría recordarle que generalmente los
aspectos más costosos (en orden) de un proyecto son:

   1. Desarrolladores
   2. Red
   3. Servidor

Por lo tanto, cuando priorice sus recursos, tenga presente la lista
anterior. También es sabido que un "atajo" tomado al principio del
proyecto (como por ejemplo no probar contra una base de datos totalmente
llena) siempre toma al menos tres veces más tiempo para corregirlo
después, y cuesta al menos tres veces más.


Desarrollo de la base de datos
==============================


Normalice su base de datos
--------------------------

No importa para qué base de datos esté desarrollando, se debe comenzar
con un buen diseño. Asegúrese de tener normalizada su base de datos
hasta al menos la tercera forma normal. Verifique que sus claves
primarias son independientes de cualquier objeto de negocio que esté
almacenando, y -por razones de rendimiento- use un entero cuando le sea
posible (los enteros tienen 32 bits y se ordenan más rápido en la
mayoría de los algoritmos comparados a los campos de tipo Char o
Varchar), a menos que no pueda hacerlo por alguna razón específica (por
ejemplo cuando necesita un identificador único para replicación, o
cuando usa una base de datos relacional para almacenar objetos).


Claves primarias
----------------

Si define una clave primaria compuesta, se crea más de un índice (uno
por cada columna que compone la clave). Dado que el Optimizador de
Consultas usará los varios índices para resolver una consulta, esto
puede causar un cuello de botella para el optimizador si los índices
múltiples usados por el optimizador son los mismos que los campos en la
consulta.


Claves externas
---------------

Las claves externas (o claves foráneas) son esencialmente restricciones
de integridad referencial. El problema con las claves externas es que se
creará un índice en la tabla respectiva, para facilitar la restricción.
Normalmente esto no es un problema, pero si Ud. tiene una restricción de
clave externa sobre columnas que tienden a repetir valores, entonces
tiene un índice muy pobre. Si el Optimizador de Consultas utiliza uno
de estos índices entonces se provocará un cuello de botella en el
rendimiento debido al índice pobre. En estos casos, eliminar los índices
puede incrementar el rendimiento de consultas en porcentajes de algunos
cientos. Entonces sea cuidadoso cuando defina sus claves externas.


Use índices en columnas de relación
-----------------------------------

Un índice es una estructura de datos en árbol balanceado que provee una
mejora en la velocidad de ordenamiento para una base de datos. Los
índices de Interbase tienen una dirección específica (ascendentes o
descendentes), por lo que si va a navegar hacia atrás en una tabla
debería definir un índice descendente. Los índices trabajan mejor con
datos que tienes a ser únicos. El optimizador de consultas de Interbase
usará índices para acelerar las consultas. Los índices son actualmente
malos para el rendimiento cuando son creados sobre una columna que tenga
pocos valores únicos. Los índices enlentecen la inserción de datos en
una tabla, ya que tienen que ser recalculados. Si va a hacer un número
grande de inserciones en una tabla debería considerar desactivar
temporalmente los índices para minimizar el impacto sobre el rendimiento
(ALTER INDEX nombre INACTIVE), y reactivar el índice después que las
inserciones han sido hechas (ALTER INDEX nombre ACTIVE). Para determinar
la efectividad de un índice, ejecute la siguiente sentencia SQL:

   Select RDB$INDEX_NAME, RDB$STATISTICS from RDB$INDICES

El valor RDB$STATISTICS muestra la efectividad del índice. Mientras
menor el valor, mejor el índice, con un valor de uno indicando un índice
muy pobre. Como una regla práctica general, debería definir sólo unos
pocos índices en una tabla (el optimizador de consultas usa múltiples
índices para los mismos campos según sea necesario en una consulta, por
lo que muchos índices pueden llevar a una degradación del rendimiento).


SQL
---

Algunas sentencias SQL son más lentas que otras. En general evite el uso
de funciones como "CONTAINING", "LIKE", "<>", "COUNT" y "UPPER" ya que
estas funciones no usan índices durante su operación, haciéndolas más
lentas que otros comandos. El libro "SQL Performance Tuning" de Peter
Gulutzan y Trudy Petzer cubre engran detalle como incrementar la efec-
tividad de sus sentencias SQL sin referencias a ninguna funcionalidad
propietaria específica. Yo recomendaría este libro a cualquiera involu-
crado en desarrollo de bases de datos.


Subconsultas correlacionadas
----------------------------

Una subconsulta correlacionada es una subconsulta donde las condiciones
de la subconsulta son diferentes para cada fila de la consulta prin-
cipal. Debido a esto, la subconsulta necesita ser ejecutada muchas veces
(una por cada fila de la consulta principal). En algunos casos, una
union (join) puede reemplazar una subconsulta correlacionada y resultará
en un mejor tiempo de ejecución de la consulta.


Combinaciones externas (Outer join)
-----------------------------------

Las combinaciones externas son una realidad de la programación de bases
de datos. Las combinaciones externas por la izquierda (left outer join)
tienen una tendencia a ser lentas, y se usará un índice únicamente para
la resolución de la primera combinación externa en una consulta. Donde
sea posible, reduzca la necesidad de combinaciones externas izquierdas.
Esto puede hacerse vía:

- Diseñar las tablas de manera que las combinaciones no sean necesarias
- Usar subconsultas (esto puede ser más rápido que resolver combina-
   ciones externas por la izquierda)
- Usar un procedimiento almacenado que devuelva un cursor para
   incrementar la velocidad


Procedimientos almacenados
--------------------------

Cuando cree un procedimiento almacenado que contenga bucles anidados
asegúrese que el bucle más externo devuelve el menor número posible de
registros. Si es posible estructure sus procedimientos almacenados de
manera que los bucles internos sean siempre los más veloces, ya que son
iterados la mayor cantidad de veces.


No utilice campos Char o Varchar largos
---------------------------------------

Antes de Interbase 7.0, los campos de tipo Varchar y Char eran comple-
tados hasta su longitud máxima al ser enviados al cliente. Si Ud.
solamente ocupa una parte de un campo Varchar o Char largo y luego pide
los resultados desde el cliente, se genera una gran cantidad de tráfico
de red, lo que puede degradar el rendimiento de su aplicación y de la
red. De ser posible no utilice campos largos de tipo Char o Varchar, o
use Blobs como una alternativa. Un Blob tiene también la ventaja de ser
almacenado en su propia página en la base de datos y esto reduce la
posibilidad de bloqueos.

Como una alternativa, actualice a Interbase versión 7.0.


BLOBs
-----

El tipo BLOB (Binary Large OBject) es un tipo de datos que soporta
objetos grandes. Un BLOB se define con un tamaño de segmento, y en
Interbase el valor por defecto para este parámetro es de 80 bytes. Si
un campo BLOB se define con un tamaño de segmento igual al tamaño de
página de la base de datos las consultas con campos BLOB se resolverán
muy rápidamente, ya que solo se necesita recuperar una página para
completar los datos. Bajo estas situaciones Interbase no es el cuello
de botella en las transferencias de datos; otros subsistemas como el
hardware, red, etc. disminuirán normalmente la tasa de transferencia
de datos.


Utilice procesamiento cliente/servidor
--------------------------------------

Interbase provee varias características que permiten que algunos
procesos se ejecuten en el servidor (el cual frecuentemente tiene más
capacidad de proceso que las máquinas cliente, y también se reduce el
tráfico por la red). Los triggers (disparadores), UDFs (funciones defi-
nidas por el usuario) y stored procedures (procedimientos almacenados)
están todos adecuadamente detallados en la Guía del Programador
(Programmer's Guide) y en la Guía de Definición de Datos (Data
Definition Guide) por lo que no serán detallados aquí.


Plan de consultas
-----------------

Interbase usa un optimizador basado en costos para optimizar la ejecu-
ción de las sentencias SQL. En la mayoría de los casos el optimizador
realiza muy bien su trabajo; pero bajo ciertas circunstancias el
optimizador no selecciona el plan que consigue el mejor rendimiento.
Tenga cuidado, ya que si Ud. especifica su propio plan de consulta el
optimizador no lo analizará para asegurarse que es correcto. Puede
encontrar detalles sobre cuándo y cómo ajustar el plan de consulta de
Interbase en los siguientes sitios:

* Specifying Query Access Plans in the Interbase Optimizer
   http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_quep

* Managing your Interbase Server - by Paul McGee
   http://www.mers.com/MANAGE.HTML


RDB$DB_KEY
----------

RDB$DB_KEY es un identificador de registros de bajo nivel, más rápido
que la clave primaria para la recuperación de registros. Estos identi-
ficadores son válidos solamente durante la transacción actual, y no
pueden tomarse como identificadores permanentes de registros. Aún así
es posible utilizar los RDB$DB_KEY para incrementar el rendimiento de
rutinas SQL en una base de datos Interbase. La desventaja de esto es
que la ganancia en rendimiento es específica para Interbase. Para más
detalles sobre cómo utilizar la RDB$DB_KEY, refiérase a los documentos
localizados en el siguiente sitio:

* IB Documentation
   http://www.cvalde.com/ibDocumentation.htm


Lineamientos para el servidor
=============================

Utilice un servidor dedicado
----------------------------

Un servidor dedicado provee el mejor rendimiento para una base de datos
Cliente/Servidor. El costo de un rendimiento inadecuado es, por mucho,
más costoso que comprar un servidor dedicado. Un rendimiento pobre se
reflejará en Ud. como desarrollador y resultará generalmente en tiempo
empleado identificando y rectificando problemas. No tomará mucho hasta
que se justifique el costo del servidor dedicado.


Utilice Linux como sistema operativo del servidor
-------------------------------------------------

Los servidores Linux o Unix hacen una mejor utilización de la memoria
real y virtual, tienen un buen modelo de priorización multiprocesador,
y frecuentemente requieren menos recursos de CPU y memoria que otros
sistemas operativos. Los servidores Linux demuestran tiempos de arranque
mucho mejores comparados con sus contrapartes Windows. Linux tampoco
parece tener procesos misteriosos que degradan el rendimiento, y que
desaparecen tan pronto como Ud. se registra en el servidor para examinar
el problema. Los servidores Linux o Unix se pueden integrar en una red
Windows con SAMBA proveyendo un enlace transparente en cuanto a los
clientes concierne.


Si Ud. tiene que usar Windows
-----------------------------

Verifique su servidor Windows para ver si está configurado para proveer
máximos recursos a la compartición de archivos o a las aplicaciones de
segundo plano. Todas estas opciones están localizadas en diferentes
lugares para distintos Windows, refiérase a la documentación de su
Windows. Esta configuración puede tener un gran impacto en el rendi-
miento de Interbase.


Use máquinas de un solo procesador con Interbase
------------------------------------------------

Si Ud. está usando una versión menor que 7.0 de Interbase bajo Windows
NT, no utilice un servidor multiprocesador. Si lo hace, el proceso de
servidor de Interbase cambiará de procesador a procesador causando
degradación del rendimiento del servidor. Si quiere usar Interbase
(anterior a la versión 7.0) en un sistema multiprocesador entonces
utilice una herramienta para fijar Interbase a un solo procesador (hay
varias disponibles, incluyendo una de Microsoft). No obstante, aún así
debería tener en cuenta que dado que algunos de los primeros sistemas
operativos Windows NT no implementaban un buen modelo de soporte SMP,
la mejora en rendimiento podría ser menor de lo que esperaría. Los
sistemas Linux tienen un soporte SMP apropiado.


Utilice un disco rígido dedicado
--------------------------------

Si Ud. tiene su base de datos en el mismo disco que el archivo de
paginación de un servidor, el incremento en las operaciones de
entrada/salida de la administración de memoria virtual del servidor
impactarán en el rendimiento de su aplicación. Siempre ubique su base
de datos en un disco separado. Si tiene el dinero yo sugeriría que su
sistema operativo estuviera en un disco, su base de datos en otro, y
el archivo de intercambio en otro.


Discos veloces
--------------

Las operaciones de entrada/salida de disco son frecuentemente un cuello
de botella para el rendimiento de las bases de datos. Los discos IDE
comúnmente usan algunos recursos de la CPU. Siempre prefiera los
sistemas SCSI más veloces que pueda comprar. El ahorro en este tema le
costará mucho en términos de degradación de rendimiento. Los sistemas
RAID también ofreces mejor rendimiento que los sistemas de discos
únicos. Un buen arreglo RAID de varios discos SCSI es la mejor solución.


Utilice una dirección IP estática en el servidor
------------------------------------------------

Una dirección IP estática en el servidor significa que la dirección IP
del servidor puede encontrarse más rápido que usando servicios de
traducción de nombres a direcciones. Esta IP debería estar fija en el
archivo Hosts del servidor, y en los archivos Hosts de las máquinas
clientes.


Utilice TCP/IP como protocolo de red
------------------------------------

TCP/IP es un protocolo basado en conexión (los paquetes son enviados al
receptor adecuado en lugar de ir a todas las máquinas) lo que genera
menos tráfico de red que los protocolos no orientados a conexiones como
NetBEUI o IPX/SPX. TCP/IP es también más rápido que cualquiera de estos
protocolos, y tiene la ventaja de estar disponible en una más amplia
variedad de plataformas. Siempre que sea posible debería usarse TCP/IP
para comunicarse con Interbase por su ventaja de velocidad. Para mejorar
todavía más el rendimiento es recomendable no instalar múltiples proto-
colos en la red ya que esto incrementa el "ruido" en la red. Si esto es
inevitable, entonces asegurando que el protocolo que utiliza está
primero en la pila Ud. tendrá más prioridad en la red.


No utilice salvapantallas
-------------------------

Los salvapantallas, particularmente los de tipo 3GL, pueden usar
intensamente el procesador y degradar notoriamente el rendimiento del
sistema. En la mayoría de los casos los salvapantallas no son necesarios
ya que los monitores modernos son diseñados de manera tal que el riesgo
de "quemar" la pantalla es ínfimo, e incluso los monitores que ahorran
energía se apagarán solos. Si no tiene un monitor con ahorro de energía,
simplemente apáguelo, como mínimo estará usando menos electricidad y no
generará tanto calor en el cuarto del servidor. Si tiene que utilizar un
salvapantallas entonces use "pantalla en blanco" o "marquesina" (con la
velocidad de desplazamiento del texto lenta para evitar una utilización
excesiva de la CPU) ya que éstos utilizan la menor cantidad de recursos.


Ingreso al servidor a través de consola
---------------------------------------

Mucha gente tiende a usar Windows NT/2000 porque están más familiari-
zados con el sistema operativo Windows. Si Ud. usa Windows NT, no inicie
una sesión en el servidor innecesariamente, o permanezca en una. Aparte
de constituir un problema de seguridad, dejar una sesión funcionando en
el servidor permite a los procesos correr en segundo plano, lo que puede
degradar el rendimiento del servidor. Aún los procesos de segundo plano
pueden usar un 20%-30% de los recursos del servidor. Hay muchas herra-
mientas que permiten mantener un servidor Interbase sin la necesidad de
tener una sesión iniciada en el servidor.


Utilice la misma versión del cliente de Interbase que su servidor
-----------------------------------------------------------------

Si Ud. tiene una versión desactualizada del cliente de Interbase
instalada en la máquina cliente, comparando con la versión instalada en
su servidor podría estar sufriendo una baja de rendimiento. Pruebas con
Interbase 5.1 y 5.6 pueden mostrar una diferencia de rendimiento de un
poco mas del 50% debida al uso de una instalación de cliente
desactualizada. También puede tener problemas para acceder a las nuevas
características si está usando versiones diferentes para el cliente y el
servidor y pueden aparecer errores de aplicación (en algunos casos esto
puede causar que el servidor Interbase se caiga y posiblemente que se
corrompa la base de datos).


Superando restricciones de entrada/salida de disco
--------------------------------------------------

Es posible reducir el problema de las operaciones de entrada/salida de
disco en Interbase. Después de realizar un respaldo y restauración, cree
una tabla temporal en la base de datos (usando campos Blob o columnas
Varchar grandes). Llene esta tabla con una gran cantidad de datos. A
continuación elimine la tabla temporal (drop) y realice un sweep en la
base de datos. Esto significa que Interbase reutilizará el espacio
dentro de la base de datos durante las operaciones, y no pedirá más
espacio en disco al sistema operativo hasta que todo el espacio libre
dentro de la base de datos haya sido reutilizado. Esto incrementa la
velocidad de las operaciones de escritura en la base de datos, ya que
las E/S de disco no son esencialmente un factor limitante.


Protección de archivos de Windows
---------------------------------

Algunas versiones de Windows (Windows XP) han implementado mecanismos
de protección para archivos con extensión .GDB (bases de datos de
Interbase). Si Ud. utiliza un sistema operativo superior a Windows 2000
puede experimentar a desactivar la protección de archivos de Windows o
renombrar su base de datos con otra extensión (para bases de datos
mayores que Interbase 7.0 o Firebird 1.5). Los cínicos entre nosotros
se preguntarán si Microsoft hizo esto para reducir el rendimiento de
Interbase en comparación con su propia base de datos SQL Server...

________________________________________________________________________

¿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!"
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
Sólo hay que seguir el enlace y hacer clic en "here" ("aquí") donde dice
"Click here to vote!" ("¡Haga clic aquí para votar!"). Luego aparecerá
el ranking de los más votados. Su voto significa mucho para nosotros.
________________________________________________________________________


3. Incluyendo componentes en una StatusBar

    Por Alex Schlecht
        http://www.bombus-software.de


El componente TStatusbar no permite colocar componentes en él, pero a
veces resultaría muy útil agregar -por ejemplo- un TProgressBar (barra
de progreso) en una barra de estado.

Este artículo muestra cómo agregar componentes a un TStatusbar y cómo
hacer que encajen en uno de los paneles de la barra de estado.

Hay (por lo menos) dos maneras de agregar componentes en su barra de
estado:


1) Creando su propia barra de estado
------------------------------------

Cree su propia barra de estado y permita que se le agreguen componentes.
Esto es posible sobrescribiendo el constructor Create:

   type
     TMyStatusBar = class(TStatusBar)
     public
       constructor Create(AOwner: TComponent); override;
     end;

   implementation

   constructor TMyStatusBar.Create(AOwner: TComponent);
   begin
     inherited Create(AOwner);
     ControlStyle := ControlStyle + [csAcceptsControls];
     // ¡Eso es todo!
   end;

Eso es todo. Ahora este componente puede aceptar otros componentes como
"hijos", los que pueden ser colocados en tiempo de diseño en la barra de
estado.

Pero no me gusta mucho esta forma de hacerlo porque tiene que usar este
nuevo componente. Prefiero usar el componente "viejo" manipulándolo un
poco, así que démosle un vistazo a mi forma favorita:


2) "Adoptando" al otro componente
---------------------------------

La manera más simple de incluir componentes en una StatusBar es
adoptando los componentes. Coloque un TStatusbar en su formulario, y
también coloque la ProgressBar (o cualquier otro componente que desee
incluir en su StatusBar). Luego haga lo siguiente en el evento OnShow
de su formulario:

   ProgressBar1.Parent := StatusBar1;
   ProgressBar1.Top := 1;
   ProgressBar1.Left := 1;

Ahora la ProgressBar ha sido "adoptada" por la StatusBar.

Pero desafortunadamente no se ve muy bien porque la ProgressBar es más
grande que el panel y la posición no es correcta, así que tenemos que
determinar la posición exacta de la ProgressBar usando las propiedades
Border, Width y Height de la StatusBar. Tenemos que añadir este código
al evento OnShow del formulario porque en el evento OnCreate no hay
"manejadores" (handles) disponibles.

   uses CommCtrl;

   procedure TForm1.FormShow(Sender: TObject);
   var r : TRect;
   begin
     StatusBar1.Perform(SB_GETRECT,0,integer(@R));
     // Determinar el tamaño del panel 1

     // SB_GETRECT necesita la unidad CommCtrl
     // 0 = primer panel de StatusBar; 1 = segundo; y así sucesivamente.

     ProgressBar1.Parent := StatusBar1;       // Adopta la ProgressBar

     ProgressBar1.Top := r.Top;               // Establece el tamaño...
     ProgressBar1.Left := r.Left;             // ...de la ProgressBar...
     ProgressBar1.Width := r.Right - r.Left;  // ...para que encaje...
     ProgressBar1.Height := r.Bottom - r.Top; // ...en el panel
   end;

Ahora la ProgressBar encaja exactamente en el primer panel de la barra
de estado. Si desea usar el segundo panel o cualquier otro panel, sólo
tiene que cambiar el parámetro del comando "Perform".

Comentarios y mejoras son bienvenidos.

Alex Schlecht

________________________________________________________________________

           ¡Vote por el Boletín Pascal en The Programming Pages!
     http://www.programmingpages.com/topsite.asp?r=latium&Language=29
________________________________________________________________________


4. Notas de un desarrollador (I)


La presente es parte de una serie de pequeños artículos narrando expe-
riencias en el desarrollo de una aplicación.


Rx TSpeedBar y TToolBar
=======================

Es de hacer notar que las RX son el conjunto de componentes "freeware"
más representativos en el mundo de Delphi. Siempre que se habla de
Delphi y "freeware" se pasa por la Rx (las "rusas" para muchos).

Bien, éstas van por la versión 2.75. Estaban en www.rxlib.com. Ya no.
Fui hace unos meses para encontrar que un ser maquiavélico adquirió el
dominio y puso un buscador (muy malo por cierto). Me molesta sentirme
engañado y me resulta estúpido que alguien crea que si llego a un sitio
engañado voy a comprar (no, de hecho por eso odio a los vendedores de
resorts). No todo esta perdido; las Rx se encuentran en SourceForge.net
junto con otros valiosos trabajos (esperemos que nadie compre
SourceForge.net para vender resorts).

Volviendo a las Rx, yo utilizo mayormente los controles de DBGrid,
Fechas, la tabla en memoria, el panel secreto y TSpeedBar. De hecho lo
uso en HalZip (http://www.gavidia.org/halzip) y CC Cyber Café
(http://www.gavidia.org/cc). Todo muy bien hasta que uno de los
reportes que tengo por fallas en CC señaló una excepción por falta de
recursos bajo Windows 98. De antemano señalo que pude reproducir la
falla (más o menos), luego de arduos esfuerzos, para al final no poder
resolverla. Opté entonces por usar TToolBar en remplazo de TSpeedBar
(de las Rx).

TToolBar se porta bien (sin la falla de falta de recursos) pero carece
de una ventaja práctica de las Rx al colocar un fondo gráfico en la
barra. Es  problema se resuelve manejando el evento OnCustomDraw. He
aquí el ejemplo.

   // fondo : TBitMap; <- esto va en la sección
   //                     privada del formulario.

   procedure TfrmMain.ToolBar1CustomDraw(Sender:
       TToolBar; const ARect: TRect;
       var DefaultDraw: Boolean);
   var
     ix, iy: Integer;
     BmpWidth, BmpHeight: Integer;
     hCanvas, BmpCanvas: THandle;
   begin
     if assigned(fondo) and
       ((fondo.Height <> 0) or
       (fondo.Width <> 0)) then
     begin
      BmpWidth := fondo.Width;
      BmpHeight := fondo.Height;
      BmpCanvas := fondo.Canvas.Handle;
      hCanvas := Sender.Canvas.Handle;
      for iy := 0 to Sender.ClientHeight div BmpHeight do
         for ix := 0 to Sender.ClientWidth div BmpWidth do
           BitBlt (hCanvas, ix * BmpWidth, iy * BmpHeight,
             BmpWidth, BmpHeight, BmpCanvas, 0, 0, SRCCOPY);
       DefaultDraw := true;
     end;
   end;

"Fondo" es de tipo TBitMap, es creado en el evento "FormCreate" del
formulario principal ("fondo := TBitMap.Create;" ) y destruido también
con el formulario (con "FreeAndNil(fondo)").

En mi caso particular (Halzip), si el archivo "fondo.bmp" existe lo
usamos. No hay que olvidar refrescar el "ToolBar".

   if FileExists(ExtractFilePath(Application.ExeName)+
                'fondo.bmp') then
   begin
     fondo.LoadFromFile(ExtractFilePath(Application.ExeName) +
       'fondo.bmp');
     ToolBar1.Refresh;
   end


Menú movible
============

Encontré también algo que está en la documentación de Delphi y que
cuando lo necesité no sabía que estaba allí. ¿Se han fijado que el menú
en muchas aplicaciones puede ser movido de sitio? La solución es usar
TToolBar.

Asumiendo que tenemos un menú creado en el formulario. Simplemente:

1) Colocamos un "ToolBar" en el formulario
2) Creamos tantos botones como entradas al menú principal.
3) Cada botón tiene una propiedad "MenuItem" que apuntaremos a cada menú
    que tenemos.
4) La propiedad "Grouped" del "Toolbar" se hace "True".
5) El formulario principal tiene una propiedad llamada "Menu" (aunque la
    ayuda de Delphi 5 diga "MainMenu"). Colóquenla apuntando a la nada.
6) Para que quede bien es bueno que la propiedad "ShowCaptions" esté
    encendida.
7) Luego ajusten lo que les provoque. Ya debe funcionar.


Por favor no dejen de usar las Rx; es mejor dejar de usar Windows 98.
Sin embargo, si encuentran el problema de la excepción por falta de
recursos y lo resuelven, avísenme.

Gracias.

Alirio A. Gavidia
desde www.gavidia.org

__________________

Próximo tema: Convertir archivos gráficos de distinto tipo: ico, wmf,
               emf, jpg y gifs (más de RX).

________________________________________________________________________


5. Enumerando las conexiones de red
    Detectando las conexiones de red actuales

    Por Igor Siticov
        SiComponents: http://www.sicomponents.com


¿Cómo detectar las conexiones de red actuales?

Desde la línea de órdenes de MS-DOS uno puede enumerar las conexiones de
red (unidades) usando el siguiente comando:

   net use

Para hacerlo programáticamente debemos llamar a la API WNetOpenEnum()
para comenzar la enumeración de los recursos conectados y luego a la
API WNetEnumResources() para continuar la enumeración.

La siguiente muestra de código enumera las conexiones de red:

   procedure TForm1.Button1Click(Sender: TObject);
   var
     i, dwResult: DWORD;
     hEnum: THANDLE;
     lpnrDrv: PNETRESOURCE;
     s: string;
   const
     cbBuffer:DWORD = 16384;
     cEntries: DWORD = $FFFFFFFF;
   begin
     dwResult := WNetOpenEnum(RESOURCE_CONNECTED, RESOURCETYPE_ANY,
                              0, nil, hEnum);
     if dwResult <> NO_ERROR then begin
       ShowMessage('No se pudo enumerar las unidades de red.');
       Exit;
     end;
     s := '';
     repeat
       lpnrDrv := PNETRESOURCE(GlobalAlloc(GPTR, cbBuffer));
       dwResult := WNetEnumResource(hEnum, cEntries, lpnrDrv, cbBuffer);
       if dwResult = NO_ERROR then begin
         s := 'Unidades de red:'#13#10;
         for i := 0 to cEntries - 1 do begin
           if lpnrDrv^.lpLocalName <> nil then
             s := s + lpnrDrv^.lpLocalName + #9 + lpnrDrv^.lpRemoteName;
           Inc(lpnrDrv);
         end;
       end else if dwResult <> ERROR_NO_MORE_ITEMS then begin
         s := s+'No se pudo completar la enumeración de unidades de red';
         GlobalFree(HGLOBAL(lpnrDrv));
         break;
       end;
       GlobalFree(HGLOBAL(lpnrDrv));
     until dwResult = ERROR_NO_MORE_ITEMS;
     WNetCloseEnum(hEnum);
     if s = '' then s := 'No hay conexiones de red.';
     ShowMessage(s);
   end;

__________________

Igor Siticov es el autor de TsiLang Components Suite (un completo juego
de componentes para construir en dos minutos aplicaciones multilingües
elegantes, útiles y amistosas con el usuario) y de Resource Builder (un
muy completo editor visual de RC script, ideal para reemplazar al
Borland Image Editor y al Borland Resource WorkShop para crear y editar
archivos de recursos), por SiComponents: http://www.sicomponents.com

________________________________________________________________________


6. Buscando archivos en Delphi

    Por Charl Linssen


¡Hola lector! Para uno de mis proyectos necesitaba un procedimiento que
buscara un directorio y todos sus subdirectorios, y que mostrara todos
los archivos que contenían. Pensé que podría encontrar un procedimiento
como ese en la Internet, pero no pude hallar uno que fuera adecuado, así
que decidí escribir uno propio. Aquí esta:

   Const MAXFILES = 1000;

   var CurrSearchedDir: Array [1..MAXFILES] of String;
       OriginalPath, OldSearchedDir: String;
       InSubDir: Boolean = False;
       CurrInstance: Integer;

   [...]

   procedure search(BasePath:String);
   var DirInfo: TSearchRec;
       I:Integer;
   begin
     Inc(CurrInstance);
     If InSubDir then
       CurrSearchedDir[CurrInstance] := OldSearchedDir + '\' +
                                        CurrSearchedDir[CurrInstance-1];
     FindFirst(BasePath+'\*', faDirectory, DirInfo);
     repeat
       If (DirInfo.Name = '.') or (DirInfo.Name = '..') then Continue;
       If (ExtractFileExt(DirInfo.Name) <> '.html') and not
          ((DirInfo.attr and faDirectory) = faDirectory) then Continue;
       // Remover la línea de arriba si uno busca cualquier archivo
       if (DirInfo.attr and faDirectory) = faDirectory then
       Begin
         InSubDir := True;
         OldSearchedDir := CurrSearchedDir[CurrInstance];
         CurrSearchedDir[CurrInstance] := DirInfo.Name;
         Search(BasePath + DirInfo.Name + '\');
         Continue;
       End;
       frMain.ListBox1.Items.Add(OriginalPath +
         CurrSearchedDir[CurrInstance] + '\' + DirInfo.Name);
     Until FindNext(DirInfo) <> 0;
     Dec(CurrInstance);
   end;

Como puede ver al examinar detenidamente este procedimiento, el mismo
es recursivo. Esto significa que se llama a sí mismo. Hace eso cuando
encuentra un subdirectorio y necesita buscar en ese subdirectorio
archivos y posiblemente otros subdirectorios. Esto hace que el
procedimiento sea apto para tantos subdirectorios como uno necesite.

¡Divértanse!

-- Charl

________________________________________________________________________


7. Inline Assembler en Delphi (VIII) - Aritmética entera de 128 bits (2)

    Por Ernesto De Spirito


En el ejemplo de código fuente (adjunto) encontrará la implementación de
algunas funciones para operar con el tipo de datos Hugeint que fuera
presentado en la edición pasada. El propósito es ejemplificar las
instrucciones que hemos visto hasta ahora, junto con algunas nuevas:

   BT (Bit Test):

     BT dword ptr [eax], edx  --> CF = valor del bit número EDX en la
                                       memoria apuntada por EAX

   BTS (Bit Test and Set):

     BTS dword ptr [eax], edx  --> Establece en 1 el bit número EDX en la
                                   memoria apuntada por EAX
                                   CF = valor anterior de ese bit

   BTR (Bit Test and Reset):

     BTR dword ptr [eax], edx  --> Establece en 0 el bit número EDX en la
                                   memoria apuntada por EAX
                                   CF = valor anterior de ese bit

   BTC (Bit Test and Complement):

     BTC dword ptr [eax], edx  --> Invierte el valor del bit número EDX
                                   en la memoria apuntada por EAX
                                   CF = valor anterior de ese bit

No reproduciremos aquí las funciones puesto que puede encontrarlas en el
código fuente adjunto, pero sí mostraremos diferentes implementaciones
posibles de la función _IsNeg, simplemente con el propósito de proveer
más ejemplos de las instrucciones que hemos visto hasta ahora:

   function _IsNeg(x: Hugeint): boolean;
   // Result := x < 0;
   // Si x < 0 devuelve True (1), de lo contrario devuelve False (0)
   // Parámetros: EAX = @x
   asm
     mov eax, [eax+_3_] // EAX := 32 bits de orden alto de x
     shr eax, 31        // AL  := bit de orden alto de EAX (bit de signo)
   end;

   function _IsNeg(x: Hugeint): boolean;
   asm
     cmp dword ptr [eax+_3_], 0   //   if x[3] < 0 then
     jl @@negativo                //     goto @@negativo
     mov al, 0                    //   Result := False;
     ret                          //   exit;
   @@negativo:                    // @@negativo:
     mov al, 1                    //   Result := True;
   end;

   function _IsNeg(x: Hugeint): boolean;
   asm
     // Establecer la Señal de Signo con el bit 127 y ponerla en AL
     mov eax, [eax+_3_]  // EAX := 32 bits de orden alto de x
     or eax, eax         // SF := Bit de signo de EAX
                         // alt.: add eax, 0
                         // ...o: sub eax, 0
                         // ...o: and eax, eax
                         // ...o: and eax, -1   // o cualquier valor < 0
                         // ...o: test eax, eax
                         // ...o: test eax, -1  // o cualquier valor < 0
     sets al             // AL := SF;  // Señal de Signo (Sign Flag)
                         // alt.: lahf; shr ax, 31
                         // ...o: lahf; rol ax, 1; and al, $1
   end;

   function _IsNeg(x: Hugeint): boolean;
   asm
     // Establecer la Señal de Acarreo con el bit 127 y asignarla a AL
     mov eax, [eax+_3_]  // EAX := 32 bits de orden alto de x
     bt eax, 31          // CF := Bit de signo de EAX
                         // alt.: shl/rol/rcl eax, 1
     setc al             // AL := CF;  // Señal de Acarreo (Carry Flag)
                         // alt.: mov al, 0; rcl, 1
                         // ...o: mov al, 0; adc al, al
                         // ...o: lahf; mov al, ah; and al, $1
                         // ...o: lahf; ror/rcr/shr/sar ax, 1; shr al, 7
                         // ...o: lahf; ror/shr/sar ax, 8; and al, $1
                         // ...o: lahf; rol ax, 8; and al, $1
                         // ...o: lahf; rcl ax, 9; and al, $1
   end;

   function _IsNeg(x: Hugeint): boolean;
   asm
     // Establecer la señal de paridad con el bit de signo negado
     // y negarla en AL
     mov al, [eax+_3_+3] // EAX := 8 bits de orden alto de x
     or al, $7F          // PF := Bit de signo negado
                         // alt.: and eax, $80000000
     setnp al            // AL := Not PF;  // Señal de paridad negada
                         // alt.: lahf; rol/shl ax, 6 ó rcl ax, 7;
                                  xor al,-1 ó not al; and al, $1;
                         // ...o: lahf; ror/shr/sar ax, 10 ó rcr ax, 11;
                                  xor al,-1 ó not al; and al, $1;
   end;

En la próxima parte veremos funciones para sumar, restar, multiplicar y
dividir enteros gigantes.

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


8. Foros / listas de correo


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).
   http://espanol.groups.yahoo.com/group/delphi-abierto
   Suscripción:
     http://espanol.groups.yahoo.com/group/delphi-abierto/join
     delphi-abierto-subscribe@...

* 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@...

* 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

________________________________________________________________________

¿Errores Delphi?  Capture y registre cada error mostrando unidad, clase,
método y número de línea. http://www.eurekalog.com/bannerclick.php?id=15
________________________________________________________________________


9. Delphi en la Red

    Por Dave Murray <irongut @ vodafone.net>


Componentes, librerías y aplicaciones
=====================================


Shareware/Comercial
-------------------

* LMD StoragePack - by LMD Innovative - Shareware (EUR 59)
   Eight components for saving/restoring of configuration data (e.g. at
   design time, via extended Property Selection dialog) to/from the
   Windows Eegistry or Ini-, XML- and binary files, being easy to switch
   between these formats. Full source code and demo projects included.
   http://www.ceberus.com/lmd/products/index.php3#P9


Freeware
--------

* Mozilla v1.3 - by mozilla.org
   Mozilla 1.3 is now available for download. First there was image
   blocking, then came pop-up blocking and now we have junk-mail
   filtering. Mozilla 1.3 also offers image auto-sizing, newsgroup
   filters, dynamic profile switching, nearly 2000 bug fixes, and more.
   http://www.mozilla.org/

* Compile Time Expert v1.12 - by Vit Kovalcik (with source)
   Compile Time is expert, which generates small file right before
   compilation. You can include this file in some of your units and
   easily use time of compilation stored in this file.
   http://www.fi.muni.cz/~xkovalc

* Local Heap Memory Manager v1.0 - by Carsten Zeumer (with source)
   A Delphi memory manager replacement which allows you to limit the
   memory available to your application. Helps in finding memory holes in
   your components or to simmulate low memory conditions.
   http://www.torry.net/vcl/system/memory/localheapmm.zip

* TOpacityForm v1.6.0 - by Vjacheslav Maslov (with source)
   Allows you to create transparent form. You can change transparency at
   runtime. Uses Layered technology so only Win2k and later supported.
   http://www.torry.net/vcl/forms/effects/opcform.zip

* JG's TIMDBImport v1.02 - by JustGuy (with source)
   Native Delphi class for importing data from The Internet Movie
   Database and process it. Including search results and movie info.
   http://www.torry.net/vcl/internet/other/imdbimport.zip

* TVortex OpenSource IRC v2.8.5 - by JoepezT (w. source) (DELPHI/KYLIX)
   OpenSource IRC components, includes: TVortexIRC for IRC connectivity;
   TClusterFile for handling incoming files; TClusterChat for handling
   incoming/outgoing DCC chats; Identd Server for auth services.
   http://www.berzerk.net

* yEnc into a String - by Joao Barata (with source) (DELPHI/KYLIX)
   Converts a file into a string, which can be imported to TStringList.
   http://b-tools.hopto.org


Actualizaciones de Delphi
-------------------------

* Update: Delphi 6 RTL Update Pack 3
   A fix for frame streaming is available for download. This update pack
   is not cumulative, so you need to have installed the General Update
   and the Update Pack 2 before applying this update.
   http://community.borland.com/article/0,1410,29932,00.html

* Update: StarTeam integration for Delphi 6, 7 and C++Builder 6
   Get access to the functionality of StarTeam directly from within the
   IDE with these new plug-ins (for owners of purchased products).
   http://community.borland.com/article/0,1410,29831,00.html


Artículos, trucos y consejos
============================

* Sip from the Firehose: CodeWright - by David I
   About the new Borland CodeWright Product Group.
   http://community.borland.com/article/0,1410,29854,00.html

* Non-Rectangular Translucent Forms - by Philippe Randour
   How, on Windows 2000/XP, you can easily add a non-standard UI to your
   application by taking advantage of translucency and transparency.
   http://community.borland.com/article/0,1410,29579,00.html

* Sip from the Firehose: Borland Wins Three Jolt Awards - by David I
   http://community.borland.com/article/0,1410,29882,00.html

* Using Semaphores in Delphi: Part 1 - by Cary Jensen
   Semaphores are like mutexes on steroids. Not only can they coordinate
   multiple threads and process, but they can permit more than one
   simultaneous lock. This article shows how to use these useful objects
   in a multithreaded environment.
   http://community.borland.com/article/0,1410,29908,00.html

* Registering DLL and ActiveX controls from code - by Zarko Gajic
   How to register and unregister OLE controls such as DLLs or ActiveX
   Controls from a Delphi application.
   http://delphi.about.com/library/weekly/aa040803a.htm

* How to convert a WideString to a String?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1692

* How to know if a form already exist before you dynamically create it?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1693

* Pointer to variant - caution!
   http://www.swissdelphicenter.ch/en/showcode.php?id=1450

* How to create a database at run-time with ZEOS?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1552

* How to enable/disable cut, copy, paste, clear of a TEdit?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1700

* How to use a format parameter more than once?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1690

* How to insert text at a Bookmark (MS Word)?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1691

* How to create an Access Database?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1695

* How to copy/paste TStringGrids cells to/from ClipBoard?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1696

* How to Get the image size of a JPG, GIF and PNG image file?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1698

* Determine whether the computer supports hibernation, the sleep states?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1699

* How to get the language of MS Word?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1688

* How to locate on a non-indexed field in a TTable?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1348

* How to add records to TStrings (TTreeview / TListview)?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1482

* How to convert a ADO Recordset to XML and the reverse way?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1498

* How to create a TListView which automatically resorts by column click?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1500

* How to stretch a bitmap?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1566

* How to rotate the text in a StringGrid cell by 90°?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1596

* How to change the OnClick behavior of a TRadioButton, TCombobox?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1609

* How to combine two icons?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1636

* How to save a TImagelist with all its images to a file?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1626

* How to show a indeterminate ProgressBar in Win XP?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1680

* How to search a directory tree for a specified file?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1654

* How to align Text in a TRichEdit?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1655

* How to detect whether a file's volume is NTFS?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1657

* How to sort a Stringlist with the CustomSort Method?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1664

* How to read/write REG_DWORD values from/to the Registry?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1665

* How to get notified when the user changes the theme (XP)?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1669

* How to store a TDateTime in the registry?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1670

* How to Convert method pointers into function pointers?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1671

* How to Get / Set the Clipboard text (without using VCL)?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1677

* How to convert a WideString to a String?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1692

* How to know if a form already exists before you dynamically create it?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1693

* How to do a 2D Convolution on an Image?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1704

* How to capture a Delphi CLX Form?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1708

* Creating a System Restore Point - by Thomas Stutz
   How to create and cancel system restore points.
   http://www.delphi3000.com/articles/article_3575.asp

* TEdit that damn background - by Matt Harrison
   Using WMEraseBkGnd to create a TEdit descendant that is transparent or
   has a background.
   http://www.delphi3000.com/articles/article_3576.asp

* Introduction to SSL - by Eugene Mayevski
   Why SSL and how it works.
   http://www.delphi3000.com/articles/article_3577.asp

* Certificate basics - by Eugene Mayevski
   Key management can be an issue in security-related tasks. Certificates
   define a standard way of managing keys and associated information.
   They are also used in SSL/TLS protocol and S/MIME.
   http://www.delphi3000.com/articles/article_3578.asp

* How to store and retrieve GIF,BMP + JPG in a RDBMS - by Marcello Dias
   http://www.delphi3000.com/articles/article_3579.asp

* Add task job - by Smile xiao
   Add a scheduled task job to your system.
   http://www.delphi3000.com/articles/article_3582.asp

* Complete TFTP Server example, using Indy components - by Kim Sandell
   Example of multi-thredded TFTP Server, using Indy components.
   http://www.delphi3000.com/articles/article_3583.asp

* Retrieve DSN names and ODBC Drivers list - by Oscar Noe Martin
   http://www.delphi3000.com/articles/article_3584.asp

* No, You're not crazy Sql Server doesnt have generators - Marcello Dias
   How to make a 'Work around' on this limitation.
   http://www.delphi3000.com/articles/article_3586.asp

* An Application Loader with a TCPServer - by Max Kleiner
   We had the requirement starting different Delphi apps from a linux or
   windows server, wherever you are. We call it Delphi Web Start (DWS).
   http://www.delphi3000.com/articles/article_3588.asp

* Drawing a Shaded Rectangle - by Serhiy Perevoznyk
   Using GradientFill API function.
   http://www.delphi3000.com/articles/article_3591.asp

* Bitmap Rotation - by Serhiy Perevoznyk
   Rotate a Bitmap Image in 90-Degree Increments.
   http://www.delphi3000.com/articles/article_3592.asp

* Drawing Transparent Bitmaps - by Serhiy Perevoznyk
   http://www.delphi3000.com/articles/article_3593.asp

* Alpha Blending a Bitmap - by Serhiy Perevoznyk
   http://www.delphi3000.com/articles/article_3594.asp

* Simple example for the COMPOSITE Design Pattern - by Jochen Fromm
   What is the Composite Design Pattern? How do you copy a directory
   with all subdirectories in a simple way?
   http://www.delphi3000.com/articles/article_3595.asp

* Get and use Sender properties, typecast it - by Steen Pedersen
   How to use the Senders Properties.
   http://www.delphi3000.com/articles/article_3596.asp

* Get FullPath Application of Any Object - by Gilberto Saraiva
   http://www.delphi3000.com/articles/article_3597.asp

* Add Line into the end of a file - by Gilberto Saraiva
   http://www.delphi3000.com/articles/article_3598.asp

* Mouse Moviment Limiting - by Gilberto Saraiva
   If you want limit the mouse region, use this procedure.
   http://www.delphi3000.com/articles/article_3599.asp

* How to disable the TreeView Hint - by Gilberto Saraiva
   http://www.delphi3000.com/articles/article_3600.asp

* OpenGL II: moving and rotating 2D shapes - by Eber Irigoyen
   This article shows you some basic movement and rotating and also tries
   to explain how openGL works.
   http://www.delphi3000.com/articles/article_3603.asp

* Improve Interbase Client Server Performance - by Peter Mc Leod
   How do you get the best out of your Interbase Client Server System?
   http://www.delphi3000.com/articles/article_3606.asp

* language for MS Office - by Mike Shkolnik
   How to read the default language of installed MS Office application?
   http://www.delphi3000.com/articles/article_3607.asp

* PHP Alike implode & explode functions for Delphi - by Ronald Buster
   Implode returns a string containing the elements of a string array in
   order with a glue string between each element. Explode is the reverse.
   http://www.delphi3000.com/articles/article_3609.asp

* OutlookExpress Directorie - by Ronald Buster
   How to find the OutlookExpress mailbox dir.
   http://www.delphi3000.com/articles/article_3611.asp

* Ms Access LastinsertID - by Ronald Buster
   Retrieve the last insert id of the autoincrement field in Access.
   http://www.delphi3000.com/articles/article_3612.asp

* OpenGL III: Moving and rotating 3D shapes - by Eber Irigoyen
   How to rotate around a shape's axis or rotate around another object.
   http://www.delphi3000.com/articles/article_3617.asp

* Retrieve Current User and Domain Names on Win NT - Serhiy Perevoznyk
   How to retrieve the Current User and Domain Names on Windows NT using
   security functions within the Win32 API.
   http://www.delphi3000.com/articles/article_3618.asp

* How to use TClientDataset as memory dataset - by Mike Shkolnik
   http://www.delphi3000.com/articles/article_3619.asp

* Extended Mapi - by Tommy Andersen
   Accessing the Extended Mapi interface is not allways trivial. This
   component helps a quite a bit with this problem.
   http://www.delphi3000.com/articles/article_3620.asp

* Simple way to rotate region - by Nik Ozniev
   http://www.delphi3000.com/articles/article_3623.asp

* Understanding Threads - by Subha Narayanan
   http://www.delphi3000.com/articles/article_3624.asp

* Setting File Summary Information - by Serhiy Perevoznyk
   How to set File Summary Information for non Office files (NTFS).
   http://www.delphi3000.com/articles/article_3625.asp

* Give Me the Details or File Summary Info - by Serhiy Perevoznyk
   How to retrieve File Summary Information for non Office files (NTFS).
   http://www.delphi3000.com/articles/article_3626.asp

* D7 ActiveX Web deployment bug workaround - by Robert White
   A workaround for Delphi 7 bug that disables Web Deployment.
   http://www.delphi3000.com/articles/article_3628.asp

* Removing the popup menu in Flash .OCX with Delphi 4 - by Miguel Lucero
   Removing the popup menu in Macromedia Flash .OCX with Delphi 4.
   http://www.delphi3000.com/articles/article_3630.asp

* OpenGL IV: Texture mapping - by Eber Irigoyen
   Texture mapping: The process of applying an image to a primitive.
   Texture mapping is often used to add realism to a scene. For example,
   you can apply a picture of a building facade to a polygon representing
   a wall. This article shows how to do texture mapping so your 3D
   objects become more realistic.
   http://www.delphi3000.com/articles/article_3631.asp

* Making a reliable drawing procedure (random numbers) - Martin Strand
   How to make sure the same field/name/whatever is not drawn twice?
   http://www.delphi3000.com/articles/article_3632.asp

* DOC to PRN - by Eddie Shipman
   Creating PRN file from MS Word DOC File. This works with the Word97
   components and to make it work with the Word2000 components, some
   function calls and parameters must be changed.
   http://www.delphi3000.com/articles/article_3633.asp

* Display a Property dialog for file, folder or drive - by Mike Shkolnik
   http://www.delphi3000.com/articles/article_3634.asp

* HTML Dialog Boxes - by Wes Mess
   Using the ShowHTMLDialog function.
   http://www.delphi3000.com/articles/article_3635.asp

* A Pragmatic Book for Programmers of Any Level - by Brian Kotek
   If you ever thought it would be great to have a veteran developer
   answer all of your methodology questions, take a look at this book.
   Appropriate for all experience levels it explains the development
   process from a language-neutral perspective. It's one of my favourite
   books and it includes some examples in Pascal as well as C and Java.
   http://builder.com.com/article.jhtml?id=u00320030317BXK01.htm

* Deciding Between mySQL and SQL Server - by Sanders Kaufman, Jr.
   MySQL may be free but what if money isn't the only determining factor?
   Find out how these two database heavyweights stack up against each
   other and how to decide which one to use as your database system.
   http://builder.com.com/article.jhtml?id=u00320030318SKJ01.htm

* Relational Databases: Inspiration Behind The Theory - by Susan Harkins
   Discover the origin of the modern relational data model and what every
   developer should know about this theory. Also, find out what the most
   important step is toward creating an efficient and flexible database.
   http://builder.com.com/article.jhtml?id=u00320030402ssh01.htm

* Four Things to Consider Before Upgrading to .NET v1.1 - Tim Landgrave
   Architects and developers will need to consider four key areas that
   have changed from v1.0 v1.1 of the .NET Framework. These areas are
   newly integrated features, new functionality, compatibility issues,
   and security changes.
   http://builder.com.com/article.jhtml?id=u00320030409lan02.htm

* Fast and Furious Guide to MySQL Database Engines - Sanders Kaufman Jr
   What if you were a racecar driver and could swap engines with the flip
   of a switch instead of having to make a trip to the garage? The MySQL
   database does something like this for developers; it gives you a
   choice of database engines and an easy way to switch them. Let's look
   at how you choose the engine and how to change between engines that
   are available to you.
   http://builder.com.com/article.jhtml?id=u00320030407SKJ01.htm

* Tweak Oracle Data Buffers to Cache Entire Databases - Donald Burleson
   This advanced Oracle article explores the internal mechanisms of the
   Oracle data buffers, the RAM that Oracle uses to prevent unnecessary
   rereads of data blocks from disk. Understanding how data buffers
   operate is an important key to successfully using them in performance
   tuning an Oracle database.
   http://builder.com.com/article.jhtml?id=u00320030408brl01.htm


Tutoriales
==========

* Nesting DataSets in ClientDataSets - by Cary Jensen
   Like the name suggests, a nested dataset is a dataset within a
   dataset. By nesting one dataset inside another, you can reduce your
   overall storage needs, increase the efficiency of network
   communications, and simplify data operations.
   http://community.borland.com/article/0,1410,29825,00.html

* Writing Robust Code - by Pedro Agulló Soliveres
   There are many subtle issues to be aware of when it comes to ensuring
   code correctness and robustness: this article examines some of these
   issues, with a special emphasis on contract-based programming.
   http://www.thedelphimagazine.com/samples/1599/1599.htm

* Connection Closed Gracefully - by Chad Z. Hower
   http://www.swissdelphicenter.ch/en/showarticle.php?id=1

* Introduction to Web Development with Delphi - by Hadi Hariri
   http://www.swissdelphicenter.ch/en/showarticle.php?id=2

* Introduction to sockets - by Chad Z. Hower
   http://www.swissdelphicenter.ch/en/showarticle.php?id=3

* Introduction to Indy - by Chad Z. Hower
   http://www.swissdelphicenter.ch/en/showarticle.php?id=4

* Building Kylix Applications: Indy Chapters - by Chad Z. Hower
   http://www.swissdelphicenter.ch/en/showarticle.php?id=5

* IntraWeb: Implementing a "Hello World" application - Atozed Software
   http://www.swissdelphicenter.ch/en/showarticle.php?id=6

* IntraWeb Tutorial: User Input - by Atozed Software
   http://www.swissdelphicenter.ch/en/showarticle.php?id=7

* Creating Oracle User-Defined Aggregate Functions - by Beth Bowden
   By creating your own aggregate functions, you can extend Oracle's
   functionality and encourage code reuse in your applications. Find out
   how easy it is to add this skill to your repertoire.
   http://builder.com.com/article.jhtml?id=u00320030401adm01.htm

* Download Builder.com's 'Remedial XML' series - by Lamont Adams
   Six-part series, which started with the basics of XML and moved on
   through data validation and parsers now available to download complete
   with all the code in either DOC or HTML format.
   http://builder.com.com/article.jhtml?id=u00320020717adm01.htm

* Relational Databases: Inspiration Behind The Theory - by Susan Harkins
   Trying to use an RDBMS without applying relational database theory to
   your design is like trying to drive a standard transmission without
   using the clutch: you're not going to get very far. This series of
   articles shows how to apply relational rules and develop an efficient
   design that protects the validity of your data. The series starts with
   a look at the origins of the relational data model.
   http://builder.com.com/article.jhtml?id=u00320030402ssh01.htm

* Relational Databases: Using Normal Forms to Create Databases
   - by Susan Harkins
   Developers have certain rules, known as normal forms, that they follow
   to create well-designed databases. This article examines normal forms
   through the creation of a simple database for storing information
   about a collection of books.
   http://builder.com.com/article.jhtml?id=u00320030409ssh01.htm

* Relational Databases: Applying the First Normal Form - Susan Harkins
   The normal forms are so abstract that some developers have trouble
   figuring out how to apply them. Perhaps the best way to understand
   the normal forms is to start applying them to data, since rules tend
   to make more sense when you actually have data to divide. This article
   works through applying the 1NF rule, which is initially the most
   complicated to apply, to a sample book catalog database.
   http://builder.com.com/article.jhtml?id=u00320030416ssh01.htm

* Relational Databases: Achieving Normalization - by Susan Harkins
   The last installment of this series began with a single table and
   worked through making it conform to 1NF. This table wound up becoming
   four tables. this article finishes the normalizing process by applying
   2NF, 3NF and BCNF.
   http://builder.com.com/article.jhtml?id=u00320030423ssh01.htm


Otros enlaces
=============

* Pascal Newsletter: Mozilla Sidebar - by Dave Murray
   Our latest feature for Mozilla and Netscape 6+ users is a sidebar that
   lets you keep up to date with the latest issue of the newsletter while
   you browse the web. Just visit our website and click the 'add sidebar'
   button on the right-hand side of most pages.
   http://www.latiumsoftware.com/en/index.php

* Pascal Newsletter: Opera Hotlist Panel - by Dave Murray
   Our latest feature for Opera 7 users is a hotlist panel that lets you
   keep up to date with the latest issue of the newsletter while you
   browse the web. Just visit our website and click the 'add hotlist
   panel' button on the right-hand side of most pages.
   http://www.latiumsoftware.com/en/index.php

* Get Set for .NET with Borland launch events - by Anders Ohlsson
   http://community.borland.com/article/0,1410,29953,00.html

* Built With Delphi - by Baltic Solutions
   Provides a list of all quality commercial, shareware and freeware
   products that have been developed using Delphi.
   http://www.balticsolutions.com/bwd/

* Mastering Delphi 7 - by Marco Cantu
   At the end of February, Sybex released Marco Cantu's latest book,
   Mastering Delphi 7. To learn more about its contents, differences from
   the previous version and download the source code visit Marco's site.
   http://www.marcocantu.com/md7

* Project JEDI Alliance Program
   Recently a number of people have approached Project JEDI, interested
   in having their projects become part of JEDI. The Steering Group
   announces the JEDI Alliance Program and provides guidelines for
   projects interested in joining.
   http://www.delphi-jedi.org/Jedi%3AADMIN_JEDI_ALLIANCE%3A441740

* Complete ASCII Table
   http://www.asciitable.com

* The Latest Builder.com Technology Use Survey - by Lamont Adams
   http://builder.com.com/article.jhtml?id=u00320030331adm02.htm


Noticias
========

* Octane - La nueva versión de Delphi

   - Open Letter to the Delphi Community - por Simon Thornhill
     http://bdn.borland.com/article/0,1410,29951,00.html

   - Octane and Delphi Q&A - por Anders Ohlsso
     http://bdn.borland.com/article/0,1410,29952,00.html

* Blog with Delphi and Borland news
   http://svd.blogspot.com/

* Delphi / InterBase WebLog - by Craig Stuntz
   News of interest to Delphi and InterBase developers.
   http://delphi.weblogs.com/

* News Digest: Update for Borland Customers
   An analyst news digest for Borland Customers.
   http://community.borland.com/article/0,1410,29848,00.html

* Your Future: Delphi 8 OCTANE - by Zarko Gajic
   Octane is the code name for the next release of your favorite RAD
   tool. For the 8th anniversary of Delphi, Borland is preparing the most
   significant Delphi release: Octane will continue to provide VCL and
   CLX development for Win32 and Linux as well as new features and
   continued framework, compiler, IDE, and design time enhancements.
   http://delphi.about.com/cs/delphifornet/a/aa041703a.htm

* SwissDelphiCenter NewsFeed
   Get the 10 most recent programming tips and developer news from
   SwissDelphiCenter as an RDF NewsFeed file. With the RDF file you can
   integrate the tips into your website or use them with a newsticker.
   http://www.swissdelphicenter.ch/en/newsfeed.php

________________________________________________________________________

           ¡Vote por el Boletín Pascal en The Programming Pages!
     http://www.programmingpages.com/topsite.asp?r=latium&Language=29
________________________________________________________________________


¡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@...

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.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
http://news.optimax.com/topdelphi/links.exe/click?id=70C517ECAE6E
http://www.top219.org/cgi-bin/vote.cgi?delphi&83
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
http://213.65.224.200/cgi-bin/toplist.cgi/hits?Id=80
http://www.programacion.net/votar-enlace.php?id=474
http://www.lawebdelprogramador.com/buscar/enlace.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/descarga/p0046.zip
________________________________________________________________________

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@...
Para cancelar / removerse:    boletin-pascal-unsubscribe@...
¿Problemas con tu suscripción?      boletin-pascal-owner@...
________________________________________________________________________

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) 2003 por Ernesto De Spirito. Todos los derechos reservados
________________________________________________________________________

#12 De: "Ernesto D'Spirito" <edspirito@...>
Fecha: Mar, 11 de Mar, 2003 4:06 am
Asunto: Boletín Pascal #45 - 11-MAR-2003
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #45 - 11-MAR-2003

Índice

1. Unas palabras del editor
2. Administrador de depuración avanzado (manejador de excepciones)
    Como implementar una clase Debug que muestre el nombre de la unidad,
    el nombre de la función y el número de línea de una excepción
3. Interceptando mensajes de Windows en componentes no visuales
    Como hacer que un componente sin ventana reciba mensajes de Windows
4. Asocie su programa con extensiones de archivo
    Como hacer asociaciones de archivo a sus ejecutables
5. Inline Assembler en Delphi (VII) - Aritmética entera de 128 bits (1)
6. Foros / listas de correo
7. Delphi en la Red
    - Componentes, librerías y aplicaciones
      · Shareware
      · Freeware
      · Actualizaciones de Delphi
    - Artículos, trucos y consejos
      · Kylix, CLX y Linux
    - Tutoriales
    - Otros enlaces
    - Noticias

________________________________________________________________________


1. Unas palabras del editor


Me gustaría agradecer a Olivier Rogier, Peter Johnson, e Igor Siticov
por contribuir artículos para esta edición, y me complace entregarles
los premios para esta edición a los dos primeros:

* Olivier Rogier (Administrador de depuración avanzado...)
· SDL Component Suite 7.0 - por Software Development Lohninger ($99)
   La SDL Component Suite provee un amplio rango de componentes para la
   ciencia y la ingeniería, por ejemplo matemáticas, estadísticas,
   química, diagramas, visualización de datos, transformadas de Fourier
   (FFT), ploteos 3D, mapas geográficos, ajuste de curvas, etc.
   Disponible para Delphi 3-7 y BCB 4-6.
   http://www.lohninger.com/sdlindex.html

* Peter Johnson (Interceptando mensajes de Windows en componentes...)
· LMD DesignPack - por LMD Innovative - Shareware (EUR 59)
   Cinco componentes para agregar características de diseño a sus
   aplicaciones (un clon del Inspector de Objetos, un diseñador de
   formularios y controles basados en diagramas), con código fuentes
   extensivos proyectos de ejemplo demostrando las características
   avanzadas - hasta se incluye básicamente un diseñador de reportes.
   http://www.ceberus.com/lmd/products/index.php3#P4

Para la próxima edición, tenemos disponible el siguiente premio para
uno de los autores que colabore artículos en inglés:

* 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/

Si usan Delphi 6 ó 7, no se olviden de ver Actualizaciones de Delphi en
la sección Delphi en la Red de este boletín. A propósito, Borland está
realizando un par de encuestas, una para los usuarios de Delphi y otra
para los miembros de la Borland Development Network. Encontrarán los
enlaces bajo el título Otros Enlaces en la sección Delphi en la Red.

Espero que disfruten esta edición.

Saludos,

Ernesto D'Spirito
boletin-pascal-owner@...

__________________

Colaboró en esta edición: Dave Murray

________________________________________________________________________

Greatis  Runtime Fusion  incluye  Form Designer  Pro ($ 49.95)  y Object
Inspector Pro ($ 49.95), y  cuesta sólo $89.90  - Ahórrese $10 y obtenga
demos adicionales.  Permita que el usuario  diseñe formularios en tiempo
de ejecución con Runtime Fusion. >>>> http://www.greatis.com/runtime.htm
________________________________________________________________________


2. Administrador de depuración avanzado (manejador de excepciones)
    Como implementar una clase Debug que muestre el nombre de la unidad,
    el nombre de la función y el número de línea de una excepción

    Por Olivier Rogier <software @ urimont.com>
        Software Engineering - Ingénierie Logicielle
        http://www.urimont.com


Lea el archivo file_id.diz en la carpeta XAM del archivo zip adjunto
para encontrar las instrucciones para instalar eXpress Application
Manager (XAM) para Delphi 5-7.

El requisito es instalar la generación detallada del archivo de mapa
en las opciones de enlace del proyecto (Project | Options | Linker |
Map file | Detailed).

DEBUG_MODE es una constante booleana que indica si el objeto Debug está
activado de manera predeterminada al iniciar. Puede ser modificada con
los comandos en línea de órdenes /debug y /nodebug.

TObjectInfos se usa para obtener información de la instancia de la
clase como nombre, padre(s), dueño(s). TMapFile se usa para obtener
información sobre la excepción: nombre de la unidad, nombre del proce-
dimiento y número de línea.

IDebug es una interfaz implementada por TDebug. La función GetDebug
devuelve un puntero a IDebug referenciando una instancia TDebug creada y
destruida en la secciones initialization y finalization de la unidad. El
usuario no puede destruirla o crear más instancias.

El usuario puede establecer los eventos Before y After y establecer el
estado de activación. ShowException se usa por el manejador de excep-
ciones interno y puede ser usado por el usuario.

Se puede implementar un bonito formulario de excepción y un archivo de
registro.

________________________________________________________________________

¿Cómo calificaría al boletín? ¡Califique al Boletín Pascal en el ranking
Top 200 Delphi! · http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________


3. Interceptando mensajes de Windows en componentes no visuales
    Como hacer que un componente sin ventana reciba mensajes de Windows

    By Peter Johnson, Copyright (c) 2003
       <delphidabbler @ contactbox.co.uk> - http://www.delphidabbler.com/


A veces necesitamos que un componente sin ventana (es decir, uno que no
derive de TWinControl) reciba mensajes de Windows - pero los componentes
sin ventana no tienen manejador ("handle") de ventana. Por ejemplo
suponga que está desarrollando un componente no visual que registre su
aplicación como un visor del portapapeles de modo que la aplicación
pueda responder a cambios en el portapapeles (si desea saber como hacer
eso vea el artículo http://www.delphi3000.com/articles/article_575.asp
que lo explica). Para obtener información acerca de los cambios en el
portapapeles nuestro componente necesita recibir mensajes de Windows.

La función AllocateHWnd de la librería de Delphi se usa para crear por
nosotros una ventana oculta, y la función relacionada DeallocateHWnd
libera la ventana cuando hayamos terminado con ella.

La ventana oculta necesita un procedimiento de ventana. Podemos usar un
método de nuestra clase componente para proveer un procedimiento de
ventana. AllocateHWnd toma una referencia al método como parámetro - y
se ocupa por nosotros de registrar el método como un procedimiento de
ventana. En el método manejamos los mensajes que nos interesan y le
dejamos el resto a Windows usando la llamada a la API DefWindowProc.

El siguiente código ofrece el esqueleto de como usar AllocateHWnd.
Primero, aquí está la declaración de la clase en la sección interface
del código:

   type
     // Nuestra clase derivada de TComponent
     // (u otra clase ancestro)
     TMyClass = class(TComponent)
     private
       FHWnd: HWND;
         // campo para almacenar el manejador ("handle") de ventana
       ...
     protected
       procedure WndMethod(var Msg: TMessage); virtual;
         // el procedimiento de ventana (window proc) - llamado por
         // Windows para manejar mensajes
       ...
     public
        constructor Create(AOwner: TComponent); override;
          // crear el manejador de ventana aquí
        destructor Destroy; override;
          // liberar el manejador de ventana aquí
        ...
     end;

Y aquí están los detalles de implementación:

   TMyClass.Create(AOwner: TComponent);
   begin
     inherited Create(AOwner);
     ...
     // Crea la ventana
     FHWnd := AllocateHWnd(WndMethod);
     ...
   end;

   TMyClass.Destroy;
   begin
     ...
     // Destruye la ventana
     DeallocateHWnd(FHWnd);
     ...
     inherited Destroy;
   end;

   TMyClass.WndMethod(var Msg : TMessage);
   var
     Handled: Boolean;
   begin
     // Asumimos que manejamos el mensaje
     Handled := True;
     case Msg.Msg of
       WM_ALGO: HacerAlgo;
         // Código para manejar un mensaje
       WM_OTRACOSA: HacerOtraCosa;
         // Código para manejar otro mensaje
       ...
       else
         // No manejamos el mensaje
         Handled := False;
     end;
     if Handled then
       // Manejamos el mensaje - lo indicamos en el resultado del mesaje
       Msg.Result := 0
     else
       // No manejamos el mensaje
       // Se lo pasamos a DefWindowProc y registramos el resultado
       Msg.Result := DefWindowProc(FHWnd, Msg.Msg,
         Msg.WParam, Msg.LParam);
   end;

Por supuesto, podríamos usar la API de Windows para crear una ventana de
la manera difícil, y proveer un procedimiento de ventana. Pero es más
difícil usar un método como procedimiento de ventana (en vez de un
simple procedimiento) si lo hacemos de esta manera. Las características
inteligentes de AllocateHWnd son que (a) crea la ventana oculta por
nosotros y (b) nos permite usar un método, en vez de un simple proce-
dimiento como el procedimiento de ventana -- y un método es más útil
puesto que tiene acceso a los datos privados de la clase.

Se adjunta a este artículo un componente visor del portapapeles
(cbview).

__________________

Peter Johnson es un programador hobbyista que vive en West Wales (Reino
Unido) y que "chapotea" en Delphi. Mantiene el sitio web DelphiDabbler
(http://www.delphidabbler.com/) donde publica sus artículos y sus
aplicaciones y componentes Delphi gratuitos.

________________________________________________________________________

¿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!"
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
Sólo hay que seguir el enlace y hacer clic en "here" ("aquí") donde dice
"Click here to vote!" ("¡Haga clic aquí para votar!"). Luego aparecerá
el ranking de los más votados. Su voto significa mucho para nosotros.
________________________________________________________________________


4. Asocie su programa con extensiones de archivo
    Como hacer asociaciones de archivo a sus ejecutables

    Por Igor Siticov
        SiComponents: http://www.sicomponents.com


     ¿Cómo puedo asociar mi extensión de archivo con mi aplicación?

Para crear asociaciones de archivo debe hacer algunos cambios en el
registro de Windows e informar al Explorador de Windows acerca de sus
cambios.

Para ejecutar su programa como predeterminado para todos los tipos de
archivo no registrados simplemente asócielo con el tipo de archivo "*".

La siguiente unidad incluye la realización de una función para crear
una asociación de archivo. Vea los comentarios en el código fuente para
más detalles.

   unit utils;

   interface

   uses Registry, ShlObj, SysUtils, Windows;

   procedure RegisterFileType(cMyExt, cMyFileType, cMyDescription,
     ExeName: string; IcoIndex: integer; DoUpdate: boolean = false);

   implementation

   procedure RegisterFileType(cMyExt, cMyFileType, cMyDescription,
     cExeName: string; IcoIndex: integer; DoUpdate: boolean = false);
   var
     Reg: TRegistry;
   begin
     Reg := TRegistry.Create;
     try
       Reg.RootKey := HKEY_CLASSES_ROOT;

       // 1) Asignar la extensión al tipo de archivo,
       //    creando la extensión si no existe

       // Abre o crea la clave HKCR\<cMyExt>
       Reg.OpenKey(cMyExt, True);
       // HKCR\.<cMyExt>\(Predeterminado)="<cMyFileType>"
       Reg.WriteString('', cMyFileType);
       Reg.CloseKey;

       // 2) Asignar la descripción del tipo de archivo,
       //    creando el tipo de archivo si no existe

       // Abre o crea la clave HKCR\<cMyFileType>
       Reg.OpenKey(cMyFileType, True);
       // HKCR\<cMyFileType>\(Predeterminado)="<cMyDescription>"
       // Esto es lo que se verá en la descipción del tipo de archivo
       // en las propiedades de los archivos de ese tipo.
       Reg.WriteString('', cMyDescription);
       Reg.CloseKey;

       // 3) Asignar el índice del icono para el tipo de archivo,
       //    creando la clave correspondiente si no existiera

       // Abre o crea la clave HKCR\<cMyFileType>\DefaultIcon
       Reg.OpenKey(cMyFileType + '\DefaultIcon', True);
       // HKCR\<cMyFileType>\DefaultIcon\(Predeterminado)
       // ="<cExeName>,<IcoIndex>"
       Reg.WriteString('', cExeName + ',' + IntToStr(IcoIndex));
       Reg.CloseKey;

       // 4) Establece el texto de la acción Open (abrir) en el
       //     Explorador, creando la acción si no existiera

       // Abre o crea la clave HKCR\<cMyFileType>\Shell\Open
       Reg.OpenKey(cMyFileType + '\Shell\Open', True);
       // HKCR\<cMyFileType>\Shell\Open\(Predeterminado)="&Abrir"
       Reg.WriteString('', '&Abrir');
       Reg.CloseKey;

       // 5) Asigna la aplicación con la que ejecutar la acción

       // Abre o crea la clave HKCR\<cMyFileType>\Shell\Open\Command
       Reg.OpenKey(cMyFileType + '\Shell\Open\Command', True);
       // HKCR\<cMyFileType>\Shell\Open\Command\
       // (Predeterminado)=""<cExeName>" "%1""
       // Su aplicación debe revisar el parámetro en la línea de
       // comandos para saber que archivo se le pasó.
       Reg.WriteString('', '"' + cExeName + '" "%1"');
       Reg.CloseKey;

       // 6) Finalmente, si queremos que el Explorador de Windows se de
       //    cuenta que agregamos nuestro tipo de archivo, llamamos a la
       //    API SHChangeNotify.

       if DoUpdate then
         SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
     finally
       Reg.Free;
     end;
   end;

   end.

Llamada de ejemplo:

   RegisterFileType('.abc', 'abc_type', 'Archivo ABC',
     'U:\Camino\Programa.exe', 0, True);

__________________

Igor Siticov es el autor de TsiLang Components Suite (un completo juego
de componentes para construir en dos minutos aplicaciones multilingües
elegantes, útiles y amistosas con el usuario) y de Resource Builder (un
muy completo editor visual de RC script, ideal para reemplazar al
Borland Image Editor y al Borland Resource WorkShop para crear y editar
archivos de recursos), por SiComponents: http://www.sicomponents.com

________________________________________________________________________

Difunda el Boletín Pascal entre sus colegas programadores invitándolos a
visitar nuestra página http://www.latiumsoftware.com/es/pascal/index.php
o a que se suscriban por email: boletin-pascal-subscribe@...
________________________________________________________________________


5. Inline Assembler en Delphi (VII) - Aritmética entera de 128 bits (1)

    Por Ernesto D'Spirito


Introducción
============

Con 32 bits podemos representar 2^32 números diferentes, es decir,
4294967296 (~4 mil millones, o ~4 millardos) de números diferentes, como
enteros con signo de -2147483648 a +2147483647 o enteros sin signo del 0
al 4294967295 (tipos Longint y Longword respectivamente).

Eso es suficiente para muchos propósitos, como por ejemplo representar la
posición de un byte en un archivo de 4GB, pero algunas veces necesitamos
más, y allí tenemos TLargeInteger (unidad Windows) e Int64 (desde Delphi
4) para representar enteros de 64 bits que pueden tener 2^64 valores
diferentes, es decir, 18446744073709551616 (~18 trillones de) valores,
que van de -9223372036854775808 a +9223372036854775807 (~9 trillones).

Esa cantidad de dígitos es más que suficiente para mí, y en este
instante la verdad que no puedo imaginarme ningún uso práctico para más
de eso. ¡Hey, ni siquiera Bill Gates cuenta su dinero en trillones! ;)
Pero de tanto en tanto veo alguien en algún foro preguntando por más
dígitos de los que ofrece Int64...

De todos modos, ya sea útil para un propósito práctico o completamente
inútil, veremos la implementación de muchos procedimientos y funciones
diseñandos para trabajar con enteros de 128 bits, que servirán para el
propósito de mostrar ejemplos de instrucciones básicas de ensamblador.
Estos "enteros grandes", "enteros enormes" o "enteros gigantes" pueden
contener 2^128 valores diferentes, es decir, 38-39 dígitos decimales
significativos.


Representación de un entero de 128 bits
=======================================

He llamado al nuevo tipo Hugeint (por "huge integer" = "entero enorme"
o "entero gigante"), pero por ejemplo Bigint ("big integer" = "entero
grande"), o Int128 también son buenos nombres.

En lo que respecta a la representación del nuevo tipo, también hay
muchas formas de hacerlo. Decidí que lo más simple es representarlo como
un arreglo de 4 enteros de 32 bits:

   type
     Hugeint: packed array [0..3] of Longword;

Usaremos el formato "little-endian" puesto que es el estándar en la
arquitectura Intel. Esto significa que el primer elemento del arreglo
(dirección más baja) contendrá los 32 bits de orden bajo (menos
significativos) del entero gigante, mientras que el último elemento
(dirección más alta) del arreglo contendrá los 32 bits de orden alto
(más significativos) del entero gigante.

Así es como serían representados los números 5 y 5000000000
($12A05F200):

          +---- 32 bits de orden bajo (menos significativos)
          |
          v
   +-------------+-------------+-------------+-------------+
   |  $00000005  |  $00000000  |  $00000000  |  $00000000  | = 5
   +-------------+-------------+-------------+-------------+
          0             1             2             3
   +-------------+-------------+-------------+-------------+
   |  $2A05F200  |  $00000001  |  $00000000  |  $00000000  | = 5000000000
   +-------------+-------------+-------------+-------------+   $12A05F200
                                                    ^
                                                    |
     32 bits de orden alto (más significativos) ----+

Los enteros en sí mismos también se almacenan en formato little-endian.
La representación de bytes de los números en un volcado de memoria se
verá como se muestra a continuación (los valores de los bytes se
representan en notación hexadecimal):

      $00000005
   +-------------+-------------+-------------+-------------+
   | 05 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | = 5
   +-------------+-------------+-------------+-------------+
          0             1             2             3
   +-------------+-------------+-------------+-------------+
   | 00 F2 05 2A | 01 00 00 00 | 00 00 00 00 | 00 00 00 00 | = 5000000000
   +-------------+-------------+-------------+-------------+   $12A05F200
      $2A05F200     $00000001

Sin embargo, para casi todas las operaciones podemos hacer abstracción
del orden de los bytes y considerar los enteros de 32 bits como unidades
atómicas, pues el orden de los bytes se maneja transparentemente.


Algunas instrucciones útiles
============================

Antes de comenzar, veamos algunas instrucciones útiles que posiblemente
usemos en este artículo (sobre todo en la continuación de esta primera
parte), pero primero permítanme decirles que el propósito de este
artículo no es enseñarles ensamblador. Todo lo que puedo hacer en este
espacio limitado es mostrarles ejemplos de algunas instrucciones. Por
material de referencia, les recomiendo estos enlaces:

* Intel 80386 Reference Programmer's Manual
   Una versión HTML de este manual de Intel. El pseudo-código ayuda a
   explicar las instrucciones y sus efectos en las señales. Excelente.
   http://people.freebsd.org/~jhb/386htm/toc.htm
   Hay algunos enlaces rotos, pero las páginas están allí. Intenten
   desde el índice del directorio si tienen algún problema:
   http://people.freebsd.org/~jhb/386htm/

* iAPx86 - Norton Guide
   No tan explicativo como el documento de arriba, pero contiene todas
   las instrucciones desde el 8086 hasta el Pentium y Pentium Pro, con
   información sobre tamaño y tiempo de ejecución que no se incluye en
   el documento de arriba.
   http://www.clipx.net/ng/iapx86/index.php

* The IA-32 Intel Architecture Software Developer's Manual, Volume 2:
   Instruction Set Reference
   Manual PDF describiendo las instructiones para los procesadores IA-32
   (Pentium, Pentium Pro, Pentium II, Pentium III, Pentium 4, y Xeon).
   Incluye pseudo-código para explicar las instrucciones y sus efectos en
   las señales (flags) del registro de señales (flags register).
   http://www.intel.com/design/pentium4/manuals/245471.htm

* Optimización

   - How to optimize for the Pentium family of microprocessors
     Excelente guía de optimización escrita por Agner Fog
     http://fatphil.org/x86/pentopt/index.html

   - Optimizations for Intel's 32-Bit Processors
     Otra excelente guía de optimización, pero en formato PDF.
     http://x86.ddj.com/ftp/manuals/686/optimgd.pdf

Muy bien, ahora vayamos a las instrucciones.

Referencia:

   Z/ZF: Zero Flag      (señal de cero)
   S/SF: Sign Flag      (señal de signo)
   C/CF: Carry Flag     (señal de acarreo)
   P/PF: Parity Flag    (señal de paridad)
   A/AF: Auxiliary Flag (señal de acarreo auxiliar)
   O/OF: Overflow Flag  (señal de sobreflujo)

   s: bit de sign (bit de orden alto)
   o: bit de imparidad (bit de orden bajo)
   x: valor del bit
   0: literalmente, el valor 0
   1: literalmente, el valor 1

   r: el bit está invertido respecto del valor previo
   u: el bit conserva su valor

   XX: valor desconocido (registro, inmediato, o referencia a memoria)

En los ejemplos se debe asumir que el valor de AL previo a cada
operación es sxxxxxxo (bit de signo, 6 bits desconocidos, y bit de
imparidad).

Aquí hay algunas instrucciones para comenzar:

   SHL al,1    AL := xxxxxxo0  CF := s   SHift Left
   SAL al,1    AL := xxxxxxo0  CF := s   Sinónimo de SHL
   SHR al,1    AL := 0sxxxxxx  CF := o   SHift Right
   SAR al,1    AL := ssxxxxxx  CF := o   Shift Arithmetic Right
   SAR al,7    AL := ssssssss  CF := x   Esto extiende el bit de signo

   ROL al,1    AL := xxxxxxos  CF := s   ROtate Left
   ROR al,1    AL := osxxxxxx  CF := o   ROtate Right
   RCL al,1    AL := xxxxxxoC  CF := s   ROtate thru Carry Left
   RCR al,1    AL := Csxxxxxx  CF := o   ROtate thru Carry Right

   AND al,al   AL := uuuuuuuu  CF := 0   Establece señales (ver abajo)
   AND al,-1   AL := uuuuuuuu  CF := 0   -1 = $FF = 1111111
                                         Establece señales (ver abajo)
   AND al,$01  AL := 0000000u  CF := 0   $01 = 00000001
   AND al,$80  AL := u0000000  CF := 0   $80 = 10000000
   AND al,$5A  AL := 0u0uu0u0  CF := 0   $5A = 01011010
   AND al,0    AL := 00000000  CF := 0   XOR AL,AL o MOV AL,0 es mejor

   TEST AL,XX  AL := uuuuuuuu
               TEST es como AND, pero el resultado no se almacena en el
               destino, sino que se usa para establecer flags (ver abajo)
   TEST AL,-1  Habitualmente es mejor que AND AL,-1 y que OR AL,AL porque
               no escribe en AL, lo que permite ciertas optimizaciones en
               algunos casos.

   OR  al,al   AL := uuuuuuuu  CF := 0   Establece señales (ver abajo)
   OR  al,$01  AL := uuuuuuu1  CF := 0   $01 = 00000001
   OR  al,$80  AL := 1uuuuuuu  CF := 0   $80 = 10000000
   OR  al,$5A  AL := u1u11u1u  CF := 0   $5A = 01011010
   OR  al,-1   AL := 11111111  CF := 0   Igual que MOV AL,1

   XOR al,al   AL := 0         CF := 0   MOV AL,0 preserva las señales
   XOR al,$5A  AL := ururruru  CF := 0   $5A = 01011010
   XOR al,-1   AL := rrrrrrrr  CF := 0   Igual que NOT AL

Excepto por las instrucciones de rotación (ROL, RCL, ROR, y RCR), todas
las de arriba establecen las señales SF, ZF y PF en base al resultado de
la operación:

   SF = valor del bit de orden alto del resultado (bit de signo)
   ZF = 1 ("establecida") si el resultado es cero, 0 ("limpia") en caso
        contrario
   PF = 1 ("encendida") si el byte de orden bajo del resultado contiene
        un número par de bits 1, en caso contrario es 0 ("limpia")

Veamos más instrucciones:

   STC         CF := 1          SeT Carry flag
   CLC         CF := 0          CLear Carry flag
   CMC         CF := r          CoMplement Carry flag

   LAHF        AH := SZxAxPxC
   SAHF        Asumiendo que AH es SZxAxPxC:
                 ZF := S; ZF := Z; AF := A; PF := P; CF := C

   SETc  AL    AL := CF         SET if Carry
   SETs  AL    AL := SF         SET if Sign
   SETz  AL    AL := ZF         SET if Zero
   SETe  AL    AL := ZF         SET if Equal (sinónimo de SETZ)
   SETp  AL    AL := PF         SET if Parity
   SETpe AL    AL := PF         SET if Parity Even (sinónimo de SETP)
   SETo  AL    AL := OF         SET if Overflow
   SETnc AL    AL := NOT CF     SET if Not Carry
   SETns AL    AL := NOT SF     SET if Not Sign
   SETnz AL    AL := NOT ZF     SET if Not Zero
   SETne AL    AL := NOT ZF     SET if Not Equal (sinónimo de SETNZ)
   SETnp AL    AL := NOT PF     SET if Not Parity
   SETpo AL    AL := NOT PF     SET if Parity Odd (sinónimo de SETNP)
   SETno AL    AL := NOT OF     SET if Not Overflow

   SETa (o SETNbe), SETae (o SETnb), SETb (o SETnae), SETbe (o SETna),
   SETg (o SETNle), SETge (o SETnl), SETl (o SETnge), y SETle (o SETng)
   establecen el byte destino en 1 o 0 dependiendo de si la condición
   especificada se cumple o no.

   ADD AL,XX   AL := AL+XX     CF := 1 si la operación generó un acarreo
                                     0 en caso contrario

   SUB AL,XX   AL := AL-XX     CF := 1 si la operación requirió un bit
                                     prestado, 0 en caso contrario
   SUB AL,0    AL := uuuuuuuu  Establece señales en base a AL
   SUB AL,AL   AL := 0         Igual que XOR AL,AL o MOV AL,0

   CMP AL,XX   CMP es como SUB, pero el resultado no se almacena en el
               destino. La operación simplemente establece señales.

   ADC AL,XX   AL := AL+XX+C   CF := 1 si la operación generó un acarreo
                                     0 en caso contrario
   SBB AL,XX   AL := AL-C-XX   CF := 1 1 si la operación requirió un bit
                                     prestado, 0 en caso contrario

   NEG AL      AL := -AL       CF := 1 si el valor previo de AL es <> 0
                                          NOT AL; INC AL es lo mismo
   NOT AL      AL := rrrrrrrr  CF := u    Igual que XOR AL,-1


Funciones de conversión
=======================

Estas funciones nos ayduarán a entender la representación de estos
enteros enormes.


Longword a Hugeint
------------------

Comencemos convirtiendo un Longword en un entero gigante. Los 32 bits
más bajos del resultado serán los 32 bits del parámetro, y los 96 bits
más altos serán todos cero.

   function UToHugeint(const x: Longword): Hugeint; overload;
   // Result := Hugeint(x);
   // Parámetros: EAX = x; EDX = @Result;
   asm
     xor ecx, ecx         // ECX := 0;
     mov [edx+_0_], eax   // Result[0] := x;
     mov [edx+_1_], ecx   // Result[1] := 0;
     mov [edx+_2_], ecx   // Result[2] := 0;
     mov [edx+_3_], ecx   // Result[3] := 0;
   end;

Comentarios:

* ¿"_0_", "_1_", "_2_" y "_3_"? ¿Qué son?

   Son constantes que representan los desplazamientos (en bytes) de los
   cuatro elementos del arreglo, las que nos permiten escribir código más
   limpio.

     const
       _0_ = 0;
       _1_ = 4;
       _2_ = 8;
       _3_ = 12;


Longint a Hugeint
----------------

Los 32 bits más bajos del resultado serán los 32 bits del parámetro. Si
el número es positivo, entonces los 96 bits más altos serán 0, pero si
el número es negativo, los 96 bits más altos serán 1.

Puede parecer que necesitamos realizar una comparación o comprobar el
signo y luego realizar un salto condicional basado en el resultado:

   function IntToHugeint(x: Longint): Hugeint; overload;
   // Convierte un entero con signo de 32 bits a Hugeint
   // Parámetros: EAX = x; EDX = @Result;
   asm
     or  eax, eax        // EAX := EAX or EAX; // EAX permanece igual
                         // Efecto secundario: SF (Sign Flag) := EAX < 0;
     mov ecx, 0          // ECX := 0;
     jns @@no_negativo   // if not SF then goto @@no_negativo;
     dec ecx             // ECX := ECX - 1; // 0 - 1 = -1 = $FFFFFFFF
   @@no_negativo:
     mov [edx+_0_], eax  // Result[0] := x;
     mov [edx+_1_], ecx  // Result[1] := ECX; // 0 o $FFFFFFFF
     mov [edx+_2_], ecx  // Result[2] := ECX; // 0 o $FFFFFFFF
     mov [edx+_3_], ecx  // Result[3] := ECX; // 0 o $FFFFFFFF
   end;

Comentarios:

* Nótese el uso de "MOV ECX, 0" en vez de "XOR ECX, ECX" para evitar
   cambiar el estado de la señal de signo (Sign Flag - SF) establecida en
   la instrucción precedente (OR) y luego usada en el salto condicional
   que aparece en la instrucción siguiente (JNS). Por supuesto que
   pudimos haber cambiado el orden de las operaciones para que esto no
   sea necesario...

* En vez de:

     or eax, eax
     jns @@no_negativo

   los siguientes pares de instrucciones hubieran logrado lo mismo:

   * and eax, eax         // EAX inalterado, pero SF obtiene el signo
     jns @@not_negative   // if SF = 0 then goto @@not_negative

   * test eax, eax        // EAX inalterado, pero SF obtiene el signo
                          // Es mejor porque no se escribe en EAX
     jns @@not_negative   // if SF = 0 then goto @@not_negative

   * test eax, $87654321  // Cualquier valor con el bit 31 (signo) = 1
     jns @@not_negative   // if SF = 0 then goto @@not_negative

   * test eax, $80000000  // el resultado será 0 y la señal de cero (Zero
                          // Flag - ZF) será encendida si el bit de signo
                          // (el más significativo) es cero (eax >= 0).
     jz @@no_negativo     // if Zero Flag then goto @@no_negativo

   * cmp eax, 0           // compara EAX con 0
     jge @@not_negative   // if mayor o igual then goto @@not_negative

* Nótese el uso de "DEC ECX" para tornar el valor de ECX de $00000000 a
   $FFFFFFFF (decrementanto el valor del registro). "NOT ECX" habría
   logrado lo mismo (invirtiendo los bits), con la misma velocidad, y
   tomando la misma cantidad de bytes para codificar la instrucción, pero
   NOT no es una instrucción emparejable mientras que DEC sí lo es. Por
   esta razón habitualmente se evita NOT y se sustituye como sigue:

   - Si sabe de antemano que el valor previo es 0, use DEC Destino
   - Si sabe de antemano que el valor previo es 1, use INC Destino
   - Si no sabe de antemano cual es el valor previo, use XOR Destino, -1

* También noten en el orden de las instrucciones que nunca usamos un
   registro que fuera escrito en la instrucción previa. Esta es una de
   las condiciones para que ocurra el emparejamiento. Encontrarán más
   información acerca del emparejamiento de instrucciones en los
   documentos sobre optimización que recomendamos arriba.

Pordemos simplificar la función gracias a la instrucción CDQ que
extiende el signo de EAX en EDX. Así es básicamente como trabaja CDQ:

   if EAX >= 0 then
     EDX := $0
   else
     EDX := $FFFFFFFF;

He aquí una implementación más pequeña y simple usando CDQ:

   function ToHugeint(const x: Longint): Hugeint; overload;
   // Result := Hugeint(x);
   // Parámetros: EAX = x; EDX = @Result;
   asm
     mov ecx, edx        // ECX := @Result;
     cdq                 // EDX := IIF(x>=0, 0, $FFFFFFFF);
     mov [ecx+_0_], eax  // Result[0] := x;
     mov [ecx+_1_], edx  // Result[1] := EDX; // 0 o $FFFFFFFF
     mov [ecx+_2_], edx  // Result[2] := EDX; // 0 o $FFFFFFFF
     mov [ecx+_3_], edx  // Result[3] := EDX; // 0 o $FFFFFFFF
   end;

CDQ habitualmente se reemplaza por MOV y SAR, que ofrecen la ventaja
que el origen no tiene que ser EAX y que el destino tampoco tiene que
ser EDX, además que son instrucciones emparejables. Veamos un ejemplo:

   function ToHugeint(const x: Longint): Hugeint; overload;
   // Result := Hugeint(x);
   // Parámetros: EAX = x; EDX = @Result;
   asm
     mov ecx, eax        // ECX := x;
     sar ecx, 31         // ECX := IIF(x>=0, 0, $FFFFFFFF);
     mov [edx+_0_], eax  // Result[0] := x;
     mov [edx+_1_], ecx  // Result[1] := EDX; // 0 o $FFFFFFFF
     mov [edx+_2_], ecx  // Result[2] := EDX; // 0 o $FFFFFFFF
     mov [edx+_3_], ecx  // Result[3] := EDX; // 0 o $FFFFFFFF
   end;


Hugeint a Longint
-----------------

Un Hugeint puede ser convertido a Longint simplemente tomando los 32 bits
más bajos. Los 96 bits más altos del Hugeint deberían ser todos 0 o todos
1 coincidiendo con el bit 31 (bit de signo de lo que sería el resultado)
para que el valor del Hugeint esté en el rango de un Longint, pero la
función no comprueba esto y realiza la conversión ciegamente (del mismo
modo que por ejemplo un Longint se convierte en un Shortint).

   function ToLongint(const x: Hugeint): Longint; overload;
   // Result := Longint(x);
   // No se lanza una excepción si el valor está fuera de
   // rango (se descartan los 96 bits más significativos).
   // Parámetros: EAX = @x;
   asm
     mov eax, [eax+_0_]  // Result := x[0];
   end;


Int64 a Hugeint
---------------

Los parámetros Int64 se pasan en la pila, así que las funciones con un
parámetro Int64 automáticamente crearán un marco de pila (stack frame).
Los 64 bits más bajos del resultado serán los 64 bits del parámetro y
los 64 bits más altos del resultado extenderán el bit de signo del
entero más significativo que forma el valor int64.

   {$IFDEF DELPHI4}
   function ToHugeint(const x: Int64): Hugeint; overload;
   // Result := Hugeint(x);
   // Parámetros: x en la pila; EAX = @Result;
   asm
     mov edx, dword[x+_0_]  // EDX := x[0];
     mov ecx, dword[x+_1_]  // ECX := x[1];
     sar ecx, 31            // ECX := IIF(x[1]>=0, 0, $FFFFFFFF);
     mov [eax+_0_], edx     // Result[0] := x[0];
     mov [eax+_1_], ecx     // Result[1] := x[1];
     mov [eax+_2_], ecx     // Result[2] := ECX; // 0 o $FFFFFFFF
     mov [eax+_3_], ecx     // Result[3] := ECX; // 0 o $FFFFFFFF
   end;
   {$ENDIF}

Los valores Int64 se almacenan en formato little-endian, así que el
entero de orden bajo (menos significativo) está primero (en el
desplazamiento 0 a partir de la dirección base de la variable), mientras
que el entero de orden alto (más significativo) está después (en el
desplazamiento 4 a partir de la dirección base de la variable). En este
caso, la dirección base de la variable es EBP+8 (véase el primer
capítulo de esta serie de artículos), así que el primer elemento está en
EBP+8 (EBP+8+0) y el segundo elemento está en EBP+12 (EBP+8+4). Podría
haber usado EBP+8 y EBP+12 para direccionar los elementos, pero "x+_0_"
y "x+_1_" refieren esas direcciones más transparentemente. El especi-
ficador de tamaño "DWORD" es necesario puesto que el ensamblador toma
"x+_0_" y "x+_1_" como punteros a datos de 64 bits (ya que considera que
"x" es un puntero a datos de 64 bits) y no permite mover el valor
referenciado a un registro de 32 bits.


Int64 a Hugeint
---------------

Un Hugeint puede ser convertido a Int64 simplemente tomando los 64 bits
más bajos. Los 64 bits más altos del Hugeint deberían ser todos 0 o
todos 1 coincidiendo con el bit 63 (bit de signo de lo que sería el
resultado) para que el valor del Hugeint esté en el rango de un Int64,
pero la función no comprueba esto y realiza la conversión ciegamente:

   {$IFDEF DELPHI4}
   function ToInt64(const x: Hugeint): Int64; overload;
   // Result := Int64(x)
   // No se lanza una excepción si el valor está fuera de
   // rango (se descartan los 64 bits más significativos).
   // Parámetros: EAX = @x;
   asm
     mov edx, [eax+_1_]  // EDX := x[1];
     mov eax, [eax+_0_]  // EAX := x[0];
     // Result = EDX:EAX = x[1]:x[0]
   end;
   {$ENDIF}

Comentario:

* Los valores de retorno Int64 deben colocarse en EDX (32 bits más
   significativos) y EAX (32 bits menos significativos).


Eso es todo por ahora. En futuras ediciones veremos funciones para
realizar operaciones matemáticas y lógicas con estos enteros largos.

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


6. Foros / listas de correo


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).
   http://espanol.groups.yahoo.com/group/delphi-abierto
   Suscripción:
     http://espanol.groups.yahoo.com/group/delphi-abierto/join
     delphi-abierto-subscribe@...

* 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@...

* 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

________________________________________________________________________

¿Errores Delphi?  Capture y registre cada error mostrando unidad, clase,
método y número de línea. http://www.eurekalog.com/bannerclick.php?id=15
________________________________________________________________________


7. Delphi en la Red

    Por Dave Murray <irongut @ vodafone.net>


Componentes, librerías y aplicaciones
=====================================


Shareware/Comercial
-------------------

* EurekaLog v4.0.4 - by Fabio Dell'Aria (Std $29, Pro $49, Ent $99)
   EurekaLog gives your application (GUI, Console, Web, etc.) the ability
   to catch every exception, generate a detailed log (with unit, class,
   method and line #) and send it via email. Fully integrated into the
   IDE, you only need a single rebuild to add EurekaLog to your apps.
   Does not decrease performance and increases compiled file size by just
   0.5% - 4%. Compatible with Delphi 3 - 7 and all Windows platforms.
   http://www.eurekalog.com/bannerclick.php?id=15


Freeware
--------

* eXpress Application Manager (XAM) for Delphi (with source code).
   Don't loose more time with error messages like "Access violation",
   "Division by zero" or "List index out of bounds"! Find quickly the
   line of code concerned with the advanced exception manager XAM for
   Delphi 5, 6 and 7. The XAM Debugger will help you to improve your
   test phase or your users bug reporting.
   http://www.urimont.com/index.php?page=delphi&subpage=delphi_xam

* InterBase Performance Monitor 1.1 Released
   InterBase Performance Monitor provides a user-friendly interface for
   InterBase 7's performance monitoring and administration features. You
   can easily watch and control who is using resources on your server.
   http://community.borland.com/article/0,1410,29632,00.html

* Audio Components Suite v2.0 - Andrei Borovsky (source) (DELPHI/KYLIX)
   Components designed to perform different sound-processing tasks. ACS
   can play sound via the sound card, acquire audio data from different
   sources such as soundcard, audio CD and so on. Can also read and store
   audio data in several file formats (including Ogg Vorbis).
   http://www.mtu-net.ru/aborovsky/

* IdCGIRunner v3.1 - by Serhiy Perevoznyk (with source)
   Execute CGI scripts using Indy TidHTTPServer.
   http://users.chello.be/ws36637/

* IdISAPIRunner v3.1 - by Serhiy Perevoznyk (with source)
   Execute ISAPI modules using Indy TidHTTPServer.
   http://users.chello.be/ws36637/

* Icarus - Uses List Analyzer for Delphi v1.4.1 - by Peganza
   Helps Delphi and Borland Pascal developers remove unnecessary units in
   uses lists. Can also tell which units can be moved from the interface
   to the implementation uses list.
   http://www.torry.net/tools/developers/other/icarus.zip

* BDEChecker v1.0 - by Nick Moon
   Performs a number of tests on your machine to check various settings
   that are known/believed to cause problems with Paradox data tables.
   http://www.nixsoft.co.uk/bdechecker.html

* LinLocalize v1.0 - by Jens Kuhner (with source) (KYLIX)
   Free translation-tool for multilingual Kylix applications. It extracts
   the Kylix-resources (resource strings and forms) of elf-files and
   writes the translated resources back.
   http://linlocalize.sourceforge.net/

* TurboPower Visual PlanIt v1.03 - by TurboPower (with source)
   A set of synchronized, data-aware components for adding time, task and
   contact management capabilities to applications written in Delphi and
   C++Builder. Get that Outlook look & feel without the hassle.
   https://sourceforge.net/projects/tpvplanit/

* TurboPower Abbrevia v3.04 - by TurboPower (with source) (DELPHI/KYLIX)
   A compression toolkit for Delphi, C++Builder and Kylix. It supports
   PKZIP 4, Microsoft CAB, TAR and gzip formats and the creation of self-
   extracting archives. It includes visual components that simplify the
   manipulation of ZIP files.
   https://sourceforge.net/projects/tpabbrevia/


Actualizaciones de Delphi
-------------------------

* Update: Bold for Delphi Architect
   Registered users of purchased versions of Delphi 7 Architect can
   download Bold for Delphi Architect R4.0-D7.
   http://community.borland.com/article/0,1410,29798,00.html

* Update: IntraWeb and Rave for Delphi 7
   Delphi 7 updates for AtoZed IntraWeb and Nevrona Rave Reports are now
   available to download for registered users of purchased versions of
   Delphi 7 Pro, Enterprise, and Architect.
   http://community.borland.com/article/0,1410,29792,00.html

* Update: Delphi 6 Runtime Library Update 2
   An update for Delphi 6 is now available to download for registered
   users of purchased versions of Delphi 6.
   http://community.borland.com/article/0,1410,29791,00.html

* Borland Product Companion CDs are online
   Companion CD submissions are now available for download for:
   C++Builder 6 Companion CD; Delphi 7 Companion CD, disk 1; Delphi 7
   Companion CD, disk 2; InterBase 7 Companion CD; JBuilder 8 Companion
   CD; Kylix 3 Companion CD.
   http://community.borland.com/article/0,1410,29797,00.html


Artículos, trucos y consejos
============================

* Multi-threaded programming contest winners - by John Kaster
   Winners have been selected for the multi-threaded programming contest.
   http://community.borland.com/article/0,1410,29786,00.html

* Building a stand-alone Web service with Indy in Delphi 7: Part I
   - by Serge Dosyukov and Mike Pham
   Shows how to build a stand-alone Web service using Indy and Delphi 7.
   http://community.borland.com/article/0,1410,29484,00.html

* Building a stand-alone Web service with Indy in Delphi 7: Part II
   - by Serge Dosyukov and Mike Pham
   Part 2 demonstrates one technique for creating a single web service
   that contains more than one TSoapDataModule instance.
   http://community.borland.com/article/0,1410,29542,00.html

* Known Causes of Corruption in InterBase Databases - by Craig Stuntz
   InterBase is, in general, a very stable database server and corruption
   is rare. When corruption does occur, then, it is important to
   determine the cause of the corruption. This article describes
   circumstances that can cause corruption.
   http://community.borland.com/article/0,1410,29515,00.html

* Monitoring System Shell Changes - by Zarko Gajic
   Wanna get notified when a file gets created, renamed or deleted on the
   system? Need to know the exact folder and file name? Let's start
   monitoring system shell changes!
   http://delphi.about.com/library/weekly/aa030403a.htm

* "Essential .NET" is not for the faint-of-heart - by Barb Seewer
   http://builder.com.com/article.jhtml?id=u00220030220swr01.htm

* Tips for documenting an XML DTD - by William T. Kelly
   http://builder.com.com/article.jhtml?id=u00420030219WTK01.htm

* An Overview of the new XPointer Specification - by Edmond Woychowsky
   What are the details about the XPointer XML proposal, and how does it
   compare to XPath? Learn more about this new standard and check out
   some examples on how to put it to use.
   http://builder.com.com/article.jhtml?id=u00320030220woy01.htm

* How to get the Selected Objects in a TWebbrowser?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1190

* How to Get Rid Of the Annoying SQL Wait Cursor?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1305

* How to Explode a String?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1326

* How to flash the modal window title when user clicks the parent form?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1393

* How to search a TreeView Item through its Text property?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1414

* How to hook a function (in your own application)?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1422

* How to make deleting items in a TListView faster?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1479

* How to implement flickerless animation of a sprite moving across a
   background image?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1491

* How to jump to a certain key in Regedit?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1542

* How to Draw a line without using the LineTo function?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1569

* How to show balloon tooltips in my Delphi program?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1587

* How to popup the system menu at a specified position?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1594

* How to get paths of the folders in 'My Computer'?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1598

* Get CPU Speed - by Amir Mosavian
   http://www.delphi3000.com/articles/article_3552.asp

* FEEDBACK: D6+ADO+MS.SS => D6+ADO+Oracle - by Hans Pieters
   The results of a migration D6+ADO+MS.SS => D6+ADO+Oracle.
   http://www.delphi3000.com/articles/article_3553.asp

* Auto LiveUpdate - by Xiao Smile
   Auto LiveUpdate your program from an FTP server.
   http://www.delphi3000.com/articles/article_3556.asp

* OnOffBtn - by Pete Coe
   How to make a custom On/Off button with default Glyphs.
   http://www.delphi3000.com/articles/article_3557.asp

* Event Chain Mechanism II - by Alex Wijoyo
   Attach and detach many event handlers to an event at runtime.
   http://www.delphi3000.com/articles/article_3560.asp

* Extracting complete list of URL's from the web server - by Sergey S
   This article describes how to extract a list of all web resources
   (URL's) from a web server like http://www.borland.com using the Clever
   Internet Suite components. It can be implemented with any other
   internet library.
   http://www.delphi3000.com/articles/article_3561.asp

* Using the Google web APIs with Delphi - by Herbert Poltnik
   http://www.delphi3000.com/articles/article_3563.asp

* Writing MS SQL Server Extended Stored Procedures with Delphi
   - by Berend de Boer
   http://www.delphi3000.com/articles/article_3564.asp

* Using the Affinity Mask in multi-CPU environments - by Kim Sandell
   When writing applications that are designated to run in multi-CPU
   environments, it is very useful to be able to control which CPU's the
   application executes on. By optimizing the CPU usage one can
   dramatically increase the performance of the application.
   http://www.delphi3000.com/articles/article_3565.asp

* Quick Sort - by Sébastien Charest
   How to quick sort an array?
   http://www.delphi3000.com/articles/article_3566.asp

* Convert numbers to words - by Abdulaziz Jasser
   http://www.delphi3000.com/articles/article_3567.asp

* Using XML in Delphi applications: Part II - by Sergey Kucherov
   Implementing XML Parser using Microsoft SAX interface.
   http://www.delphi3000.com/articles/article_3571.asp

* OpenGL I: Hello World - by Eber Irigoyen
   Base code for your OpenGL Delphi applications.
   http://www.delphi3000.com/articles/article_3572.asp

* mIRC DLL basics - by Gareth Ablett
   Basic design use and layout of a Delphi DLL for mIRC.
   http://www.delphi3000.com/articles/article_3573.asp

* Sort Order of Internet Explorer Favorites - by Daaron Dwyer
   You can easily get the list of favorites from the directory, but how
   can you emulate the same sort order showing in Internet Explorer?
   http://www.delphi3000.com/articles/article_3574.asp

* Shell Programming with Delphi - by Marcel van Brakel
   Some tricks for using Delphi for shell programming on Windows.
   http://www.delphi-jedi.org/Jedi%3AVOY_SHELLPROG%3A372530

* ColorMask Lab Report
   The purpose of this project is to display only the selected bits of
   a 24-bit color image. Any or all of the 24-bits of each pixel can be
   masked for display.
   http://www.efg2.com/Lab/Graphics/Colors/ColorMask/index.htm

* Active Directory programming - by Marcel van Brakel
   Active Directory programming isn't as hard as you thought, this
   article steps through what you need to do.
   http://www.delphi-jedi.org/Jedi%3AVOY_ACTIVEDIR%3A372530

* .Net Architecture - by Jon Shemitz
   Overview of the .Net architecture, presented at BorCon London, 2002.
   midnightbeach.com/jon/pubs/2002/BorCon.London/dotNetArchitecture.html

* PNG Graphics with Delphi and Kylix - by Chris Rorden
   http://www.psychology.nottingham.ac.uk/staff/cr1/png.html

* 3D Controls - by Chris Rorden
   This article is about controls that you can provide to allow a user to
   select a viewpoint for a 3D image. It includes source code that
   demonstrates the Euler Angles, Vector and Roll and ArcBall controls.
   http://www.psychology.nottingham.ac.uk/staff/cr1/3d.html

* Scientific Mathematics - by Chris Rorden
   Explains the use and benefits of 'Single Instruction, Multiple Data'
   (SIMD) commands, ie. SSE, SSE2 and 3DNow!. Includes a Delphi app that
   measures the time to complete a large number of maths operations using
   either standard or SIMD commands.
   http://www.psychology.nottingham.ac.uk/staff/cr1/simd.html


Kylix, CLX y Linux
------------------

* Kylix Deployment Notes for "Hello World" - by efg
   Just how hard can it be to deploy a simple CLX application in Linux?
   http://www.efg2.com/Lab/Library/Kylix/deployment.htm

* PNG Graphics with Delphi and Kylix - by Chris Rorden
   http://www.psychology.nottingham.ac.uk/staff/cr1/png.html

* Graphics with Kylix - by Chris Rorden
   http://www.psychology.nottingham.ac.uk/staff/cr1/kylix.html

* CLX and Cursors - by Matthias Thoma
   CLX supports Bitmaps and Icons, as files and as resources, but misses
   support for cursors. This article will fill that gap and show how to
   create QCursors and how to load and use windows cursor resources.
   http://www.efg2.com/Lab/Library/Kylix/MatthiasThoma/wincur.html

* KDE System Tray Applets - by Matthias Thoma
   An easy way to add common TForms to KDEs system tray area.
   http://www.efg2.com/Lab/Library/Kylix/MatthiasThoma/KDESystemTray.html

* Kylix for Delphi programmers - by Jon Shemitz
   Presented at BorCon London, October 2002.
   http://www.midnightbeach.com/jon/pubs/2002/BorCon.London/
     KylixForDelphiProgrammers.html


Tutoriales
==========

* Speech Synthesis & Speech Recognition: Overview - by Brian Long
   Overview of adding speech synthesis and speech recognition
   capabilities into Delphi applications using the Microsoft Speech API.
   http://community.borland.com/article/0,1410,29580,00.html

* Using SAPI 4 High Level Interfaces - by Brian Long
   Details of adding speech synthesis and speech recognition capabilities
   into Delphi applications using the high-level programming interfaces
   in Microsoft Speech API v4.0 (SAPI 4).
   http://community.borland.com/article/0,1410,29581,00.html

* Using SAPI 4 Low Level Interfaces - by Brian Long
   Details of adding speech synthesis and speech recognition capabilities
   into Delphi applications using the low-level programming interfaces
   in Microsoft Speech API v4.0 (SAPI 4).
   http://community.borland.com/article/0,1410,29582,00.html

* Speech Synthesis & Speech Recognition: Using SAPI 5.1
   Details of adding speech synthesis and speech recognition capabilities
   into Delphi apps using the Microsoft Speech API v5.1 (SAPI 5.1).
   http://community.borland.com/article/0,1410,29583,00.html

* Windows NT Privileges - by Marcel van Brakel
   This article describes how to discover and set Windows NT privileges
   from your applications, so you can make better use Windows built-in
   security capabilities.
   http://www.thedelphimagazine.com/Samples/1577/1577.htm

* Creating an Internet Explorer-style User Interface Part 2
   In the February 2003 issue of Hardcore Delphi, Fabio Lucarelli began
   demonstrating how to build and maintain a user interface that mimics
   the one in Internet Explorer and Outlook. In this article he continues
   that task by introducing toolbar customization and chevrons, by using
   two common controls: the toolbar and the Coolbar control.
   pinnaclepublishing.com/dd/DDMag.nsf/0/BFBE071686BC1F6A85256CD9007AD663

* NTFS Disk Quotas - by Marcel van Brakel
   Describes how to set and manage NTFS disk quotas programmatically.
   http://www.thedelphimagazine.com/samples/1488/1488.htm

* File Sharing On Linux - by Primoz Gabrijelcic
   Explores file locking support on Linux and presents a cross-platform
   scheme for using the file system for interprocess synchronisation.
   http://www.thedelphimagazine.com/samples/1481/1481.htm

* Interfaces: Off The Beaten Track - by Malcolm Groves
   Shows how to use interfaces to automatically destroy objects, restore
   objects to previous states, cut away swathes of try..finally blocks,
   and deal with memory leaks.
   http://www.thedelphimagazine.com/samples/1415/1415.htm

* Introduction to Design Patterns - by Ader Gonzalez
   Introduces the concept of Design Patterns through the eyes of a Delphi
   programmer.
   http://www.delphi-jedi.org/Jedi%3AVOYPATTERNS

* Delphi: Type Safe Programming - by Richard A. Morris
   A Run-Time Type Information tutorial from the 10th Borland Developer's
   Conference. Includes a component called the RTTI Explorer which allows
   us to delve into the innards of Delphi classes.
   http://www8.pair.com/rmorris/rtti.htm

* Upcoming Borland WebEx events  - by Anders Ohlsson
   Feeling lazy today? Want to sit down in your pajamas and learn about
   the technical details of software development utilizing some of the
   finest technologies available today? Register for these seminars and
   participate from the comfort of your own home to learn about: Delphi
   for .NET, IntraWeb in Delphi, WebServices in Delphi and more.
   Presented by Alain "Lino" Tadros.
   http://community.borland.com/article/0,1410,29784,00.html


Otros enlaces
=============

* Borland Delphi Developer Survey 2003 - by John Kaster
   Let Borland know what you would like to see in future Delphi releases
   by taking this survey. Five winners will receive a free Borland RAD
   Enterprise/Architect software product of their choice.
   http://community.borland.com/article/0,1410,29822,00.html

* 2003 Borland Developer Network (BDN) Survey - by David I
   Help make sure that Borland continues to provide products, services
   and support that you count on. Complete this comprehensive survey to
   help Borland better understand your priorities and better serve your
   needs going forward. As a small "thank you" for participation, you'll
   be entered in a drawing for copies of Borland products - each valued
   at up to $4000.
   http://whatever.borland.com/bdnsurvey.html

* Public beta: Quality Central browser client
   The public beta of the browser interface to QualityCentral (QC) is now
   live. This beta of the web client (WC) is focused on functionality,
   browser compatibility, and ease of use.
   http://community.borland.com/article/0,1410,29803,00.html

* The FirebirdSQL Foundation
   We are very pleased to announce the formation of "The FirebirdSQL
   Foundation", a non-profit association with the objectives of
   supporting and advancing the development of the open source
   FirebirdSQL relational database engine.
   http://www.swissdelphicenter.ch/en/shownews.php?id=349


Noticias
========

* Blog with Delphi and Borland news
   http://svd.blogspot.com/

* Delphi / InterBase WebLog - by Craig Stuntz
   News of interest to Delphi and InterBase developers.
   http://delphi.weblogs.com/

* 28-FEB-2003: Update: Bold for Delphi Architect - by John Kaster
   An update to Bold for Delphi 7 Architect is now available.
   http://bdn.borland.com/article/0,1410,29798,00.html

* 01-MAR-2003: Borland Fires "Sidewinder" at VS.NET - by Alan Zeichick
   Forthcoming C# IDE for Windows to support models, non-Microsoft
   databases. Bringing together its compiler and IDE expertise, newly
   acquired modeling software from TogetherSoft, and the .NET Framework
   SDK licensed from Microsoft Corp., Borland Software Corp. is preparing
   to release its own C# IDE for .NET.
   http://www.sdtimes.com/news/073/story4.htm

* 01-MAR-2003: Borland Pulls Together
   Talk about hitting the ground running. Borland Software Corp. has
   already revamped its developer tools to incorporate key technologies
   from its TogetherSoft acquisition—and the deal closed only one month
   ago.
   http://www.sdtimes.com/opinions/opinion_073.htm

* Borland Delphi .NET - Scheduled for April 2003
   Borland's .NET tools lag behind Microsoft's, but the prospect of
   cross-platform integration and strong modelling features should
   ensure a significant share of the .NET market.
   http://www.pcpro.co.uk/?reviews/reviews_story.php?id=38828

________________________________________________________________________

           ¡Vote por el Boletín Pascal en The Programming Pages!
     http://www.programmingpages.com/topsite.asp?r=latium&Language=29
________________________________________________________________________


¡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@...

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.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
http://news.optimax.com/topdelphi/links.exe/click?id=70C517ECAE6E
http://www.top219.org/cgi-bin/vote.cgi?delphi&83
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
http://213.65.224.200/cgi-bin/toplist.cgi/hits?Id=80
http://www.programacion.net/votar-enlace.php?id=474
http://www.lawebdelprogramador.com/buscar/enlace.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/descarga/p0045.zip
________________________________________________________________________

Página del grupo:  http://espanol.groups.yahoo.com/group/boletin-pascal/
Para suscribirse / apuntarse:   boletin-pascal-subscribe@...
Para cancelar / removerse:    boletin-pascal-unsubscribe@...
¿Problemas con tu suscripción?      boletin-pascal-owner@...
________________________________________________________________________

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) 2003 por Ernesto D'Spirito. Todos los derechos reservados.
________________________________________________________________________

#11 De: "Ernesto D'Spirito" <edspirito@...>
Fecha: Jue, 27 de Feb, 2003 3:38 pm
Asunto: Boletín Pascal #44 - 27-FEB-2003
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #44 - 27-FEB-2003

Índice

1. Unas palabras del editor
2. Operaciones de disco - Como detectar si hay un disektte en la unidad
    de discos o si está protegido, y más...
3. Usando MS Word como generador de reportes
4. Número de serie del disco duro IDE - Usando la API S.M.A.R.T. IOCTL
5. En las noticias
    - Borland lanza Optimizeit Profiler para .NET
    - SideWinder: Borland está desarrollando un IDE para C# para .NET
    - Otras noticias y artículos
6. Foros / listas de correo
7. Delphi en la Red
    - Componentes, librerías y aplicaciones
      . Shareware
      . Freeware
    - Artículos, trucos y consejos
    - Tutoriales

________________________________________________________________________


1. Unas palabras del editor


Me gustaría agradecer a Rafael Ribas Aguiló, Igor Siticov y Alex Konshin
por contribuir artículos para esta edición, y me complace entregarles
los premios para esta edición a los dos últimos:

* Igor Siticov (Usando MS Word como generador de reportes)
· 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/

* Alex Konshin (Número de serie del disco duro IDE)
· 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

Para la próxima edición, tenemos disponibles los siguientes premios para
dos de los autores que colaboren artículos en inglés:

* LMD DesignPack - por LMD Innovative - Shareware (EUR 59)
   Cinco componentes para agregar características de diseño a sus
   aplicaciones (un clon del Inspector de Objetos, un diseñador de
   formularios y controles basados en diagramas), con código fuentes
   extensivos proyectos de ejemplo demostrando las características
   avanzadas - hasta se incluye básicamente un diseñador de reportes.
   http://www.ceberus.com/lmd/products/index.php3#P4

* SDL Component Suite 7.0 - por Software Development Lohninger ($99)
   La SDL Component Suite provee un amplio rango de componentes para la
   ciencia y la ingeniería, por ejemplo matemáticas, estadísticas,
   química, diagramas, visualización de datos, transformadas de Fourier
   (FFT), ploteos 3D, mapas geográficos, ajuste de curvas, etc.
   Disponible para Delphi 3-7 y BCB 4-6.
   http://www.lohninger.com/sdlindex.html

Hasta mañana 28 únicamente, Greatis Software ofrece Greatis Object
Inspector Pro con un descuento significativo, exclusivo para suscrip-
tores de este boletín y visitantes de nuestro sitio web. Vean el
aviso abajo de la nota del editor.

¿Qué pasó con la serie Inline Assembler en Delphi? ¿Ya terminó? Defini-
tivamente no. En futuras ediciones veremos algunos usos de ejemplo de
inline assembler, comenzando en la próxima edición con aritmética de
128 bits. Mientras tanto, espero que disfruten esta edición.

Saludos,

Ernesto D'Spirito
boletin-pascal-owner@...

__________________

Colaboró en esta edición: Dave Murray

________________________________________________________________________

OFERTA Object Inspector Pro: $29.95 (ahorre $20 sobre el precio normal).
Greatis  Object Inspector Pro es  un conjunto de componentes que incluye
un componente para acceder todas las propiedades y eventos publicados de
cualquier componente,  un inspector común  que puede usarse para inspec-
cionar todo en su aplicación, y un inspector de componentes que imita al
Object Inspector.    http://www.latiumsoftware.com/en/objinspspecial.php
________________________________________________________________________


2. Operaciones de disco - Como detectar si hay un disektte en la unidad
    de discos o si está protegido, y más...

    Por Rafael Ribas Aguiló <rribas @ facilities.com.br>
        http://www.facilities.com.br/


Si quiere asegurarse si un diskette está en la unidad de diskettes sin
mostrar esos extraños mensajes de error, debería usar estas funciones:

   function ComposeFileName(Dir, Name: string): string;
   function HasDiskSpace({$IFDEF WIN32}Drive: string{$ELSE}Drive:
                         char{$ENDIF}; MinRequired: longint): boolean;
   function GetDirectorySize(const Path: string): longint;
   function GetFileSizeByName(const Filename: string): longint;
   function IsDiskRemovable(Drive: char): boolean;
   function IsDiskInDrive(Drive: char): boolean;
   function IsDiskWriteProtected(Drive: char): boolean;
   function AskForDisk(Drive: char; Msg: string;
                       CheckWriteProtected: boolean): boolean;
   procedure GetAvailableDrives(DriveType: TDriveType; Items: TStrings);

Estas funciones se implementan en la unidad lDrives (adjunta).

________________________________________________________________________

¿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!"
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
Sólo hay que seguir el enlace y hacer clic en "here" ("aquí") donde dice
"Click here to vote!" ("¡Haga clic aquí para votar!"). Luego aparecerá
el ranking de los más votados. Su voto significa mucho para nosotros.
________________________________________________________________________


3. Usando MS Word como generador de reportes

    Por Igor Siticov
        SiComponents: http://www.sicomponents.com


¿Por qué no usar MS Word como generador de reportes en sus proyectos?
Podemos fácilmente construir un reporte y luego permitir al usuario
modificarlo de cualquier forma que quiera usando este conocido editor.

El ejemplo de abajo muestra como construir el reporte basado en los
contenidos de un StringGrid.

   procedure TsiGridReporter.ShowReport;
   var
     Range: Variant;
     i, j: integer;
   begin
     if FGrid = nil then
       raise Exception.Create('¡No hay grilla seleccionada!');
     try
       FWordApp := CreateOleObject('Word.Application');
     except
       raise Exception.Create('¡No se puede iniciar MS Word!');
     end;
     FWordApp.Visible := True;
     FWordApp.Documents.Add;
     if FShowDate then begin
       Range := FWordApp.Documents.Item(1);
       Range := Range.Sections.Item(1);
       Range := Range.Headers.Item(1).Range;
       Range.Text := 'Fecha: ' + DateToStr(Date) + ' Hora: ' +
         TimeToStr(Time);
     end;
     Range := FWordApp.Documents.Item(1);
     Range := Range.Sections.Item(1);
     Range := Range.Footers.Item(1);
     Range.Range.Text := 'Page:';
     Range.Range.ParagraphFormat.Alignment := ord(waAlignParagraphRight);
     Range.PageNumbers.Add;
     FWordApp.Documents.Item(1).Paragraphs.Add;
     Range := FWordApp.Documents.Item(1).Range(
     FWordApp.Documents.Item(1).Paragraphs.Item(
       FWordApp.Documents.Item(1).Paragraphs.Count - 1).Range.End,
       FWordApp.Documents.Item(1).Paragraphs.Item(
       FWordApp.Documents.Item(1).Paragraphs.Count - 1).Range.End);
     Range.Text := FTitle;
     Range.Bold := fsBold in FTitleFont.Style;
     Range.Italic := fsItalic in FTitleFont.Style;
     Range.Underline := fsUnderline in FTitleFont.Style;
     Range.Font.StrikeThrough := fsStrikeOut in FTitleFont.Style;
     Range.Font.Name := FTitleFont.Name;
     Range.Font.Size := FTitleFont.Size;
     Range.Font.ColorIndex := ord(FTitleColor);
     Range.ParagraphFormat.Alignment := ord(FTitleAlignment);
     FWordApp.Documents.Item(1).Paragraphs.Add;
     FWordApp.Documents.Item(1).Paragraphs.Add;
     Range := FWordApp.Documents.Item(1).Range(
     FWordApp.Documents.Item(1).Paragraphs.Item(
       FWordApp.Documents.Item(1).Paragraphs.Count - 1).Range.End,
       FWordApp.Documents.Item(1).Paragraphs.Item(
       FWordApp.Documents.Item(1).Paragraphs.Count - 1).Range.End);
     FWordApp.Documents.Item(1).Tables.Add(Range, FGrid.RowCount,
       FGrid.ColCount);
     Range := FWordApp.Documents.Item(1).Tables.Item(
       FWordApp.Documents.Item(1).Tables.Count);
     for i := 1 to FGrid.RowCount do
       for j := 1 to FGrid.ColCount do begin
         Range.Cell(i, j).Range.InsertAfter(FGrid.Cells[j-1, i-1]);
         if (i <= FGrid.FixedRows) or (j <= FGrid.FixedCols) then begin
           Range.Cell(i, j).Range.Bold := True;
           Range.Cell(i, j).Range.Shading.BackgroundPatternColorIndex :=
             ord(wcGray25);
         end
         else begin
           Range.Cell(i, j).Range.Bold := fsBold in FCellFont.Style;
           Range.Cell(i, j).Range.Italic := fsItalic in FCellFont.Style;
           Range.Cell(i, j).Range.Underline := fsUnderline in
             FCellFont.Style;
           Range.Cell(i, j).Range.Font.StrikeThrough := fsStrikeOut in
             FCellFont.Style;
           Range.Cell(i, j).Range.Font.Name := FCellFont.Name;
           Range.Cell(i, j).Range.Font.Size := FCellFont.Size;
           // Range.Cell(i, j).Range.Font.ColorIndex := ord(FCellColor);
           Range.Cell(i, j).Range.Shading.BackgroundPatternColorIndex :=
             FCellColor;
         end;
       end;
   end;

Este ejemplo es sólo un método del componente adjunto a este artículo.
Este componente también tiene los métodos PrintReport y PrintPreview.

Vea al código fuente adjunto para más detalles. Este componente le dará
sólo el primer paso para crear su propio generador de reportes basado en
el uso de MS Word.

P.D.: El componente y el código fuente son FREEWARE, así que puede
       usarlos como quiera.

__________________

Igor Siticov es el autor de TsiLang Components Suite (un completo juego
de componentes para construir en dos minutos aplicaciones multilingües
elegantes, útiles y amistosas con el usuario) y de Resource Builder (un
muy completo editor visual de RC script, ideal para reemplazar al
Borland Image Editor y al Borland Resource WorkShop para crear y editar
archivos de recursos), por SiComponents: http://www.sicomponents.com

________________________________________________________________________

Vote por el Pascal Newsletter (Boletín Pascal) en The Programming Pages!
          http://www.programmingpages.com/topsite.asp?r=latium
  Sólo encuéntrelo en la sección Delphi y haga clic en el enlace "Vote".
________________________________________________________________________


4. Número de serie del disco duro IDE - Usando la API S.M.A.R.T. IOCTL

    Por Alex Konshin
        http://home.earthlink.net/~akonshin/


Casi todas las FAQs recomiendan el uso de GetVolumeInformation para
obtener el "número de serie del disco duro", pero lo que en realidad
esta función obtiene es el número de volumen, no el número de serie
del disco duro del fabricante. El número de serie del volumen se asigna
y cambia durante el formateo de la partición. Algunas empresas usan
herramientas de clonación para instalar software en computadoras nuevas,
copiando de un disco duro a todos los otros. Por supuesto, el numero de
serie de volumen para estos discos será idéntico.

Puede obtener el verdadero número de serie del disco duro IDE, nombre
del modelo, revisión del firmware, y otra información del disco duro IDE
usando la API S.M.A.R.T. IOCTL.

   // Copyright (c) 2000 Alex Konshin

   program IdeSN;

   // PROPÓSITO: Simple aplicación de consola que extrae
   //            el número de serie del primer disco IDE.

   {$APPTYPE CONSOLE}

   uses
     Windows,
     SysUtils; // sólo para Win32Platform y SysErrorMessage

   // -------------------------------------------------------------
   function GetIdeDiskSerialNumber : String;
   type
    TSrbIoControl = packed record
       HeaderLength : ULONG;
       Signature    : Array[0..7] of Char;
       Timeout      : ULONG;
       ControlCode  : ULONG;
       ReturnCode   : ULONG;
       Length       : ULONG;
     end;
     SRB_IO_CONTROL = TSrbIoControl;
     PSrbIoControl = ^TSrbIoControl;

     TIDERegs = packed record
       bFeaturesReg     : Byte; // Usado p/especificar "comandos" SMART.
       bSectorCountReg  : Byte; // Registro cantidad de sectores
       bSectorNumberReg : Byte; // Registro número de sector
       bCylLowReg       : Byte; // Valor bajo de cilindro
       bCylHighReg      : Byte; // Valor alto de cilindro
       bDriveHeadReg    : Byte; // Registro unidad/cabeza
       bCommandReg      : Byte; // Comando IDE real.
       bReserved        : Byte; // Reservado. Debe ser cero.
     end;
     IDEREGS   = TIDERegs;
     PIDERegs  = ^TIDERegs;

     TSendCmdInParams = packed record
       cBufferSize  : DWORD;
       irDriveRegs  : TIDERegs;
       bDriveNumber : Byte;
       bReserved    : Array[0..2] of Byte;
       dwReserved   : Array[0..3] of DWORD;
       bBuffer      : Array[0..0] of Byte;
     end;
     SENDCMDINPARAMS   = TSendCmdInParams;
     PSendCmdInParams  = ^TSendCmdInParams;

     TIdSector = packed record
       wGenConfig                 : Word;
       wNumCyls                   : Word;
       wReserved                  : Word;
       wNumHeads                  : Word;
       wBytesPerTrack             : Word;
       wBytesPerSector            : Word;
       wSectorsPerTrack           : Word;
       wVendorUnique              : Array[0..2] of Word;
       sSerialNumber              : Array[0..19] of Char;
       wBufferType                : Word;
       wBufferSize                : Word;
       wECCSize                   : Word;
       sFirmwareRev               : Array[0..7] of Char;
       sModelNumber               : Array[0..39] of Char;
       wMoreVendorUnique          : Word;
       wDoubleWordIO              : Word;
       wCapabilities              : Word;
       wReserved1                 : Word;
       wPIOTiming                 : Word;
       wDMATiming                 : Word;
       wBS                        : Word;
       wNumCurrentCyls            : Word;
       wNumCurrentHeads           : Word;
       wNumCurrentSectorsPerTrack : Word;
       ulCurrentSectorCapacity    : ULONG;
       wMultSectorStuff           : Word;
       ulTotalAddressableSectors  : ULONG;
       wSingleWordDMA             : Word;
       wMultiWordDMA              : Word;
       bReserved                  : Array[0..127] of Byte;
     end;
     PIdSector = ^TIdSector;

   const
     IDE_ID_FUNCTION               = $EC;
     IDENTIFY_BUFFER_SIZE          = 512;
     DFP_RECEIVE_DRIVE_DATA        = $0007c088;
     IOCTL_SCSI_MINIPORT           = $0004d008;
     IOCTL_SCSI_MINIPORT_IDENTIFY  = $001b0501;
     DataSize = sizeof(TSendCmdInParams)-1+IDENTIFY_BUFFER_SIZE;
     BufferSize = SizeOf(SRB_IO_CONTROL)+DataSize;
     W9xBufferSize = IDENTIFY_BUFFER_SIZE+16;
   var
     hDevice : THandle;
     cbBytesReturned : DWORD;
     pInData : PSendCmdInParams;
     pOutData : Pointer; // PSendCmdOutParams
     Buffer : Array[0..BufferSize-1] of Byte;
     srbControl : TSrbIoControl absolute Buffer;

     procedure ChangeByteOrder( var Data; Size : Integer );
     var ptr : PChar;
         i : Integer;
         c : Char;
     begin
       ptr := @Data;
       for i := 0 to (Size shr 1)-1 do
       begin
         c := ptr^;
         ptr^ := (ptr+1)^;
         (ptr+1)^ := c;
         Inc(ptr,2);
       end;
     end;

   begin
     Result := '';
     FillChar(Buffer,BufferSize,#0);
     if Win32Platform=VER_PLATFORM_WIN32_NT then
        begin // Windows NT, Windows 2000, Windows XP
          // Obtener manejador de puerto SCSI
          hDevice := CreateFile('\\.\Scsi0:',
           // Nota: '\\.\C:' requiere privilegios administrativos.
           GENERIC_READ or GENERIC_WRITE,
           FILE_SHARE_READ or FILE_SHARE_WRITE,
           nil, OPEN_EXISTING, 0, 0);
         if hDevice=INVALID_HANDLE_VALUE then Exit;
         try
           srbControl.HeaderLength := SizeOf(SRB_IO_CONTROL);
           System.Move('SCSIDISK',srbControl.Signature,8);
           srbControl.Timeout      := 2;
           srbControl.Length       := DataSize;
           srbControl.ControlCode  := IOCTL_SCSI_MINIPORT_IDENTIFY;
           pInData := PSendCmdInParams(PChar(@Buffer)
                      +SizeOf(SRB_IO_CONTROL));
           pOutData := pInData;
           with pInData^ do
           begin
             cBufferSize  := IDENTIFY_BUFFER_SIZE;
             bDriveNumber := 0;
             with irDriveRegs do
             begin
               bFeaturesReg     := 0;
               bSectorCountReg  := 1;
               bSectorNumberReg := 1;
               bCylLowReg       := 0;
               bCylHighReg      := 0;
               bDriveHeadReg    := $A0;
               bCommandReg      := IDE_ID_FUNCTION;
             end;
           end;
           if not DeviceIoControl( hDevice, IOCTL_SCSI_MINIPORT,
             @Buffer, BufferSize, @Buffer, BufferSize,
             cbBytesReturned, nil ) then Exit;
         finally
           CloseHandle(hDevice);
         end;
       end
     else
        begin // Windows 95 OSR2, Windows 98, Windows ME
         hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil,
           CREATE_NEW, 0, 0 );
         if hDevice=INVALID_HANDLE_VALUE then Exit;
         try
           pInData := PSendCmdInParams(@Buffer);
           pOutData := @pInData^.bBuffer;
           with pInData^ do
           begin
             cBufferSize  := IDENTIFY_BUFFER_SIZE;
             bDriveNumber := 0;
             with irDriveRegs do
             begin
               bFeaturesReg     := 0;
               bSectorCountReg  := 1;
               bSectorNumberReg := 1;
               bCylLowReg       := 0;
               bCylHighReg      := 0;
               bDriveHeadReg    := $A0;
               bCommandReg      := IDE_ID_FUNCTION;
             end;
           end;
           if not DeviceIoControl( hDevice, DFP_RECEIVE_DRIVE_DATA,
             pInData, SizeOf(TSendCmdInParams)-1, pOutData,
             W9xBufferSize, cbBytesReturned, nil ) then Exit;
         finally
           CloseHandle(hDevice);
         end;
       end;
       with PIdSector(PChar(pOutData)+16)^ do
       begin
         ChangeByteOrder(sSerialNumber,SizeOf(sSerialNumber));
         SetString(Result,sSerialNumber,SizeOf(sSerialNumber));
       end;
   end;


   // =============================================================
   var s : String;
       rc : DWORD;
   begin
     s := GetIdeDiskSerialNumber;
     if s='' then
     begin
       rc := GetLastError;
       if rc=0 then WriteLn('La unidad IDE no soporta SMART')
        else WriteLn(SysErrorMessage(rc));
     end
     else WriteLn('Número de serie del disco: ''', s,'''');
     ReadLn;
   end.

Notas:

- El código es sólo para unidades IDE que soporten S.M.A.R.T. (Self
   Monitoring, Analysis and Reporting Technology). Para unidades
   SCSI-2 vea: http://www.delphi3000.com/articles/article_1174.asp

- El hardware IDE debe soportar S.M.A.R.T. y tiene que estar habilitado.

- Windows 95 no soporta esta característica hasta Windows 95 OSR2. El
   código funciona con Windows 95 OSR2/98/98SE/Me/NT4/2000/XP.

   - Windows 9x: SMARTVSD.VXD debe estar instalado: simplemente cópielo
     de la carpeta del Sistema (típicamente C:\WINDOWS\SYSTEM) a la
     carpeta System\IoSubsys (típicamente C:\WINDOWS\SYSTEM\IOSUBSYS) y
     reinicie.

   - Windows NT/2000/XP: El código no requiere privilegios administra-
     tivos y funciona bajo la cuenta 'everyone'.

- Para más información acerca de la API SMART IOCTL vea la aplicación de
   ejemplo SmartApp en la MSDN Knowledge Base:
   http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B208048

   - Si necesita información acerca de un disco esclavo o un disco
     conectado a la controladora IDE secundaria, vea el ejemplo IdeInfo2
     en mi sitio web: http://home.earhlink.net/~akonshin/

   - Para más información acerca de S.M.A.R.T. y otros estándares
     relacionados con dispositivos de almacenamiento ATA, vea el sitio
     del Technical Committee T13:
     http://www.t13.org/
     Puede encontrar información relacionada con el tema de este artículo
     en las páginas 87-105 del siguiente documento:
     http://www.t13.org/project/d1321r3.pdf

______________

Alex Konshin es un Ingeniero de Software Sr. y ex-programador Delphi
que programa en Delphi como hobby, pero ha sido mencionado en los cré-
ditos de Delphi 7. Puede encontrar algunos componentes útiles freeware
y con fuentes en su sitio web: http://home.earthlink.net/~akonshin/

________________________________________________________________________

¿Cómo calificaría al boletín? ¡Califique al Boletín Pascal en el ranking
Top 200 Delphi! · http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________


5. En las noticias


Borland lanza Optimizeit Profiler para .NET
===========================================

Optimizeit Profiler es una nueva solución de garantía de rendimiento
para la plataforma .NET Framework. Optimizeit Profiler soporta todo el
código administrado .NET y hace los ajustes de rendimiento más fáciles
proveyendo evaluaciones de rendimiento en tiempo real que rápidamente
identifica y prioriza las cuestiones de rendimiento, resaltanto la línea
relevante de código fuente para resolución inmediata, permitiendo a los
programadores entregar más rápido aplicaciones de alto rendimiento
basadas en la Microsoft .NET Framework.

Para más información:

- Optimizeit Profiler
   http://www.borland.com/opt_profiler/index.html

- Borland Launches Performance Assurance Solution for Microsoft .NET
   Framework
   http://www.planetanalog.com/pressreleases/bizwire/57199

- Microsoft Partners Rally Around Visual Studio .NET
   http://www.internetnews.com/dev-news/print.php/1582361


SideWinder: Borland está desarrollando un IDE para C# para .NET
===============================================================

Borland está trabajando en el desarrollo de un IDE para C#, que se
conoce actualmente como SideWinder, pero por ahora este es el nombre
clave público del producto, y no necesariamente significa que será el
nombre del producto cuando sea lanzado (aunque es muy probable).

He aquí algunas noticias y artículos sobre SideWinder:

- 28-JAN-2003: Borland Becomes First to License the Microsoft .NET
   Framework Software Development Kit
   http://www.certificationsuccess.com/index.cfm?pageid=401

- 31-JAN-2003: Borland prepares new IDE for .Net
   http://www.vnunet.com/News/1138406

- 04-FEB-2003: Borland moves ahead with .NET tools; inks pact with
   Microsoft
   http://www.adtmag.com/article.asp?id=7224

- 04-FEB-2003: Borland to offer IDE for Microsoft's .Net
   http://www.infoworld.com/article/03/02/04/HNsidewinder_1.html

- 04-FEB-2003: Borland targets .Net developers
   http://news.com.com/2100-1001-983321.html
   http://msnbc-cnet.com.com/2100-1001-983321.html
   http://www.businessweek.com/technology/cnet/stories/983321.htm

- 07-FEB-2003: First SideWinder screenshots
   http://www.drbob42.com/SideWinder/home.htm

- 14-FEB-2003: Interview with Jason Vokes (Borland EMEA) about .NET
   development at Borland, including SideWinder and Delphi for .NET
   http://www.drbob42.com/SideWinder/interview.htm

SideWinder será el primer producto del proyecto Galileo, un proyecto
mucho más grande de Borland anunciado en la BorCon 2002:

* Borland to wield tools against Microsoft - By Wylie Wong
   http://news.com.com/2100-1001-954958.html

El objetivo de Galileo es crear un IDE 100% .NET, mulilenguaje, que
apunte a diferentes plataformas (una especie de Visual Studio .NET
multiplataforma, si quiere verlo de esa manera, pero será mucho más
que eso pues por ejemplo integraría modelado y diseño).


Otras noticias y artículos
==========================

* Flurry Of New Tools Target Microsoft Visual Studio .Net Developers -
   by Gregg Keizer
   http://www.techweb.com/wire/story/TWB20030211S0004

* Microsoft rebuilds .Net tools - by Martin LaMonica
   Borland tools will be integrated into Visual Studio.Net.
   http://news.com.com/2100-1001-984129.html

* .NET: Great Hope or Great Hype - by Alan C. Moore, Ph.D
   www.delphizine.com/opinion/2003/03/di200303fn_o/di200303fn_o.asp

* Short interview with David Intersimone (Borland's VP of Developer
   Relations) about Kylix.
   http://www.programmersparadise.com/promo/QA_062402_2.pasp

* Borland Defies the Skeptics - by Elise Ackerman
   Days after President and CEO Dale Fuller joined Borland Software in
   April 1999, an industry pundit singled out the Scotts Valley company
   as one of five tech firms unlikely to make it to the new millennium.
   Fuller has been gleefully quoting the prediction ever since...
   http://www.belleville.com/mld/belleville/business/4865330.htm

* Sip From The Firehose: A message from Borland to developers - David I
   We've begun an advertising campaign targeted at executives in charge
   of development. The topic? Borland's new application lifecycle studio
   of products.
   http://community.borland.com/article/0,1410,29597,00.html

* Blog with Delphi and Borland news
   http://svd.blogspot.com/

________________________________________________________________________

¿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!"
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
Sólo hay que seguir el enlace y hacer clic en "here" ("aquí") donde dice
"Click here to vote!" ("¡Haga clic aquí para votar!"). Luego aparecerá
el ranking de los más votados. Su voto significa mucho para nosotros.
________________________________________________________________________


6. Foros / listas de correo


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).
   http://espanol.groups.yahoo.com/group/delphi-abierto
   Suscripción:
     http://espanol.groups.yahoo.com/group/delphi-abierto/join
     delphi-abierto-subscribe@...

* 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@...

* 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

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


7. Delphi en la Red

    Por Dave Murray <irongut @ vodafone.net>


Componentes, librerías y aplicaciones
=====================================


Shareware/Comercial
-------------------

* LMD DesignPack - por LMD Innovative - Shareware (EUR 59)
   Cinco componentes para agregar características de diseño a sus
   aplicaciones (un clon del Inspector de Objetos, un diseñador de
   formularios y controles basados en diagramas), con código fuente y
   extensivos proyectos de ejemplo demostrando las características
   avanzadas - hasta se incluye básicamente un diseñador de reportes.
   http://www.ceberus.com/lmd/products/index.php3#P4

* NTTools 7 For Delphi - por i-tivity (USD 39.95)
   ¡Basta de batallar con la API de Seguridad de Windows NT! Obtenga su
   copia de NTTools 7 para Delphi 4/5/6/7 ahora y ahórrese incontables
   horas con esta colección de 40 componentes VCL escritos específica-
   mente para tratar con las funciones de Seguridad de Windows NT. Se
   incluye código fuente completo.
   http://www.i-tivity.biz/nttools.htm


Freeware
--------

* ODBCTools For Delphi - by i-tivity (with source)
   ODBCTools is a complete replacement package for the BDE and consists
   of the following components: ODBC_Database, ODBC_Table, ODBC_Exec,
   ODBC_Conformance, ODBC_TableList, ODBC_FieldList, ODBC_Info,
   ODBC_PrimaryKeys, ODBC_Procedures, ODBC_DSNList and ODBC_Admin.
   http://www.i-tivity.biz/odbctools.htm

* TurboPower SysTools v4.03 - by TurboPower (with source)
   A library of utility routines & algorithms for Delphi, C++Builder and
   environments that support COM. Among other things, it supports 1-D and
   2-D bar codes, sorting, money routines, logging classes, high-
   precision math and a run-time math expression analyzer.
   https://sourceforge.net/projects/tpsystools/

* Interbase 6.0 Open Edition
   Can't find the link to download the free version of Interbase at
   Borland's web site? Well, here it is:
   http://info.borland.com/devsupport/interbase/opensource/


Artículos, trucos y consejos
============================

* New Delphi feature: Multiple inheritance for interfaces in Delphi for
   .NET  - by John Kaster
   Update 3 of the Delphi for .NET preview includes compiler enhancements
   for multiple inheritance for interfaces.
   http://community.borland.com/article/0,1410,29779,00.html

* Delphi for .NET preview Update 3 available for download - John Kaster
   An update containing improvements to the compiler, RTL and VCL of the
   Delphi for .NET preview is now available for download.
   http://community.borland.com/article/0,1410,29780,00.html

* Implementing Callbacks to a Datasnap Server Interface - Xavier Pacheco
   Add the ability for a Datasnap Server to call your client application
   through a callback.
   http://community.borland.com/article/0,1410,29539,00.html

* Metadata.NET - by Noel Rice
   This article shows the capability of requesting information from .NET
   providers at runtime and deals with Databases, Table, Fields,
   constraints, Index and data Types.
   http://community.borland.com/article/0,1410,29708,00.html

* Exchanging Raw Data over the Network 2 - by Zarko Gajic
   An introduction to sending data over the network using Delphi + Indy.
   Focuses on sending / receiving record data and raw (binary) data
   using TCP/IP connections.
   http://delphi.about.com/library/weekly/aa020403a.htm

* How to display fonts in a list box - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=216

* How to delete a file the next time the PC is rebooted - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=217

* How to convert a long filename to a short filename - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=218

* How to create a Access-Database (mdb) without Access - by Alex Schlecht
   Using MS-Jet-Engine to create a *.mdb File.
   http://www.delphi3000.com/articles/article_3536.asp

* Advanced Indy 1: Server Side Techniques - by Romeo Lefter
   http://www.delphi3000.com/articles/article_3538.asp

* Creating "Hidden" Registry Values - by Daniel Wischnewski
   Using the undocumented MS Native API.
   http://www.delphi3000.com/articles/article_3539.asp

* Delphi and Automation with Word - by Herbert Poltnik
   Automation allows one application to control another application.
   The application being controlled is called an automation server (in
   our case Word). The application controlling the server is called an
   automation controller.
   http://www.delphi3000.com/articles/article_3541.asp

* Event Chain Mechanism - by Alex Wijoyo
   How can we attach more than one event handler to a component event?
   http://www.delphi3000.com/articles/article_3543.asp

* BPL Analyze - by quark quark
   What in BPL? How many Units in BPL?
   http://www.delphi3000.com/articles/article_3548.asp

* How to load big bitmaps with few memory requirement? - by Alex Sanchez
   http://www.swissdelphicenter.ch/en/showcode.php?id=1526

* How to disable CTRL+ALT+DELETE under XP? - by Andreas Kirchmeyer
   http://www.swissdelphicenter.ch/en/showcode.php?id=1528

* How to set the background color of a MDI Form? - by Alex Pierson
   http://www.swissdelphicenter.ch/en/showcode.php?id=1554

* How to resize an image (undistorsioned result image)? - Josep Ma Feliu
   http://www.swissdelphicenter.ch/en/showcode.php?id=1463

* How to show a preview for a TRichEdit/ TRxRichEdit? - by Robert Dunn
   http://www.swissdelphicenter.ch/en/showcode.php?id=1467

* How to use the Microsoft Speech API? - by Marco Parreira
   http://www.swissdelphicenter.ch/en/showcode.php?id=1572

* How to print a TStringgrid? - by Reinhard Schatzl
   http://www.swissdelphicenter.ch/en/showcode.php?id=1577

* How to enumerate the logged in users on a Remote or Local NT
   Workstation? - by Manfred Ruzicka
   http://www.swissdelphicenter.ch/en/showcode.php?id=1578

* How to install an INF file with Delphi? - by patrick
   http://www.swissdelphicenter.ch/en/showcode.php?id=1585

* Creating an Internet Explorer-style User Interface, Part 1
   By Fabio Lucarelli
   <http://www.pinnaclepublishing.com/dd/DDmag.nsf/0/
     95505F4719043C1185256CC300743624>


Tutoriales
==========

* The Dynamics of Agile Software Processes, Part I - by Randy Miller
   Part one describes the characteristics of good agile software
   development process design.
   http://bdn.borland.com/article/0,1410,29726,00.html

* Adding Auto-Persistence Capabilities To Options Dialogs - by D. Jewell
   How to avoid the pain of re-coding the saving and restoring of your
   user-configurable settings for each and every new application, with a
   little bit of lateral thinking.
   http://www.thedelphimagazine.com/samples/1560/1560.htm

* Using Customisable Keyboard Shortcuts - by Stephen Posey
   Demonstrates how keyboard shortcuts can be very easy using Actions.
   http://www.thedelphimagazine.com/samples/1521/1521.htm

* Extracting XML Data From SQL Server 2000 - by Jani Järvinen
   Describes how to use the XML features built into SQL Server 2000 from
   your Delphi applications, through ADO, HTTP and SOAP.
   http://www.thedelphimagazine.com/samples/1507/1507.htm

* Enhance Reuse by Embracing Service-Oriented Architecture - T Landgrave
   Thinking of your apps strictly in terms of components can limit your
   reuse options. Find out how to increase your options by defining
   applications as services.
   http://builder.com.com/article.jhtml?id=u00320030129lan01.htm

* Adventures in Kylix - by James R. Knowles
   A blog style tutorial for Kylix.
   http://www.ifm-services.com/people/jamesk/kylix/

________________________________________________________________________


¡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@...

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.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
http://news.optimax.com/topdelphi/links.exe/click?id=70C517ECAE6E
http://www.top219.org/cgi-bin/vote.cgi?delphi&83
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
http://213.65.224.200/cgi-bin/toplist.cgi/hits?Id=80
http://www.programacion.net/votar-enlace.php?id=474
http://www.lawebdelprogramador.com/buscar/enlace.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/descarga/p0044.zip
________________________________________________________________________

Página del grupo:  http://espanol.groups.yahoo.com/group/boletin-pascal/
Para suscribirse / apuntarse:   boletin-pascal-subscribe@...
Para cancelar / removerse:    boletin-pascal-unsubscribe@...
¿Problemas con tu suscripción?      boletin-pascal-owner@...
________________________________________________________________________

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) 2003 por Ernesto D'Spirito. Todos los derechos reservados.
________________________________________________________________________

#10 De: "Ernesto D'Spirito" <edspirito@...>
Fecha: Lun, 3 de Feb, 2003 6:13 pm
Asunto: Boletín Pascal #43 - 03-FEB-2003
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #43 - 03-FEB-2003

Índice

1. Unas palabras del editor
2. MS Exchange API vía CDO (Collaboration Data Objects)
    Librería de base para CDO - Hablando con el servidor MS-Exchange
3. Aplicaciones distribuidas, la forma fácil (II)
    Conceptos básicos de MsgConnect. Un simple sistema de chat.
4. Modificando los diálogos estándar de Windows
    Modificando controles de los diálogos Abrir/Guardar de Windows
5. Huevo de Pascua de Delphi
    Conozca mejor su Delphi
6. Foros / listas de correo
7. Delphi en la Red
    - Componentes, librerías y aplicaciones
      . Shareware
      . Freeware
    - Artículos, trucos y consejos
    - Tutoriales
    - Otros enlaces

________________________________________________________________________

¿Necesitas alojamiento para tu sitio web? http://www.tecnosoftonline.com
________________________________________________________________________


Me gustaría agradecer a Mike Heydon, Eugene Mayevski, Igor Siticov y
a Bogdan Grigorescu por contribuir artículos para esta edición, y me
complace entregarles a Igor y a Mike las licencias de premio para esta
edición:

* Igor Siticov ("Modificando los diálogos estándar de Windows")
· TSDBGridFooter v2.0 por Jovan Sedlan, Shareware ($74.50)
   Este componente es una poderosa herramienta que provee cálculos auto-
   máticos para su DBGrid y muestra información en un pie configurable
   debajo de la grilla. Ha sido diseñado para trabajar con TSDBGrid
   (también incluido), aunque puede usarse con cualquier descendiente de
   TCustomDBGrid.
   http://www.sedlan.com/dbgrid_footer.php

* Mike Heydon ("MS Exchange API vía CDO (Collaboration Data Objects)")
· SDL Component Suite 7.0 - por Software Development Lohninger ($99)
   La SDL Component Suite provee un amplio rango de componentes para la
   ciencia y la ingeniería, por ejemplo matemáticas, estadísticas,
   química, diagramas, visualización de datos, transformadas de Fourier
   (FFT), ploteos 3D, mapas geográficos, ajuste de curvas, etc.
   Disponible para Delphi 3-7 y BCB 4-6.
   http://www.lohninger.com/sdlindex.html

Para la próxima edición, tenemos disponibles los siguientes premios para
dos de los autores que colaboren artículos en inglés:

* 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

* 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/

En otro orden de cosas, se ha abierto un nuevo lugar donde los usuarios
de Delphi y Kylix pueden compartir componentes, tutoriales y ejemplos
con otros programadores. Los navegantes pueden no sólo subir y bajar
archivos, sino también calificar las descargas y añadir comentarios:

* Descargas Delphi y Kylix - del Club de Programadores
   http://descargas.clubdeprogramadores.com/tema.php?Id=15

Espero que disfruten esta edición.

Saludos,

Ernesto D'Spirito
boletin-pascal-owner@...

________________________________________________________________________

Object Inspector 1.2 (por Greatis Software) es un juego de componentes
que incluye un componente especial para acceder a las propiedades y
eventos de cualquier componente, un inspector común que se puede usar
para inspeccionar todo en su aplicación, y un inspector de componentes
listo para usar que imita al Inspector de Objetos del IDE. Admite la
configuración de fuentes y colores. http://www.greatis.com/objinsp.htm
________________________________________________________________________


2. MS Exchange API vía CDO (Collaboration Data Objects)
    Librería de base para CDO - Hablando con el servidor MS-Exchange

    Copyright (c) 2002 Mike Heydon


Este es un vasto tema y está fuera del alcance de este artículo el
tratarlo en profundidad. Esta librería provee las bases para alguien que
quiera desarrollar usando CDO. Hay muchas referencias en la Red, pero la
mejor fuente es el archivo CDO.HLP que viene en el CD de Exchange o que
está en <http://www.cdolive.com/start.htm>. El sitio cdolive.com es un
excelente sitio de referencia que discute todos los aspectos incluyendo
instalación y versiones, y también ofrece descargas (CDO.HLP se puede
descargar desde allí).

Mi clase básica provee la siguiente funcionalidad:

* Funciones y métodos de utilidad

     function CdoNothing(Obj : OleVariant) : boolean;
     function CdoDefaultProfile : string;
     function VarNothing : IDispatch;

     procedure CdoDisposeList(WorkList : TList);
     procedure CdoDisposeObjects(WorkStrings : TStrings);
     procedure CdoDisposeNodes(WorkData : TTreeNodes);

* Constructores Create que permiten el logon del perfil predeterminado,
   el logon de un perfil específico, y un logon de usuario impersonado
   con perfil (esto se requiere para un logon exitoso en aplicaciones
   de servicios de Windows).

     constructor Create; overload;
     constructor Create(const Profile : string); overload;
     constructor Create(const Profile : string;
                        const UserName : string;
                        const Domain : string;
                        const Password : string); overload;

* Métodos para cargar stringlists, treeviews, etc. e iteración de
   objetos.

     function LoadAddressList(StringList : TStrings) : boolean;
     function LoadObjectList(const FolderOle : OleVariant;
                             List : TList) : boolean;
     function LoadEMailTree(TV : TTreeView;
                            Expand1stLevel : boolean = false;
                            SubjectMask : string = '') : boolean;
     function LoadContactList(const FolderOle : OleVariant;
                              Items : TStrings) : boolean; overload;
     function LoadContactList(const FolderName : string;
                              Items : TStrings) : boolean; overload;
     procedure ShowContactDetails(Contact : OleVariant);

   Los métodos de arriba cargan varias listas en stringlists, lists o
   treeviews. Las listas con los objetos construidos dentro de estas
   estructuras de datos se liberan en cada sucesiva llamada a un método
   Load*. Sin embargo, la liberación final es responsabilidad del
   desarrollador. Puede hacer esto por sí mismo o usando las funciones
   de utilidad CdoDispose*(). Vea la documentación del código fuente
   para mayor entendimiento.

     function First(const FolderOle : OleVariant;
                    out ItemOle : OleVariant) : boolean;
     function Last(const FolderOle : OleVariant;
                   out ItemOle : OleVariant) : boolean;
     function Next(const FolderOle : OleVariant;
                   out ItemOle : OleVariant) : boolean;
     function Prior(const FolderOle : OleVariant;
                    out ItemOle : OleVariant) : boolean;
     function AsString(const ItemOle : Olevariant;
                       const FieldIdConstant : DWORD) : string;

   Los métodos de arriba proveen iteración a través de los objetos en
   listas como Bandeja de entrada, Contactos, etc. La función AsString
   devuelve un valor de campo, tal como dirección de email, nombre,
   nombre de la empresa, etc. (hay una miríada de estos campos definidos
   en la sección CONST, bajo "Field Tags").

* Propiedades

     property CurrentUser : OleVariant read FCurrentUser;
     property Connected : boolean read FConnected;
     property LastErrorMess : string read FlastError;
     property LastErrorCode : DWORD read FlastErrorCode;
     property InBox : OleVariant read FOleInBox;
     property OutBox : OleVariant read FOleOutBox;
     property DeletedItems : Olevariant read FOleDeletedItems;
     property SentItems : Olevariant read FOleSentItems;
     property GlobalAddressList : Olevariant read FOleGlobalAddressList;
     property Contacts : Olevariant read FOleContacts;
     property Session : OleVariant read FOleSession;
     property Version : string read GetFVersion;
     property MyName : string read FMyName;
     property MyEMailAddress : string read FMyEMailAddress;

El constructor Create establece los objetos predefinidos InBox (bandeja
de entrada), OutBox (bandeja de salida), DeletedItems (elementos elimi-
nados), SentItems (elementos enviados), GlobalAddressList (lista global
de direcciones), Session (sesiones) y Contacts (contactos). Las otras
propiedades se explican por sí mismas.

Tal como mencioné antes, la funcionalidad de CDO es vasta en la medida
que objetos como InBox (bandeja de entrada) tienen muchos métodos y
propiedades que incluyen actualizar, insertar, eliminar, etc. El archivo
CDO.HLP le ayudará a exponer estos miembros de clase. Mi clase es la
base de CDO para ayudarle a simplificar la construcción de aplicaciones
y probablemente se muestre mejor con fragmentos de código de ejemplo.
Créame, se puede escribir todo un libro sobre este tema, pero vale la
pena estudiar una alternativa más rápida que usar la API de MS Outlook.

   uses Cdo_Lib;
   var
     Cdo: TcdoSession;
     MailItem: OleVariant;

     // Itera a través de los emails en la bandeja de entrada
   begin
     Cdo := TCdoSession.Create;

     if Cdo.Active then
     begin
       Cdo.First(Cdo.InBox, MailItem);

       while true do
       begin
         if not Cdo.Nothing(MailItem) then
         begin
           Subject := MailItem.Subject;

           EMailAddress := Cdo.AsString(MailItem.Sender,
                                        CdoPR_EMAIL_AT_ADDRESS);
           EMailName := MailItem.Sender.Name;
           BodyText := MailItem.Text;

           // Borra el email
           MailItem.Delete;
           // Obtiene el siguiente email
         end;

         MailItem := Cdo.Next(Cdo.Inbox.MailItem);
       end;
     end;
     Cdo.Free;
   end;

   // Ejemplo de cargar emails en un treeview y mostrarlos
   // al hacer clic en el treeview

   unit UBrowse;
   interface

   uses
     Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
     Dialogs, ComCtrls, ToolWin, Menus, ExtCtrls, StdCtrls, Buttons,
     ImgList, CDO_Lib;

   type
     TFBrowse = class(TForm)
       Panel1: TPanel;
       Panel3: TPanel;
       Label1: TLabel;
       Label2: TLabel;
       lbFrom: TLabel;
       lbDate: TLabel;
       Memo1: TMemo;
       Panel2: TPanel;
       OKBtn: TBitBtn;
       tvCalls: TTreeView;
       ImageList1: TImageList;
       StatusBar1: TStatusBar;
       procedure FormShow(Sender: TObject);
       procedure FormClose(Sender: TObject; var Action: TCloseAction);
       procedure tvCallsClick(Sender: TObject);
       procedure btnPrintClick(Sender: TObject);
     private
       { Private declarations }
       Doc: OleVariant;
       Cdo: TCdoMapiSession;
     public
       { Public declarations }
     end;

   var
     FBrowse: TFBrowse;

   implementation

   {$R *.DFM}

   procedure TFBrowse.FormShow(Sender: TObject);
   var
     TN: TTreeNode;
   begin
     Screen.Cursor := crHourGlass;
     Application.ProcessMessages;
     Cdo := TCdoMapiSession.Create;
     Cdo.LoadEMailTree(tvCalls, true, '*Support ---*');
     tvCalls.SortType := stText;
     TN := tvCalls.Items[0];
     TN.Expand(false);
     tvCalls.SetFocus;
     Screen.Cursor := crDefault;
   end;

   procedure TFBrowse.FormClose(Sender: TObject;
                                var Action: TCloseAction);
   begin
     CdoDisposeNodes(TvCalls.Items);
     Cdo.Free;
   end;

   procedure TFBrowse.tvCallsClick(Sender: TObject);
   var
     TN: TTreeNode;
   begin
     TN := tvCalls.Selected;
     Memo1.Clear;
     lbFrom.Caption := '';
     lbDate.Caption := '';

     if TN.Data <> nil then
     begin
       Doc := TOleVarPtr(TN.Data)^;
       Memo1.Text := Doc.Text;
       lbFrom.Caption := Doc.Sender.Name;
       lbDate.Caption := FormatDateTime('dd/mm/yyyy hh:nn',
         Doc.TimeSent);
     end;
   end;

   end.

________________________________________________________________________

¿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!"
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
Sólo hay que seguir el enlace y hacer clic en "here" ("aquí") donde dice
"Click here to vote!" ("¡Haga clic aquí para votar!"). Luego aparecerá
el ranking de los más votados. Su voto significa mucho para nosotros.
________________________________________________________________________


3. Aplicaciones distribuidas, la forma fácil (II)
    Conceptos básicos de MsgConnect. Un simple sistema de chat.

    Por Eugene Mayevski <Mayevski @ eldos.org>


      En la primera parte de este artículo echamos un breve vistazo
      a los métodos usados para intercambiar información ente dife-
      rentes partes de la aplicación. Esta parte tratará con el
      deasarrollo de una simple aplicación de chat para Intranets.


Encontrará un ejemplo (muy primitivo, pero completo) incluido con la
aplicación MsgConnect: http://www.msgconnect.com/download.html
Se llama SendNote (EnviarNota). Como su nombre lo indica, esta
aplicación le permite enviar notas de texto al destinatario. Puede
usar este ejemplo como material de referencia para este texto.

Comencemos por el principio. Decidimos usar MsgConnect pues se jacta de
ser de plataformas cruzadas y orientado a mensajes. Para entregar un
mensaje necesitamos tres cosas:

   1. Un componente para enviar el mensaje
   2. Un componente para entregar el mensaje
   3. Un componente para recibir el mensaje

A diferencia de la mayoría de las formas de intercambio de datos, donde
las partes remitente y destinatario están en diferentes componentes,
MsgConnect usa el mismo componente para enviar y recibir mensajes.

Tal como se describe en la sección "Getting Started" de la documentación
de MsgConnect, necesitará sólo tres componentes: Messenger (mensajero),
Transport (transporte) y Queue (cola).

Messenger es el núcleo de MsgConnect -lleva a cabo todo el procesamiento
del mensaje. Al igual que el subsistema de mensajes de Windows®, que
está basado en hilos, la clase Messenger fue diseñada para ser el único
componente Messenger en un hilo. En otras palabras, sólo una instancia
de la clase Messenger puede ser creada por cada hilo de ejecución. Puede
crear más, pero esto (a) no tiene mucho sentido y (b) complica la lógica
de su aplicación.

Transport se usa para entregar el mensaje al destinatario. Actualmente
hay dos transportes, uno basado en Archivos Mapeados en Memoria (MMF) y
el otro en Sockets. Se está creando un transporte basado en HTTP y hay
planes para otros transportes más adelante. El transporte toma el
mensaje de Messenger, lo empaqueta (adicionalmente también aplica
encripción, compresión y control de integridad) y lo transfiere al
destinatario. La aplicación destinataria también tiene que tener una
instancia activa del transporte de la misma clase. Esto significa que si
envía un mensaje usando un transporte Socket, es necesario tener un
transporte Socket activo en el otro lado (el del destinatario).

Queue (cola) se usa para despachar los mensajes recibidos de una manera
cómoda. Puede tratarse como una casilla de correo en una oficina postal.
Cuando envía una carta a una casilla postal, envía un mensaje binario a
la cola. Probablemente Mailbox (casilla de correo) hubiera sido un mejor
nombre para el objeto Queue, pero no lo cambiaremos ahora. Cada
Messenger puede tener tantas colas como quiera. Las colas se identifican
con un nombre simbólico. Hay ciertas limitaciones para los nombres de
las colas, y se describen en la documentación.

¿Cómo hace el Messenger para saber donde enviar un mensaje? Cuando le
pide al Messenger que envíe algo, le pasa la dirección del destinatario.
Esta dirección contiene tres partes:

   * Identificador del transporte. Este puede ser el nombre del
     componente de transporte o de la clase, tal como se describe
     en la documentación.
   * Dirección del destinatario. Esta dirección es específica a cada
     transporte.
   * Nombre de la cola destino.

Y la última pregunta importante: ¿MsgConnect garantiza el envío y el
orden de los mensajes? Bueno, los sistemas distribuidos son diferentes
a los monoproceso respecto de cuando y como estos sistemas se inician
y detienen y que enlaces externos mantienen. En otras palabras, no es
posible garantizar que el sistema remoto recibirá y procesará el
mensaje. Esto está más allá del control de MsgConnect. Pero al menos el
envío se garantiza de la siguiente forma: si usa uno de los métodos
SendMessage*() (y no PostMessage()) para enviar un mensaje, obtendrá una
notificación acerca del éxito o fracaso del envío.

En cuanto al orden de la entrega, dada la naturaleza bidireccional de
MsgConnect (si la conexión existe puede usarse para enviar mensajes en
cada dirección, completamente independiente la una da la otra) existe
una posibilidad de que dos mensajes programados para entregarse a un
destinatario al mismo tiempo no sean entregados en el orden en que
fueron puestos en la cola. Esta situación puede ocurrir sólo cuando se
usa el mismo transporte tanto en el cliente como en el servidor (o sea,
inician y aceptan conexiones al mismo tiempo). Esto se llama modo de
transporte p2p para la clase SocketTransport. La solución es fácil, pero
trataremos esta cuestión en la próxima parte del artículo - por ahora no
la necesitamos.

Ahora que ya sabemos lo básico, comencemos a construir nuestra primera
aplicación "powered by MsgConnect": un chat simple.

Primero creamos el objeto Messenger, el objeto Queue y el objeto
SocketTransport. En diferentes entornos de desarrollo esto puede
hacerse por código o colocando un componente en el Diseñador.

Luego necesitamos enlazar los objetos Queue y SocketTransport al
Messenger estableciendo su propiedad Messenger a la instancia
agregada la clase Messenger. En lenguajes que no soportan propiedades,
esto se hace llamando al método SetMessenger().

Luego establecemos las propiedades del transporte (como se muestra en
los proyectos de ejemplo): MessengerPort (14583 en nuestro ejemplo),
TransportMode (p2p en nuestro caso porque nuestro chat envía y recibe
mensajes por el mismo transporte) y por supuesto la propiedad Active.
MessengerPort es donde el SocketTransport espera las conexiones
entrantes, y TransportMode define como se comporta el transporte cuando
sea activado.

La aplicación recibe los mensajes ya sea (a) usando el evento
OnUnhandledMessage de la clase Queue o (b) usando objetos
MessageHandler. El uso de objetos MessageHandler es una forma cómoda de
poner manejadores para diferentes mensajes en diferentes métodos. Para
nuestro simple sistema de chat con un mensaje usamos un evento
OnUnhandledMessage, así que necesitaremos crear un método manejador del
evento OnUnhandledMessage. Este método será llamado cuando llegue un
mensaje.

Tal como dijimos antes, MsgConnect emula el subsistema de mensajes de
Windows y el objeto Messenger se usa dentro de un hilo. Enviamos un
mensaje usando uno de los métodos PostMessage() o SendMessage*().
Recuerde llamar estos métodos desde el mismo hilo en que se creó el
objeto Messenger (la versión Java de MsgConnect no tiene esta restric-
ción).

Para enviar un mensaje al destinatario de nuestra simple aplicación de
chat, el usuario deberá ingresar el texto, el nombre del remitente (no
se usa para despachar los mensajes y es sólo informativo) y la dirección
del destinatario. Aquí viene la parte engañosa: en nuestra aplicación de
chat permitimos al usuario ingresar el nombre de la computadora o la
dirección de IP. Más tarde se usan sin traducción como la dirección del
destinatario del mensaje. En aplicaciones más complejas uno buscará los
nombres de usuarios en una lista o realizará otra traducción nombre->
dirección (usaremos esto al desarrollar una aplicación de mensajería
instantánea).

El siguiente paso es desarrollar un protocolo. Un protocolo es una
secuencia de llamadas o mensajes, usados para intercambiar información
entre las dos partes de la conexión. En nuestro simple chat usamos un
protocolo muy primitivo que consiste de un solo mensaje - todos los
datos que se envían se incluyen en este mensaje.

Así que tenemos algo para enviar. ¿Cómo enviamos enviamos el mensaje?
Recuerde que a diferencia de la mensajería de Windows, MsgConnect puede
transferir datos binarios con tamaño de hasta 2 Gb.

Para enviar un mensaje usamos una instancia de la clase Message (un
registro en C++ y en Delphi). Llenamos las propiedades enteras:
Param1, Param2 y MsgCode. MsgCode tiene el mismo significado que en la
mensajería de Windows: se usa para encontrar el manejador correcto en el
arreglo de MessageHandlers dentro de la cola (Queue) destino.

Luego necesitamos adjuntar los datos de nuestra aplicación. Enviamos el
nombre del remitente y el cuerpo del mensaje. Los empaquetamos en una
sola cadena y la empaquetamos a la clase Message.

Un poco más de poesía ahora. MsgConnect puede enviar datos binarios
dentro de un mensaje enviado con los métodos SendMessage*() en una o
ambas direcciones. En otras palabras, puede adjuntar algunos datos;
el destinatario los procesará y adjuntará los datos binarios result-
tantes a la respuesta. Recuerde que en la mayoría de los casos envía
datos en una sola dirección, así que de modo predeterminado la pro-
piedad BinDataType de la clase/registro Message es bdtConst. Si el
destinatario del mensaje debe reemplazar los datos asociados con sus
propios datos y devolverlos, necesitará establecer la propiedad
BinDataType a bdtVar. bdtVar le dice al Messenger que ponga los datos
junto con la respuesta al empaquetar.

OK, hemos creado un mensaje y estamos listos para enviarlo. ¿Cuál de los
métodos PostMessage()/SendMessage*() deberíamos usar? Eso depende de la
forma en que construyamos nuestra aplicación.

La forma más simple es -por supuesto- PostMessage(). Coloca un mensaje
en la cola y regresa inmediatamente. En este caso, el mensaje se envía
en una sola dirección y el mensaje resultado no se devuelve. Sin
embargo, hay una contra en este enfoque: su aplicación nunca sabe si el
mensaje fue realmente enviado. Esto es como un "pager": puede enviar un
mensaje, pero a menos que le pida a su contacto que lo llame inmediata-
mente no sabrá si el mensaje ha sido enviado. Y peor aún, si su contacto
no lo llama no significa que no recibió el mensaje.

Así que SendMessage*() parece una mejor opción. Hay tres funciones
SendMessage*() similares: SendMesage(), SendMessageCallback(), y
SendMessageTimeout(). Todas envían un mensaje e intentan esperar el
resultado, pero los detalles de su comportamiento difieren.

SendMessage() no regresa hasta que el mensaje resultado se recibe u
ocurre un error. Durante la llamada a este método los mensajes de
Windows (donde corresponda) no se procesan y su interfaz de usuario
no se actualizará (a menos que envíe mensajes desde otro hilo, pero
esto va más allá del presente artículo).

SendMessageTimeout() es similar a SendMessage(), con la diferencia que
SendMessageTimeout() regresa incondicionalmente ya sea cuando se recibe
la respuesta o cuando el plazo expira. En realidad, SendMessage se
implementa a través de SendMessageTimeout().

Mientras que SendMessageTimeout() es útil en ciertos casos, hay otros en
que necesitamos otra solución. Ésta es el método SendMessageCallback().
Envía un mensaje y regresa inmediatamente. La aplicación deberá llamar
luego al método DispatchMessages() del Messenger.

Como en Windows, la aplicación debe llamar al método DispatchMessages()
para despachar los mensajes recibidos y llamar los manejadores apro-
piados. DispatchMessages() se usa para recibir tanto mensajes originales
como respuestas. Cuando la aplicación recibe una respuesta, la siguiente
llamada a DispatchMessages llamará la función callback.

Este esquema requiere que la aplicación (a) llame DispatchMessages() de
vez en cuando y que (b) continúe sus operaciones después de que expiró
el tiempo de "timeout". Este requerimiento obliga al uso de un tempori-
zador (timer). El temporizador llama a la función que se usa para llamar
a DispatchMessages() y además lleva la cuenta del tiempo transcurrido
desde que el mensaje se envió.

En nuestro simple chat empleamos un temporizador, tal como mencionamos
arriba. La función callback recibe la notificación acerca del envío y
añade un registro al historial del cuadro memo.

Ahora tenemos descritas todas las partes de la aplicación. Nada ayudará
más que una muestra de código, así que puede ver en lo que hemos
terminado en el ejemplo SendNote.

En la siguiente parte de este artículo crearemos un el diseño completo
de una aplicación de mensajería instantánea con MsgConnect.

________________________________________________________________________

Greatis  Runtime Fusion  incluye  Form Designer  Pro ($ 49.95)  y Object
Inspector Pro ($ 49.95), y  cuesta sólo $89.90  - Ahórrese $10 y obtenga
demos adicionales.  Permita que el usuario  diseñe formularios en tiempo
de ejecución con Runtime Fusion. >>>> http://www.greatis.com/runtime.htm
________________________________________________________________________


4. Modificando los diálogos estándar de Windows
    Modificando controles de los diálogos Abrir/Guardar de Windows

    Por Igor Siticov
        SiComponents: http://www.sicomponents.com


      Pregunta: ¿Cómo cambiar textos como "Nombre de archivo:",
                "Tipo de archivos:" y los textos de los botones
                en los diálogos estándar de Windows?


A veces necesitamos cambiar algún texto u otra cosa en los diálogos
Abrir/Guardar de Windows. Desafortunadamente, los componentes de
diálogos de Delphi no proveen acceso a todos los controles de los
diálogos comunes de Windows, pero podemos realizar esto con la API de
Windows.

El ejemplo de abajo muestra como cambiar el texto de los controles del
diálogo Abrir.

Primero, necesitamos determinar los identificadores de los controles
del diálogo. Estos son los siguientes:

   const
     LB_FILETYPES_ID = 1089;   // etiqueta "Tipo de archivos:"
     LB_FILENAME_ID = 1090;    // etiqueta "Nombre de archivo:"
     LB_DRIVES_ID = 1091;      // etiqueta "Buscar en:"

Segundo, necesitamos enviar un mensaje a la ventana de diálogo para
cambiar los controles deseados; algo como lo siguiente:

   // uses ..., Windows, CommDlg;

   procedure TForm1.OpenDialog1Show(Sender: TObject);
   const
     LB_FILETYPES_ID = 1089;
     LB_FILENAME_ID = 1090;
     LB_DRIVES_ID = 1091;
     Str1 = 'Four';
     Str2 = 'Five';
     Str3 = 'One';
     Str4 = 'Two';
     Str5 = 'Three';
   begin
     SendMessage(GetParent(OpenDialog1.Handle), CDM_SETCONTROLTEXT,
       IDOK, LongInt(Pchar(Str1)));
     SendMessage(GetParent(OpenDialog1.Handle), CDM_SETCONTROLTEXT,
       IDCANCEL, LongInt(Pchar(Str2)));
     SendMessage(GetParent(OpenDialog1.Handle), CDM_SETCONTROLTEXT,
       LB_FILETYPES_ID, LongInt(Pchar(Str3)));
     SendMessage(GetParent(OpenDialog1.Handle), CDM_SETCONTROLTEXT,
       LB_FILENAME_ID, LongInt(Pchar(Str4)));
     SendMessage(GetParent(OpenDialog1.Handle), CDM_SETCONTROLTEXT,
       LB_DRIVES_ID, LongInt(Pchar(Str5)));
   end;

Nota: Los identificadores de los diferentes cuadros de diálogo y sus
valores pueden ser obtenidos importando los recursos de diálogo de
comctrl32.dll en cualquier editor de recursos y viendo estos identi-
ficadores en formato RC.

__________________

Igor Siticov es el autor de TsiLang Components Suite (un completo juego
de componentes para construir en dos minutos aplicaciones multilingües
elegantes, útiles y amistosas con el usuario) y de Resource Builder (un
muy completo editor visual de RC script, ideal para reemplazar al
Borland Image Editor y al Borland Resource WorkShop para crear y editar
archivos de recursos), por SiComponents: http://www.sicomponents.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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


5. Huevo de Pascua de Delphi
    Conozca mejor su Delphi

    Por Bogdan Grigorescu [bogdang@...]
        deGrigg Solutions - www.aiua.ro disponible pronto


                Pregunta: ¿Hay huevos de Pascua en Delphi?


Sé que esta no es la clase de artículos técnicos que Ud. esperaría en
este boletín, pero mucha gente preguntó si no hay "huevos de Pascua" en
Delphi. Aquí va:

1) En Delphi 5 (lo he visto trabajar una edición Enterprise no parchada,
    pero creo que es lo mismo para todas) abra el diálogo About.

2) Mantenga presionada la tecla Alt y escriba JEDI o DEVELOPERS o TEAM
    o QUALITY.

3) Después de una gran palabra DELPHI que se desplaza fuera de la
    pantalla verá:

    - una alabanza al Joint Endeavour of Delphi Innovators (y un enlace a
      su sitio en el diágolo About) o

    - los nombres de los desarrolladores/equipo/QA que hizo de Delphi
      un producto tan bueno

4) Mientras el texto tipo "Gerra de las Galaxias" todavía se mueve,
    puede usar la tecla Abajo (o Arriba) para rotar el texto que se
    mueve hasta darlo vuelta por completo, y ahora verá el mensaje:

     "Use the Source, Luke" (1)

__________________

(1) N. de T.: "Usa el Fuente, Luke",  rima intraducible con
               "Use the Force, Luke" --> "Usa la Fuerza, Luke")

__________________

Nota del Editor: El huevo de Pascua parece estar presente en otras
versiones y ediciones de Delphi, pero hay reportes de excepciones
fatales al tratar de comprobar su existencia. Use bajo su propio riesgo.

________________________________________________________________________


6. Foros / listas de correo


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).
   http://espanol.groups.yahoo.com/group/delphi-abierto
   Suscripción:
     http://espanol.groups.yahoo.com/group/delphi-abierto/join
     delphi-abierto-subscribe@...

* 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@...

* 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@...>


Componentes, librerías y aplicaciones
=====================================


Shareware/Commercial
--------------------

* LMD-Tools 6.1 - por LMD Innovative
   Una librería de más de 300 componentes incluyendo controles para un
   superior diseño de la interfaz, programación de sistema, trabajo con
   archivos y con bases de datos, componentes para Internet, multimedia,
   entrada de texto/datos (RichEdit), visualización de texto con formato
   y mucho más. Las características avanzadas incluyen transparencias,
   efectos de fuentes y fondos, y hasta soporte HTML en varios controles.
   http://www.ceberus.com/lmd/products/lmdtool6/index.php3

* 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


Freeware
--------

* MsgConnect - By EldoS Group and TamoSoft - License: GPL/Commercial
   MsgConnect is a cross-platform protocol-independent communication
   framework designed to simplify the task of building peer-to-peer and
   client-server applications and middleware components. MsgConnect takes
   care of a wide range of low-level technical tasks, letting developers
   concentrate on the business logic of the application.
   http://www.msgconnect.com

* PGP Components for Delphi v3.3.2 - by Michael in der Wiesche (source)
   Provides a direct interface from Delphi 2-7 to PGP 6.5.x, 7.x or 8.x.
   Capabilities: Encode and decode (encrypt/decrypt/sign/verify); Create
   and verify file detached signatures; Import, export, revoke and delete
   keys; Several key management functions; Key generation (DH/DSS, RSA);
   Keyserver functions; Utilities.
   http://home.t-online.de/home/idw.doc/PGPcomp.htm

* TurboPower Async Professional v4.06 - by TurboPower (with source)
   A comprehensive communications toolkit, it provides direct access to
   serial ports, TAPI, and the MS Speech API. It supports fax, terminal
   emulation, VOIP, & more.
   https://sourceforge.net/projects/tpapro/

* TurboPower FlashFiler v2.13 - by TurboPower (with source)
   A client-server database for Delphi and C++Builder. It features a
   component-based architecture and the server engine can be embedded in
   your applications. FlashFiler is easy to configure, performs well and
   includes SQL support.
   https://sourceforge.net/projects/tpflashfiler/

* TurboPower Orpheus v4.06 - by TurboPower (with source)
   An award-winning UI toolkit for Delphi and C++Builder. It contains
   over 120 components covering everything from data entry to calendars
   and clocks. Other components include an Object Inspector, LookOut bar,
   and report views.
   https://sourceforge.net/projects/tporpheus/

* TurboPower Internet Professional v1.15 - by TurboPower (with source)
   A set of VCL components providing Internet connectivity for Delphi and
   C++Builder. Includes POP3, SMTP, NNTP, FTP, HTTP, Instant Messaging
   and HTML viewer as well as components for low-level socket access.
   https://sourceforge.net/projects/tpipro/

* TurboPower Essentials v1.11 - by TurboPower (with source)
   Contains 13 native VCL controls for Delphi and C++Builder. They
   include drop-down calendars and calculators, roll-up dialogs, 3D
   labels, tiled backgrounds, scrolling messages, menu buttons and more.
   https://sourceforge.net/projects/tpessence/

* TurboPower ShellShock v1.02 - by TurboPower (with source)
   Provides a set of components that let you customize applications with
   the functionality available in the Windows Shell and Windows Explorer,
   all without writing code. The components are written in native VCL for
   Delphi and C++Builder.
   https://sourceforge.net/projects/tpshellshock/

* TurboPower LockBox v2.07 - by TurboPower (with source) (DELPHI/KYLIX)
   A cross-platform toolkit for data encryption. It contains routines and
   components for use with Delphi, C++Builder and Kylix. It provides
   support for Blowfish, RSA, MD5, SHA-1, DES, triple- DES, Rijndael and
   digital signing of messages.
   https://sourceforge.net/projects/tplockbox/

* TurboPower B-Tree Filer v5.55 - by TurboPower (with source)
   A fast library of file-based database routines for Turbo Pascal and
   Delphi. Supports stand-alone programs or those running on Microsoft-
   compatible networks including Novell Netware.
   https://sourceforge.net/projects/tpbtreefiler/

* TurboPower OnGuard v1.13 - by TurboPower (with source)
   A library to create demo versions of your Delphi and C++Builder
   applications. Create demo versions that are time-limited, feature-
   limited, limited to a certain number of uses, or limited to a certain
   number of concurrent network users.
   https://sourceforge.net/projects/tponguard/

* TurboPower String Resource Manager v1.0.4 - by TurboPower (w/source)
   A tool for building string resource libraries in Delphi. It prevents
   string resource clashes + simplifies translation of string resources.
   https://sourceforge.net/projects/tpsrmgr/

* TurboPower Async Professional CLX v1.01 - TurboPower (source) (KYLIX)
   A comprehensive communications toolkit for Borland Kylix. It provides
   direct access to serial ports, and supports terminal emulation, file
   transfer protocols and much more.
   https://sourceforge.net/projects/tpaproclx/

* Drag and Drop Component Suite 3.7 - by Angus Johnson and Anders
   Melander (with source)
   Enables COM drag-and-drop of files, folders, text, bitmaps and URLs
   between applications. Copy, move and link operations. Clipboard
   support. Drag image support. Automatic scrolling of the target window
   during the drag operation. Relatively simple to derive custom drag-
   and-drop components to support other data formats.
   http://www.torry.net/vcl/system/draganddrop/dragdrop.exe

* TMPAnimatedCursors - by Markus Stephany (with source)
   A component to manage + use animated cursors within your applications.
   http://www.mirkes.de/en/delphi/vcls.php

* TukangOmong 0.0.1 (with source)
   Indonesia Text-to-Speech Engine.
   http://www.kioss.com/kioss/proyek.php?nama=aTukangOmong


Artículos, trucos y consejos
============================

* IntraWeb: A New Way to the Web - by Cary Jensen
   IntraWeb is a framework and component set that permits you to quickly
   and easily build interactive Web sites using Delphi, Kylix or
   C++Builder and it may very well change the way you develop Web
   applications from now on.
   http://community.borland.com/article/0,1410,29650,00.html

* WebSnap Tips and Tricks - by Nick Hodges
   Nick shares some of his tips and tricks to make WebSnap do the things
   you need it to do.
   http://community.borland.com/article/0,1410,29537,00.html

* Web Services Training: Free Trial! - by Anders Ohlsson
   You may not know this, but Borland has an *awesome* Web Services
   training CD for sale. And a free teaser for it.
   http://community.borland.com/article/0,1410,28381,00.html

* Protect your Delphi Software - by Zarko Gajic
   Want to know more about the issues surrounding the protection of your
   Delphi applications from any unauthorized usage?
   http://delphi.about.com/library/weekly/aa012803a.htm

* "The Big Brother" Delphi Code Toolkit 2 - by Zarko Gajic
   Taking control over the system - the Delphi way. Disabling Windows
   system keys, Windows shell elements - this time using dWinLock Delphi
   component.
   http://delphi.about.com/library/weekly/aa012103a.htm

* Top 6 Testing and Debugging Tools - by Zarko Gajic
   If you're looking for the best Delphi testing and debugging tools,
   look no further. The list contains tools to help you speed up your
   development by finding possible bugs, memory leaks, etc.
   http://delphi.about.com/cs/toppicks/tp/aatpdebug.htm

* Learn the Security Ropes for .NET with this Book - by Lamont Adams
   Review of ".NET Security" by Jason Bock, Pete Stromquist, Tom Fischer,
   and Nathan Smith.
   http://builder.com.com/article.jhtml?id=u00320030109adm01.htm

* How to detect if an application is being debugged - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=214

* How to get the date a file was last accessed - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=215

* Link Label Component - by Daniel Wischnewski
   A simple label component for links to web pages, Email, etc.
   http://www.delphi3000.com/articles/article_3511.asp

* Extract field from DataSet into TStringList - by Stewart Moss
   Component to extract a specific field from a dataset in a TStringList.
   Useful for populating TlistBoxes that you dont want to be data aware.
   http://www.delphi3000.com/articles/article_3512.asp

* D6 + ADO + SQLServer Convert to Oracle Backend ???? - by Hans Pieters
   http://www.delphi3000.com/articles/article_3513.asp

* Save DataSet as CSV Textfile - by Kjetil Rodal-Jalasto
   Procedure that saves the content of a DataSet as a CSV textfile, works
   fine with both BDE and DBExpress datasets.
   http://www.delphi3000.com/articles/article_3514.asp

* Distributed Applications, the easy way II - by Eugene Mayevski
   Is there a way to have a flexible data exchange system and don't go to
   deep into technical details? This second part of the article describes
   basics of MsgConnect usage.
   http://www.delphi3000.com/articles/article_3515.asp

* OLE Drag and Drop Delphi Overview - by Herbert Poltnik
   http://www.delphi3000.com/articles/article_3520.asp

* Multi Socket Port Scanner - by guy gafni
   http://www.delphi3000.com/articles/article_3521.asp

* Adjust a TWinControl's size at RunTime - by quark quark
   http://www.delphi3000.com/articles/article_3523.asp

* Delphi ActiveX/Midas Development Hints - by Herbert Poltnik
   This document provides a basis for developing multi-tier database
   applications that have zero client configuration administration.
   http://www.delphi3000.com/articles/article_3524.asp

* Duplicating a Database Record - by Andrew Baylis
   http://www.delphi3000.com/articles/article_3525.asp

* Pass a recordset from COM object to ASP VBScript - by Bernhard Angerer
   How to return a resultset (dataset) from COM to ASP.
   http://www.delphi3000.com/articles/article_3527.asp

* Messing with other applications memory - by Colin Myerscough
   http://www.delphi3000.com/articles/article_3528.asp

* Creating a system wide shortcut or hotkey - by Jim McKeeth
   http://www.delphi3000.com/articles/article_3529.asp

* How to create a thumbnail from a JPEG image - by Rafael Cotta
   http://www.delphi3000.com/articles/article_3530.asp

* OLE Drag and Drop - by Herbert Poltnik
   How to drop an email from Outlook into a Delphi form.
   http://www.delphi3000.com/articles/article_3533.asp

* Automation Interface Confusions Straightened Out - by Graham Wideman
   Interfaces, dispinterfaces, variants, IDispatch, etc.
   http://www.wideman-one.com/gw/tech/Delphi/autointf/index.htm

* Understanding Delphi COM (OLE) Interface References, AddRef and All
   That - by Graham Wideman
   COM References Reference Counting, AddRef and Release, and a test
   application to demonstrate how it really works.
   http://www.wideman-one.com/gw/tech/Delphi/dragdrop/comrefs/index.htm

* Notes on Delphi Constructors and Destructors - by Graham Wideman
   Constructors and Destructors: Virtual or not?
   http://www.wideman-one.com/gw/tech/Delphi/ConstDest.htm

* Delphi ActiveX Controls: Unusable in MS Office Document Pages - by
   Graham Wideman
   Click and paint Problems when single-component ActiveX control
   inserted is in Office document pages.
   http://www.wideman-one.com/gw/tech/Delphi/dax/index.htm

* Delphi ActiveForm Controls: Clipping bug on scrolled pages ...with
   plausible solution... - by Graham Wideman
   ActiveForm clipping problem in Office document pages.
   http://www.wideman-one.com/gw/tech/Delphi/dax/afxclipbug.htm

* Hardware I/O Port Programming with Delphi and NT - by Graham Wideman
   Delphi I/O Port Programming under Windows NT and an I/O Port Map
   Manipulator driver (gwiopm.sys).
   http://www.wideman-one.com/gw/tech/Delphi/iopm/index.htm

* Precision Timing Under Windows Operating Systems - by Graham Wideman
   Measuring Time, and Scheduling Routines under Windows. Checking the
   Scheduler granularity. Numerous references.
   http://www.wideman-one.com/gw/tech/dataacq/wintiming.htm

* Multitasking discussion - by Graham Wideman
   Basics of Processes, Threads, Time Slices and Priority
   http://www.wideman-one.com/gw/tech/dataacq/multitasking.htm

* Observing the Timing Behavior of Applications in Windows 95/98/NT
   Using LabVIEW - by Graham Wideman
   How well can applications that you write in LabVIEW or other languages
   perform under Windows OSes? Does LV use Special Magic or simply make
   most judicious used of the OS timing services?
   http://www.wideman-one.com/gw/tech/dataacq/labview/index.htm


Tutoriales
==========

* .NET Remoting - by Alain "Lino" Tadros
   This article explains and demonstrates the .NET Remoting framework and
   builds Remotable Objects, Hosting servers and Clients to exercise the
   different activation models.
   http://community.borland.com/article/0,1410,29563,00.html

* Maximize DataSnap efficiency in Delphi - by Bob Swart
   This tutorial is mainly concerned about the data throughput bottleneck
   between the DataSnap Server and Client, including ways to prevent it
   by limiting the amount of data being sent. But, before you can limit
   throughput you have to measure it.
   http://builder.com.com/article.jhtml?id=u00220030117swa01.htm

* Tweak App Performance with Index Tuning Wizard - by Eric Roland
   Debugging is a critical aspect of any development project. SQL Server
   provides the Profiler tool and the Index Tuning Wizard to aid you in
   the search for rogue code in your applications.
   http://builder.com.com/article.jhtml?id=u00320021220ero01.htm

* .NET Demystifies Encryption - by  William Dawson
   .NET makes cryptography a little simpler by putting everything into
   one SDK. Find out how to encrypt and decrypt a text file with the
   System.Security.Cryptography namespace. Code in C# but good tutorial.
   http://builder.com.com/article.jhtml?id=u00220030120wdx01.htm

* OLE Drag and Drop In Delphi - por Graham Wideman
   Comprehensive tutorial with source code examples.
   http://www.wideman-one.com/gw/tech/Delphi/dragdrop/index.htm


Otros enlaces
=============

* Descargas Delphi y Kylix - del Club de Programadores
   Componentes, tutoriales y ejemplos para descargar. También puedes
   subir tu material para compartirlo con otros.
   http://descargas.clubdeprogramadores.com/tema.php?Id=15

* Borland Rolls Out Branding Effort - by Scott Van Camp
   Borland Software Corp., a company considered dead in the water in the
   mid-1990s but now in the midst of a comeback, has launched a $12
   million ad campaign to reintroduce the Borland brand.
   http://www.technologymarketing.com/mc/news/
     article_display.jsp?vnu_content_id=1807206

________________________________________________________________________


¡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@...

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.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
   http://news.optimax.com/topdelphi/links.exe/click?id=70C517ECAE6E
   http://www.top219.org/cgi-bin/vote.cgi?delphi&83
   http://top100borland.com/in.php?who=20
   http://top200.jazarsoft.com/delphi/rank.php3?id=latium
   http://www.programacion.net/votar-enlace.php?id=474

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/descarga/p0043.zip
________________________________________________________________________

Página del grupo:  http://espanol.groups.yahoo.com/group/boletin-pascal/
Para suscribirse / apuntarse:   boletin-pascal-subscribe@...
Para cancelar / removerse:    boletin-pascal-unsubscribe@...
¿Problemas con tu suscripción?      boletin-pascal-owner@...
________________________________________________________________________

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) 2003 por Ernesto D'Spirito. Todos los derechos reservados.
________________________________________________________________________

#9 De: "Ernesto D'Spirito" <edspirito@...>
Fecha: Sáb, 18 de Ene, 2003 4:05 pm
Asunto: Boletín Pascal #42 - 18-ENE-2003
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #42 - 18-ENE-2003

Índice

1. Unas palabras del editor
2. TDataSet => Excel (No se requiere OLE ni EXCEL)
    Clase TDataSetToExcel
3. Aplicaciones distribuidas, la forma fácil (I)
    Como intercambiar datos entre procesos en aplicaciones distribuidas
4. Llamadas a Qt causan problemas de instalación para componentes en el
    IDE BCB de Kylix
5. Inline Assembler en Delphi (VI) - Llamando procedimientos externos
6. Foros / listas de correo
7. Delphi en la Red
    - Componentes, librerías y aplicaciones
      . Shareware
      . Freeware
    - Artículos, trucos y consejos
    - Tutoriales
    - Otros enlaces

________________________________________________________________________

¿Necesitas alojamiento para tu sitio web? http://www.tecnosoftonline.com
________________________________________________________________________


¡Feliz Año Nuevo! Ha transcurrido un largo tiempo desde la última
edición. Lo siento por eso, pero con afán de compensar, al menos para
la primera parte del año habrá dos ediciones del boletín por mes.

Me enorgullece anunciar que el boletín ha alcanzado 7.500 suscriptores,
y quisiera agradecer a todos por haber hecho esto posible, en especial
a quienes recomiendan el boletín a sus colegas o lo votan en los
rankings. A propósito, espero que puedan seguir contribuyendo para que
alcancemos la meta de los 10.000 suscriptores para permitir que esta
publicación pueda continuar. Una forma simple es votando por el boletín
en este ranking:

http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium

Sólo hay que seguir el enlace y hacer clic en "here" ("aquí") donde
dice "Click here to vote!" ("¡Haga clic aquí para votar!"). Eso es todo;
luego aparecerá el ranking de los más votados. Son sólo unos segundos
que significan mucho para nosotros.

Quisiera agradecer a Mike Heydon, Eugene Mayevski y Richard Winston por
contribuir artículos para esta edición, y me complace entregarle a
Eugene Mayevski una licencia de llPDFLib:

* 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/

Para la próxima edición, tenemos disponibles los siguientes premios para
dos de los autores que colaboren artículos en inglés:

* SDL Component Suite 7.0 - por Software Development Lohninger ($99)
   La SDL Component Suite provee un amplio rango de componentes para la
   ciencia y la ingeniería, por ejemplo matemáticas, estadísticas,
   química, diagramas, visualización de datos, transformadas de Fourier
   (FFT), ploteos 3D, mapas geográficos, ajuste de curvas, etc.
   Disponible para Delphi 3-7 y BCB 4-6.
   http://www.lohninger.com/sdlindex.html

* TSDBGridFooter v2.0 por Jovan Sedlan, Shareware ($74.50)
   Este componente es una poderosa herramienta que provee cálculos auto-
   máticos para su DBGrid y muestra información en un pie configurable
   debajo de la grilla. Ha sido diseñado para trabajar con TSDBGrid
   (también incluido), aunque puede usarse con cualquier descendiente de
   TCustomDBGrid.
   http://www.sedlan.com/dbgrid_footer.php

En las noticias, en el sitio web de Borland hay un parche oficial para
Delphi 6, y una actualización de Delphi for .NET preview (disponible
para descarga para los usuarios registrados de Delphi 7). Pueden
encontrar las descripciones y los enlaces correspondientes más abajo
en la sección Delphi en la Red (bajo el título "Otros enlaces").

Espero que disfruten esta edición.

Saludos,

Ernesto D'Spirito
boletin-pascal-owner@...

________________________________________________________________________

Object Inspector 1.2 (por Greatis Software) es un juego de componentes
que incluye un componente especial para acceder a las propiedades y
eventos de cualquier componente, un inspector común que se puede usar
para inspeccionar todo en su aplicación, y un inspector de componentes
listo para usar que imita al Inspector de Objetos del IDE. Admite la
configuración de fuentes y colores. http://www.greatis.com/objinsp.htm
________________________________________________________________________


2. TDataSet => Excel (No se requiere OLE ni EXCEL)
    Clase TDataSetToExcel

    Copyright (c) 2002 Mike Heydon


Esta clase producirá una hoja de cálculo de Excel desde un TDataSet. No
se requiere OLE o que el Excel esté instalado para crear el archivo. El
problema con Excel OLE es que tiende a ser algo lento. La clase usa
funciones estándar de E/S de Delphi y es considerablemente más rápida
que las llamadas OLE.

Ejemplo:

   var
     XL : TDataSetToExcel;
   begin
     XL := TDataSetToExcel.Create(MyQuery,'c:\temp\prueba.xls');
     XL.WriteFile;
     XL.Free;
   end;

Se define el tamaño de las columnas correctamente. Los números son
formateados en "Courier" con formato "###.###.##0,00" para los flotantes
y "0" para los enteros. Las fechas se formatean como "dd-MMM-yyyy
hh:nn:ss". Las cabeceras de las columnas están en negrita y están
recuadradas y sombreadas.

__________________

NOTA DEL EDITOR: Esta clase se provee en la creencia que es de algún
modo útil para algunos propósitos, pero debe advertirse que es sólo una
clase básica y que necesita muchas mejoras. Por ejemplo, el formateado
de las celdas está incrustado en el código, así que la clase no soporta
configuraciones regionales. La clase necesitaría propiedades para varios
formatos de celdas, por ejemplo

    property FormatText : string
    property FormatInt : string
    property FormatFloat : string
    property FormatDateTime : string
    property FormatDate : string
    property FormatTime : string

o métodos de salto de página, propiedades para los colores de las
celdas... ¡la lista es interminable! Por favor no contacten al autor
requiriendo características. La clase se provee "COMO ESTÁ".

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


3. Aplicaciones distribuidas, la forma fácil (I)
    Como intercambiar datos entre procesos en aplicaciones distribuidas

    Por Eugene Mayevski <Mayevski @ eldos.org>


      Hay muchas formas de transferir datos de un proceso a otro.
      Todos esos métodos tienen algunas ventajas, pero también
      algunas desventajas. ¿Hay alguna forma de tener un sistema
      flexible de intercambio de dato sin tener que ahondar en
      los detalles técnicos?


Cuando una aplicación consiste de más de un proceso, uno se ve ante la
cuestión de optimizar las comunicaciones entre estos procesos. Estas
aplicaciones distribuidos incluyen rejillas computacionales, redes
peer-to-peer, aplicaciones cliente-servidor y aplicaciones de negocio
de 3 capas. Todas usan diferentes formas de enviar información a otros
procesos y de recibir respuestas.

Además, hay muchos tipos de aplicaciones comunes que se beneficiarían de
ser divididas en dos o más partes. Éstas son aplicaciones que realizan
tareas de fondo como monitorear sitios web, filtrar tráfico de Internet,
revisar archivos y correo en busca de virus, por citar algunas. Usual-
mente la lógica de negocio puede ser fácilmente separada de la interfaz
de usuario, y la interfaz de usuario puede ser cargada baja petición.

Todas estas aplicaciones tienen algo en común. Esto es la necesidad de
proveer alguna forma de intercambio de datos entre las diferentes partes
de la aplicación.

Hay muchas formas de intercambio de datos, que se usan en diferentes
situaciones. Las más frecuentemente usadas en el mundo de Windows son
(comenzando por la más simple):

   1) Mensajes de Windows;
   2) Mailslots de Windows;
   3) Archivos mapeados en memoria (Memory-mapped files - MMF);
   4) Sockets TCP o UDP;
   5) COM/DCOM

Cada uno de estos métodos tiene sus propias ventajas. Los mensajes de
Windows son muy fáciles de usar y de trabajar con ellos. Los mailslots
son bastante como los mensajes de Windows pero funcionan en redes
locales. Los archivos mapeados en memoria son una forma rápida y
relativamente fácil de intercambiar datos cuando uno no puede trabajar
con manejadores (handles) de ventana (por ejemplo servicios y aplica-
ciones de consola). Los sockets son universales y multiplataforma.
COM/DCOM está orientado a objetos y es de bastante alto nivel.

Sin embargo, cada uno de esos métodos tiene sus propias desventajas.
COM, los mensajes de Windows y los archivos mapeados en memoria sólo son
utilizables dentro de la misma computadora (los archivos mapeados en
memoria se pueden abrir desde unidades de red, pero no se garantiza la
integridad y actualidad de los datos). Los mailslots y los sockets UDP
no son confiables (esto significa que cuando uno envía datos no puede
fácilmente preguntar si el receptor recibió los datos exitosamente).
Los sockets TCP se pueden usar en una amplia variedad de escenarios,
pero hay un problema: sólo trabajan con corrientes (streams), quedando
a cargo de nuestra aplicación dividir las corrientes de datos en bloques
de datos y procesar estos bloques. DCOM es una solución sofisticada que
es muchas veces difícil de instalar y mantener, y se transforma en una
pesadilla cuando comenzamos a tratar con la seguridad.

No hace decir que todos los métodos descritos, excepto los sockets (y
caras implementaciones DCOM de terceros creadas para sistemas basados
en Unix), son sólo para Windows. Si uno crea una aplicación que debería
trabajar no sólo en la plataforma Windows, quedaría limitado a los
sockets.

Los sockets son una solución poderosa al permitirnos controlar casi
todos los aspectos del envío de datos – como y cuando se envían los
datos, cuanto tiempo la aplicación espera una respuesta, y otras cosas.
Un aspecto negativo de esta flexibilidad es que uno DEBE controlar estos
aspectos (tal vez no todos, pero la mayoría de ellos).

Volvamos a los mensajes de Windows. Son realmente simples – una
estructura con varios campos que pueden ser llenados y enviados al
receptor con una llamada. Y cuando uno necesita pasar un bloque de
datos, puede usar el mensaje WM_COPYDATA. "Qué lindo sería si hubiera
métodos que usan la misma técnica tanto en la misma computadora como a
través de redes", Ud. puede pensar. Nosotros pensamos lo mismo. Desa-
fortunadamente, no es posible... Bueno, hasta ahora.

Ahora puede combinar la simplicidad del sistema de mensajes de Windows
con el poder y la flexibilidad de la comunicación por sockets o de los
archivos mapeados en memoria usando el armazón MsgConnect.

MsgConnect encapsula las operaciones de bajo nivel usadas para esta-
blecer comunicación e intercambiar información, y provee una API simple
API que se parece mucho al sistema de mensajes de Windows. La secuencia
de acciones necesarias para agregar comunicaciones multiplataforma a su
aplicación puede caber en 20 líneas de código:

1) crear una instancia del objeto Messenger (usado para enviar un
    mensaje);
2) crear una instancia del objeto Transport (usado para enviar mensajes
    a los receptores. Necesitará una instancia de Transport por cada
    transporte que use, ya sea sockets o MMF);
3) crear una instancia del objeto Queue (usado para recibir mensajes);
4) vincular estos objetos con un par de llamadas a métodos;
5) definir un manejador para el evento que se dispara cuando se recibe
    un mensaje.

Eso es todo. Ya puede comenzar a enviar y recibir mensajes.

¿Por qué usar MsgConnect es más fácil que usar formas convencionales de
comunicación?

Antes que nada, MsgConnect oculta los detalles, pero los mantiene
disponibles para usar. El armazón le permite ajustar los objetos de
transporte para alcanzar el máximo rendimiento para cualquier tipo de
aplicación, desde mensajería convencional hasta pesado intercambio de
datos. Si no quiere ahondar en los detalles, MsgConnect funcionará
perfectamente con la configuración predeterminada.

Por supuesto, necesitará diseñar el protocolo, es decir, definir que
mensajes se usan para diferentes propósitos en su aplicación, y esto
será una parte de la lógica de negocios de su aplicación. No necesita
excavar en los detalles de la implementación del protocolo TCP o
administrar la seguridad para los MMF.

La segunda cosa es que que el intercambio de mensajes es universal. Con
MsgConnect el mensaje puede contener cualquier dato binario y el
receptor puede cambiar este bloque de datos y devolverlo con el mismo
mensaje. En otras palabras, los lados del intercambio de datos pueden
hacer transferencia de datos ida y vuelta con apenas un mensaje. El
resultado es que MsgConnect se puede utilizar tanto en comunicaciones
unidireccionales como bidireccionales sin limitaciones.

La tercera ventaja es que para cambiar la comunicación de computadora
local a remota sólo necesita agregar otro objeto Transport y cambiar la
dirección a la que serán enviados los mensajes. No necesita implementar
otro algoritmo o manejar otro algoritmo de bajo nivel.

Cuarto, su aplicación puede intercambiar información con aplicaciones
que funcionen en diferentes plataformas. MsgConnect soporta un amplio
rango de plataformas (actualmente Windows, Windows CE, Linux, Unix,
Java, .NET y más por venir en el futuro cercano).

Y último pero no menos importante, si usted desarrolla un proyecto de
código abierto o un gran sistema propietario, MsgConnect tiene una
licencia conveniente para usted. Está disponible como código abierto y
provee servicios adicionales para los usuarios que obtengan la
licencia comercial.

__________________


MsgConnect es un proyecto conjunto de EldoS Group (http://www.eldos.org)
(http://www.eldos.org) y TamoSoft (http://www.tamos.com), y se puede
obtener gratis con código fuente completo en http://www.msgconnect.com
(ya sea bajo la licencia GPL o una licencia de Evaluación, actualizable
a una licencia Comercial).

________________________________________________________________________

Greatis  Runtime Fusion  incluye  Form Designer  Pro ($ 49.95)  y Object
Inspector Pro ($ 49.95), y  cuesta sólo $89.90  - Ahórrese $10 y obtenga
demos adicionales.  Permita que el usuario  diseñe formularios en tiempo
de ejecución con Runtime Fusion. >>>> http://www.greatis.com/runtime.htm
________________________________________________________________________


4. Llamadas a Qt causan problemas de instalación para componentes en el
    IDE BCB de Kylix

    Por Richard Winston


       Resumen: Si un componente escrito en Delphi realiza una
       llamada a Qt, instalar el componente en el IDE de Kylix
       BCB puede ser difícil. Este artículo describe como superar
       este problema.


Tuve problemas con un componente que escribí que usaba llamadas a Qt.

El procedimiento que causaba los problemas escribía Texto en la
ubicación (X,Y) con el ángulo especificado en Angulo usando el siguiente
código:

   Uses Qt, QGraphics;

   procedure TRbwRegla.PintarRotado(const X, Y, Angulo: double;
     const Texto: string);
   begin
     Canvas.Start;
     QPainter_translate(QPainterH(Canvas.Handle),X,Y);
     try
       QPainter_rotate(QPainterH(Canvas.Handle),Angulo);
       try
         Canvas.TextOut(0,0,Texto);
       finally
         QPainter_rotate(QPainterH(Canvas.Handle),-Angulo);
       end;
     finally
       QPainter_translate(QPainterH(Canvas.Handle),-X,-Y);
       Canvas.Stop;
     end;
   end;

Esto funcionaba bien en el IDE de Kylix Delphi, pero no compiló en el
IDE de Kylix C++. Los mensajes de error fueron:

   [Linker Error] Unresolved external 'Qt::QPainter_translate(
   QT::QPainter *, double, double)' referenced from QrbwRuler.o

y

   [Linker Error] Unresolved external 'Qt::QPainter_rotate(
   QT::QPainter *, double, double)' referenced from QrbwRuler.o

Pude escribir un componente similar en el IDE de Kylix C++ usando código
como este:

   void __fastcall TRbwRegla::PintarRotado(const double X, const double
     Y, const double Angulo, const AnsiString Texto)
   {
     Canvas->Start();
     Qt.QPainter_translate((QPainter__*)Canvas->Handle,X,Y);
     __try
     {
       Qt.QPainter_rotate((QPainter__*)Canvas->Handle,Angulo);
       __try
       {
         Canvas->TextOut(0,0,Texto);
       }
       __finally
       {
         Qt.QPainter_rotate((QPainter__*)Canvas->Handle,-Angulo);
       };
     }
     __finally
     {
       Qt.QPainter_translate((QPainter__*)Canvas->Handle,-X,-Y);
       Canvas->Stop();
     };
   }

Logré obtener componentes que trabajaran en ambos IDE declarando un
procedimiento virtual abstracto y luego declarando dos nuevos
componentes - uno para cada IDE - y sobreescribiendo (overriding) ese
procedimiento abstracto con el código que funcione en ese IDE.

Sin embargo, si se desea usar herencia de formularios visual en el IDE
de C++ para heredar de formularios creados en el IDE de Delphi, esto no
funciona. Podía ver estos formularios en el IDE, pero cuando trataba de
compilar el proyecto, reportaba errores del enlazador. Esto parecía
deberse a que las versiones Delphi y C++ del componente en realidad no
fueran la misma cosa, aún si tenían idénticos nombres y funcionalidad.

Esta es realmente la misma clase de problema que estaba intentando
evitar al crear los dos componentes en primer lugar. El IDE de C++ y el
de Delphi parecen necesitar diferentes versiones de QPainter_translate y
QPainter_rotate. El IDE de Delphi parece querer las que están declaradas
en Qt.pas mientras que el IDE de C++ parece querer las que están
declaradas en qpainter.hb.

Mi solución final fue instalar el componente en el IDE C++ como un
paquete.

   Seleccionar Component|Install Packages...
   Hacer clic en el botón Add...
   Seleccionar un archivo *.so generado por el IDE de Delphi.
   Hacer clic en el botón Open.
   Hacer clic en el botón OK.

Por cada paquete, necesitamos generar un archivo *.a:

   File|CloseAll
   File|New|Other|Library
   File|Save Project As... y guardar con mismo nombre raíz que al archivo
     paquete para el IDE de Delphi
   Project|Add to Project
   Seleccionar el archivo *.so
   File | Save All
   Ahora estamos listos para realmente construir la librería:
   Project | Build
   Click the OK button.

__________________

Richard Winston desarrolla interfaces gráficas para programas de
modelado de aguas subterráneas para el U.S. Geological Survey.

________________________________________________________________________

¿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!"
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
Sólo hay que seguir el enlace y hacer clic en "here" ("aquí") donde dice
"Click here to vote!" ("¡Haga clic aquí para votar!"). Luego aparecerá
el ranking de los más votados. Su voto significa mucho para nosotros.
________________________________________________________________________


5. Inline Assembler en Delphi (VI) - Llamando procedimientos externos


Funciones API y la convención de llamadas Stdcall
=================================================

Las funciones API se llaman transparentemente desde inline assembler con
la sentencia CALL. Sin embargo debemos tener en cuenta que el paso de
parámetros a las funciones API es diferente puesto que normalmente usan
la convención de llamadas Stdcall, en vez de la convención de llamadas
Register, que es la que hemos visto hasta ahora por ser la convención
predeterminada.

En la convención de llamadas Stdcall, todos los parámetros se pasan en
la pila, de derecha a izquierda, es decir, el último parámetro (el de la
derecha) se empuja primero, y el primer parámetro (el de la izquierda)
se empuja último, de modo que será el que quede arriba de la pila. He
aquí un ejemplo de un procedimiento que llama a una función API:

   procedure OcultarFormulario(Handle: THandle);
   // Windows.ShowWindow(Handle, SW_HIDE);
   asm
     push SW_HIDE               // push 0    // Pasa el 2do parámetro
     push Handle                // push eax  // Pasa el 1er parámetro
     call Windows.ShowWindow    // Llama a la API ShowWindow
   end;

Si tenemos que llamar a un método que use la convención stdcall,
recordemos que el puntero Self es un primer parámetro invisible, así que
sería empujado al último en la pila.

Si tenemos que escribir funciones que usen la convención stdcall, no hay
nada especial de lo que debamos preocuparnos. El compilador siempre crea
un marco de pila (stack frame) y las referencias a nombres de parámetros
se convierten en direcciones relativas al puntero base (EBP):

   function SumarYMultiplicar(i1, i2, i3: integer): integer; stdcall;
   asm  // ==> push ebp; mov ebp, esp
     // Result := (i1 + i2) * i3;
     mov eax, i1   // mov eax, [ebp+8]
     add eax, i2   // add eax, [ebp+12]
     imul i3       // imul [ebp+16]
   end; // ==> pop ebp; ret 12

Esta es una llamada de ejemplo a la función:

   asm
     // a := SumarYMultiplicar(1, 2, 3); // el resultado debería ser 9
     push 3 // primero se empuja el último parámetro
     push 2
     push 1
     call SumarYMultiplicar
     mov a, eax
   end;

Tras entrar a la función, la pila se vería así:

   |                |
   +----------------+
   |   Viejo EBP    |  [EBP], [ESP]
   +----------------+
   | Dir.de Retorno |  [EBP+4]
   +----------------+
   |     i1 = 1     |  [EBP+8]
   +----------------+
   |     i2 = 2     |  [EBP+12]
   +----------------+
   |     i3 = 3     |  [EBP+16]
   +----------------+
   |                |


Librerías C/C++ y la convención Cdecl
=====================================

A veces necesitamos acceder a funciones en archivos objeto (.OBJ),
librerías estáticas (.LIB) o librerías dinámicas (.DLL) escritas en C o
C++, y bastante frecuentemente estas funciones usan la convención de
llamadas Cdecl. Es muy parecida a la convención Stdcall, pero la pila
debe ser limpiada por el llamador, es decir, el llamador debe hacer
"pop" a los parámetros que empujó en la pila, o -mejor aún- incrementar
el puntero de pila.

   function SumarYMultiplicar(i1, i2, i3: integer): integer; cdecl;
   asm  // ==> push ebp; mov ebp, esp
     // Result := (i1 + i2) * i3;
     mov eax, i1   // mov eax, [ebp+8]
     add eax, i2   // add eax, [ebp+12]
     imul i3       // imul [ebp+16]
   end; // ==> pop ebp; ret

Nótese en el comentario de la última línea que la función no mueve el
puntero de pila como lo hizo en el ejemplo anterior que usaba la
convención Stdcall, de modo que el llamador es quien es responsable de
ello. Esta es una llamada de ejemplo para la función:

   asm
     // a := SumarYMultiplicar(1, 2, 3); // el resultado debería ser 9
     push 3 // primero se empuja el último parámetro
     push 2
     push 1
     call SumarYMultiplicar
     add esp, 12           // limpiar la pila
     mov a, eax
   end;

Obsérvese que si los parámetros fueran de tipo Byte en vez de Integer,
aún así deberíamos mover el puntero de pila en 12 bytes pues cada uno de
los tres parámetros igual tomaría 32 bits (4 bytes).


La convención de llamadas Pascal
================================

Muchos programadores en C/C++ prefieren la convención de llamadas Pascal
por sobre la convención de llamadas Cdecl porque es más compacta y
también rápida puesto que la función llamada limpia la pila en la
sentencia RET, tal como también sucede en la convención Stdcall. La
convención Pascal es como la convención Stdcall, pero los parámetros se
pasan de izquierda a derecha en vez de derecha a izquierda, es decir,
el primer parámetro (el de la izquierda) se empuja primero, y el último
parámetro (el de la derecha) se empuja último:

   function SumarYMultiplicar(i1, i2, i3: integer): integer; pascal;
   asm  // ==> push ebp; mov ebp, esp
     // Result := (i1 + i2) * i3;
     mov eax, i1   // mov eax, [ebp+16]
     add eax, i2   // add eax, [ebp+12]
     imul i3       // imul [ebp+8]
   end; // ==> pop ebp; ret 12

Nótese que las direcciones de los parámetros se traducen de manera
diferente que en los ejemplos anteriores.

Este es un ejemplo de llamada a la función:

   asm
     // a := SumarYMultiplicar(1, 2, 3); // el resultado debería ser 9
     push 1  // primero se empuja el primer parámetro
     push 2
     push 3
     call SumarYMultiplicar
     mov a, eax
   end;

Tras entrar a la función, la pila se vería así:

   |                |
   +----------------+
   |   Viejo EBP    |  [EBP], [ESP]
   +----------------+
   | Dir.de Retorno |  [EBP+4]
   +----------------+
   |     i3 = 3     |  [EBP+8]
   +----------------+
   |     i2 = 2     |  [EBP+12]
   +----------------+
   |     i1 = 1     |  [EBP+16]
   +----------------+
   |                |

________________________________________________________________________


6. Foros / listas de correo


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).
   http://espanol.groups.yahoo.com/group/delphi-abierto
   Suscripción:
     http://espanol.groups.yahoo.com/group/delphi-abierto/join
     delphi-abierto-subscribe@...

* 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@...

* 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@...>


Componentes, librerías y aplicaciones
=====================================


Shareware/Commercial
--------------------

* 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


Freeware
--------

* ConvertFiles - por Dennys dos Santos Sobrinho
   Asistente para migrar aplicaciones VCL de Delphi a CLX de Kylix.
   http://www.delphibr.com.br/artigos/ConvertFiles.php

* HalZip - por Alirio A. Gavidia B. <alirio@...>
   Clon de WinZip en español, con búsqueda, "shceduler" (programador de
   tareas) que permite realizar respaldos automáticos, "drag & drop"
   (arrastrar y soltar) desde el Explorador de Windows, asociaciones de
   archivo, y capacidad de partir un archivo en múltiples archivos y de
   unirlos nuevamente.
   http://www.gavidia.org/halzip/

* ImageFileLib v1.00 - by Michael Vinther (with source)
   With this library, Delphi programs can read and write JPEG 2000, PNG,
   ICO, CUR and PCX images. RAS, PNM, PGM, PPM, HIPS images can be loaded
   but not created. Both lossy and lossless coding of JPEG 2000 images
   are supported. In this library also provides support for 24 bit and
   256 color palette icons and cursors.
   http://www.logicnet.dk/lib/

* TBalloonControl v1.0 - by JWB Software (with source)
   The TBalloon component provides an easy interface to balloon-shaped
   tooltips which appear more and more in modern software. You can
   choose to attach a balloon-window to a control, but you can also place
   it anywhere on your desktop, just define the coordinates of the point.
   http://people.zeelandnet.nl/famboek/delphi/balloon.html

* TMSNPopUp v5.0 - by JWB Software (with source)
   The TMsnPopUp component is created to mimic the behavior of the popup
   windows that can be seen in MSN/Windows Messenger from Microsoft. But
   it even gets better, because TMsnPopup is fully customizable, so you
   can give it your own look and feel.
   http://people.zeelandnet.nl/famboek/delphi/msnpopup.html

* TXMLSerializer v2.0 - by JWB Software (with source)
   The TXMLSerializer component can save Delphi objects and components to
   disk in XML-format. Being an open format, XML has many advantages, it
   is a good way to save information in a readable form. You can even
   save complete forms as XML-files.
   http://people.zeelandnet.nl/famboek/delphi/xmlserializer.html

* Delphi SmartCard Component v0.91 - by N Hüttisch (with source)
   Access any SmartCardReader which has drivers for the Microsoft
   SmartCard API (PC/SC) from Delphi. Easy-to-use routines to find the
   reader, to get informed if a card is inserted/removed and to send and
   receive data to / from the reader.
   http://www.nobbi.com/download.htm#delphi

* WinTab Interface + Sample Component v1.0 - by Qr Li (with source)
   Delphi API translation for WinTab, the standard pointing device
   interface to support tablets.
   http://www.torry.net/vcl/system/otherhardware/wintab32.zip

* WallSwap v1.1 - by Conspiracy Software (Delphi source on request)
   WallSwap, the automatic wallpaper changer for Windows. Give WallSwap a
   list of files or point it at an entire directory of pictures and it
   will automatically cycle your Windows desktop background through them.
   Features include: Support for bmp, gif, jpeg and PNG images; Center,
   Stretch or Tile your wallpaper; Use HTML web pages as your wallpaper;
   Change wallpaper every time or once daily; Compatible with Active
   Desktop. TopQualityFreeware.com Rating 5/5!
   http://www.winsite.com/bin/Info?6500000036556

* ClassExplorer Pro - by toolsfactory (with source)
   ClassExplorer Pro dramatically simplifies the development process by
   adding perfectly integrated code navigation, code creation and code
   documentation capabilities to your Delphi development environment.
   http://www.toolsfactory.com/download.shtml

* deBold v2.2 - by Droopy Eyes Software (with source)
   These components make development with Bold for Delphi simpler. Bold
   is the MDA (Model Driven Architecture) product which was recently
   acquired by Borland and included with some versions of Delphi 7. These
   components are based on this framework and help the developer to
   perform automatic object validation, etc.
   http://www.droopyeyes.com/default.asp?mode=ShowProduct&ID=12

* DIB Controls v1.16 - by Droopy Eyes Software (with source)
   DIB Controls are a set of native Delphi VCL components based around a
   very fast DIB drawing engine (Device Independant Bitmap). The drawing
   engine utilises inline assembly language for optimum speed. This speed
   allows these features: Real-time zooming; Real-time rotation; Real-
   time alpha masking; 3 x 3 matrix filter (blur, sharpen, emboss, etc).
   http://www.droopyeyes.com/default.asp?mode=ShowProduct&ID=3

* FastStrings v2.6 - Droopy Eyes Software (with source) (DELPHI/KYLIX)
   A set of string routines for manipulating large strings at high speed.
   Includes Boyer-Moore searching algorithm, backwards string searching
   and a very high-speed alternative for StringReplace.
   http://www.droopyeyes.com/default.asp?mode=ShowProduct&ID=4

* Inno Setup v3.0.6 - by JR Software (with source)
   A free installer for Windows programs that rivals and surpasses many
   commercial installers in feature set and stability. Features include:
   Support for all 32-bit Windows versions; Creation of a single EXE or
   disk spanning; Standard wizard interface, including Win2k/XP style;
   Customizable setup types; Complete uninstall capabilities; Zip / bzip2
   compression; Creation of shortcuts, registry and .INI entries; Silent
   install and uninstall.
   http://www.jrsoftware.org/isinfo.php

* SQLyog v2.51 - by webyog
   SQLyog is an easy to use, compact and fast graphical tool to manage
   your MySQL database anywhere in the world. SQLyog was developed keep
   in mind the necessities of all who use MySQL as their preferred RDBMS.
   Whether you enjoy the control of handwritten SQL or prefer to work in
   a visual environment, SQLyog makes it easy for you get started and
   provides you with tools to enhance your MySQL experience.
   http://www.webyog.com/sqlyog/


Artículos, trucos y consejos
============================

* Overview of the VCL for .NET - by J Kaster, E Churchill and D Thorpe
   This article provides an overview of the architecture, design, and
   intent of the VCL for .NET included with the Delphi for .NET preview.
   http://community.borland.com/article/0,1410,29460,00.html

* Building + Running Delphi for .NET projects using DLite - by M. Binder
   The Delphi for .NET preview included with Delphi 7 gives us a peek at
   the .NET world from the Delphi point of view. This article shows how
   to use DLite to help you build and run your Delphi for .NET projects.
   http://community.borland.com/article/0,1410,29077,00.html

* How To Use Scanlines - by Leonel Togniolli
   This article shows a fast way to manipulate bitmaps without using the
   canvas : the scanlines.
   http://community.borland.com/article/0,1410,29173,00.html

* Using Web Services with the Delphi for .NET preview command-line
    compiler - by Bob Swart
   This article shows how you can use existing Web Services with the
   preview command-line compiler Delphi for .NET.
   http://community.borland.com/article/0,1410,29486,00.html

* Get TreeView Node By Text - by Zarko Gajic
   How to locate (search and select) a TreeView node given by node text.
   http://delphi.about.com/library/weekly/aa010703a.htm

* Dephi components to access MySQL - by Zarko Gajic
   Overview of VCL components allowing you to access a MySQL database from
   Delphi using standard data controls without using BDE/ADO/ODBC. Plus a
   few MYSQL related tools.
   http://delphi.about.com/cs/toppicks/tp/aatpmysql.htm

* Exchanging Data over the Network - by Zarko Gajic
   Examine two Delphi components: TServerSocket and TClientSocket both
   designed to let you read and write information over TCP/IP - thus
   enabling you to write network-aware applications.
   http://delphi.about.com/library/weekly/aa112602a.htm

* Conspiracy Theory: .NET IS Borland's
   Is it possible that the whole .NET framework is Borland's idea?
   http://delphi.about.com/library/weekly/aa112902a.htm

* How to encode / decode Base64 string?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1524

* How to get the Internet Explorer typed urls?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1521

* How to use URL highlighting in TRichEdit?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1505

* How to show the select directory dialog and specify initial directory?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1509

* How to make a flickerless animation using CopyRect?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1536

* How to zoom the view of a TWebBrowser?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1537

* How to follow the mouse in TMemo to set the cursor position?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1538

* How to show a indeterminate ProgressBar in Win XP with PBS_MARQUEE?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1541

* How to install Kylix when error -10 popups up - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=206

* How to register Kylix - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=207

* How to get an screen shot of a control - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=208

* How to move components at runtime - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=209

* How to use function overloading - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=210

* How to enter a NULL value - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=211

* How to copy your own application - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=212

* How to change the database name - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=213

* Save a webpage with images - by Ken Wilcox
   Ever wanted to duplicate the functionality of your browser and save a
   web page with images to disk? This example that does just that and you
   can pass in a progress bar to show the status of the operation.
   http://www.delphi3000.com/articles/article_3464.asp

* MS Exchange API via Collaboration Data Objects - by Mike Heydon
   This is a vast subject that is beyond the scope of this article to
   fully detail here. This library provides the basic building blocks for
   someone who wants to develop using CDO.
   http://www.delphi3000.com/articles/article_3467.asp

* How to Build Aggregate/Composite Components in Delphi - by Mark Miller
   http://www.delphi3000.com/articles/article_3468.asp

* Handling Winsock errors - by Herbert Poltnik
   http://www.delphi3000.com/articles/article_3469.asp

* Getting a Mac Address - The JEDI way - by Michael Brooks
   How to get the Mac Address for the local Windows PC (and possibly
   other computers on the LAN) without writing/translating a lot of code
   or relying completely on NetBios support.
   http://www.delphi3000.com/articles/article_3470.asp

* Add Link to MsgBox (Updated) - by Fu-Hun-Ru Kaje-Ja
   http://www.delphi3000.com/articles/article_3473.asp

* Building Real-Life Web Services - by Marc Hoffmann
   How to build a 'real-world' Web-Service with mixed method calls,
   data-aware connections, user-authorisation and session support.
   http://www.delphi3000.com/articles/article_3474.asp

* TDataSet => Excel (No OLE or EXCEL required) - by Mike Heydon
   This class will produce an Excel Spreadsheet from a TDataSet. No OLE
   or Excel Installation is needed to create the file. The problem with
   Excel OLE is that it tends to be rather Sloooow. This class uses
   standard Delphi I/O functions and is considerably faster than the OLE.
   http://www.delphi3000.com/articles/article_3475.asp

* Bmp into StatusBar - by Rodrigo Poli
   http://www.delphi3000.com/articles/article_3476.asp

* Introductory Principles of Indexed Searching - by Jim McKeeth
   Describe the principles of an Indexed search engine (like google). How
   this works when a lot of text information is compressed into an index
   - so that a search can be done within a very short time.
   http://www.delphi3000.com/articles/article_3479.asp

* WebSnap II: Interacting with the User - by Eber Irigoyen
   This article shows one way to allow the user to enter some data and
   use that to query your database.
   http://www.delphi3000.com/articles/article_3481.asp

* Distributed applications, the easy way (I) - by Eugene Mayevski
   There are many ways of transferring data from one process to another.
   All those methods have some advantages, but also some drawbacks...
   http://www.delphi3000.com/articles/article_3489.asp

* GetDocumentation for Type Library - by Nik Ozniev
   How get the Help String for a Type Library.
   http://www.delphi3000.com/articles/article_3490.asp

* Calls to Qt cause installation problems for components in
    Kylix BCB IDE - by Richard Winston
   If a component written in Delphi makes a call to Qt, installing it in
   the Kylix BCB IDE can be difficult. This article describes how to
   overcome this problem.
   http://www.delphi3000.com/articles/article_3491.asp

* Getting an exe File Type - by Lutfi Baran
   http://www.delphi3000.com/articles/article_3496.asp

* Call a Procedure in an MDI Child - by Moof Foof
   How do I call a procedure or function in an MDI child when Delphi
   keeps telling me that TForm is not compatible with my TChildForm?
   http://www.delphi3000.com/articles/article_3498.asp

* Build a Table Tree from Records to Objects - by Max Kleiner
   How to show a database self join in a TreeView.
   http://www.delphi3000.com/articles/article_3499.asp

* How to Prevent an Application Being Closed by User - Manfred Suesens
   http://www.delphi3000.com/articles/article_3501.asp

* Balloon Tooltips - by Calin Marinescu
   http://www.delphi3000.com/articles/article_3504.asp


Tutoriales
==========

* Under Construction: Delphi, dbExpress And MySQL - by Bob Swart
   The BDE has had its day but some of the alternatives seem very costly
   (SQL Server at £1,612 for a 10-client standard version?). So this
   article looks at MySQL to see how easy it is to use with Delphi. Oh,
   and it's either free or cheap, depending on the licence you choose!
   http://www.thedelphimagazine.com/Samples/1540/1540.htm

* DotNet Buzz Words Explained - by Alain "Lino" Tadros
   This article will explain the different buzz words in the DotNet world
   like CTS, CLS, VES, Managed Code, Managed Data, Unmanaged Code,
   Assemblies, Metadata, Manifest, Strong Names, etc....
   http://community.borland.com/article/0,1410,29344,00.html

* Write your own Reflector - by Alain "Lino" Tadros
   Want to write your own "ILDASM" or ".NET Reflector"? Start here by
   seeing how easy it is to get RTTI from .NET Assemblies.
   http://community.borland.com/article/0,1410,29423,00.html

* Cloning ClientDatSet Cursors - by Cary Jensen
   When you clone a ClientDataSet cursor you create an additional pointer
   to a shared memory store and also an independent view of the data.
   This article shows you how to use this important capability.
   http://community.borland.com/article/0,1410,29416,00.html

* Object Destructors and Finalizers in .NET Using C# and Delphi for .NET
    - by Brian Long
   This in-depth article looks at the role and usage of destructors (or
   equivalent) in the managed world of .NET. It examines in detail the
   areas of garbage collection, finalizers, the dispose pattern and
   language specifics, using both C# and Delphi for .NET.
   http://community.borland.com/article/0,1410,29365,00.html

* Memory: from VCL via VCL for .NET to .NET - by Bob Swart
   How to migrate a VCL application (the game of Memory) to VCL for .NET
   and finally to WinForms on .NET, all using the Delphi for .NET Preview
   command-line compiler.
   http://community.borland.com/article/0,1410,29320,00.html

* Hanging by a WebSnap Thread - by Nick Hodges
   Covers the basics of webmodule threading in both WebSnap and WebBroker
   as well as some strategies for dealing with the traps it can create.
   http://community.borland.com/article/0,1410,29300,00.html

* Cleaning Your Delphi Code Errors - by Zarko Gajic
   A Beginner's Guide to Delphi Programming: Chapter 9. A discussion on
   Delphi design, run and compile time errors and how to prevent them.
   Also, take a look at some solutions to most common logic errors.
   http://delphi.about.com/library/weekly/aa121002a.htm

* Send Binary Data in XML - by Brian Schaffner
   XML is generally thought of as a method for describing data using
   text. For example, elements are given text names, and element contents
   are usually text-based. There are times, however, when you'll want to
   put data other than text into your XML documents.
   http://builder.com.com/article.jhtml?id=u00220021127sch01.htm

* Build and Customize Modular XML to Simplify XML Documents - E. Tittel
   Developers have been working with objects + modules for some time but
   now XHTML 1.1 introduces this concept to the XML world. Find out more
   about this important advancement and how to put it to use in your XML
   documents.
   http://builder.com.com/article.jhtml?id=u00320021210edt01.htm

* Pass Parameters to XSL Templates Programmatically - Brian Schaffner
   Imagine you have a list of items in an XML document that you display
   to a user on a Web page. Users will select which column they want to
   sort on and the order of the sort. Using XSL to convert your XML
   document to HTML might sound complicated but passing parameters to the
   XSL template that performs the conversion is easier than you think.
   http://builder.com.com/article.jhtml?id=u00220021212sch01.htm

* Best Practices to Enhance Your SQL Server Applications - Roy Hoobler
   Get the most out of your development efforts by familiarizing yourself
   with SQL Server. Follow these guidelines to build better applications.
   http://builder.com.com/article.jhtml?id=u00320021212RCH01.htm

* Heavyweight vs. Lightweight Methodologies - by Jason P. Charvat
   In software development "lightweight" methodologies are gaining ground
   on more traditional "heavyweight" methodologies. Both have advantages
   and disadvantages and which one you choose depends on your needs. This
   article examines some key differences between them.
   http://builder.com.com/article.jhtml?id=u00420021016vat01.htm

* Find + Dissect Errors with SQL Server's Bug Hunter - by Tony Patton
   Debugging is a necessary evil of software development and tools are
   available to make the process less painful. Microsoft provides the SQL
   Server Debug Interface to streamline SQL development.
   http://builder.com.com/article.jhtml?id=u00320021212ton01.htm


Otros enlaces
=============

* Delphi 6 Update: official run-time patch is available
   official patch that fixes some variant and a deadlock issue for
   Delphi 6's run-time package.
   http://community.borland.com/article/0,1410,29361,00.html

* Borland Logo Stuff
   Buy Borland T-shirts, golfballs and other essential stuff.
   http://www.borlandstyle.com

* Updated Delphi for .NET preview available for download
   Registered users of Delphi 7 can now download an update to the Delphi
   for .NET preview.
   http://community.borland.com/article/0,1410,29302,00.html

* Quake2.exe Converted to Delphi - by Q2D
   The Quake II to Delphi Conversion Team is proud to announce that an
   important milestone has been reached: Quake2.exe has been fully
   converted to Delphi from the original C sources. All known conversion
   bugs have been corrected and the Delphi-compiled binary is able to run
   flawlessly using the original DLLs supplied with Quake II 3.20.
   Conversion of the game DLLs has almost been completed and we are now
   focusing on fixing conversion bugs in the source. We seeking any help
   we can get, visit the project's webpage at:
   http://www.sulaco.co.za/quake2/

________________________________________________________________________


¡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.php3
   boletin-pascal-subscribe@...

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.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
   http://news.optimax.com/topdelphi/links.exe/click?id=70C517ECAE6E
   http://www.top219.org/cgi-bin/vote.cgi?delphi&83
   http://top100borland.com/in.php?who=20
   http://top200.jazarsoft.com/delphi/rank.php3?id=latium
   http://www.programacion.net/votar-enlace.php?id=474

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/descarga/p0042.zip
________________________________________________________________________

Página del grupo:  http://espanol.groups.yahoo.com/group/boletin-pascal/
Para suscribirse / apuntarse:   boletin-pascal-subscribe@...
Para cancelar / removerse:    boletin-pascal-unsubscribe@...
¿Problemas con tu suscripción?      boletin-pascal-owner@...
________________________________________________________________________

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.php3

Copyright (c) 2003 por Ernesto D'Spirito. Todos los derechos reservados.
________________________________________________________________________

#8 De: "Ernesto D'Spirito" <edspirito@...>
Fecha: Mié, 4 de Dic, 2002 1:31 am
Asunto: Boletín Pascal #41 - 03-DIC-2002
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #41 - 03-DIC-2002

Índice

1. Unas palabras del editor
2. Clases para información y administración de servidor NT/W2000 remoto
3. Inline Assembler en Delphi (V) - Una introducción a objetos
4. Usando Objetos para guardar la configuración del programa
5. Foros / listas de correo
6. Delphi en la Red
    - Componentes, librerías y aplicaciones
      . Shareware
      . Freeware
    - Artículos, trucos y consejos
    - Tutoriales
    - Otros enlaces

________________________________________________________________________

¿Necesitas alojamiento para tu sitio web? http://www.tecnosoftonline.com
________________________________________________________________________


1. Unas palabras del editor


Agradezco a Mike Heydon por contribuir un artículo para esta edición, y
me complace hacerle entrega de la licencia de TSDBGridFooter:

* TSDBGridFooter v2.0 por Jovan Sedlan, Shareware ($74.50)
   Este componente es una poderosa herramienta que provee cálculos auto-
   máticos para su DBGrid y muestra información en un pie configurable
   debajo de la grilla. Ha sido diseñado para trabajar con TSDBGrid
   (también incluido), aunque puede usarse con cualquier descendiente de
   TCustomDBGrid.
   http://www.sedlan.com/dbgrid_footer.php

Para la próxima edición, tenemos disponible el siguiente premio para el
autor de uno de los artículos contribuidos al boletín (en inglés):

· 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/

En las noticias, ha sido lanzado Interbase 7, representando una signifi-
cativa actualización desde Interbase 6.5, hay una actualización no
oficial para las ActionBands de Delphi 7 en el sitio de Borland, ha
aparecido una versión del generador de reportes gratuito Rpv Printing
System y en nuestro sitio web se encuentran los archivos de recursos en
español para Delphi 6 Update Pack 1 y 2, y también la edición digital
en formato PDF del conocidísimo libro La Cara Oculta de Delphi 4 de Ian
Marteens. Pueden encontrar las descripciones y los enlaces correspon-
dientes más abajo en la sección Delphi en la Red.

Espero que disfruten esta edición.

Saludos,

Ernesto D'Spirito
boletin-pascal-owner@...

__________________

Colaboraron en esta edición: Dave Murray y Charl Linssen

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


2. Clases para información y administración de servidor NT/W2000 remoto

    Por Mike Heydon <mheydon@...>
        EOH Outsourcing http://www.eoh.co.za


Esta unidad define clases que acceden a máquinas remotas y obtienen
información de ellas. La unidad actualmente sólo lee información.
Muchas de las llamadas NetServerGetInfo tienen equivalentes llamadas
NetServerSetInfo. Tendría que ser suficientemente fácil modificar
estas clases y escribir la funcionalidad deseada (sólo para pocos).

Se implementan las siguientes clases:

   TNTServerInfo      = class(TObject)
   TNTServerEventLog  = class(TObject)
   TNTServerServices  = class(TObject)
   TNTServerSessions  = class(TObject)
   TNTServerOpenFiles = class(TObject)
   TNTServerGroups    = class(TObject)
   TNTServerDisks     = class(TObject)

Más estos procedimientos y funciones:

   procedure GetServerResources(const RootObject : string;
                                StringList    : TStrings;
                                RecursiveEnum : boolean;
                                ResourceTypes : TNTServerResSet=[resAny])

    function ValidateUserLogon(const UserName : string;
                               const Domain   : string;
                               const PassWord : string) : boolean;

NOTA: Para acceso remoto al Registro, ver "TRegistry.RegistryConnect()"
       de Borland.

Los métodos que establecen TStrings asignan la propiedad Items o Lines
con campos delimitados por punto y coma (";"). Este formato es ideal
para my componente TMultiColListBox para la función
General.ExtractField(). Los campos Flag DWORD se pueden comprobar vía
la función General.AndEqual(), por ejemplo:

   if AndEqual(SI.ServerType,SV_TYPE_SERVER_UNIX) then ...

La mayoría de las funciones que establecen TStrings también permiten un
Set (conjunto) de Field Options que controla la información devuelta en
las columnas de los Items/Lines individuales de los TStringList.

Algunas clases tienen constructores Create sobrecargados. Esto le
permite ya sea crear una instancia ATTACHED (adjunta) o una instancia
UNATTACHED (no adjunta) simple. En el caso de TNTServerEventLog puede
crear una instancia que se adjunte al servidor y abra la bitácora de
eventos (eventlog) SourceName inmediatamente, o sólo crear la clase y
luego llamar a OpenLog() para adjuntarse a la bitácora (log).

NOTA: OpenLog y métodos similares en otras clases automáticamente
       cerrarán cualquier bitácora previamente abierta antes de abrir la
       nueva. Llamar al método Free también cierra cualquier bitácora
       abierta, por lo que no hay necesidad para un CloseLog() o métodos
       similares.

Debido a limitaciones de espacio, la documentación se incluye en el
código fuente (adjunto).

________________________________________________________________________

¿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!"
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
________________________________________________________________________


3. Inline Assembler en Delphi (V) - Una introducción a objetos


Los objetos son registros
=========================

Desde la perspectiva del ensamblador, un objeto es como un registro
cuyos campos son sus propios campos más los campos de sus ancestros,
más el puntero a la VMT (Virtual Methods Table = Tabla de Métodos
Virtuales). Veámoslo con un ejemplo:

   type
     TClase1 = class
       CampoA: integer;
       CampoB: string;
     end;

     TClase2 = class(TClase1)
       CampoC: integer;
     end;

En el ejemplo, TClase2 es como una especie de registro de cuatro campos:

   TClase2 = record
     VMT: pointer;       // campo invisible, siempre primero
     CampoA: integer;    // heredado de TClase1
     CampoB: string;     // heredado de TClase1
     CampoC: integer;    // declarado en TClase2
   end;


Las variables objeto son punteros
=================================

Una variable objeto es simplemente un puntero a un objeto, es decir, un
puntero a un registro.

   var
     a, b: TClase2;
   begin
     a := TClase2.Create;
     b := a;                // una simple asignación de punteros
     a.Free;
   end;

Un constructor asigna memoria para una instancia (objeto) de su clase,
la inicializa, y devuelve un puntero a la memoria asignada. Por
consiguiente, después de la llamada a TClass.Create la variable "a"
apunta al registro (el objeto):

   +---+             +--------+
   | a | ----------> |   VMT  |
   +---+             +--------+
                     | CampoA |
                     +--------+
                     | CampoB |
                     +--------+
                     | CampoC |
                     +--------+

La asignación "b := a" no crea un nuevo objeto copia del primero, sino
que en realidad hace que ambas variables apunten al mismo objeto:

   +---+             +--------+             +---+
   | a | ----------> |   VMT  | <---------- | b |
   +---+             +--------+             +---+
                     | CampoA |
                     +--------+
                     | CampoB |
                     +--------+
                     | CampoC |
                     +--------+


Métodos en ensamblador
======================

Los métodos reciben un primer parámetro invisible (no declarado) llamado
Self, que es un puntero al objeto sobre el cual deben operar.

   type
     TPrueba = class
       FCodigo: integer;
     public
       procedure SetCodigo(NuevoCodigo: integer);
     end;

   procedure TPrueba.SetCodigo(NuevoCodigo: integer);
   begin
     FCodigo := NuevoCodigo;
   end;

   var
     a: TPrueba;
   begin
     :
     a.SetCodigo(2);
     :
   end;

El código Object Pascal de arriba se puede traducir de alguna manera a
Pascal estándar como sigue:

   type
     TPrueba = record
       VMT: pointer;
       FCodigo: integer;
     end;

   procedure SetCodigo(Self: TPrueba; NuevoCodigo: integer);
   begin
     Self.FCodigo := NuevoCodigo;
   end;

   var
     a: ^TPrueba;
   begin
     :
     SetCodigo(a, 2);
     :
   end;

El ejemplo sirve para explicar que los métodos reciben el puntero Self
como primer parámetro, es decir, reciben el puntero Self (recordemos
que los registros se pasan por referencia como un putero a los datos)
en el registro EAX, y el primer parámetro declarado se pasa como segundo
parámetro en EDX y así (el segundo parámetro declarado se pasa entonces
como tercero en ECX, y el resto de los parámetros se pasan en la pila).
El método SetCodigo se puede escribir en ensamblador como sigue:

   procedure TPrueba.SetCodigo(NuevoCodigo: integer);
   asm
     // EAX = Self = Dirección de la instancia de TPrueba
     // EDX = Parámetro NuevoCodigo

     // FCodigo := NuevoCodigo;
     mov TPrueba[eax].FCodigo, edx     // TPrueba(EAX)^.FCodigo := EDX;
   end;

Como puede verse, los campos de los objetos se acceden de la misma
manera que los campos de un registro.

NOTA: Las propiedades no son campos (son nombres para referenciar
       campos y métodos), y no se pueden acceder directamente desde
       inline assembler.

Aquí va un ejemplo de un método llamando a otro método:

   procedure TPrueba.Increment;
   asm
     // SetCodigo(Codigo+1);
     mov edx, TPrueba[eax].FCodigo     // ECX := TPrueba(EAX)^.FCodigo;
     inc edx
     call TPrueba.SetCodigo;
   end;

No establecimos el valor de EAX antes de la llamada a SetCodigo pues
EAX ya contiene el valor deseado (Self), así que el método llamado
operará sobre el mismo objeto que el llamador.

NOTAS:

* Los métodos virtuales sólo pueden llamarse estáticamente, pues se
   necesita una referencia a la clase en la sentencia CALL.

* En inline assembler no se pueden distinguir los métodos sobrecargados.


Constructores en ensamblador
============================

Los constructores son métodos muy especiales. Se puede llamar a un
constructor para crear una instancia de una clase (o sea para asignar
la memoria para el objeto e inicializarla), o simplemente para reini-
cializar un objeto ya creado:

   a := TPrueba.Create;   // asigna memoria
   a.Create;              // sólo reinicializa un objeto existente

Para distinguir entre estas dos situaciones, a los constructores se
les pasa un invisible segundo parámetro de typo Byte (es decir, en el
registro DL), el que puede ser positivo o negativo respectivamente (el
compilador usa 1 y -1 respectivamente).

Si llamamos a un constructor desde código ensamblador con DL = $01 (para
asignar memoria para el objeto), tenemos que pasar una referencia a la
clase en EAX, y puesto que no hay símbolo para accederla directamente
desde ensamblador, entonces tenemos que hacer algo similar a lo que
hicimos con la información de tipo de los registros:

   var
     TPrueba_TypeInfo: pointer;

   :

   initialization
     TPrueba_TypeInfo := TPrueba;

Ahora que hemos inicializado una variable global con la referencia a la
clase desde nuestro código Pascal, podemos usarla en nuestro código en
ensamblador:

   var
     a: TPrueba;
   begin
     // a := TPrueba.Create(2);
     asm
       mov eax, TPrueba_TypeInfo
       mov dl, 1
       mov ecx, 2
       call TPrueba.Create
       mov a, eax
     end;
     :
   end;

Llamar a un constructor para reinicializar el objeto es más simple, pues
no necesitamos una referencia a la clase:

   var
     a: TPrueba;
   begin
     :
     // a.Create(2);
     asm
       mov eax, a
       mov dl, -1
       mov ecx, 2
       call TPrueba.Create
     end;
     :
   end;

No tenemos nada de que preocuparnos si tenemos que escribir un cons-
tructor en ensamblador dado que Delphi se hace cargo de la cuestión
de la asignación de memoria por nosotros al entrar al constructor, y
-luego de ello- EAX apuntará al nuevo objeto, tal como sucede con
cualquier otro método, pero lo que es relevante es que si el constructor
tiene parámetros, el primer parámetro declarado será internamente pasado
tercero, o sea en ECX (en vez de segundo, o sea en EDX, tal como ocurre
con cualquier otro método), y el resto de los parámetros será pasado en
la pila.

   constructor TPrueba.Create(NuevoCodigo: integer);
   asm
     // FCodigo := NuevoCodigo
     mov TPrueba[eax].FCodigo, ecx
   end;

__________________

NOTA: Se adjunta un ejemplo de código fuente completo.

________________________________________________________________________


4. Usando Objetos para guardar la configuración del programa


Este artículo de Sebastián Mayorá se incluye en formato HTML dentro del
archivo adjunto correspondiente a esta edición, en la carpeta ObjConfig.

________________________________________________________________________


5. Foros / listas de correo


To join any of our forums, the best way is to subscribe from the web,
since that way you'll be able to access the features available at the
web site (like changing your subscription options, viewing the past
messages, accessing the files section, etc.). A Yahoo! ID is required
for that, and you can get yours free by registering as a Yahoo! user,
but if you don't want to register or if you don't have full Internet
access, you can also subscribe by email (you'll only have email access).

* Delphi: If you know a lot about Delphi but you are still far from
   being a guru this forum is for you. This is the only forum for
   intermediate-level Delphi programmers on the Web (Delphi experts are
   also welcome :-)
   http://groups.yahoo.com/group/delphi-en/
   Subscription:
     http://groups.yahoo.com/group/delphi-en/join
     delphi-en-subscribe@yahoogroups.com

* Kylix: Kylix programming.
   http://groups.yahoo.com/group/KylixGroup/
   Subscription:
     http://groups.yahoo.com/group/KylixGroup/join
     KylixGroup-subscribe@yahoogroups.com

* Components: This is a forum for searching/recommending software
   components (VCL and CLX components, ActiveX objects, DLL libraries,
   shared objects, etc.), as well as utilities, tutorials, information,
   etc.
   http://groups.yahoo.com/group/components/
   Subscription:
     http://groups.yahoo.com/group/components/join
     components-subscribe@yahoogroups.com

* Software Developers: This is a forum for discussions about software
   development and to share experience in the work, professional or
   commercial environments. It is not a programming forum, matters
   treated here are supposed to be more general or language independent.
   http://groups.yahoo.com/group/software-developers/
   Subscription:
     http://groups.yahoo.com/group/software-developers/join
     software-developers-subscribe@yahoogroups.com

________________________________________________________________________


6. Delphi en la Red

    Por Dave Murray <irongut@...>


Componentes, librerías y aplicaciones
=====================================


Shareware/Commercial
--------------------

* SDL Component Suite 7.0 - por Software Development Lohninger ($99)
   La SDL Component Suite provee un amplio rango de componentes para la
   ciencia y la ingeniería, por ejemplo matemáticas, estadísticas,
   química, diagramas, visualización de datos, transformadas de Fourier
   (FFT), ploteos 3D, mapas geográficos, ajuste de curvas, etc.
   Disponible para Delphi 3-7 y BCB 4-6.
   http://www.lohninger.com/sdlindex.html


Freeware
--------

* Archivos de recursos en español para Delphi 6 UP 1 y 2, traducidos
   por Felipe Eduardo Ortiz López. Una vez que se haya instalado
   Delphi 6 y aplicados los Update Packs 1 y 2 de Borland, sustituir
   los DCUs y PASs respectivos en sus lugares (normalmente $Delphi\Lib,
   $Delphi\Lib\Debug y $Delphi\Source\VCL) para tener las cadenas de
   mensajes traducidas al español.
   http://www.latiumsoftware.com/descarga/Delphi6EspP12.zip

* Generador de reportes Rpv Printing System 2.2
   Permite generar reportes de alta calidad, incluyendo imágenes,
   códigos de barras y links a la web, a otros reportes o a ejecutables.
   Compatible con cualquier lenguaje de programación, permite imprimir
   también desde DOS, o desde UNIX, Linux, AS/400, etc. Ideal para uso
   en intranets, permite generar e imprimir reportes en el cliente,
   utilizando PHP, ASP, etc. Fácil de usar y aprender.
   http://www.rpvreport.com/span/

* Max's components page
   Freeware and commercial components for Delphi and C++ Builder
   http://www.maxcomponents.net/

* PHP4Delphi v2.2 - by Serhiy Perevoznyk, FREEWARE with source
   PHP4Delphi allows you to execute the PHP scripts within the Delphi
   program directly without a WebServer.
   http://users.chello.be/ws36637/

* CEditIPAddr by Netta El-al, FREEWARE with source
   IP Address Edit component.
   http://www.torry.net/vcl/edits/diffedits/neipaddredit.zip

* IE Information Component v4.9 - by Ch Bergmann, FREEWARE with source
   IE Availability, Version & Information Component features include:
   Availability of IE, Version and Build Number, Encryption-Strength,
   IE WindowTitle, IE ShellFolder and SpecialFolder Paths, and more.
   http://yazno.tripod.com/ieinstver/

* TssVolumeController v1.0 - by Shen Min, FREEWARE with source
   TssVolumeController is a component to control the mixer volume.
   http://www.sunisoft.com/volumectrl/

* MiTeC System Information Component v7.73 - by Michal Mutl, FREEWARE
   Component providing detailed system information including:
   CPU architecture, type, count, level, revision, vendor, id, speed
   OS version, build, platform, CSD version, user name, serial number
   Graphic adapter chip name, dac, memory, color depth, modes, resolution
   Sound card name, WaveIn, WaveOut, MIDIIn, MIDIOut, AUX, Mixer name
   Memory info, allocation granularity, min.and max.application address
   BDE, ODBC, DAO, ADO, ASPI, DirectX information
   and a lot more!
   http://www.mitec.d2.cz/

* Delphi Fast Zlib v1.1.2 - by Roberto Della Pasqua, FREEWARE w source
   A Delphi zlib 1.1.4 implementation for fastest performance, including
   targeted P6 code generation, 64bit alignment, source changes and
   optimizations following Borland C++ full standards adherence, and a
   Delphi added low level copy memory function to speedup typical strings
   management. Embed the newest zlib 1.1.4 objects into your programs
   without using external dlls, take a look into the example to see how
   to work with streams and strings.
   http://www.dellapasqua.com/delphizlib/


Artículos, trucos y consejos
============================

* A Book, a Book, a Kingdom for a Book! - by Zarko Gajic
   Find what are the best Delphi books on the market and read expert
   reviews. Also, see what are the top picks in the .NET arena!
   http://delphi.about.com/cs/magazines/

* Tips on Designing Data-Driven XML - by Edward Tittel
   One of the powerful aspects of XML is the ability to define and
   structure content or data. Learn a few tips for designing XML
   documents based on the structure of the data.
   http://builder.com.com/article.jhtml?id=u00320021007edt01.htm

* How to get Kylix to notice function key shortcuts - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=205

* How to identify drives assigned by the Subst command - Flurin Honegger
   Recognizing virtual drives and combining 32 Bit and 16 Bit code to fit
   from Win95 up to WinXp!
   http://www.delphi3000.com/articles/article_3447.asp

* Find text in MS Word files without Word app loading - Dmitry Lifatov
   Easy way to find a text in MS Word.
   http://www.delphi3000.com/articles/article_3450.asp

* Building a Terminal Server Client-Application - by Max Kleiner
   Working with MSTerminal Services Advanced Client ActiveX.
   http://www.delphi3000.com/articles/article_3451.asp

* Copy NTFS file security from a source to a destination - Wayne Sherman
   By default when coping a folder or file to a destination on an NTFS
   partition the destination file takes the security and access control
   settings of the destinations parent folder. This function provides an
   easy way to copy the original settings to the destination file or copy
   security settings from another file/folder.
   http://www.delphi3000.com/articles/article_3452.asp

* OnChange Event for TDBLookupComboBox - by Alex Schlecht
   How to make a new DBLookupComboBox-Component with OnChange-Event.
   http://www.delphi3000.com/articles/article_3454.asp

* Function to Determine Oracle Version Number - by Mike Heydon
   GetOraVersion()
   http://www.delphi3000.com/articles/article_3455.asp

* Create an ActiveX friendly TSplitter - by Simon Moscrop
   Prevent the 'Component has no parent window' error message appearing
   when you use a TSplitter in a Delphi ActiveX control.
   http://www.delphi3000.com/articles/article_3456.asp

* Function to determine MS SQL Server Version Number - by Mike Heydon
   GetSqlVersion().
   http://www.delphi3000.com/articles/article_3457.asp

* Check Valid IP Address - by Jerry Pylarinos
   A simple way to check whether an IP address is valid.
   http://www.delphi3000.com/articles/article_3458.asp

* Instant Messaging in Delphi: The MSN One - by César Nicolás Peña Núñez
   An implementation of the MSN Messenger protocol, it isnt complete and
   in order to build it you will need the WSocket package. Most of what
   is presented here is a part of the specification.
   http://www.delphi3000.com/articles/article_3459.asp

* How to get JPEG Image Size, including big images - by Mauricio Herrera
   http://www.delphi3000.com/articles/article_3460.asp

* Sip from the Firehose: Short Computer Books I've Enjoyed  - by David I
   There are so many great computer books and so little time to read them
   all. What I really love are the short books, the focused books with
   low page counts...
   http://community.borland.com/article/0,1410,29253,00.html

* How to use AutoInc fields with DataSnap - by Dan Miser
   Implementing auto-incrementing fields for any DataSnap server.
   http://community.borland.com/article/0,1410,20847,00.html

* If you are The Lone Gun, Take Aim at Time Bandits - by Jeffrey Kay
   The author is the only developer in his small startup, but he also has
   other duties as a member of the management team. Check out his tips on
   how to stay on time and on track when you wear many hats.
   http://builder.com.com/article.jhtml?id=u00420021023JBK01.htm

* How to adapt DateTime values for different SQL-Server formats?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1423

* How to load the CD-ROM icon?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1417

* How to patch a process?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1364

* How to center a TControl?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1415

* How to maker the mouse wheel works correct in TDBGrid?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1454

* How to use regular expressions in Delphi?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1478

* How to list all directories, files and drives in a listbox?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1495

* How to display the 'Organize Favorite' dialog box?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1494

* How to preform a Shell Sort - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=195

* How to convert an Icon to Bitmap - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=196

* How to set the transparent color of an image - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=197

* How to check if a font is a TrueType font - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=198

* How to read DOS environment variables - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=199

* How to programatically start the screen saver - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=203

* How to change the system date - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=204

* Quick untyped fileaccess - by DenShade Hyp
   How can we read quickly from an untyped file consisting out of bytes
   without making the code complicated?
   http://www.delphi3000.com/articles/article_3415.aspo

* ADO Recordset <-> XML - by Dmitry Lifatov
   Provides two functions: function RecordsetToXML and function
   RecordsetFromXML.
   http://www.delphi3000.com/articles/article_3416.asp

* Modulo for huge numbers - by Andreas Schmidt
   http://www.delphi3000.com/articles/article_3417.asp

* How To Make Your Own Self Extractor - by William Anthony
   How to create a Self Extracting Executable.
   http://www.delphi3000.com/articles/article_3419.asp

* Create You Own Custom Dataset (Part 1) - by William Anthony
   How to create a custom DataSet.
   http://www.delphi3000.com/articles/article_3420.asp

* Create You Own Custom Dataset (Part 2) - by William Anthony
   How to create direct access dataset.
   http://www.delphi3000.com/articles/article_3421.asp

* Get the published properties of an persistent object - Boris Wittfoth
   How to get the published properties of an persistent object / Using
   the pPropInfo-Pointer and the RTTI of Delphi.
   http://www.delphi3000.com/articles/article_3423.asp

* Moving Controls over the form - by Boris Benjamin Wittfoth
   Dragging / moving TWincontrol-Component over a TForm.
   http://www.delphi3000.com/articles/article_3424.asp

* How to draw in a StringGrid Cell? - by Boris Benjamin Wittfoth
   The standard Delphi-StringGrid can only hold one color for all cells.
   How to create an multiple colored Stringgrid ?
   http://www.delphi3000.com/articles/article_3425.asp

* TString Super Sort Class (descending,ignore case, etc) - Mike Heydon
   http://www.delphi3000.com/articles/article_3427.asp

* Randomizing with the linear congruence method - by DenShade Hyp
   The standard randomize function does not return a set of uniformly
   randomized numbers.How can i truly randomize values?
   http://www.delphi3000.com/articles/article_3429.asp

* Random string generator - by Uros Gaber
   Ever wanted to generate a random string with specific random char on a
   specific position in the string?
   http://www.delphi3000.com/articles/article_3430.asp

* Date String (any format) to TDateTime - by Mike Heydon
   http://www.delphi3000.com/articles/article_3431.asp

* Moving objects with snapgrid functionality - by  Tommy Andersen
   Here's an object that enables you to move your objects on a form
   easily during runtime...
   http://www.delphi3000.com/articles/article_3432.asp

* Display The Add to favorite Dialog Box - by Khaled Al Ahmad
   How To Display the IE Add to favorite Dialog Box.
   http://www.delphi3000.com/articles/article_3433.asp

* Screencapture with animated gif support - Christiaan Ten Klooster
   How to create a screenshot of the entire screen, a selection or a
   specific window to a bitmap, jpeg compressed or (animated) GIF file?
   http://www.delphi3000.com/articles/article_3434.asp

* Standard RichEdit and URL highlighting/navigation - by Mike Shkolnik
   How can I highlight URLs in RichEdit and how can I detect a mouse
   click in text where URL is?
   http://www.delphi3000.com/articles/article_3435.asp

* LogonUser() Win API call vs SSPI call - by Mike Heydon
   Using the LogonUser API or the Security Support Provider Interface
   (SSPI) to verify user credentials.
   http://www.delphi3000.com/articles/article_3436.asp

* Redefining TCP/IP Client... - by S S B Magesh Puvananthiran
   How do we create a TCP/IP Server/Client in Delphi?
   http://www.delphi3000.com/articles/article_3437.asp

* Using queued components in Delphi - by Helmut Dollinger
   Example showing queued components in Delphi. Queued Components are
   feature of COM+ based on Microsoft Message Queuing Services (MSMQ).
   They provide an easy way to invoke and execute components
   asynchronously. Processing can occur without regard to the
   availability or accessibility of either the sender or the receiver.
   http://www.delphi3000.com/articles/article_3439.asp

* How do I unlock a Active Server Library DLL? - by Helmut Dollinger
   How to make this a little bit easier during development...
   http://www.delphi3000.com/articles/article_3440.asp

* Reading and writing RIFF base files (WAVE, AVI etc) - by Liran Shahar
   Ever wanted to read and write user sound into a valid WAVE file? Ever

   wanted to read all the available chunks with additional file data from
   a WAVE fie?
   http://www.delphi3000.com/articles/article_3441.asp

* Delphi 5 TToolbar does not resize correctly when XP common controls
   6.0 are enabled - by Flurin Honegger
   Altering Delphi 5 comctrls.pas to fit your needs!
   http://www.delphi3000.com/articles/article_3445.asp


Tutoriales
==========

* CLR, startup your engines! - by Alain "Lino" Tadros
   The Common Language Runtime is the solid rock on which the .NET
   Framework was built. From it's many features, we start with one that
   defines the way CLR starts .NET applications.
   http://community.borland.com/article/0,1410,29291,00.html

* Filtering ClientDataSets - by Cary Jensen
   When applied to a dataset, a filter limits the records that are
   accessible. This article explores the ins and outs of filtering
   ClientDataSets.
   http://community.borland.com/article/0,1410,29271,00.html

* ClientDataSet Aggregates and GroupState - by Cary Jensen
   How to use aggregates to calculate simple statistics as well as how to
   use group state to improve your user interfaces.
   http://community.borland.com/article/0,1410,29272,00.html

* Locate and format XML data with XPath functions - Tony Patton
   XPath allows you to locate + extract information from an XML hierarchy
   and offers functions which provide an easy way to work with numeric
   and textual data.
   http://builder.com.com/article.jhtml?id=u00320021108ton01.htm&page=1

* Welcome to Caught in the .NET - By Alain "Lino" Tadros
   Welcome to "Caught in the .NET" series of articles, my goal is to
   introduce myself and set the stage and expectation for the next few
   months of reading these series of articles.
   http://community.borland.com/article/0,1410,29254,00.html

* Take a Guided Tour of XML Support in .NET - by Lamont Adams
   If you're trying to learn your way around .NET's XML neighborhood, let
   us take you on a tour. Here's a look at the Framework's various reader
   and writer classes.
   http://builder.com.com/article.jhtml?id=u00220021101adm01.htm

* Working With XML Entities - by Roy C. Hoobler
   XML entities are often overlooked in the XML dialect, but they provide
   a powerful vehicle for XML developers. Learn how to effectively use
   them in your DTDs as placeholders or to retrieve external data.
   http://builder.com.com/article.jhtml?id=u00320021105RCH01.htm

* Use XPath to Locate Information in XML Documents - by Tony Patton
   XML offers a wonderful vehicle for packaging and exchanging data but
   getting data from an XML document can be troublesome. Find out how
   XPath provides a simple, consistent vocabulary for getting the data.
   http://builder.com.com/article.jhtml?id=u00320020827ton02.htm

* Principles to Help Create Robust,Reusable OO Design Apps - Rahul Tyagi
   Object-oriented software design provides a cleaner design and enhances
   the ability to add new features in the future. Learn the basic
   elements of good and bad design and two principles you can follow to
   build solid object-oriented design code.
   http://builder.com.com/article.jhtml?id=u00320021107tyr01.htm

* MVC Design Pattern: Better Organization + Code Reuse - by Brian Kotek
   Consider the MVC design pattern for your development projects. Using
   its three components, you can open up new levels of robustness, code
   reuse and organization.
   http://builder.com.com/article.jhtml?id=u00320021008BXK01.htm


Otros enlaces
=============

* El Rinconcito de Delphi
   Sitio dedicado a Delphi y Kylix. Tutorial, Articulos, Noticias,
   Libros, Componentes.
   http://www.elrinconcito.com/delphi/

* La Cara Oculta de Delphi 4 - por Ian Marteens
   Esta es la versión digital en formato PDF del conocidísimo libro de
   Ian Marteens. El libro es muy bueno, pero claro, de Delphi 4 a Delphi
   7 han habido muchas y muy grandes novedades, así que el libro puede
   considerarse obsoleto, pero creo que será muy útil a estudiantes que
   normalmente están cortos de dinero para invertir en libros, pero para
   el profesional que gana dinero y que tiene que estar medianamente
   actualizado le recomendamos que pase por las librerías y pregunte por
   el libro La Cara Oculta de Delphi 6 que ya está a la venta.
   http://www.latiumsoftware.com/descarga/lcod4.php  (3,7MB)

* Unofficial update of ActionBands feature of Delphi 7.0
   This patch will affect both end user applications that use ActionBands
   as well as the Delphi IDE itself since the menus in the IDE are
   ActionBand menus.
   http://codecentral.borland.com/codecentral/ccWeb.exe/listing?id=19151

* Borland Releases Hot New Upgrade to InterBase
   Borland has announced the release a significant upgrade to InterBase.
   InterBase 7 has features intended to improve application performance
   and developer productivity. Support for SMP and hyperthreading can
   speed up applications, support more users and more complex application
   architecture. New transaction monitoring capabilities can improve
   developer productivity and ease deployment issues. According to field
   testers, InterBase 7 is a "must have" upgrade.
   http://www.borland.com/interbase/pdf/ib7_whatsnew.pdf

* BorCon France
   Paris, November 21-22 2002.
   http://info.borland.fr/conference/2002/


________________________________________________________________________


¡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.php3
   boletin-pascal-subscribe@...

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.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
   http://news.optimax.com/topdelphi/links.exe/click?id=70C517ECAE6E
   http://www.top219.org/cgi-bin/vote.cgi?delphi&83
   http://top100borland.com/in.php?who=20
   http://top200.jazarsoft.com/delphi/rank.php3?id=latium
   http://www.programacion.net/votar-enlace.php?id=474

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/descarga/p0041.zip
________________________________________________________________________

Página del grupo:  http://espanol.groups.yahoo.com/group/boletin-pascal/
Para suscribirse / apuntarse:   boletin-pascal-subscribe@...
Para cancelar / removerse:    boletin-pascal-unsubscribe@...
¿Problemas con tu suscripción?      boletin-pascal-owner@...
________________________________________________________________________

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.php3

Copyright (c) 2002 por Ernesto D'Spirito. Todos los derechos reservados.
________________________________________________________________________

#7 De: "Ernesto D'Spirito" <edspirito@...>
Fecha: Jue, 31 de Oct, 2002 1:02 am
Asunto: Boletín Pascal #40 - 30-OCT-2002
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
Boletín Pascal #40 - 30-OCT-2002

Índice

1. Unas palabras del editor
2. Ganchos (hooks) de Windows (o "¿Cómo trabajan esos programas espía?")
3. Codificar y decodificar Base64 (MIME)
4. Ejemplo de un servicio Windows, con un hilo
5. Capturando la salida de una aplicación de consola
6. Creación de Objetos - Introducción (0 de 3)
7. Inline Assembler en Delphi (IV) - Registros
8. Foros / listas de correo
9. Delphi en la Red
    - Componentes, librerías y aplicaciones
      . Freeware
    - Artículos, trucos y consejos
    - Tutoriales
    - Otros enlaces

________________________________________________________________________

¿Necesitas alojamiento para tu sitio web? http://www.tecnosoftonline.com
________________________________________________________________________


1. Unas palabras del editor


Tenía la intención de publicar esta edición hace un par de semanas como
había prometido, pero en circunstancias muy particulares un nuevo virus
no identificado entró en mi PC y sobrescribió el primer cilindro de mi
disco duro (el sector de arranque maestro, y el sector de arranque y
parte de la tabla de asignación de archivos -FAT- de la primera
partición), así que imagínense... (Todavía estoy instalando todos los
componentes Delphi que solía tener). Lamento mucho la demora.

Para disipar dudas, los nombres de dos de nuestros foros/listas de
correo (grupos en Yahoo! Grupos) han cambiado:

   delphi-es   -->   delphi-intermedio
   Delphi      -->   delphi-avanzado

Por lo tanto, han cambiado todas sus direcciones, por lo que se deberán
realizar las sustituciones correspondientes. Por ejemplo, para publicar
mensajes en el foro Delphi de nivel intermedio:

   Antes: <delphi-intermedio@...>
   Ahora: <delphi-intermedio@...>

Quisiera agradecer a los autores que contribuyeron artículos para este
número, y me complace entregarles los siguientes premios:

* Florin Sabau ("Ganchos (hooks) de Windows")
· 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/

* Jochen Fromm ("Capturando la salida de una aplicación de consola")
· 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

* Kim Sandell ("Ejemplo de un servicio Windows, con un hilo")
· 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/html/dil.asp

Para la próxima edición, tenemos disponible el siguiente premio para el
autor de uno de los artículos contribuidos al boletín:

* TSDBGridFooter v2.0 por Jovan Sedlan, Shareware ($74.50)
   Este componente es una poderosa herramienta que provee cálculos auto-
   máticos para su DBGrid y muestra información en un pie configurable
   debajo de la grilla. Ha sido diseñado para trabajar con TSDBGrid
   (también incluido), aunque puede usarse con cualquier descendiente de
   TCustomDBGrid.
   http://www.sedlan.com/dbgrid_footer.php

Cambiando de tema, he sido lanzado el primer update pack para Delphi 7:

* Delphi 7 Update Pack 1
   http://community.borland.com/article/0,1410,29209,00.html

Espero que disfruten esta edición.

Saludos,

Ernesto D'Spirito
boletin-pascal-owner@...

__________________

Colaboraron en esta edición: Dave Murray y Charl Linssen

________________________________________________________________________

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-7 y C++ Builder 3-6.    http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________


2. Ganchos (hooks) de Windows (o "¿Cómo trabajan esos programas espía?")

    Por Florin Sabau <aaa111@...>


¿Alguna vez se preguntó cómo obtienen esos programas espía todo lo que
se escribe en la computadora en la que están instalados? Bueno, no sé
exactamente como ELLOS lo hacen :), pero les voy a mostrar una forma
posible usando ganchos (hooks) de Windows. Este artículo le mostrará
cómo Ud. puede crear un programa que "escuche" cierta combinación de
teclas y cuando sea activado que haga algo significativo (abrir la
bandeja de CDROM).

Técnicamente, un gancho es simplemente otra subrutina ("procedimiento
gancho" o "procedimiento de gancho") que "se me mete en el camino" del
mecanismo normal de administración de mensajes de Windows. El proce-
dimiento gancho puede ser instalado en el sistema de modo que reciba
ciertos mensajes de Windows ANTES que estos sean despachados a su
procedimiento de ventana asignado. Windows contiene muchos tipos
diferentes de ganchos; cada tipo provee acceso a aspectos diferentes del
mecanismo de administración de mensajes de manejo de Windows. He aquí
algunos de ellos (en realidad las constantes que los identifican han
sido tomadas de windows.pas) con una breve descripción:

   WH_KEYBOARD: Instala un procedimiento gancho que monitorea los
   mensajes de teclado. Usaremos este en nuestro programa.

   WH_MOUSE: Instala un procedimiento gancho que monitorea los
   mensajes del ratón.

   WH_CBT: Instala un procedimiento gancho que recibe notificaciones
   útiles para una aplicación de entrenamiento basado en computadora
   (CBT, computer-based training)

   WH_JOURNALRECORD: Instala un procedimiento gancho que registra
   mensajes de entrada en la cola de mensajes del sistema. Este
   gancho es útil para registrar macros.

   WH_JOURNALPLAYBACK: Instala un procedimiento gancho que emite
   mensajes previamente registrados por un procedimiento gancho
   WH_JOURNALRECORD.

Puesto que más de un programa puede instalar un gancho en el sistema
al mismo tiempo, Windows mantiene internamente una "cadena de ganchos"
(hook chain), que es simplemente una lista de punteros a los procedi-
mientos ganchos que tiene instalados. Cuando ocurre un mensaje en el
sistema, Windows primero se lo pasa a cada procedimiento en la cadena
de ganchos, uno tras otro. Luego, si el mensaje no fue "bloqueado" por
ninguno de los procedimientos gancho, Windows lo despacha al proce-
dimiento de ventana designado.

Una cosa más antes de entrar en la siguiente sección: los ganchos
pueden ser clasificados de otra forma. Hay ganchos de sistema (globales)
que reciben mensajes para todos los hilos en el sistema, y ganchos
específicos de un hilo (locales), que reciben mensajes sólo designados
para un hilo individual. Puesto que un procedimiento de gancho global
puede ser llamado en el contexto de cualquier aplicación (para capturar
mensajes de todas las aplicaciones), debe estar localizado en una DLL
(Dynamic Link Library). Esta restricción no se aplica a los ganchos
específicos de un hilo, así que el procedimiento gancho puede estar
ubicado en cualquier parte de la aplicación que es dueña del hilo a
ser enganchado

En este artículo trataremos solamente con ganchos globales.


Instalando un procedimiento gancho WH_KEYBOARD en la cadena de ganchos
----------------------------------------------------------------------

La API de ganchos contiene 3 funciones muy importantes: SetWindowsHookEx
(que instala un procedimiento gancho), UnhookWindowsHookEx (que desins-
tala un procedimiento gancho) y CallNextHookEx (que llama al siguiente
procedimiento gancho en la cadena de ganchos). Los parámetros que toman
estas funciones se muestran abajo (de windows.pas):

   function SetWindowsHookEx(idHook: Integer; lpfn: TFNHookProc; hmod:
   HINST; dwThreadId: DWORD): HHOOK; stdcall;
     "idHook": tipo de gancho a instalar (por ejemplo WH_KEYBOARD);
     "lpfn": puntero la procedimiento gancho al que deben enviarse los
       mensajes;
     "hmod": manejador (handle) de la DLL que instala el gancho, general-
       mente hInstance para ganchos globales o 0 para ganchos locales;
     "HINST": identificador del hilo al que se asociará el gancho. Si es
       0, el procedimiento de gancho se asociará con todos los hilos.
   Devuelve un valor usado para identificar el gancho.

   function UnhookWindowsHookEx(hhk: HHOOK): BOOL; stdcall;
     "hhk": identificador del gancho a desinstalar.
   Devuelve True si tiene éxito, False si fracasa.

   function CallNextHookEx(hhk: HHOOK; nCode: Integer; wParam: WPARAM;
   lParam: LPARAM): LRESULT; stdcall;
     "hhk": identificador del gancho actual;
     "nCode","wParam","lParam": parámetros que deberían ser enviados al
       siguiente procedimiento en la cadena de ganchos.
   Devuelve el valor retornado por el siguiente procedimiento en la
   cadena. Más adelante veremos en el ejemplo lo que significa.


El procedimiento gancho
-----------------------

El procedimiento gancho para un gancho de teclado tiene un formato
estándar que y para que el gancho funcione, el programador debe proveer
este formato exacto:

   function HookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM):
   LRESULT; stdcall;

   "nCode":
     = HC_ACTION - los parámetros wParam y lParam contiene información
       acerca del mensaje de teclado.
     = HC_NOREMOVE - los parámetros wParam y lParam contiene información
       acerca del mensaje de teclado, y el mensaje de teclado no ha sido
       removido de la cola de mensajes (una aplicación llamó la función
       PeekMessage especificando la bandera PM_NOREMOVE).

   "wParam": especifica el código de tecla virtual de la tecla que
       generó el mensaje (por ejemplo VK_F9 para la tecla de función F9).

   "lParam": especifica información adicional (como la cantidad de
       repeticiones, el código de exploración, ...); no usado en
       nuestro programa (ver Win32SDK para detalles).

HookProc debería devolver un valor no nulo para impedir que Windows pase
el mensaje al resto de la cadena de ganchos o al procedimiento de
ventana destino, o cero para permitir que Windows pase el mensaje al
procedimiento de ventana destino.


Ejemplo
-------

Este ejemplo crea un gancho global sobre el teclado y cuando ocurre una
cierta combinación de teclas realiza algo significativo:

   WinKey + F9:  Muestra la ventana principal si está oculta;
   WinKey + F10: Eyecta la bandeja de CDROM;
   WinKey + F12: Termina la aplicación.

La comunicación entre la DLL que implementa el gancho y la aplicación se
realiza con la función API SendMessage, la que envía un mensaje HOOK_MSG
(definido en constants.inc) a la aplicación principal, con el comando
(SHOW, EJECT, QUIT) en wParam (ver más abajo).

Dado que no queremos ser molestados por el formulario siendo mostrado
todo el tiempo, al hacer clic en el botón Minimizar se oculta (incluso
de la lista de tareas), pero puede ser mostrado más tarde con la
combinación Winkey+F9.

Para el código fuente completo ver el archivo adjunto. Aquí sólo
mostraré las partes más importantes de la aplicación:

1. HookDll.dpr

   function KeyboardProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM):
     LRESULT; stdcall;
   var
     Handled: Boolean;
     KeyState: TKeyboardState;
     Han: HWND;

   function WinKeyPressed: boolean;
   begin
     Result := (KeyState[VK_LWIN] and $80 <> 0)
       or (KeyState[VK_RWIN] and $80 <> 0);
   end;

   begin
     Handled := False;
     Result := 1;
     if nCode = HC_ACTION then
     begin
       GetKeyboardState(KeyState);
       Han:=FindWindow('TForm1', APP_CAPTION);
       if (IsWindow(Han)) and (KeyState[wParam] and $80 <> 0)
           and WinKeyPressed then
       begin
         Handled := True;
         case wParam of
           VK_F9: SendMessage(Han,HOOK_MSG, APP_SHOW, 0);
           VK_F10: SendMessage(Han,HOOK_MSG, EJECT_CDROM, 0);
           VK_F12: SendMessage(Han,HOOK_MSG, APP_QUIT, 0);
         else
           Handled := False;
         end;
       end;
     end;
     if not Handled then
       Result := CallNextHookEx(hhk, nCode, wParam, lParam);
   end;

Al entrar el procedimiento gancho comprobamos la bandera HC_ACTION en
nCode (así sabemos si tenemos una acción de teclado), y luego guardamos
en KeyState el estado (si está presionada o levantada, invertida con
CapsLock, etc.) para todas las teclas virtuales usando GetKeyboardState.
También encontramos el manejador de ventana (window handle) de la apli-
cación principal a la que enviaremos los comandos (APP_SHOW, EJECTCDROM
y APP_QUIT). Si la encontramos (IsWindow(han)) y tenemos un mensaje de
teclado PRESSED (KeyState[wParam] and $80 <> 0) y la tecla Winkey
también está presionada, entonces enviamos un comando al formulario
principal de acuerdo a la tecla que ha sido presionada. Si no podemos
manejar el mensaje de teclado (Handled=False), entonces se lo pasamos
al siguiente gancho en la cadena.

2. Hooks.Dpr y Unit1.pas

La función más importante aquí es HOOK_MSG_PROC, que es la que recibe
los comandos enviados desde la DLL:

   type TForm1=class(TForm)
   ...
     procedure HOOK_MSG_PROC(var Msg: TMessage); message HOOK_MSG;
   ...
   end;
   ...
   procedure TForm1.HOOK_MSG_PROC(var Msg: TMessage);
   begin
     case Msg.WParam of
       APP_SHOW:
       begin
         Application.ShowMainForm := True;
         Visible:=True;
       end;
       EJECT_CDROM: mciSendString('set CDAudio door open',nil,0,0);
       APP_QUIT: Close;
     end;
   end;

La característica "ocultar al minimizar" se logra capturando el mensaje
WM_SYSCOMMAND que envía Windows cuando ocurre un mensaje de sistema
(como cerrar, minimizar, maximizar). Entonces ocultamos el formulario si
tenemos un comando SC_MINIMIZE:

   procedure TForm1.OnMinimize(var Msg: TMessage);
   begin
     if Msg.WParam = SC_MINIMIZE then
     begin
       if not IsHookInstalled then
       begin
         ShowMessage('Primero instale el gancho o no'#13#10 +
           'podrá acceder al programa');
         Exit;
       end;
       Application.ShowMainForm := False;
       Visible := False;
     end else
       Inherited;
end;

To hide the program from the tasks list we use:

   function RegisterServiceProcess(dwProcessID, dwType: integer):
     integer; stdcall; external 'KERNEL32.DLL';

NOTE: The above hiding technique works only on Windows 9x.

Of course this is only a very simple application of hooks, but the
possibilities are numerous. A small spy program, perhaps! :) Anyway, if
you have any questions about this article feel free to send me a note
to <aaa111@...>.

__________________

NOTA: Se adjunta el código fuente completo.

________________________________________________________________________

¿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!"
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
________________________________________________________________________


3. Codificar y decodificar Base64 (MIME)

    Por Daniel Wischnewski
        delphi3000@...


Escribí la siguiente unidad para reemplazar los componentes INDY
TIdEncoderMIME y TIdDecoderMIME. Este "Codec" se usa principalmente en
software de email.

La razón principal fue la carencia de velocidad de estos componentes.
La segunda razón fue que son componentes y consiguientemente requieran
la VCL - una pesada carga adicional para sistemas no-VCL.

Ambas rutinas están escritas en ensamblador y sobrecargadas en
distintas versiones para fácil acceso.

Estoy seguro que muchos de ustedes pueden incrementar la velocidad aún
más. Por favor háganmelo saber (en inglés). Gracias.

__________________

NOTA: Se adjunta el código fuente completo.

________________________________________________________________________

AnyShape Transpack v2.0 - por MindBlast Software (DELPHI + KYLIX)
¿Cansado de las aburridas ventanas rectangulares? AnyShape Transpack es
un componente multiplataforma (Delphi/Kylix) que facilita la creación de
ventanas transparentes y de formas extrañas con edición WYSIWYG, vista
previa en tiempo de diseño, arrastre automático, verdaderos formularios
en primer plano, combinación de regiones, y más. Shareware ($30).
http://www.mindblastsoftware.com/?page=transpack&ref=PascalNL
________________________________________________________________________


4. Ejemplo de un servicio Windows, con un hilo

    Por Kim Sandell - kim.sandell@...
        www.nsftele.com


Delphi 5 y 6 tienen una plantilla de proyectos para servicios, pero está
incompleta. Este ejemplo se construye sobre esa plantilla y completa el
servicio. También muestra cómo comenzar un hilo que emite un pitido cada
dos segundos. Puede usarlo como base al desarrollar servidores y
servicios.

El ejemplo ha sido diseñada para Delphi 5-7 y funciona en Windows
NT/2000/XP. La opción de inicio del servicio ha sido establecida a
MANUAL. Si quiere hacer un servicio que se inicie automáticamente con
Windows, entonces necesita cambias esto. ¡SEA CUIDADOSO! Si su aplica-
ción se cuelga cuando está corriendo como un servicio, NO HAY FORMA de
terminarla.

__________________

NOTA: Se adjunta el código fuente completo.

__________________

Author's Profile Summary:

Name   : Kim Sandell               Born : 1973 Helsinki, Finland
Skills : VB, Delphi (1-6), C/C++, SQL, Interbase, IP Networks.
Special areas: System Service, Protocols, Security (VPN),
                Authentication, Servers (Deamons) + More
Company: NSF Telecom Ab            Title: CTO
WWW    : http://www.nsftele.com    EMail: kim.sandell@...

________________________________________________________________________


5. Capturando la salida de una aplicación de consola

    Por Jochen Fromm <Jochen.Fromm@...>


¿Cómo ejecuta una aplicación de consola o DOS y captura su salida
mientras está corriendo? ¿Por ejemplo, cómo captura la salida del
comando FileCompare (FC)?

Ya hay dos artículos acerca de este problema,

   http://www.delphi3000.com/articles/article_2112.asp
   http://www.delphi3000.com/articles/article_2298.asp

pero obtienen la salida cuando el proceso ha finalizado. También hay dos
artículos de Microsoft acerca de redireccionamiento de aplicaciones DOS:

* Microsoft Knowledge Base Article - Q190351
   HOWTO: Spawn Console Processes with Redirected Standard Handles
   http://support.microsoft.com/default.aspx?scid=kb;en-us;Q190351

* Microsoft Knowledge Base Article - Q150956
   INFO: Redirection Issues on Windows 95 MS-DOS Applications
   http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q150956

La idea básica es ejecutar la aplicación de consola con CreateProcess y
redirigir la salida con tuberías (pipes), permitiendo al proceso
llamador acceder a la salida de la aplicación de consola.

Es importante capturar la salida mientras el proceso se encuentra aún en
ejecución. Si la tubería de salida se bloquea por un sobreflujo, la
nueva información no podrá ser escrita desde la aplicación de consola a
la tubería de salida, y el programa se detendrá. En este caso tenemos
situación de "abrazo mortal" (deadlock): el usuario (proceso padre) está
esperando que el proceso hijo termine, y el proceso hijo está esperando
que el padre limpie el buffer.

__________________

NOTA: Se adjunta el código fuente completo.

________________________________________________________________________


6. Creación de Objetos - Introducción (0 de 3)

    Por Oscar A. Esqueda Cortes


Antecedentes OOP
================

Antes de entrar a la programación de componentes, debemos recordar
conceptos básicos de la programación orientada a objetos.

Nota: En el boletín 36 se encuentra un articulo mío sobre POO (OOP por
sus siglas en inglés), más extenso que esta parte. Considere leerlo.

* ¿Que es POO?

   Básicamente no es un lenguaje, y tampoco es una técnica para hacer
   ventanitas y usar el Mouse, sino más bien es un conjunto de técnicas y
   metodologías (filosofías si quieren decirlo) para incrementar nuestra
   productividad al desarrollar software.

   El aumento de productividad significa tanto crear nuestros programas
   en poco tiempo, como también poder darles mantenimiento de una manera
   más rápida y eficaz.

   Las partes vitales de la POO son las clases y objetos, pero la piedra
   filosofal son: la Herencia, el Polimorfismo y la Encapsulación.

* Definición de Clase
   Una clase, es simplemente una abstracción que hacemos de nuestra
   experiencia sensible.

* Definición de Objeto
   Un objeto es un conjunto de datos y métodos que se comporta de acuerdo
   a las reglas de su clase.

* Herencia
   Crear una clase a partir de otra, pero tomando todas sus caracte-
   rísticas y funcionamiento es heredar una clase.

* Encapsulación
   El concepto de encapsulación consiste en implementar el comportamiento
   de una clase dentro de ella, sin que terceros ojos sepan como
   funciona.

* Polimorfismo
   La idea del polimorfismo consiste en crear una clase base de la cual
   dependerán varias clases, por herencia claro, pero el comportamiento
   de una clase hija no tiene porque ser igual a otra, aunque tengan los
   mismos métodos.

* Sobrecarga
   La sobrecarga no es estrictamente una característica OOP, pero la
   mencionamos aquí porque muchas veces se la asocia erróneamente con
   ella (posiblemente debido a su casi simultaneidad de aparición y
   porque es en la OOP donde más se observa se uso). La sobrecarga nos
   brinda versatilidad al permitirnos declarar más de una vez un mismo
   procedimiento o función con distintos parámetros (y opcionalmente
   distinto tipo de valor de retorno, en el caso de las funciones).


Arquitectura VCL
================

La herencia es la piedra angular de la VCL de Delphi. Todo está basado
en Clases y Objetos, desde la primera clase TObject que está declarada
en la unidad System.pas. De esta clase base derivan todas las demás
clases y componentes/controles con los que jugamos en tiempo de diseño.


Diagrama de la VCL
------------------

Este es un diagrama muy simple y resumido, pero cumple los requisitos
que necesitamos.

(Por lo regular al comprar el Delphi, se entrega un mapa de las clases,
péguenlo en la pared junto al poster de Cameron Díaz o quien tengan en
la pared, JE).

  ---------
| TOBJECT |
  ---------
      |
      |------------------|
  -----------      -------------
| EXCEPTION |    | TPERSISTENT |
  -----------      -------------
                         |
                   ------------
                  | TCOMPONENT |
                   ------------
                         |
                    ----------
                   | TCONTROL |
                    ----------
                         |
                         |----------------------|
                  -----------------       -------------
                 | TGRAPHICCONTROL |     | TWINCONTROL |
                  -----------------       -------------


Veamos un poco de las características de las clases principales de
Delphi.


TObject
-------

Esta clase es la clase principal en la VCL de Delphi. Todas las clases
(u objetos) derivan de esta clase principal. Esta clase implementa
información RTTI o de clases para identificación de las mismas. Es
decir, mantiene métodos que identifican a cada clase. Por ejemplo vea
algunos de ellos:

- ClassInfo  : Puntero a información del objeto.
- ClassName  : Nombre de la clase devuelta como string (útil para
                comparaciones).
- ClassParent: Clase de la que heredamos el objeto, nil si es TObject.
- ClassType  : Clase actual, devuelve un tipo TClass.

Esta clase base solamente da opciones de identificación de clases,
construcción y destrucción de objetos básica. Para mas información
busque TObject en la ayuda de Delphi.

Los objetos que derivan de TObject son Exception, TIniFile y TRegistry
entre otros, además de la siguiente clase en la escala jerárquica:
TPersistent.


TPersistent
-----------

Como su nombre lo indica es útil para mantenerse, es decir, todas las
clases que deseemos que se guarden en el archivo DFM de una forma deben
heredar de TPersistent. Básicamente, contiene métodos para guardar
información de la clase en Streams o conjunto de datos permanentes.
Útil para objetos dentro de objetos, por ejemplo las propiedades
HorzScrollBar y VertScrollBar de un TForm o las columnas de un DBGrid.
Los objetos que derivan de esta clase son por ejemplo las colecciones
como las columnas de un DBGrid o de un ListView.


TComponent
----------

La clase TObject es la principal de toda la VCL, pero la TComponent es
la principal para el diseño visual en Delphi. Todos los componentes no
visuales (TTable, TDatasource, TTimer, TActionList) heredan de esta
clase. Si vamos a crear un componente no visual, lo tendremos que
derivar de TComponent.

PROPIEDAD

La clase TComponent introduce un concepto de propiedad, es decir, cuando
uno crea componentes, digamos TLabel u otro, la llamada a su constructor
es así:

   := TLabel.Create(Form1);

donde decimos que el propietario del objeto es Form1. O sea que al
destruirse Form1, se encarga de destruir sus objetos designados. Esto
es útil para mantener una forma limpia de destrucción de objetos y
liberación de memoria.

NOTA: Aun así, si construye objetos en tiempo de ejecución, use un
Try/Finally para destruirlos.

Hay propiedades para el control de sus objetos designados, como:
- ComponentCount: Total de componentes dependientes.
- Componentes   : Arreglo iniciando de 0 de los componentes designados
                   al TComponent.

EJEMPLO
Viene un ejemplo llamado lstComp, para Delphi 5, donde muestra cómo
funciona esto. Es una lista que se llena con todos los componentes de
la forma. Además introduce el concepto de nombrado de objetos con su
propiedad Name, concepto que no tienen las clases anteriores, para
identificar a los componentes y sus descendientes.

Existen dos propiedades que merecen un poco de tiempo:

- ComponentState, que indica el estado del componente. Veamos algunas de
   sus propiedades.
   · csDesigning : El componente esta en tiempo de diseño.
   · csDestroying: El componente se esta destruyendo.

- ComponentStyle, para asignar el comportamiento del componente, estos
   son algunos de sus valores:
   · csInheritable: puede ser heredado.

Para la creación de componentes es útil el saber si estamos en tiempo de
diseño o alguna otra situación.

Los componentes derivados de TComponent son: TDatasource, TTable,
TQuery, TTimer, y todos los no visuales que sólo se ven en diseño.


TControl
--------

Los componentes visuales derivan de TControl. Es raro que creen un
componente de éste; lo mejor es de sus descendientes. La función de éste
es definir la finalidad del componente Padre. A excepción del TForm,
todo componente tiene un padre, que es su componente contenedor, los
componentes como TPanel y TGroupBox entre otros, permiten agrupar
componentes dentro de ellos.

Además, el TControl introduce propiedades que controlan su visibilidad,
como Top, Left, Width, Height y Visible, así como Fonts, Color, Anchors,
entre otras, pero hay dos que merece la pena verlas con calma (parecidas
al TComponent):

- ControlState: indica el estado del control, veamos algunos de sus
   valores:
   · csCreating : El control se esta creando.
   · csLButtonDown : se capturo un evento de botón de Mouse.
   · csFocusing : el control trata de obtener el foco.

- ControlStyle: la cual determina las características del control, el
   cual puede tener los siguientes valores:
   · csAcceptsControls : es un control contenedor.
   · csCaptureMouse : captura los eventos del Mouse.
   · csSetCaption : tiene titulo.
   · csMenuEvents : responde a eventos del menú del sistema.
   · csFixedWidth y csFixedHeight : Tamaño fijo.

De nuevo pido al lector que se de una vuelta por la ayuda en el tema
"TControl, ControlStyle" para mas información.

Estas dos son útiles en el caso de querer comprobar el estado del
control o el estilo del control nuevo, si es contenedor, aceptar
controles de Mouse u otros casos.

No hay objetos derivados de TControl que se usen directamente en la VCL.
Más bien se heredan dos para los cuales se crean todos los objetos
visuales: TGraphicControl y TWinControl.


TGraphicControl
---------------

Esta clase es la base para todos los objetos visuales que no reciben el
foco. Implementa una clase llamada TCanvas en una propiedad llamada
Canvas, la cual permite procedimientos de dibujo en ella.

Los objetos que reciben un foco, deben llevar un manejador o Handle de
ventana y requiere más recursos. Los GraphicControls usan los recursos
de su Parent para dibujarse y no gastar más recursos de los que
requeriría, por lo que un descendiente de TGraphicControl no tiene
Handle o manejador y no puede ser manipulado con API's, pero sí puede
recibir mensajes Windows o notificaciones. No recibe mensajes del
teclado sino sólo del Mouse, por el motivo de no recibir el foco.

Los controles que derivan de esta clase son: TBevel, TCustomLabel
(TLabel y TDBText), TImage, TPaintBox, TShape, TSpeedButton, TSplitter
y TToolButton (colección de TToolBar).


TWinControl
-----------

Los objetos TWinControl (TWidgetControl en Linux) encapsulan los objetos
Windows. En realidad todos los controles visuales Windows son Ventanas,
desde un punto de vista técnico, ya que todos tienen un Handle o
Manejador, que es un identificador único en todo el sistema operativo,
útil para las funciones API de Windows.

Las características que implementa la clase son:
- Poder recibir el foco y por lo tanto manejar eventos relacionados
   con el teclado.
- Ser contenedor de otros controles, vea las propiedades mas útiles.

Las propiedades más útiles son:
- ControlsCount     : Total de componentes dentro del contenedor.
- Controls          : Arreglo iniciando de 0 con los componentes
                       contenidos, devuelve un TControl.
- Handle            : Manejador de ventana asignado por Windows.
- ParentWindow      : Manejador de su Parent (padre).
- TabOrder y TabStop: Propiedades para el tab.

EJEMPLO:

El ejemplo que viene en el archivo adjunto muestra un TTreeView en el
cual se llenan, en el orden que están, los Parent (padre) de los
controles visuales.

En realidad, sólo pocos objetos son creados directamente de TWinControl
(TAnimate, THeaderControl, TProgressBar, TScrollBar), pero todos los
controles Windows, heredan de esta.


Las clases TCustomX
-------------------

Ahora, casi todos los controles derivan de alguna clase base que inicia
con TCustom, por ejemplo:

   TLabel = Class(TCustomLabel)
   TEdit = Class(TCustomEdit)
   TForm = Class(TCustomForm)

Estas clases fueron creadas para poder crear componentes nuevos a partir
de esos, es decir. Las clases como TLabel no traen nada distinto a la
clase TCustomLabel, solo el hecho de publicar ciertas propiedades y
métodos, para eso están las clases base TCustom.

Veamos la clase TCustomLabel (tomada del código VCL de Delphi 6):

   TCustomLabel = class(TGraphicControl)
   private
     FFocusControl: TWinControl;
     FAlignment: TAlignment;
     FAutoSize: Boolean;
     FLayout: TTextLayout;
     FWordWrap: Boolean;
     FShowAccelChar: Boolean;
     FOnMouseLeave: TNotifyEvent;
     FOnMouseEnter: TNotifyEvent;
     function GetTransparent: Boolean;
     procedure SetAlignment(Value: TAlignment);
     procedure SetFocusControl(Value: TWinControl);
     procedure SetShowAccelChar(Value: Boolean);
     procedure SetTransparent(Value: Boolean);
     procedure SetLayout(Value: TTextLayout);
     procedure SetWordWrap(Value: Boolean);
     procedure CMTextChanged(var Message: TMessage);
       message CM TEXTCHANGED;
     procedure CMFontChanged(var Message: TMessage);
       message CM FONTCHANGED;
     procedure CMDialogChar(var Message: TCMDialogChar);
       message CM DIALOGCHAR;
     procedure CMMouseEnter(var Message: TMessage);
       message CM MOUSEENTER;
     procedure CMMouseLeave(var Message: TMessage);
       message CM MOUSELEAVE;
   protected
     procedure AdjustBounds; dynamic;
     procedure DoDrawText(var Rect: TRect; Flags: Longint); dynamic;
     function GetLabelText: string; virtual;
     procedure Loaded; override;
     procedure Notification(AComponent: TComponent;
       Operation: TOperation); override;
     procedure Paint; override;
     procedure SetAutoSize(Value: Boolean); override;
     property Alignment: TAlignment read FAlignment write SetAlignment
       default taLeftJustify;
     property AutoSize: Boolean read FAutoSize write SetAutoSize
       default True;
     property FocusControl: TWinControl read FFocusControl
       write SetFocusControl;
     property ShowAccelChar: Boolean read FShowAccelChar
       write SetShowAccelChar default True;
     property Transparent: Boolean read GetTransparent
       write SetTransparent default False;
     property Layout: TTextLayout read FLayout write SetLayout
       default tlTop;
     property WordWrap: Boolean read FWordWrap write SetWordWrap
       default False;
   public
     constructor Create(AOwner: TComponent); override;
     property Caption;
     property Canvas;
     property OnMouseEnter: TNotifyEvent read FOnMouseEnter
       write FOnMouseEnter;
     property OnMouseLeave: TNotifyEvent read FOnMouseLeave
       write FOnMouseLeave;
   end;

Todas las propiedades están en Protected y la clase TLabel, lo que
hace es pasarlas a published, esto lo veremos en la siguiente parte
de este articulo.

   TLabel = class(TCustomLabel)
   published
     property Align;
     property Alignment;
     property Anchors;
     property AutoSize;
     property BiDiMode;
     property Caption;
     property Color;
     property Constraints;
     property DragCursor;
     property DragKind;
     property DragMode;
     property Enabled;
     property FocusControl;
     property Font;
     property ParentBiDiMode;
     property ParentColor;
     property ParentFont;
     property ParentShowHint;
     property PopupMenu;
     property ShowAccelChar;
     property ShowHint;
     property Transparent;
     property Layout;
     property Visible;
     property WordWrap;
     property OnClick;
     property OnContextPopup;
     property OnDblClick;
     property OnDragDrop;
     property OnDragOver;
     property OnEndDock;
     property OnEndDrag;
     property OnMouseDown;
     property OnMouseMove;
     property OnMouseUp;
     property OnMouseEnter;
     property OnMouseLeave;
     property OnStartDock;
     property OnStartDrag;
   end;


Reglas para escribir componentes
--------------------------------

Para terminar, les paso unos cuantos tips para escribir componentes, los
tome "prestados" de Marco Cantu (http://www.marcocantu.com, ya le tome
esto de su libro, pues les paso la dirección de su pagina), espero sirva
de orientación.

* Estudiar el Lenguaje de Pascal Orientado a Objetos: Herencia,
   Sobrescritura y sobrecarga de métodos, la diferencia entra las partes
   publicas y privadas de una clase y la diferencia entra propiedades y
   eventos. (NOTA: lean mi artículo de OOP y también varios de estos
   conceptos los veremos en el próximo artículo).

* Estudiar la jerarquía de las estructuras VCL (Nota: aquí tienen una
   pista en este artículo).

* Crear componentes sencillos, imitar a otros componentes y evitar
   dependencias.

* Usar excepciones. (bloques, try except, finally y el uso del raise con
   excepciones personalizadas).

* Identificar a cada componente con un mapa de bits para la paleta de
   componentes, además de nombrar lo mas significativamente el
   componente, ponerle una notación al principio para identificar de
   quien son y diferenciarlos de otros ya existente (ToecLabel, por
   ejemplo).

* Prepararnos para escribir código real, es decir, al escribir
   componentes por lo regular no se usara el aspecto Visual.

Estas son reglas muy básicas, mas bien para orientarnos, en las
siguientes ediciones haremos componentes, este fue el único artículo
teórico, en el siguiente haremos 5 componentes y explicaremos un poco
de ellos, además de darles el código fuente de ellos claro.

Hasta la próxima

Ing. Oscar A. Esqueda Cortes
Information Technology Consulting
http://www14.brinkster.com/itcmx
oesqueda@...

________________________________________________________________________


7. Inline Assembler en Delphi (IV) - Registros

    Por Ernesto D'Spirito <edspirito@...>


Pasando registros como parámetros
=================================

Al igual que los arreglos estáticos, los registros se pasan internamente
como punteros a los datos, independientemente de si el parámetro se pasa
por valor o por referencia (ya sea como "var" o como "const").

Dadas las siguientes declaraciones...

   type
     TRecord = record
       Id: integer;
       Name: string;
     end;

   var
     a, b: TRecord;

   procedure InitRecord(var r: TRecord; Id: integer; const Name: string);
   begin
     r.Id := Id;
     r.Name := Name;
   end;

...una llamada al procedimiento InitRecord en ensamblador sería así:

     // En Object Pascal:
     //   InitRecord(a, n, s);
     // En Inline Assembler:
     asm
       lea eax, a               // EAX := @a; // 1er parámetro en EAX
       mov edx, n               // EDX := n;  // 2do parámetro en EDX
       mov ecx, s               // ECX := s;  // 3er parámetro en ECX
       call InitRecord          // InitRecord;
     end;


Accediendo los campos de un registro
====================================

Los campos de un registro se encuentran a un cierto desplazamiento de la
dirección del registro (la dirección del primer campo). En el ejemplo,
asumiendo que tenemos la dirección de un registro de tipo TRecord en el
registro EAX, el campo Id está ubicado en [EAX+0] (o simplemente [EAX]),
y el campo Name está ubicado en [EAX+4], pero normalmente no escribimos
"números mágicos". En vez de ello, para producir un código autoexplica-
tivo y mantenible tenemos cinco formas alternativas:

   mov edx, [eax + TRecord.Name]
   mov edx, (TRecord PTR [eax]).Name
   mov edx, (TRecord [eax]).Name
   mov edx, TRecord[eax].Name
   mov edx, [eax].TRecord.Name

Las cinco sentencias de arriba se ensamblarían como:

   mov edx, [eax + 4]

En vez de un registro (como EAX), las sintaxis también se aplican a
nombres de variables locales.

Se puede inferir de la primer sintaxis que en inline assembler la
expresión TipoRegistro.Campo se evalúa en tiempo de compilación como una
constante representando el desplazamiento en el que se encuentra el
Campo en el TipoRegistro. Por ejemplo, la siguiente sentencia es válida:

   mov ecx, TRecord.Name   // mov ecx, 4

Volviendo al tema, el procedimiento InitRecord (introducido arriba) se
puede implementar en ensamblador de esta forma:

   procedure InitRecord(var r: TRecord; Id: integer; const Name: string);
   asm // EAX = @r;  EDX = Id;  ECX = @Name[1]
     mov (TRecord PTR [eax]).Id, edx    // EAX^.Id := EDX;  // Id
     // _LStrAsg(@EAX^.Name, @Name) --> EAX^.Name := Name
     lea eax, (TRecord PTR [eax]).Name  // EAX := @(EAX^.Name);
     mov edx, ecx                       // EDX := @Name[1];
     call System.@LStrAsg               // _LStrAsg(EAX, EDX)
   end;

Al entrar al procedimiento tenemos EAX apuntando al registro (primer
parámetro), EDX conteniendo el Id (segundo parámetro), y ECX apuntando
a los datos de la cadena Name (tercer parámetro). Asignar un entero es
bastante simple, pero asignar una cadena es un poco más complicado:

   If la cadena destino no es la cadena nula then
   begin
     Decrementar la cuenta de referencias de la cadena destino;
     If la la cuenta de referencias de la cadena destino es cero then
       Liberar la cadena destino;
   end;
   If la cadena origen no es la cadena nula then
     Incrementar la cuenta de referencias de la cadena origen;
   Asignar origen a destino;

El procedimiento _LStrAsg (en la unidad System) implementa esta lógica
por nosotros. El procedimiento recibe dos parámetros: el primero (en
EAX) es la cadena destino pasada por referencia, y el segundo (en EDX)
es la cadena origen pasada por valor (lo que en realidad se pasa es el
puntero, pues las cadenas son punteros a los verdaderos caracteres).
Consiguientemente, en nuestro caso, EAX debe apuntar a la dirección de
la variable string que será asignada assigned (es decir, EAX debe
contener la dirección de r.Name), mientras que EDX debe ser el valor a
asignar:

     EAX  --> r.Name --> r.Name[1]   ==>   EAX = @r.Name
     EDX  --> Name[1]                ==>   EDX = @Name[1]

     Ref.: "-->" significa "apunta a" (o "contiene la dirección de")

Así que establecemos EAX y EDX y luego llamamos a _LStrAsg:

     lea eax, (TRecord PTR [eax]).Name  // EAX := @(EAX^.Name);
     mov edx, ecx                       // EDX := @Name[1];
     call System.@LStrAsg               // _LStrAsg(EAX, EDX)


Funciones de bajo nivel para trabajar con registros
===================================================

Al igual que con los arreglos estáticos, si un registro se pasa por
valor entonces es responsabilidad de la función llamada preservar el
registro. Cuando una función necesita cambiar los valor de uno o más
campos de un registro pasado por valor, normalmente crea una copia local
y trabaja sobre la copia. El compilador crea una copia por nosotros en
el "begin" de funciones Pascal, pero en funciones totalmente en
ensamblador tenemos que hacerlo por nosotros mismos. Una forma de
hacerlo es como mostramos en la parte III con los arreglos estáticos.
Aquí tenemos otra forma:

   procedure OperateOnRecordPassedByValue(r: TRecord);
   var
     _r: TRecord;
   asm
     // Copiar los elementos de "r" (parámetro) en "_r" (copia local)
     // Move(r, _r, sizeof(TRecord));
     lea edx, _r                   // EDX := @_r;
     mov ecx, type TRecord         // ECX := sizeof(TRecord);
     call Move                     // Move(EAX^, EDX^, ECX);

     lea eax, _r                   // EAX := @_r;
     mov edx, TRecord_TypeInfo     // EDX := TRecord_TypeInfo;
     call System.@AddRefRecord     // System._AddRefRecord(EAX,EDX);

     lea eax, _r                   // EAX := @_r; // opcional

     // Aquí va el resto de la función. Trabajaremos sobre el registro
     // "_r" (la copia local), ahora apuntado por EAX.
   end;

En esta oportunidad hemos llamado al procedimiento Move en vez de copiar
los datos allí mismo con REP MOVSB. De esta manera escribimos menos
código.

IMPORTANTE: Copiar los valores de memoria sólo funciona con registros
que no contienen campos de tipos que cuentan referencia como las
cadenas, arreglos dinámicos o variantes de tipo cadena o arreglo
dinámico.

Si tenemos uno o más campos de tipo cadena, o campos de cualquier otro
tipo con conteo de referencias, después de copiar los valores de memoria
debemos incrementar sus respectivas cuentas de referencias. El procedi-
miento _AddRefRecord (en la unidad System) hace eso. Recibe dos pará-
metros: un puntero al registro (en EAX) y un puntero a los datos de
información de tipo para el registro generada por el compilador (en
EDX).

La información de tipo (type information) para un registro es básica-
mente una estructura de datos que contiene las posiciones y tipos de los
campos con conteo de referencias en el registro. Los procedimientos que
trabajan con registros declarados en la unidad System (específicamente
_InitializeRecord, _AddRefRecord, _CopyRecord y _FinalizeRecord)
requieren un puntero a los datos de información de tipo como su último
parámetro.

Pero, ¿dónde están esos datos? Bueno, desafortunadamente no hay un
símbolo para acceder su ubicación directamente. Tenemos que obtener su
dirección llamando a la función TypeInfo, pero ésta no es una función
que podemos llamar desde código en ensamblador porque no es una verda-
dera función, sino una función incorporada (built-in) que el compilador
resuelve en tiempo de compilación.

Una solución posible es inicializar una variable global llamando a la
función TypeInfo desde nuestro código Pascal:

   var
     TRecord_TypeInfo: pointer;

   :

   initialization
     TRecord_TypeInfo := TypeInfo(TRecord);

Y luego podemos usar esta variable así:

   procedure OperateOnRecordPassedByValue(r: TRecord);
   var
     _r: TRecord;
   asm
     // Copiar los elementos de "r" (parámetro) en "_r" (copia local)
     // Move(r, _r, sizeof(TRecord));
     lea edx, _r                   // EDX := @_r;
     mov ecx, TYPE TRecord         // ECX := sizeof(TRecord);
     call Move                     // Move(EAX^, EDX^, ECX);
     // System._AddRefRecord(@_r, TypeInfo(TRecord));
     lea eax, _r                   // EAX := @_r;
     mov edx, TRecord_TypeInfo     // EDX := TypeInfo(TRecord);
     call System.@AddRefRecord     // System._AddRefRecord(EAX, EDX);

     lea eax, _r                   // EAX := @_r; // opcional

     // Aquí va el resto de la función. Trabajaremos sobre el registro
     // "_r" (la copia local), ahora apuntado por EAX.

     // Tenemos que finalizar la copia local antes de regresar
     // System._FinalizeRecord(@_r, TypeInfo(TRecord));
     lea eax, _r                   // EAX := @_r;
     mov edx, TRecord_TypeInfo     // EDX := TypeInfo(TRecord);
     call System.@FinalizeRecord   // System._FinalizeRecord(EAX, EDX);
   end;

Notomos que antes de que la función retorne debemos hacer una llamada a
_FinalizeRecord para destruir la copia local (por ejemplo, esto decre-
mentará las cuentas de referencia de las cadenas apuntadas por campos de
cadena).

Llamar a Move y luego a _AddRefRecord es una forma válida de copiar
registros si y sólo si el registro destino no ha sido inicializados
(después de llamar a _AddRefRecord el registro queda inicializado). Si
el registro destino ya estuviera inicializado, entonces tenemos que
llamar a _CopyRecord en su lugar.

Por ejemplo:

   procedure proc(const r: TRecord);
   var
     _r: TRecord;
   begin
     // _r := r;
     asm
       mov edx, eax                // EDX := @r;
       lea eax, _r                 // EAX := @_r;
       mov ecx, TRecord_TypeInfo   // ECX := TypeInfo(TRecord);
       call System.@CopyRecord     // System._CopyRecord(EAX, EDX, ECX);
     end;
   end;

Notemos que puesto que ésta es una función Pascal normal (no una función
enteramente en ensamblador), el compilador automáticamente genera código
para inicializar y finalizar la variable de registro local (en el
"begin" y el "end" del procedimiento respectivamente).

La combinación Move más _AddRefRecord es idéntica en efecto a la
combinación _InitializeRecord más _CopyRecord:

   procedure OperateOnRecordPassedByValue(r: TRecord);
   var
     _r: TRecord;
   asm
     // Copiar los elementos de "r" (parámetro) en "_r" (copia local)
     // System._InitializeRecord(@_r, TypeInfo(TRecord));
     push eax                      // Push(EAX); // @r
     lea eax, _r                   // EAX := @_r;
     mov edx, TRecord_TypeInfo     // EDX := TypeInfo(TRecord);
     call System.@InitializeRecord // System._InitializeRecord(EAX, EDX);
     // _r := r;
     lea eax, _r                   // EAX := @_r;
     pop edx                       // EDX := Pop(); // @r
     mov ecx, TRecord_TypeInfo     // EDX := TypeInfo(TRecord);
     call System.@CopyRecord       // System._CopyRecord(EAX, EDX, ECX);

     lea eax, _r                   // EAX := @_r; // opcional

     // Aquí va el resto de la función. Trabajaremos sobre el registro
     // "_r" (la copia local), ahora apuntado por EAX.

     // Tenemos que finalizar la copia local antes de regresar
     // System._FinalizeRecord(@_r, TypeInfo(TRecord));
     lea eax, _r                   // EAX := @_r;
     mov edx, TRecord_TypeInfo     // EDX := TypeInfo(TRecord);
     call System.@FinalizeRecord   // System._FinalizeRecord(EAX, EDX);
   end;

Al igual que _AddRefRecord, el procedimiento _InitializeRecord es sólo
para ser usado con registros no inicializados.


Devolviendo valores registro
============================

Devolver registros es exactamente lo mismo que devolver arreglos
estáticos. Las funciones que devuelven registros reciben un último
parámetro adicional que es el puntero a la ubicación de memoria donde
deben colocar su valor de retorno, es decir, el valor del último
parámetro es @Result. La memoria para el resultado debe ser asignada,
inicializada, y liberada por el llamador (no es responsabilidad de la
función llamada). Por ejemplo, consideremos la siguiente función:

   function MakeRecord(Id: integer; const Name: string): TRecord;
   begin
     Result.Id := Id;
     Result.Name := Name;
   end;

La función se declara para recibir dos parámetros y devolver un
registro, pero internamente es como un procedimiento que recibe tres
parámetros:

   1) EAX = el Id para el nuevo registro
   2) EDX = el nombre para el campo Name del nuevo registro
   3) ECX = la dirección del registro Result (@Result)

La función puede ser rescrita en ensamblador como sigue:

   function MakeRecord(Id: integer; const Name: string): TRecord;
   asm // EAX = Id;  EDX = @Name[1];  ECX = @Result
     mov (TRecord PTR [ecx]).Id, eax    // ECX^.Id := EAX;  // Id
                                        // (@Result)^.Id := EAX;
                                        // Result.Id := EAX;
     // Result.Name := Name;
     // System.@LStrAsg(@(Result.Name), @Name[1])
     // System.@LStrAsg(@(ECX^.Name), @Name[1])
     lea eax, (TRecord PTR [ecx]).Name  // EAX := @(ECX^.Name);
     call System.@LStrAsg               // _LStrAsg(EAX, EDX)
   end;

   NOTA: No asignamos el valor de EDX antes de llamar a _LStrAsg
         porque EDX ya contiene el valor deseado (pasado como
         parámetro).


Llamando a funciones que devuelven registros
============================================

Consideremos el siguiente código:

   a := MakeRecord(n, s);

Uno estaría tentado a pensar que el compilador lo traducirá como:

   asm
     mov eax, n
     mov edx, s
     lea ecx, a   // ECX := @a;  // @Result
     call MakeRecord
   end;

Pero las cosas no suceden de esta forma, por lo menos no en Delphi 5. El
compilador asigna e inicializa una variable local para alojar el resul-
tado, y luego copia el registro resultado al registro destino. No sólo
que tenemos una ineficiencia por realizar una copia que sería innece-
saria, sino que -como vimos arriba- la copia misma no es tan inocente
como una llamada al procedimiento Move (_CopyRecord comprueba los datos
de la información de tipo en tiempo de ejecución para localizar los
campos que requieren tratamiento especial). Desde luego, esa variable
local invisible primero es inicializada y eventualmente es finalizada.
Esta forma de hacer las cosas es terriblemente ineficiente. Si alguien
necesita velocidad, mejor llame funciones que devuelven registros
usando ensamblador como mostré arriba, pasando directamente la dirección
de la variable que recibirá el registro resultado como último parámetro
(@Result).

Bien, esto es todo por ahora. En la siguiente parte veremos algunos
conceptos básicos sobre trabajar con objetos.

__________________

NOTA: Se adjunta el código fuente completo.

________________________________________________________________________


8. 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.

Estas reglas han sido tildadas por algunos de infantiles y déspotas, por
decir lo menos. Para los que tienen buena experiencia en foros y listas
de correo, estas reglas prácticamente no aportan nada nuevo, pero para
otros admito que pueden resultar molestas y algo chocantes. Realmente lo
siento, pero si he decidido establecerlas, no ha sido porque sí. Los
foros son para profesionales, y no para quienes desean publicar mensajes
como se les da la gana simplemente porque es gratis, sino que esperamos
un mínimo de seriedad y consideración hacia los demás.

He aquí el extracto de las reglas comunes a todos los foros:

* El asunto de los mensajes tiene importancia capital. Es lo primero y a
   veces lo único que se ve de un mensaje. 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). Los foros
   no son un motor de búsqueda humano.

* Incluye abundante información sobre el problema que planteas (como
   por ejemplo versión del producto y sistema operativo que usas, etc.)
   para no hacerle perder el tiempo a alguien preparando una respuesta
   que después no te sirva porque no se aplica a tu plataforma.

* 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).

* Los archivos adjuntos en los mensajes son descartados. Si tienes
   algo para compartir, contacta directamente al interesado, u ofrécelo
   en el foro aclarando que las peticiones deben enviarse a tu cuenta de
   email, y no a la dirección del foro.

* Por cualquier cuestión administrativa del foro (como por ejemplo
   problemas con tu suscripción, reportar casos de spam, etc.) no
   escribas al foro sino a su/s moderador/es.

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).
   http://espanol.groups.yahoo.com/group/delphi-abierto
   Suscripción:
     http://espanol.groups.yahoo.com/group/delphi-abierto/join
     delphi-abierto-subscribe@...

* 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@...

* 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

________________________________________________________________________


9. Delphi en la Red

    Por Dave Murray <irongut @ vizzavi.net>


Componentes, librerías y aplicaciones
=====================================

Freeware
--------

* Copernic Agent 6.0 - Freeware (adware, but not spyware) *NEW*
   It's the successor of Copernic 2001 5.0, the top metasearch software
   for the Internet ("Top Ten Internet Tools" by USA Today, 5-star rating
   from ZDNet, and "Best For 2001 - Top Five Software" by PC Magazine).
   Are you tired of wasting your time with meaningless results from
   search engines? Try searching with Copernic. It will surprise you!
   http://www.copernic.com/desktop/products/agent/index.html

* MathX
   2D and 3D graphics of one- and two-variables functions using OpenGL.
   Full source code is included.
   http://www.opensource.as.ro/public/MathX.zip


Artículos, trucos y consejos
============================

* Migrating BDE Applications to dbExpress - by Bill Todd
   This white paper discusses the migration of BDE-based applications to
   dbExpress.
   http://community.borland.com/article/0,1410,29106,00.html

* Cross-platform Development with Borland RAD Tools
   A white paper on native cross-platform development with Borland tools.
   http://community.borland.com/article/0,1410,29139,00.html

* Report to the Delphi Community on Project JEDI - by Alan C. Moore
   Alan C. Moore, the Project JEDI director, provides an update on the
   many projects under development with the Project JEDI team.
   http://community.borland.com/article/0,1410,29157,00.html

* Borland Kylix 3 versus Linux GCC Development - by William Roetzheim
   http://community.borland.com/article/0,1410,29171,00.html

* Using the .NET Preview compiler in the Delphi 7 IDE - by John Kaster
   An Open Tool for using the preview compiler with the Delphi 7 IDE is
   available for download.
   http://community.borland.com/article/0,1410,29159,00.html

* Top Windows API Books for Delphi Developers - by Zarko Gajic
   Recommended selection of top books on programming Delphi with Windows
   API, with links to book reviews. Books cover all of the most common
   Windows API functions, and each function has the syntax and an example
   of its use in Delphi Pascal.
   http://delphi.about.com/library/toppicks/aatpdelphiapibook.htm

* How to validate an IBAN?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1470

* How to get the installed keyboard layouts?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1471

* How to get/set the caret blink time?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1472

* How to encrypt/decrypt files with Windows NTFS functions?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1473

* How to get mouse wheel line count?
   http://www.swissdelphicenter.ch/en/showcode.php?id=1474

* How to obtain all characters in Delphi 4+ IDE - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=179

* How to obtain object property list - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=180

* How to refresh Windows desktop - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=181

* How to draw rotated text - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=182

* How to swap two numbers without a third variable - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=183

* How to turn numlock on by code - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=184

* Access a MySQL database from Delphi Standard or Personal - TheSaviour
   How to access a MySQL database from Delphi Standard or Personal using
   the TMySQL component.
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=185

* How to sort a TList - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=186

* How to set the width of a TComboBox - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=187

* How to access a remote registry - by m3Rlin
   www.delphifaq.net/modules.php?op=modload&name=FAQ&op=view&id=188

* How to change a property of all components at one time - by M. Suesens
   How to change a special property of all components that own this
   property at one time.
   http://www.delphi3000.com/articles/article_3365.asp

* CPU ID unit - by Mironescu Tony
   http://www.delphi3000.com/articles/article_3367.asp

* How to implement a Sequential List in a database - by Adesh Jain
   http://www.delphi3000.com/articles/article_3372.asp

* Export ALL tables from MS jet to CSV via ADO - by John Pears
   http://www.delphi3000.com/articles/article_3373.asp

* High speed parser V1.5 - by Yuriy Pisarev
   Component is intended for some mathematics and logical calculations.
   Works at high speed - about 10000000 operations per second for simple
   mathematics formulas and a little more for logical formulas.
   http://www.delphi3000.com/articles/article_3374.asp

* Safety Design with a Static Instance - by Max Kleiner
   How to build a real Singleton?
   http://www.delphi3000.com/articles/article_3376.asp

* Interbase Backup on the Fly in a thread - by Kim Sandell
   Make interbase database backups on the fly, in a background thread.
   http://www.delphi3000.com/articles/article_3378.asp

* Example of a Windows Service, with a thread - by Kim Sandell
   Delphi 5&6 has a template project for services, but it is incomplete.
   This example builds on that template and completes the service. It
   also shows how to start a thread that beeps every 2 seconds. You can
   use this as a base when developing servers as services.
   http://www.delphi3000.com/articles/article_3379.asp

* Interbase Sweep on the Fly in a thread - by Kim Sandell
   In the Interbase Admin components there is a IBValidationService but
   is hard to use as it is. Sweeping is just one of the functions of the
   validation service. This component makes doing sweeps of databases
   alot easier, and also works in a thread.
   http://www.delphi3000.com/articles/article_3380.asp

* How to write a TCP Redirector - by Kim Sandell
   Many people ask how to write servers in Indy, this primer goes through
   how a TCP server is created, and how to redirect all traffic to
   another remote server. This is the same as port-mapping in firewalls.
   http://www.delphi3000.com/articles/article_3381.asp

* ENTER instead of TAB key - by Léo Souza
   A simple alternative to allow form navigation with the ENTER key.
   http://www.delphi3000.com/articles/article_3382.asp

* How to create a animated (rotating) hourglass - Henk Schreij
   http://www.delphi3000.com/articles/article_3383.asp

* How to implement an Array Property - Max Kleiner
   In an interface we can't use fields so when you declare a class that
   implements one or more interfaces, you must provide an implementation
   of all the methods declared in the interface and the fields too.
   http://www.delphi3000.com/articles/article_3387.asp

* Change the color of a Listview or TreeView - by LExter LExter
   http://www.delphi3000.com/articles/article_3388.asp

* SQL without bureaucracy - by Josir Gomes
   How to quickly run SQL without dropping components on your form.
   http://www.delphi3000.com/articles/article_3389.asp

* Keyboard Hook - by William Egge
   Creating a keyboard hook in your application.
   http://www.delphi3000.com/articles/article_3390.asp

* Converting a SID to a string - by Bryan Ashby
   Convert a Security Identifier (SID) into a human-readable string.
   http://www.delphi3000.com/articles/article_3391.asp

* Changing Creation and Last accessed date/time for files - David Bolton
   http://www.delphi3000.com/articles/article_3392.asp

* How to check if an OLE object is installed - by Mike Shkolnik
   http://www.delphi3000.com/articles/article_3394.asp

* How to read contact list from MS Outlook - by Mike Shkolnik
   http://www.delphi3000.com/articles/article_3395.asp

* Fast data transfer to MS Excel - by Mike Shkolnik
   http://www.delphi3000.com/articles/article_3396.asp

* Multi Lingual BoolToStr() and SexToStr() - by Mike Heydon
   http://www.delphi3000.com/articles/article_3398.asp


Tutoriales
==========

* Introducción a las aplicaciones MDI - por Pablo Castagnino
   Introduce al programador al mundo de las aplicaciones MDI en Delphi y
   aporta soluciones a problemas típicos que se presentan al programar
   este tipo de interfaz.
   http://webs.sinectis.com.ar/alvadel/docs/mdi.htm

* Breve introducción a la programación multihilo - por Enrique Gonzalez
   Algunos conceptos básicos obre programación multihilo, y ejemplo.
   http://webs.sinectis.com.ar/alvadel/docs/multihilo.htm

* Navigating and Editing a ClientDataSet - by Cary Jensen
   You navigate and edit a ClientDataSet in a manner similar to how you
   navigate and edit almost another other dataset. This article provides
   an introductory look at basic ClientDataSet navigation and editing.
   http://community.borland.com/article/0,1410,29122,00.html

* Sophisticated Delphi Pascal techniques - by Zarko Gajic
   A Beginner's Guide to Delphi Programming: Chapter 7. Time to extend
   your Delphi Pascal knowledge to the max. Here are some intermediate
   Delphi problems and articles for everyday development tasks.
   http://delphi.about.com/library/weekly/aa091702a.htm

* Designing an XML Grammar with DTDs - by Philip Page
   XML is a great medium for data transfer and definition, but it must be
   consistent to make it consumable. Learn more about creating a DTD to
   determine consistent XML.
   http://builder.com.com/article.jhtml?id=u00320021004ppg01.htm

* SQL Basics: Creating and Altering Tables - by Shelley Doll
   Learn the basic DDL commands to add, alter, and remove tables and
   databases with this article from the Builder.com SQL basics series.
   http://builder.com.com/article.jhtml?id=u00320020902dol01.htm

* SQL Basics: Number Data Types - by Shelley Doll
   Failing to understand number data types poses a DBA's greatest risk of
   compromised data. The SQL92 standard dictates how database
   manufacturers define number behaviors, such as length and truncation.
   http://builder.com.com/article.jhtml?id=u00320020924dol01.htm

* SQL Basics: String Data Types - by Shelley Doll
   Data type implementations vary from database to database but a working
   knowledge of the SQL specification will always give you a good idea of
   what's going on. This article breaks down the basic rules of deploying
   string data types.
   http://builder.com.com/article.jhtml?id=u00320020918dol01.htm

* A Guide to Automatic Garbage Collection Systems - by Paul Tyma
   Java and .NET feature automatic garbage collection, which allows you
   to worry about programming instead of system cleanup. Learn more about
   the approaches often used to add this feature to applications.
   http://builder.com.com/article.jhtml?id=u00320020930gcn01.htm


Otros enlaces
=============

* GLScene en español
   La primera página sobre GLScene, OpenGL y Delphi en español. Demos,
   manuales y artículos.
   http://glscene.tripod.com

* Delphi 7 Update 1 - by Anders Ohlsson
   This update for Delphi 7 contains an updated MSSQL driver that fixes
   the problem with empty user names and passwords. It also fixes an
   issue with extra NULL characters being added to VARCHAR columns. The
   update also contains several documentation updates.
   http://community.borland.com/article/0,1410,29209,00.html

* Delphi 7/.NET User Group Tour 2002, US / Canada - by David Intersimone
   Borland is taking Delphi 7 and the Delphi Preview for Microsoft .Net
   on the road in the US and Canada.
   http://community.borland.com/article/0,1410,29089,00.html

* The Delphi Bug List
   http://buglist.jrsoftware.org/

* Pascal and its Successors - by Niklaus Wirth
   Pascal was designed in 1969 in the spirit of Algol 60 with a concisely
   defined syntax representing the paradigm of structured programming.
   With the advent of the micro computer it became widely known and was
   adopted in many schools and universities. In 1979 it was followed by
   Modula-2 which catered for the needs of modular programming in teams.
   In an effort to reduce language complexity and to accommodate object-
   oriented programming, Oberon was designed in 1988. This article
   presents some aspects of the evolution of this family of languages.
   http://www.swissdelphicenter.ch/en/niklauswirth.php

* Pascal IRC channel
   There is a very nice IRC channel about Pascal on DalNet
   (http://www.dal.net). The channel is just about Pascal (not Delphi).
   You can find it on irc.dal.net at #turbopascal. The channel also has
   a nice page with lots of sample codes. You can find their homepage at
   http://www.pastcow.org - As you can imagine, a channel for Delphi
   users can also be found there: #delphi.

* BorCon Europe
   London UK, October 28-29 2002
   http://www.borconeurope2002.com/

* BorCon Japan
   Tokyo Japan, November 19-20 2002
   http://www.borland.co.jp/

* BorCon France
   Paris France, November 21-22 2002
   http://info.borland.fr/conference/2002/

________________________________________________________________________


¡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.php3
   boletin-pascal-subscribe@...

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.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
   http://news.optimax.com/topdelphi/links.exe/click?id=70C517ECAE6E
   http://www.top219.org/cgi-bin/vote.cgi?delphi&83
   http://top100borland.com/in.php?who=20
   http://top200.jazarsoft.com/delphi/rank.php3?id=latium
   http://www.programacion.net/votar-enlace.php?id=474

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/descarga/p0040.zip
________________________________________________________________________

Página del grupo: http://espanol.groups.yahoo.com/group/boletin-pascal/
Para suscribirse/apuntarse: boletin-pascal-subscribe@...
Para cancelar/removerse:  boletin-pascal-unsubscribe@...
¿Problemas para administrar tu suscripción? edspirito@...
________________________________________________________________________

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.php3

Copyright (c) 2002 por Ernesto D'Spirito. Todos los derechos reservados.
________________________________________________________________________

#6 De: "Ernesto D'Spirito" <edspirito@...>
Fecha: Lun, 23 de Sep, 2002 12:19 am
Asunto: Boletín Pascal #39- 13-SEP-2002
edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo
 
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

________________________________________________________________________

¿Necesitas alojamiento para tu sitio web? http://www.tecnosoftonline.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/html/dil.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/html/dil.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 D'Spirito
boletin-pascal-owner@...

________________________________________________________________________

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-6 y C++ Builder 3-5.    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://www.idg.net/go.cgi?id=738304


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.co.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/ibadmin2.htm
________________________________________________________________________


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!"
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
________________________________________________________________________


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 D'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.nevrona.com/indy

    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 tabla