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
eds2008 @ latiumsoftware.com
__________________
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/?r=latiumsoftwarecomenpascal
________________________________________________________________________
2. Lineamientos sobre el rendimiento de Interbase (y II)
Por Peter Mc Leod <PeterMcLeod@practical.com.au>
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@mec.ac.in
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-2006 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.lmdinnovative.com/products/vcl/lmdstoragepack/
________________________________________________________________________
7. Inline Assembler en Delphi (VIII) - Aritmética entera de 128 bits (3)
Por Ernesto De Spirito <eds2008 @ latiumsoftware.com>
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)
________________________________________________________________________
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). Si estás
en la etapa de aprendizaje o si no te agradan los foros discriminados
por niveles, este foro es para ti.
http://espanol.groups.yahoo.com/group/delphi-abierto
Suscripción:
http://espanol.groups.yahoo.com/group/delphi-abierto/join
delphi-abierto-subscribe@gruposyahoo.com
* Delphi-intermedio. Programación en Delphi (nivel intermedio). Si ya
sabes mucho de Delphi, pero todavía te falta un largo trecho para ser
un gurú (o no tanto), este foro es para ti.
http://espanol.groups.yahoo.com/group/delphi-intermedio
Suscripción:
http://espanol.groups.yahoo.com/group/delphi-intermedio/join
delphi-intermedio-subscribe@gruposyahoo.com
* Delphi-avanzado. Programación en Delphi. Sólo para gurús.
http://espanol.groups.yahoo.com/group/delphi-avanzado
Suscripción:
http://espanol.groups.yahoo.com/group/delphi-avanzado/join
delphi-avanzado-subscribe@yahoogroups.com
* GrupoKylix. Programación en Kylix.
http://espanol.groups.yahoo.com/group/GrupoKylix
Suscripción:
http://espanol.groups.yahoo.com/group/GrupoKylix/join
GrupoKylix-subscribe@yahoogroups.com
* FreePascal-es. Programación en Free Pascal (freepascal.org).
http://espanol.groups.yahoo.com/group/freepascal-es
Suscripción:
http://espanol.groups.yahoo.com/group/freepascal-es/join
freepascal-es-subscribe@yahoogroups.com
* Desarrolladores-Software. Un lugar para tratar todos aquellos temas
relacionados con el desarrollo de software y su comercialización, y
para compartir experiencias en el ámbito laboral, profesional o
comercial con otros.
http://es.groups.yahoo.com/group/desarrolladores-software
Suscripción:
http://es.groups.yahoo.com/group/desarrolladores-software/join
desarrolladores-software-subscribe@yahoogroups.com
* Componentes. Un foro para buscar/recomendar componentes de software
(componentes VCL y CLX, objetos ActiveX, librerías DLL, etc.), así
como utilidades, tutoriales, información, etc.
http://espanol.groups.yahoo.com/group/componentes
Suscripción:
http://espanol.groups.yahoo.com/group/componentes/join
componentes-subscribe@yahoogroups.com
________________________________________________________________________
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.networkworld.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.ccs.neu.edu/research/demeter/related-work/
pragmatic-programmer/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://dn.codegear.com/article/29139
* 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/od/beginners/a/delphicourse.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/?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@gruposyahoo.com
Otra forma es votándonos en alguno de estos rankings para darle más
visibilidad a nuestro sitio web y aumentar así el número de suscrip-
ciones al boletín:
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://www.lawebdelprogramador.com/buscar/votar.php?id=615
Por favor vota. Son sólo unos segundos para ti que REALMENTE pueden
hacer la diferencia. Necesitamos tu ayuda para poder continuar.
________________________________________________________________________
Si no has recibido el archivo con el código fuente completo de los
ejemplos que se presentan en este boletín, puedes descargarlo de la
siguiente dirección: http://www.latiumsoftware.com/es/file.php?id=p47
________________________________________________________________________
Página principal: http://www.latiumsoftware.com/es/pascal/index.php
Página del grupo: http://espanol.groups.yahoo.com/group/boletin-pascal/
Para suscribirse / apuntarse: boletin-pascal-subscribe@gruposyahoo.com
Para cancelar / removerse: boletin-pascal-unsubscribe@gruposyahoo.com
Para reportar problemas con la suscripción: eds2008 @ latiumsoftware.com
________________________________________________________________________
Este boletín se provee "TAL Y COMO ESTA", sin garantía de ninguna clase.
Su uso implica la aceptación de nuestros términos de licencia y de la
ausencia de garantía que puedes leer en nuestro sitio web. Allí también
encontrarás una nota sobre marcas registradas. Te animamos a que redis-
tribuyas este boletín, siempre y cuando lo hagas en forma completa
(incluyendo la información de copyright), sin modificaciones y de manera
gratuita. Los artículos son copyright de sus respectivos autores y se
reproducen aquí con el permiso de los mismos.
________________________________________________________________________
Latium Software http://www.latiumsoftware.com/es/index.php
Copyright (c) 2003 por Ernesto De Spirito. Todos los derechos reservados
________________________________________________________________________
|