Boletín Pascal #47
Los ejemplos completos de código fuente de este número están disponibles para descargar.
![]() |
![]() |
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 eds2004 @ 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-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 <eds2004 @ 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) 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-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.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/?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.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/p0047.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@gruposyahoo.com Para cancelar / removerse: boletin-pascal-unsubscribe@gruposyahoo.com 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 Copyright (c) 2003 por Ernesto De Spirito. Todos los derechos reservados ________________________________________________________________________ |
Los ejemplos completos de código fuente de este número están disponibles para descargar.
![]() |
¿Errores? ¿Omisiones? ¿Comentarios? Por favor contáctanos!






