Boletín Pascal #53
Los ejemplos completos de código fuente de este número están disponibles para descargar.
![]() |
![]() |
Boletín Pascal #53 - 08-FEB-2005 Índice 1. Unas palabras del editor 2. Análisis de rendimiento del código con puntos de interrupción sin interrupción (non-breaking breakpoints) 3. Presentando YAPI 4. Estableciendo el manejador de eventos predeterminado de un componente 5. Antivirus en Delphi: aRC-Anti WODE.JPG 1.0 6. Foros / listas de correo 7. Delphi en la Red - Componentes, librerías y aplicaciones · Shareware / Comercial · Freeware · Actualizaciones de productos Borland - Artículos, trucos y consejos - Tutoriales y capacitación - Noticias - Otros / Sitios misceláneos ________________________________________________________________________ Tecno Soft Solutions. Reseller Autorizado de Symbol Technologies, líder mundial en captura de códigos de barras. >>> http://www.tecno-symbol.com ________________________________________________________________________ 1. Unas palabras del editor Finalmente me encuentro al día con las publicaciones. Es un gran alivio para mí. Les agradezco el apoyo que me han brindado todo este tiempo manteniendo vivo el interés en esta modesta publicación. Espero que en el 2005 podamos mantener el calendario de publicación que nos hemos propuesto. Los usuarios de Hotmail que no hayan podido descargar el archivo con el código fuente que acompañó al Boletin Pascal #52 debido a una falsa alarma de virus producida por el análisis heurístico de Trend Micro (el antivirus que usa Hotmail), pueden descargar dicho archivo desde mi sitio web: http://www.latiumsoftware.com/descarga/p0052.zip Bien, es hora de agradecer a los autores que contribuyeron su material para hacer posible esta edición: Jim McKeeth, Owen Mooney, Peter Johnson y Furious Logic. Nos complace entregar los premios de esta edición a: * Peter Johnson - "Estableciendo el manejador de eventos..." InstallAWARE 3.0 Express Edition - por MimarSinan Int. ($69.95) Desarrolle instaladores para Windows Installer sin necesidad de conocimiento previo de MSI. InstallAWARE automáticamente convierte en tiempo de creación un script de flujo condicional en una base de datos MSI que cumple con ICE, certificable con logotipo. El IDE ofrece una interfaz visual que genera su script de instalación por usted automáticamente y cuyo comportamiento puede ser completamente adaptado. Sigue vigente la oferta especial por tiempo limitado para los lectores del Boletín Pascal: 30% de descuento para todas las ediciones. ¡La Edición Empresarial a tan sólo $559.95! http://www.installaware.com/landingea.html * Owen Mooney - "Presentando YAPI" KnowedgeBASE Vortex 2.9 por Delphinium Software ($49.35) El corazón de KnowledgeBASE es un árbol de información altamente expandible y con gran capacidad de búsqueda, que puede verse como esquema o auditado dentro de un procesador de textos incorporado. Incluye una base de datos para referencias guardadas. http://www.download.com/KnowledgeBase-Vortex/3000-2064-10342084.html * Jim McKeeth - "Análisis de rendimiento del código..." YAPI Professional - por Owen Mooney ($95) Ofrece la más fácil y aún así poderosa capacidad de impresión desde Delphi. Provee configuración WYSIWYG, vista preliminar, campos independientes, campos enlazados a datos, texto, grids, tabs, mapas de bits, operación con TCanvas, posicionamiento preciso o de flujo libre, y todo usando sentencias "writeln" simples. http://free.hostdepartment.com/o/owenmooney/ Agradecimientos especiales a Delphinium Software por donar KnowledgeBASE Vortex y a Owen Mooney por donar YAPI Professional como premios continuos para futuras ediciones. Para la próxima edición tenemos tres premios para asignar entre los colaboradores de artículos en inglés: InstallAWARE 3.0 Professional Edition, KnowedgeBASE Vortex y YAPI Professional. La edición #54 será publicada en marzo, así que si tienen una idea para un artículo y saben inglés, ¡vayan escribiendo! Nos enorgullece continuar ofreciendo a los lectores un descuento especial sobre InstallAWARE 3 para Windows Installer, gracias a la linda gente de MimarSinan International. Por un tiempo limitado, los lectores pueden obtener un 30% de descuento siguiente este enlace: http://www.installaware.com/landingea.html Y ahora, ¡vayamos al código! Saludos, Ernesto De Spirito y Dave Murray boltin-pascal-owner@gruposyahoo.com ________________________________________________________________________ Help & Manual 3.50 por EC Software · Shareware ($ 279) - Una herramienta visual de autoría de ayuda para generar archivos WinHelp (.HLP), Adobe PDF, páginas HTML y los nuevos archivos HTML HELP (.CHM) introducidos en Windows 98, así como otros formatos de archivo y documentación impresa, todo desde una misma fuente. Una herramienta imprescindible para cualquier desarrollador de software. http://www.helpandmanual.com/ ________________________________________________________________________ 2. Análisis de rendimiento del código con puntos de interrupción sin interrupción (non-breaking breakpoints) Por Jim McKeeth <jim at mckeeth dot org> Resumen: A veces es bueno saber cuánto tiempo toma en ejecutarse una porción específica de código. El IDE de Borland provee un medio para lograr esto usando puntos de interrupción que no detienen la ejecución (non-breaking breakpoints) y el registro de eventos (event log). Este artículo fue publicado originalmente en la Borland Developer Network (ver Referencias) e incluye varias imágenes, las que aquí se publican en el archivo comprimido que acompaña este número. Ya sea porque tenga un punto en su programa que corre más lento de lo esperado, o porque está debatiendo cuál sería la forma más rápida de hacer algo, necesita medir el rendimiento de una porción de código. En los viejos tiempos añadiríamos algo de código a nuestros programas para registrar la hora de inicio y final de procesos específicos. Luego lo removeríamos o lo comentaríamos hasta que lo necesitáramos nuevamente. Ahora usamos analizadores de rendimiento de código ("code profilers") que cronometran la ejecución de cada línea de nuestro código y nos proveen con reportes detallados y gráficos. Podríamos tomarnos semanas examinando todos los datos disponibles. Los analizadores de aplicaciones son muy lindos, pero a veces no disponemos de uno conveniente, o realmente no queremos lidiar con uno por tan sólo un par de líneas de código, o puede que insertar toda la información de depuración adicional para que funcione el analizador produzca un cambio en el comportamiento de nuestro programa. En vez de volver al pasado y añadir todo ese código para registrar las horas de inicio y fin, podemos usar puntos de interrupción sin interrupción. La mayor ventaja de esta técnica comparada con el uso de un analizador de rendimiento tradicional es cuando tenemos un programa bastante complejo corriendo y queremos analizar algo de código en el momento, sin tener que reiniciar el programa y ejecutar el analizador. Se puede focalizar este análisis muy específicamente, de modo que no causaría el impacto en el comportamiento general de nuestro programa que causarían otros analizadores. En los casos en los que tenga unas pocas selectas rutinas que desee analizar, encontrará esta técnica más rápida y fácil de acometer. Este artículo está escrito para Delphi 7, pero las técnicas deberían trabajar con pocos o ningún cambio en otras versiones de Delphi, así como C++ Builder y Kylix. El código adjunto es específico para Windows, pero estoy seguro que un programador Kylix con recursos sabría qué APIs de Linux usar en su lugar. Antes de enseñarles como usar los puntos de interrupción sin interrupción para analizar el rendimiento de su código, voy a cubrir algunas bases sobre los puntos de interrupción sin interrupción. Si ya se siente cómodo con las características avanzadas de los puntos de interrupción, puede saltar a la sección sobre Análisis de Rendimiento. ¿Qué son los puntos de interrupción sin interrupción? ----------------------------------------------------- Sé que probablemente estén pensando que un punto de interrupción sin interrupción sea una contradicción. Como veremos a continuación, en realidad no lo es. Cary Jensen ofrece un gran artículo titulado "Usando puntos de interrupción sin interrupción en Delphi", disponible en la Borland Developer Network (ver Referencias). No se preocupen si no lo han leído. Cubriré todo lo que necesitan saber aquí. El Free Online Dictionary of Computing (Diccionario Online Libre de Computación) define un punto de interrupción como sigue: Punto de interrupción Un punto en un programa que, al ser alcanzado, genera algún comportamiento útil al proceso de depuración. Generalmente, los puntos de interrupción se usan para detener ("pausar") la ejecución del programa, y/o volcar los valores de algunas o todas las variables del programa. Los puntos de interrupción pueden ser parte del programa mismo, o pueden ser establecidos por el programador como parte de una sesión interactiva con una herramienta de depuración para escrutinizar la ejecución del programa. Así que los puntos de interrupción no siempre detienen (o "pausan") la ejecución del programa. Un mejor nombre sería puntos de interrupción sin detención, pero independientemente de cómo los llamemos, estamos usando puntos de interrupción que no detienen la ejecución y aún así generan un comportamiento especial. Así que, ¿cómo obtenemos uno de esos divertidos puntos de interrupción? En realidad es muy simple: 1. Crear un punto de interrupción de la forma habitual (yo uso F5) 2. Traer el diálogo "Source Breakpoint Properties" (habitualmente yo hago clic derecho sobre el punto de interrupción y selecciono "Breakpoint Properties..." en el menú contextual) 3. Hacer clic en el botón "Advanced >>". 4. Desmarcar la casilla de verificación "Break". 5. Hacer clic en el botón "OK". Fig 1. Basic Breakpoint Properties Antes de presionar el botón "Advanced" (Avanzado), el diálogo "Source Breakpoint Properties" muestra la configuración predeterminada del punto de interrupción. Note que especifica el nombre de archivo y el número de línea en el que se encuentra el punto de interrupción. Están en gris en esta vista indicando que están deshabilitados porque estamos editando las propiedades de un punto de interrupción existente. Si estuviéramos creando o editando un punto de interrupción desde la "Breakpoint List" ([CTRL]+[ALT]+[B] para la lista, [CTRL]+[A] y [CTRL]+[E] para crear un punto de interrupción) entonces estos campos no estarían deshabilitados y los podríamos especificar. Fig 2. Advanced Breakpoint Properties El diálogo "Breakpoint Properties" después de hacer clic en el botón "Advanced" incluye muchas características poderosas. Por ahora estamos interesados en la casilla "Break" (interrupción). Desmárquela y haga clic en "OK". Su punto de interrupción se seguirá viendo igual. No está deshabilitado (como se indica con una línea verde y un símbolo de detención gris), pero si corre su programa ahora ya no pausa en esa línea. Si al correr el programa la línea cambia de color a verde oscuro, entonces su punto de interrupción está una línea que no ejecuta código. Elija una de las líneas con un punto azul a la izquierda y repita el proceso. Está bien, esperaré. Si lo hizo bien, su programa correrá sin detenerse en ese línea. En este momento esto no es muy útil, pero al menos ya sabe cómo establecer un punto de interrupción sin detención. Registrando con un punto de interrupción ---------------------------------------- Ahora que tenemos nuestro punto de interrupción sin interrupción, lo que queremos es que escriba en un registro cuando se ejecuta la línea de código que está marcando. Vuelva al diálogo "Breakpoint Properties". Note que va directamente a la vista avanzada pues ha hecho un cambio en la sección "Actions" (acciones). Ahora vamos a hacer otro cambio. Vamos a añadir texto al cuadro combinado "Log message" (registrar mensaje). Al analizar mi código habitualmente tengo un punto de interrupción con registro en el inicio y otro al final del bloque a analizar, y hago que esos puntos de interrupción registren "Inicio" y "Fin" respectivamente. Si corre su programa ahora, después de hacer este cambio, no notará ninguna diferencia obvia. El mensaje fue registrado en el "Event Log" (registro de eventos), el que puede ser accedido desde el menú del IDE (View -> Debug Windows -> Event Log) o presionando [Ctrl]+[Alt]+[V]. Tenía tres puntos de interrupción establecidos en mi programa, con el primero y el último registrando un mensaje. Así es como se ve mi Event Log: Fig 3. Event Log Las líneas en rojo son las que resultan de un punto de interrupción. Notará tres líneas "Source Breakpoint" (punto de interrupción en código fuente) y dos "Breakpoint Message" (mensaje de punto de interrupción). Todas las otras líneas son interesantes pero distraen un poco, así que ocultémoslas por ahora. Simplemente haga clic derecho en la ventana de registro y elija "Properties" (Propiedades). Esto mostrará el diálogo "Debugger Event Log Properties" (Propiedades del Registro de Eventos del Depurador). Fig 4. Debugger Event Log Properties En el grupo "Messages" (Mensajes) puede desmarcar cualquier casilla para un mensaje que no desea ver. Simplemente desmarque todas las casillas, incluyendo la casilla "Breakpoint messages" (mensajes de puntos de interrupción). La casilla de mensajes de puntos de interrupción es algo engañosa. En realidad quita las líneas de "Source Breakpoint", dejando las líneas de mensajes de puntos de interrupción (Breakpoint Message). También puede cambiar los colores y otra información que le guste. Yo encuentro que el registro es más fácil de leer para analizar desmarcando la casilla "Display process info with event" (Mostrar información de proceso con evento). Si usa su Event Log también para otros propósitos, recuerde volver a cambiar la configuración a la original cuando haya terminado. Ahora, cuando corro el programa, el Event Log se ve como se muestra en la figura 5. Esperemos que el suyo sea similar. Fig 5. Event Log conciso Imagino que estará de acuerdo en que esto es mucho más conciso. CONSEJO: En vez de usar Inicio y Fin puede encontrar más útiles otros mensajes. Algunas sugerencias: nombre de la función llamada, número de línea, objeto siendo accedido, nombre de la consulta ejecutada, definición del bucle, etc. Analizando el Rendimiento ------------------------- Ahora que sabemos como crear entradas en nuestro de eventos, podemos usar esa característica para analizar el rendimiento de nuestro código. Mientras que mostrar que se entra y sale de un bloque de código es útil, eso no es exactamente análisis de rendimiento. Lo que necesitamos es una medida de tiempo que muestre cuánto tiempo llevó la ejecución de algún código. Esto puede lograrse usando la característica "Eval Expression" (evaluar expresión) del punto de interrupción. Vuelva al diálogo "Source Breakpoint Properties". Esta vez coloque GetTickCount en el cuadro combinado "Eval Expression". GetTickCount es una API Win32 que devuelve un cardinal conteniendo el número de milisegundos desde que la computadora fue iniciada por última vez. Para la programación en Delphi, esta función se encuentra en la unidad Windows, así que asegúrese de incluirla en su cláusula Uses. Mientras que el número devuelto son milisegundos, la resolución en realidad no está en milisegundos. Si tiene dos llamadas distanciadas por un par de milisegundos, puede que devuelvan el mismo número. La resolución puede obtenerse con la API GetSystemTimeAdjustment. Además, puesto que se usa un cardinal (o DWORD), el valor recomenzará desde cero cada 49,7 días. No es algo de lo que probablemente se tenga que preocupar corriendo un sistema operativo MS Windows que haya estado arriba tanto tiempo, pero es algo a tener en cuenta. En mi programa añadí GetTickCount a los tres puntos de interrupción, dejando el Incio y Fin en los dos primeros. Al ejecutar mi programa nuevamente se genera mucha más información útil en el Event Log. Fig 6. Event Log con GetTickCount Las líneas coloreadas con salmón o rosa ahora muestran los resultados de la evaluación de la expresión. Note que hay dos líneas "Breakpoint Message", y tres líneas "Breakpoint Expression. Si pusiéramos un mensaje en el segundo punto de interrupción, algo como "Medio", entonces tendríamos un número para cada uno. De lo contrario, no tendríamos forma de asociar el resultado de GetTickCount con un lugar específico del código. Si en el diálogo "Debugger Event Log Properties" rehabilitamos los "Breakpoint messages" para que se muestren, tendríamos también el número de línea. Personalmente prefiero usar mensajes significativos, incluyendo el número de línea, pero puede usar lo que mejor satisfaga sus necesidades. Como podemos ver por estos datos, tomó 1,5 segundos ir del primer punto de interrupción al segundo., y cerca de 1 segundo para llegar al tercero. Parece como que tengo algo de optimización que hacer. Si tiene curiosidad por saber cómo arribé a esos valores, es una simple cuestión de restar cada número al que le sigue, y dividir por 1000, redondeando al medio segundo más cercano. Al usar la característica "Eval Expression" del punto de interrupción, la expresión evaluada debe estar referenciada globalmente y sólo puede ser una función que se incluya en su código compilado. Puesto que Delphi tiene un enlazador optimizante, quita las funciones que no tienen chance de ser ejecutadas por el programa. GetTickCount es una de esas funciones que siempre tiene una posibilidad de ser llamada y se incluye ya sea que la llamemos explícitamente o no, así que siempre está allí. Si usamos otra función, una que escribamos o una de otra librería o llamada API, debemos asegurarnos que esté enlazada. Asimismo, cuando llamamos a un método de un objeto que cambia el valor de un campo, esos cambios puede que no se hayan llevado a cabo después que termina la evaluación. Análisis de rendimiento avanzado -------------------------------- ¿Qué hay si no quisiera hacer la resta mentalmente? O tal vez realmente desea una resolución de 1 milisegundo en su análisis. Esto implica agregar algo de código a su programa, pero hay un truco para asegurar que el código no sea incluido en su programa cuando lo construya sin información de depuración. En vez de usar GetTickCount podemos usar la rutinas de temporizador de alto desempeño, también provistas en la API de Windows. Estas rutinas no son tan directas de usar, así que en vez de colocar complejas Eval Expressions le sugiero construir algunas funciones para hacer las cosas más fáciles. Estas funciones también pueden sustraer los valores entre llamadas. Las API QueryPerformanceCounter y QueryPerformanceFrequency API acceden al temporizador de alto desempeño disponible en la mayoría de los sistemas. Desconozco sobre la situación cuando estos contadores no están disponibles. Para más información sobre esta funciones API consulte la MSDN o la documentación del Windows SDK incluida con Delphi. Tenga presente que usan Int64s en vez de Cardinals, y que son precisas más allá del milisegundo. En el archivo ZIP que acompaña este número encontrará mi librería para usar estas llamadas API. Es muy simple de usar; hay tres funciones: ElapsedMS, ResetElapsed y UpTimeMS. Añada la unidad JimProfiling.pas a se cláusula Uses y podrá usar estas funciones en sus Eval Expressions. ElapsedMS Muestra cuántos milisegundos transcurrieron desde la última llamada a ElapsedMS. ResetElapsed Resetea el contador de tiempo. UpTimeMS Muestra cuántos milisegundos transcurrieron desde que se inició el programa. Después de correr su programa tiene algo útil, y bastante preciso, en la ventana Event Log. Fig 7. Event Log usando la unidad JimProfiling Note que la segunda llamada a ElapsedMS tiene un valor menor que la primera. Esto es porque es el tiempo desde la primer llamada. La llamada a UpTimeMS es en realidad mayor que la suma de las dos llamadas a ElapsedMS porque incluye el tiempo anterior a la llamada a ResetElapsed así como la pequeña cantidad de tiempo posterior a la segunda llamada a ElapsedMS. CONSEJO: Si necesita una línea para poner un punto de interrupción para llamar a ResetElapsed o alguna otra función, sólo agregue una línea Sleep(0). Aunque esto tenga algún impacto en su programa, debería ser mínimo. La excepción es si está tratando con múltiples hilos de ejecución (threads), puesto que cuando llama a Sleep le transfiere la ejecución a otro hilo. Todo el código de esta unidad se encierra en directivas {$IFOPT D+}, de modo que se dejará afuera cuando compile su aplicación sin información de depuración, así que no necesita acordarse de removerla de su cláusula Uses. Puesto que el alcance de Eval Expression es global, puede poner la unidad en cualquier cláusula Uses de su aplicación y aún así podrá usarla en todas las unidades a lo largo de su proyecto. Consejos finales ---------------- Si desea conservar su análisis entre sesiones de programación, asegúrese de usar la opción "Autosave Project Desktop" (Autoguardar Escritorio de Proyecto). Esto guardará la ubicación de todas sus ventanas así como cualquier punto de interrupción que tuviera. Puede habilitarla desde la pantalla "Tools" -> "Environment Options", en la ficha "Preferences" bajo el encabezado "Autosave Options". Si no desea que siempre se guarden sus cambios al escritorio, puede activar esta opción, guardar el proyecto una vez, y luego volverla a desactivar. Eso tomará una instantánea de las cosas que no cambiarán cuando se hagan futuros cambios. Estas configuraciones se guardan en el archivo [proyecto].dsk, que está en formato de texto plano (tipo INI). Puede editarlo directamente si gusta. Recuerde que si edita este archivo, y tiene el IDE abierto y autorguardar habilitado, entonces puede sobrescribir sus cambios. Además, los puntos de interrupción se rastrean por número de línea, así que si añade o quita una línea arriba de una línea con un punto de interrupción, entonces el punto de interrupción puede moverse a una línea incorrecta. CONSEJO: Si especifica una condición, entonces el registro sólo se efectuará si la condición es verdadera. La pantalla "Breakpoint List" es otro recurso valioso. La mencioné más arriba como otra forma más de crear puntos de interrupción. Puede ir a esta pantalla usando el atajo de teclado [CTRL]+[ALT]+[B] o desde el menú View -> Debug Windows -> Breakpoints. Fig 8. Breakpoint List Note que la columna "Action" (Acción) muestra los mensajes y expresiones que estamos registrando. Puede tener varios grupos de puntos de interrupción para análisis. Luego, desde el menú contextual puede habilitar o deshabilitar un grupo entero de puntos de interrupción. También puede usar la característica Enable / Disable Group de otro punto de interrupción para activar o desactivar estos grupos como sea necesario. CONSEJO: Editar puntos de interrupción (con clic derecho o usando [CTRL]+[E]) desde esta pantalla le permite moverlos a otras líneas o archivos. Esto es especialmente útil si tiene acciones complejas establecidas y no desea recrearlas. También puede establecer múltiples puntos de interrupción sobre una misma línea usando la opción "Keep Existing Breakpoint" (Mantener el punto de interrupción existente). Conclusión ---------- Esta técnica de analizar su código usando el IDE estándar de Delphi y puntos de interrupción sin interrupción le provee con tiempos de análisis de ejecución con precisión de 1 ms, altamente confinable a un fragmento específico del código. Mientras que esto no reemplaza completamente la necesidad de una herramienta de análisis de código en su caja de herramientas de programación, le provee con otra poderosa alternativa para crear programas más rápidos en menos tiempo usando el poderoso IDE que ya posee. Referencias ----------- - "Using Non-Breaking Breakpoints in Delphi" por Cary Jensen http://bdn.borland.com/article/0,1410,31263,00.html - "Code Profiling with Non-Breaking Breakpoints" by Jim McKeeth http://bdn.borland.com/article/0,1410,31905,00.html - "Non-Breaking Breakpoint Profiling Library 1.0" por Jim McKeeth http://codecentral.borland.com/codecentral/ccWeb.exe/listing?id=21280 ________________________________________________________________________ Ayúdanos a conseguir más suscriptores votando por el Boletín Pascal (Pascal Newsletter) en estos rankings: http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E http://www.programmingpages.com/?r=latiumsoftwarecomenpascal http://top100borland.com/in.php?who=20 http://top200.jazarsoft.com/delphi/rank.php3?id=latium ________________________________________________________________________ 3. Presentando YAPI Por Owen Mooney <owenm at scottech dot net> http://free.hostdepartment.com/o/owenmooney/ Yapi - ahora en la versión 2. Ahora soy un programador "senior". Me corté los dientes con Fortran, hice my tesis en Algol-60 (¿alguien se acuerda de eso? - antes del Pascal) y a principio de los 90 aprendí a odiar la API de Windows usando Borland C++ y OWL ("'Orrible Windows Library"). Luego descubrí Delphi y es lo que usé desde entonces. Lo único que siempre le ha faltado a Delphi, ha sido una herramienta de impresión decente. Los QReports eran inservibles para impresión general. Compramos un producto de terceros de Nevrona. Con dedos temblorosos y entusiastas abrí el manual y comencé a leer. ¡Oh, cielo! La herramienta nunca se usó. Quedó en el estante por cuatro años hasta que la tiré a la basura el año pasado. Al final, toda mi impresión la realicé sobre el lienzo (canvas) de TPrinter. Había escuchado que muchos programadores Delphi habían hecho lo mismo. No he usado las nuevas herramientas de D2005 todavía, así que no puedo comentar sobre ellas. Probablemente no las probaré porque no necesito hacerlo. Después de unos pocos años de fustración construí mis propias herramientas de impresión y --si me permiten un momento de autofelicitación-- ¡son las mejores! Diseño - La programación ------------------------ Quería que las nuevas herramientas fueran fáciles de usar, que siguieran el más importante principio Delphi: simplicidad. Después de algunos años de lidiar con C++ para Windows me crucé con Delphi y dije "¡Ah - Sí! Así es como debe ser." Quería que mis herramientas de impresión evocaran esa reacción. No sólo deberían ser más simples que otras herramientas de impresión, sino MUCHO más simples - ¡deberían ser fenomenales! Comencé por principios básicos. En los viejos tiempos programábamos reportes más o menos así: writeln(printer,' Mi Gran Reporte'); // Centrado writeln(printer); // Línea vacía writeln(printer,'La primera línea'); for i := 0 to count - 1 do begin writeln(printer,'El dato para la línea ',i,' ',Data[i]); end; Con cada writeln el cabezal de la impresora matricial cobraba vida y recorría el ancho de la página, aportando lo suyo a la contaminación sonora de la oficina. Mientras la tecnología puede parecer muy cruda para los estándares de hoy, programar este tipo de cosas era fácil. Esto es por una muy importante razón: Un reporte muy complejo podía contener cientos de writes y writelns, pero el flujo de código seguía el flujo general del reporte. Esta correspondencia hacía la programación fácil tanto de escribir como de seguir. Puede ver un reporte e imaginarse cómo estaría codificado, y podía ver el código e imaginar el reporte. Esta metodología se cae a pedazos con impresoras modernas y el requerimiento de proveer una vista previa de impresión. Herramientas como QReports y otras tienden a tener una estructura que ejecute sentencias SQL o llame a código de evento escrito por el usuario. El flujo de la ejecucución es controlado por el código de ellos, no por el suyo. Todo lo que usted obtiene son algunos eventos. Si tiene un reporte complejo, lo que obtiene es una "explosión de complejidad" a medida que su código intenta recordar qué cosa sucede cuándo. No sé usted, pero yo me di por vencido. Yapi provee el mismo flujo lógico del viejo writeln. En Yapi, el código equivalente al viejo código de arriba es: Paper.clear; Header.writeln('Mi Gran Reporte'); // Centrado, pero sin contar espacios Header.writeln; Body.writeln('La primera línea'); for i:=0 to count-1 do begin Body.write('El dato para la línea '); Body.writeattab(inttostr(i),1); Body.writeattab(inttostr(Data[i]),2); end; Paper.preview; Ese es todo el código requerido para imprimir el equivalente a la vieja impresión matricial, pero por supuesto con márgenes, bellas fuentes, encabezados y pies de página, paginación automática y una muy buena pantalla de vista preliminar. Diseño - El formateo -------------------- Bien, por supuesto que la gente espera control WYSIWYG sobre la disposición de la página, fuentes, tabulaciones y otros formatos. No soy tan tonto como para proveer otra cosa. Yapi provee varios componentes para esto, como sigue: El componente Paper: Provee configuración WYSIWYG para toda la estructura del reporte. Se configuran los márgenes y las tabulaciones, así como la orientación del papel. Típicamente las dimensiones están en milímetros, pero también se pueden proveer pulgadas. El componente Paper muestra todos estos detalles en tiempo de diseño, pero es invisible en tiempo de ejecución. El componente Text: Los componentes Text se usan para establecer las fuentes para los reportes (incluyendo su color). Se usan para el grueso de la impresión. El componente Tab: Éstos establecen las tabulaciones. Pueden ser arrastrados a la posición, o puede establecerse su posición (en milímetros o pulgadas). También se provee tabulación dinámica por código. Estos tres componentes son el conjunto básico. Probándolo ---------- Vayamos al corazón del asunto. ¿Cómo hacer que se imprima algo y cuán fácil es iniciarse? Bien, los pasos absolutos más simples son como sigue: 1. Arrastre un componente Yapi Paper a su formulario 2. Arrastre un componente Yapi Text al papel 3. Agregue un botón al formulario. En su evento OnClick añada tres líneas de código: YapiPaper1.clear; YapiText1.writeln('Hola Mundo'); YapiPaper1.preview; Eso es todo. Ejecute el programa, presione el botón y tiene una pantalla de vista previa, y otro botón en la pantalla de vista previa realiza la impresión. Los documentos tienen un tutorial de 5 minutos, que hace más o menos esto. Si no puede hacer esto en 5 minutos, tiene una promisoria carrera como tejedor de canastas. Más componentes --------------- Los tres componentes de arriba (disponibles como conjunto gratuito) le permiten realizar casi cualquier generación de impresión basada en texto. Por supuesto, la gente quiere más. Otros componentes son: * Un componente encabezado y pie (un componente hace ambos) * Un componente cuadrícula (grid) para hacer reporte como un stringgrid o un dbgrid * Un componente imagen para hacer mapas de bits (las imágenes pueden determinarse en tiempo de diseño o de ejecución) * Un componente paintbox * Un componente db report El componente encabezado y pie hace (por supuesto) números de página. Producir una cuadrícula fue un problema de diseño realmente interesante. ¿Cómo programa uno una cuadrícula sin contradecir la bella filosofía de diseño que ya tenía? La respuesta vino después de algunas cervezas (en realidad ese es un inserto colorido para aliviar el aburrimiento de lo que de otro modo es una seca disertación técnica). El componente de cuadrícula de texto es como un componente de texto ordinario, pero dibuja una caja alrededor de sí mismo. Ponga dos cajas, y sus lados adyacentes se una para formar una línea. Ponga unos abajo de otros, y los lados superiores e inferiores se unen en una sola línea de cuadrícula. Ponga filas y columnas juntas y "hey presto" - ¡una cuadrícula! Todo esto hace que las cuadrículas sean tan fáciles como texto tabulado ordinario. El componente imagen era también una razonablemente obvia inclusión, pero aún quedaba un último desafío de impresión - ¿cómo trataría Yapi con texto y gráficos arbitrarios? La respuesta vino como la Yapi PaintBox, la que opera con TODOS los métodos existentes de TCanvas. En este punto, algún gnomo como programador comentará: "¡Oye bobo! Si programas yapiPaintbox como un objeto Canvas, ¿por qué no usar el canvas de TPrinter?" La respuesta es simple: "¡Porque la yapiPaintbox también provee vista preliminar!' Con la V2 se incluye un db report. Esto es realmente sólo para aquellos programadores que creen que uno debería arrastrar y soltar todo un programa y protestar agriamente a todas y cada una de las líneas de código que tengan que escribir. Este componente produce un reporte a partir de una TQuery o una TTable con una sola sentencia: yapidbreport.open He provisto el db report como una unidad objeto separada. Esto impide que el código de bases de datos de Delphi se enlace en programas que no son de bases de datos. Implementación -------------- Bueno... ¡No fue fácil! Con cada write o writeln, Yapi crea un "token" para representar el elemento impreso. Almacena y luego usa esos tokens para renderizar la página relevante en la vista previa de impresión, o en el canvas de TPrinter. Suena fácil, ¿no? Cada token es un objeto. Se usó herencia para generalizar el código lo más posible. La jerarquía de clases para los tokens relevantes es: TyapiObject - Clase abstracta; maneja mucho del procesamiento TyapiTextObject - Puede ser un texto o una cuadrícula de texto TyapiGraphicObject - Puede ser una imagen o un paintbox Cada uso de write o writeln genera un nuevo token para representar un elemento en el reporte. En la codificación inicial todos esos componentes se almacenaban en un arreglo en el componente Paper, pero tenía una explosión de complejidad. Hora de hacer trizas el código y comenzar de nuevo. Añadí una nueva clase por cada línea y la complejidad quedó bajo control. En esta segunda versión cada write o writeln añade un nuevo token en el objeto de la línea actual. Además, cada writeln completa el objeto de la línea actual y comienza una nueva. Las líneas se almacenan en un arreglo dinámico dentro del objeto Paper. Los componentes en sí han sido creados una forma bastante estándar. El componente Paper hereda de TCustomPanel y opera como un contenedor de líneas, así como una herramienta para configurar el reporte. Tab, paintbox e image heredan del componente TGraphicControl. Tanto text como grid-text heredan de una clase base abstracta común, que a su vez hereda de TCustomLabel. Estuve muy agradecido que Borland proporcionara el código fuente de la VCL. Me arrastré bastante por él para ver cómo se hacían las cosas. La vista previa de impresión ---------------------------- La vista preliminar de impresión es un formulario Delphi estándar. La impresión se renderiza en un TPaintbox. La vista previa de impresión hace lo que esperaría. Seleccionar número de página, aumento/disminución de tamaño, selección de impresora, selección de rango de páginas - todo eso se provee. Además tiene un par de lindos trucos. El primero es la habilidad de controlar líneas viudas y huérfanas. Una característica única de la vista preliminar de Yapi es la capacidad de cambiar tabulaciones y márgenes en tiempo de ejecución, en la ventana de vista previa. Esa maldita línea al pie puede ser eliminada simplemente estirando el margen inferior de la página hacia arriba. La línea desaparece y aparece en la página siguiente. Otro truco de la pantalla de vista previa es guardarla en un archivo. Hay dos opciones: si la guarda en un archivo con extensión .csv, eso es lo que obtiene. Las tabulaciones del reporte se usan para separar las columnas del archivo csv. Si la guarda en un archivo .bmp, obtiene la página actual como un mapa de bits. Elegí el formato de salida bmp porque es el soportado por la VCL básica. Esto significa que no tendrá problemas de enlazamiento. Si necesita salida a un archivo pdf, entonces le sugiero obtener un driver de impresión pdf. Conclusión ---------- Sólo porque Yapi es muy fácil de usar no la confunda por una herramienta cruda. Hay muchos trucos sutiles tras bambalinas para hacer su vida más fácil (por ejemplo ajuste de línea, ajuste en una cuadrícula de texto y manejo de memo.text para mencionar unos pocos). Échele un vistazo a algunos de los reportes de muestra (por ejemplo FishFacts.pdf) en la página web. Son ejemplos PDFs usando el driver de impresión PDF. La Yapi básica está disponible gratis. Tiene lo básico, pero aún así es una herramienta útil. Visite http://free.hostdepartment.com/o/owenmooney/ A propósito, Yapi es un acrónimo de "Yet Another Printer Interface." ________________________________________________________________________ InstallAWARE 3.0 para Windows Installer por MimarSinan International Oferta especial: 30% de descuento en la Enterprise Edition, sólo $559.95 InstallAWARE es la siguiente generación en herramientas de autoría de instaladores con características únicas como distribución web parcial, avisadores de progreso Flash y HTML, diez temas de instalación llamativos, diálogos de instalación completamente configurables, y un lenguaje de instalación que automáticamente se convierte en archivo de Windows Installer. >>> http://www.installaware.com/landingea.html <<< ________________________________________________________________________ 4. Estableciendo el manejador de eventos predeterminado de un componente Por Peter Johnson, Copyright (c) 2004 <delphidabbler at tiscali dot co dot uk> http://www.delphidabbler.com/ ¿Por qué este artículo? ----------------------- Cuando hace doble-clic en la mayoría de los componentes Delphi en tiempo de diseño, el IDE automáticamente crea un manejador de evento vacío para el evento predeterminado. A veces necesita que un evento diferente sea el predeterminado. El propósito de este artículo es explicarle cómo hacer eso (hay más información sobre este tema en el archivo de ayuda de Delphi 7, pero el ejemplo que allí se provee es incorrecto). Hagamos esto un poco más concreto considerando estos tres componentes: type TCompA = class(TComponent) private fOnFoo: TNotifyEvent; fOnBar: TNotifyEvent; fOnClick: TNotifyEvent; fOnChange: TNotifyEvent; fOnChanged: TNotifyEvent; fOnCreate: TNotifyEvent; published property OnFoo: TNotifyEvent read fOnFoo write fOnFoo; property OnBar: TNotifyEvent read fOnBar write fOnBar; property OnChange: TNotifyEvent read fOnChange write fOnChange; property OnChanged: TNotifyEvent read fOnChanged write fOnChanged; property OnClick: TNotifyEvent read fOnClick write fOnClick; property OnCreate: TNotifyEvent read fOnCreate write fOnCreate; end; TCompB = class(TComponent) private fOnFoo: TNotifyEvent; fOnBar: TNotifyEvent; fOnChange: TNotifyEvent; published property OnFoo: TNotifyEvent read fOnFoo write fOnFoo; property OnBar: TNotifyEvent read fOnBar write fOnBar; property OnChange: TNotifyEvent read fOnChange write fOnChange; end; TCompC = class(TComponent) private fOnFoo: TNotifyEvent; fOnBar: TNotifyEvent; published property OnFoo: TNotifyEvent read fOnFoo write fOnFoo; property OnBar: TNotifyEvent read fOnBar write fOnBar; end; Haciendo doble-clic en los componentes en el Delphi IDE se crean los siguientes manejadores de evento: * TCompA: OnCreate * TCompB: OnChange * TCompC: OnBar Supongamos que quisiéramos que el evento OnFoo sea el creado en todos los casos. Veremos como hacerlo durante en el curso de este artículo. Algo de base ------------ Antes que podamos resolver nuestro problema necesitamos examinar cómo Delphi 7 decide cuál evento usar como predeterminado (las cosas son un poco diferentes en Delphi 4 - tal como veremos después). Cuando se hace doble-clic a un componente, Delphi llama al método Edit del editor de componente registrado. El editor de componente registrado predeterminado es TDefaultEditor y es éste editor el responsable de crear el manejador de evento. Ahora examinemos cómo TDefaultEditor.Edit decide cuál es el evento predeterminado. Tras pasar por un proceso, en última instancia el método Edit llama al método TDefaultEditor.EditProperty una vez por cada propiedad del componente. En vez de pasar a EditProperty una referencia a la propiedad misma, lo que se le pasa es una referencia al editor de propiedad asociado. EditProperty chequea el nombre por cada propiedad de evento y guarda el editor de propiedad del evento preferido. Estos eventos, en orden de preferencia, son: * OnCreate * OnChange * OnChanged * OnClick * el primer evento alfabéticamente Esto significa que si un evento OnCreate está presente, se usa como el predeterminado. Si no está presente, se usa el evento OnChange y así. sucesivamente. Si no está presente ninguno de los eventos de la lista, se usa el primero por orden alfabético. Redefiniendo el comportamiento predeterminado --------------------------------------------- De la discusión anterior queda claro que si hemos de especificar el evento predeterminado, tendremos que cambiar la formar en que trabaja TDefaultEditor.EditProperty. Afortunadamente para nosotros, este método es virtual, así que podemos derivar TDefaultEditor y redefinir EditProperty. La nueva clase puede ser declarada muy simplemente como sigue: type TMyCompEditor = class(TDefaultEditor) protected procedure EditProperty(const PropertyEditor: IProperty; var Continue: Boolean); override; end; La implementación es igualmente directa: procedure TMyCompEditor.EditProperty(const PropertyEditor: IProperty; var Continue: Boolean); begin // only call inherited method if required event name if CompareText(PropertyEditor.GetName, 'OnFoo') = 0 then inherited; end; Ahora examinemos cómo trabaja. Recuerde que en la clase base el método TDefaultEditor.EditProperty es llamado una vez por cada propiedad del componente. El método elige el evento predeterminado entre los que le son pasados. Ahora, si TDefaultEditor.EditProperty es llamado una sola vez, entonces el evento predeterminado será aquel cuyo editor de propiedad sea pasado en esa única llamada. Nuestro método redefinido trabaja asegurándose que el método heredado sea llamado sólo una vez - para el evento que queremos que sea el predeterminado. En nuestra clase descendiente, es el método TMyCompEditor.EditProperty el que es llamado por cada propiedad del componente. El método simplemente comprueba si el editor de propiedad tiene el nombre requerido ('OnFoo') y pasa ese editor de propiedad -y sólo ese editor de propiedad- al método heredado. ¡Y voilá - OnFoo es el evento predeterminado! Una solución reutilizable ------------------------- En el código que desarrollamos en la sección previa, el nombre del evento predeterminado es fijo, o -como se dice en la jerga- está "cableado", término derivado del inglés "(hard-)wired". Nuestro siguiente trabajo es generalizar la solución para hacer más fácil de reutilizar el código. Puesto que las clases sólo se distinguen por el nombre del evento predeterminado que seleccionan, desarrollaremos una clase base que tienen un método abstracto que las descendientes pueden redefinir para devolver el nombre del evento requerido. Esta es la declaración de la clase base: type TCompEditorBase = class(TDefaultEditor) protected function DefaultEventName: string; virtual; abstract; { override to return name of default event } procedure EditProperty(const PropertyEditor: IProperty; var Continue: Boolean); override; { records property editor of default event } end; La implementación no debería ser sorpresa - simplemente reemplazamos el nombre que estaba cableado en la clase anterior por una llamada al método abstracto: procedure TCompEditorBase.EditProperty( const PropertyEditor: IProperty; var Continue: Boolean); begin if CompareText(PropertyEditor.GetName, DefaultEventName) = 0 then inherited; end; Ahora podemos implementar un editor de componente para un evento predeterminado específico -nuesto viejo amigo OnFoo otra vez- simplemente redefiniendo el método abstracto DefaultEventName como sigue: type TCompEditor = class(TCompEditorBase) protected function DefaultEventName: string; override; end; ... function TCompEditor.DefaultEventName: string; begin Result := 'OnFoo'; end; Arrelgos finales ---------------- Para que estos ejemplos compilen necesitamos usar las unidades Classes, SysUtils, DesignIntf y DesignEditors. Note que las dos últimas sólo pueden usarse al integrar con el IDE - no pueden usarse en aplicaciones independientes. También necesitamos registrar el editor de componentes en el procedimiento Register de nuestra unidad como sigue: procedure Register; begin RegisterComponentEditor(TCompA, TCompEditor); // etc ... end; Diferencias con Delphi 4 ------------------------ En Delphi 4, TDefaultEditor.EditProperty tiene un prototipo diferente. Se lo declara como: procedure EditProperty(PropertyEditor: TPropertyEditor; var Continue, FreeEditor: Boolean); Podemos tratar con esto usando compilación condicional. Asumiendo que está definido el símbolo DELPHI6ANDUP cuando usamos Delphi 6 o superior, podemos implementar el procedimiento TCompEditorBase.EditProperty como sigue: procedure TCompEditorBase.EditProperty( {$IFDEF DELPHI6ANDUP} const PropertyEditor: IProperty; var Continue: Boolean {$ELSE} PropertyEditor: TPropertyEditor; var Continue, FreeEditor: Boolean {$ENDIF} ); begin if CompareText(PropertyEditor.GetName, DefaultEventName) = 0 then inherited; end; Adicionalmente necesitamos reemplazar las unidades DesignIntf y DesignEditors por DsgnIntf: uses Classes, SysUtils, {$IFDEF DELPHI6ANDUP} DesignIntf, DesignEditors; {$ELSE} DsgnIntf; {$ENDIF} Resumen ------- En este artículo hemos visto como cambiar el manejador de evento predeterminado que se abre en el IDE cuando se hace doble-clic en un componente. Primero examinamos la manera en la que Delphi decide cuál evento usar para este propósito y luego desarrollamos una subclase de TDefaultEditor que puede especificar explícitamente el evento predeterminado. Luego procedimos a generalizar la solución desarrollando una clase base abstracta para editores de componentes que modifica el evento predeterminado. La discusión principal cerró con un repaso de las unidades requeridas para compilar las nuevas clases y dimos una mirada a como registrar el editor de componentes. Finalmente discutimos los cambios necesarios para compilar el código con Delphi 4. Código demo ----------- Si quiere experimentar con este código, el archivo ZIP adjunto que acompaña esta edición contiene código demostrativo que implementa los componentes de ejemplo y los editores de componentes tratados en este artículo. __________________ Peter Johnson es un programador hobbyista que vive en West Wales (Reino Unido) y que "chapotea" en Delphi. Mantiene el sitio web DelphiDabbler (http://www.delphidabbler.com/) donde publica sus artículos y sus aplicaciones y componentes Delphi gratuitos. Una versión completa de este artículo se encuentra disponible en: http://www.delphidabbler.com/download.php?file=article-17-demo.zip ________________________________________________________________________ JfControls Lib. Multilenguaje. Multiapariencia. Skins. Privilegios. Más de 40 componentes integrados y personalizables. Múltiples problemas de programación resueltos. Administración centralizada de recursos. Para Delphi 3-7 y C++ Builder 3-6. http://www.jfactivesoft.com/spindex.htm ________________________________________________________________________ 5. Antivirus en Delphi: aRC-Anti WODE.JPG 1.0 Como les había prometido hace un par de números atrás, presentamos un nuevo aporte que nos envía Furious Login desde Lima, Perú. En esta oportunidad se trata de un antivirus específico para el gusano conocido popularmente como WODE.JPG o también conocido como virus de la china (o de la japonesa). Pueden encontrarse referencias de este virus bajo los nombres W32/Rayl.A, W32/Rayl.A.worm, Win32/Elomon.worm.48644, W32.Seone.A, AdClicker-BD, Exploit.HTML.Mht, Worm.MSN.Elon.a o TrojanDownloader.Win32.Delf.ed según la fuente. El virus brotó en septiembre del año pasado, y se propagaba mediante MSN, pero no se transmitía por el MSN, sino que mostraba al contacto de la persona con la PC infectada un enlace para ver una imagen wode.jpg en un sitio de Internet. Al hacer clic en el enlace no se bajaba directamente una imagen, sino una página web que contenía la imagen... ¡y algo más! Aprovechando una vulnerabilidad conocida, la página incluía un IFRAME desde el que se bajaba otra página, la que contenía código en Visual Basic Script (VBS) que a su vez bajaba un archivo en formato CHM que se ejecutaba inmediatamente en la zona de seguridad local, y a partir de allí el resto naturalmente era historia: el archivo CHM extraía su carga útil, un archivo ejecutable, y lo ejecutaba; a su vez este ejecutable extraía otros dos archivos ejecutables y procedía a la infección. El programa Delphi que les presento aquí (se incluye en el archivo adjunto con el código fuente correspondiente a este número) fue escrito originalmente en C++ Builder 6.0 y fue distribuido antes que la mayoría de los más importantes antivirus pudieran detectar y eliminar el virus. El programa hace exactamente lo que realizan los programas de este tipo: 1) Detectar la presencia del virus. 2) Terminar los procesos relacionados con el virus. 3) Eliminar los archivos del virus. 4) Eliminar las entradas usadas por el virus para ejecutarse al iniciar Windows. Para detectar la presencia de la infección se busca entre los procesos en ejecución para determinar si alguno de ellos corresponde al virus. En vez de la API EnumProcesses, este programa ilustra el uso de las API Toolhelp32Snapshot, Process32Next y CloseHandle para idéntico propósito. Habiendo determinado que un proceso corresponde a un virus, el programa hace uso de la API OpenProcess para obtener el handle con el cual llamar a TerminateProcess para terminar el proceso. ADVERTENCIA: La aplicación MSN Messenger es también terminada de modo abruto. Perderá las conversaciones y datos que no hubiera guardado. Se recomienda que usted cierre manualmente el MSN Messenger antes de ejecutar este programa. El programa luego busca y elimina los archivos principales y temporales del virus, y finalmente elimina la entrada en el registro de Windows que permite la ejecución del virus cuando Windows se inicia. ADVERTENCIA: Como toda aplicación que elimina archivos del disco duro y elimina entradas en el Registro de Windows, debe tomar sus recaudos antes de utilizarla. El programa pude ser adaptado para remover otros virus y gusanos que usan procesos de infección similares. ________________________________________________________________________ Ayúdanos a conseguir más suscriptores votando por el Boletín Pascal (Pascal Newsletter) en estos rankings: http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E http://www.programmingpages.com/?r=latiumsoftwarecomenpascal http://top100borland.com/in.php?who=20 http://top200.jazarsoft.com/delphi/rank.php3?id=latium ________________________________________________________________________ 6. Foros / listas de correo Recordamos a los suscriptores las direcciones de nuestros foros. Para unirse a algún foro, lo más recomendable es hacerlo desde la web para así tener acceso a todas las áreas del foro y la configuración de las opciones de suscripción, pero también es posible suscribirse por email. Para suscribirse desde la web es necesario poseer un ID de Yahoo! (si no tienes el tuyo, puedes conseguirlo gratis registrándote como usuario de Yahoo!). * Delphi-abierto. Programación en Delphi (todos los niveles). Si estás en la etapa de aprendizaje o si no te agradan los foros discriminados por niveles, este foro es para ti. http://espanol.groups.yahoo.com/group/delphi-abierto Suscripción: http://espanol.groups.yahoo.com/group/delphi-abierto/join delphi-abierto-subscribe@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 ________________________________________________________________________ KnowedgeBASE Vortex 2.9 por Delphinium Software ($49.35 US) KnowledgeBASE Vortex presenta un árbol de información altamente buscable y expandible, que puede verse como esquema o auditado dentro del procesador de textos incorporado en la aplicación. Incluye una base de datos para referencias almacenadas. http://www.download.com/KnowledgeBase-Vortex/3000-2064-10342084.html ________________________________________________________________________ 7. Delphi en la Red Por Dave Murray <irongut at vodafone dot net> Componentes, librerías y aplicaciones ===================================== Freeware -------- * Clearer v1.7 - by Mauro Venturini (with source) History is a great new feature of Delphi 2005. There is only a little drawback: after project completion getting rid of all the history files is a bit annoying. Clear makes this more easy. It also takes care of .NET local storage accumulation due to version changes. http://www.torry.net/tools/developers/other/Clearer1.6Clearer.zip * Delphi Scintilla Interface Components v0.16 - Jan Pettersen (w source) Use the Scintilla Project Syntax Highlighting edit control with Delphi Define your own languages based on the lexers in the SciLexer.dll (Scintilla Project), with the styles and keywords needed directly from the Delphi designer. Tested with Delphi 7. http://delphisci.sourceforge.net/ * Graphics32 v1.7 - by Graphics32 Team (open source, MPL) Graphics32 is a library designed for fast 32-bit graphics handling on Delphi and Kylix. Optimized for 32-bit pixel formats, it provides fast operations with pixels and graphic primitives, and in most cases Graphics32 outperforms the standard TCanvas classes. It is almost a hundred times faster in per-pixel access and about 2-5 times faster in drawing lines. http://graphics32.org/ * PUses v2.2 - by Mauro Venturini (with source) PUses implements orderly reformatting of uses clauses, including: rewriting the unit/namespace names one per line and sorting them; optionally adding the prefix unit (generated using PrefiIt!) names. Supports Delphi 2005 only. http://www.torry.net/tools/other/ide/PUses2.0PUses.zip * TTrimmingLabel v1.0 - by Mauro Venturini (with source) TTrimmingLabel is a Windows Forms label that can trim the Text string to adapt it to the available Width. The trimming is controlled by the Trimming property (of type System.Windows.Forms.StringTrimming). Supports Delphi 2005 only. http://www.torry.net/vcl/labels/enhancedlabels/TrimmingLabel.zip * Undo/Redo for TeeChart Pro VCL v1.02 - by Ivo Ungermann (with source) Component for limited or unlimited undo / redo function with TChart (part of TeeChart Pro VCL package from Steema Software). Automatically traced TChart events: Zoom, Unzoom, Scroll. Other chart changes traced with a bit of code. Tested with TeeChart Pro 7 VCL, Delphi 5 - 7. http://www.torry.net/vcl/charts/charts/TChartUndoRedo.zip * sTile v2.7 - by harmware A graphics program to create seamless 'tiles' which can be used as background images for web pages and applications. It has many filters and effects and is a fun little program to play with. By nature, it produces somewhat psychedelic images, but they can be toned down or muted for actual use. Samples on the web site include a brick wall. http://www.harmware.com/stile.htm Actualizaciones de productos Borland ------------------------------------ * Public Beta: Delphi 8 Update 3 This patch is designed to correct issues with .NET versioning for Delphi 8. This is a dcu breaking change. Version calculation for dcuils and dcpils has been updated to depend on symbol names rather than values of metadata tokens imported from .NET assemblies. This fixes errors that users have been experiencing with updating their service packs for NET 1.1 and will prevent any further issues. http://community.borland.com/article/0,1410,32873,00.html * Delphi 2005 Update 1 Now Available This update makes Delphi 2005 rock solid! http://community.borland.com/article/0,1410,32875,00.html Artículos, trucos y consejos ============================ * BDNradio: Database Features of Delphi 2005 with Ramesh Theivendran and Joerg Weingarten Read the chat log and listen to the replay of the live interview with Ramesh and Joerg on Delphi 2005 database features. http://community.borland.com/article/0,1410,32925,00.html * BDNradio: VCL and VCL for .NET in Delphi 2005 with Seppy Bloom and Danny Thorpe Listen to the replay and read the chat room log of the live interview with Danny and Seppy. http://community.borland.com/article/0,1410,32924,00.html * BDNradio: Unit Testing in Delphi 2005 with Mark Edington Listen to the replay and read the chat room log of Mark Edington's live chat on unit testing support in Delphi 2005. http://community.borland.com/article/0,1410,32920,00.html * BDNradio: .NET data remoting in Delphi 2005 with Ramesh Theivendran Read the chat log and listen to the live chat with Ramesh on the easy, flexible, and powerful way to develop .NET data remoting applications in Delphi 2005. http://community.borland.com/article/0,1410,32917,00.html * BDNradio: Debugging in Delphi 2005 with Chris Hesik Listen to the replay and read the chat room log of Chris Hesik's interview on debugging in Delphi 2005. http://community.borland.com/article/0,1410,32923,00.html * BDNradio: Web Development in Delphi 2005 with Jim Tierney and Steve Trefethen Read the chat log and listen to the replay of this live chat with Jim and Steve on Delphi 2005's web development support. http://community.borland.com/article/0,1410,32881,00.html * Recursions in Delphi - by Zarko Gajic Recursion is a very simple, yet useful and powerful programmer's tool. Subroutines can, and frequently do, call other subroutines, a subroutine that activates/calls itself is called recursive. Recursion is a general method of solving problems by reducing them to simpler problems of a similar type. Many programmers often avoid this type of subroutine because it can be confusing and complicated. This article is going to make recursion in Object Pascal simple ... I hope. http://delphi.about.com/od/objectpascalide/l/aa120799a.htm * Graphical Combos - by Zarko Gajic Creating owner drawn Combo Boxes in Delphi. See how to code a graphical drop-down list; examples include a combo box of colours and a true-type font picker. http://delphi.about.com/od/vclusing/l/aa101700a.htm Tutoriales y capacitación ========================= * An Introduction to COM Programming with Delphi (6/6) - by Curtis Socha Type Library: pros and cons, 5 steps to a Type Library, a look into the TLB Abyss. http://delphi.about.com/library/weekly/aa122804a.htm * Resource Files Made Easy - by Zarko Gajic Part 1 of a series of articles, explains how Delphi uses standard Windows-format resource files: icons, bitmaps and cursors. http://delphi.about.com/od/objectpascalide/l/aa113099a.htm * Inside the EXE - by Zarko Gajic Part 2 of a series of articles, this article will show you how to store (and use) sound files, video clips, animations and any kind of binary files in a Delphi executable. http://delphi.about.com/od/objectpascalide/l/aa021301a.htm * Web Site inside a Delphi EXE - by Zarko Gajic Part 3 of a series of articles, shows how HTML and associated files (pictures) can easily be included within a Delphi application. http://delphi.about.com/od/objectpascalide/l/aa113099a.htm * Creating and Using a Resource Only DLL with Delphi - by Zarko Gajic Fourth article in the series about storing more than just executable code inside a Delphi application. This part shows how to create a dynamic link library containing only resources. http://delphi.about.com/od/objectpascalide/l/aa113099a.htm * Localizing Delphi Applications using StringTable Resources - Z. Gajic Part 5 in a series of articles, while resource files enable storing more than just program code in an EXE file, by including stringtable resources to an application a Delphi developer can easily build multilanguage applications. Learn how. http://delphi.about.com/library/weekly/aa011805a.htm Noticias ======== * Borland Going After Services Revenue Services are destined to play a greater part in Borland's future as the company assists customers around Application Lifecycle Management. http://www.cbronline.com/article_news.asp? guid=B1DA308B-4561-4A9B-83EE-F4D4EFAA07E8 * Borland Purchases Brains to Drive SDO Borland has made its first corporate purchase in two years, acquiring software process consulting specialist TeraQuest Metrics Inc. Borland plans to integrate TeraQuest's expertise, encapsulated in templates for activities such as change management, project planning and requirements gathering, into its ALM tools, processes and services. http://www.cbronline.com/article_news.asp? guid=C5F6EE17-B508-432B-987B-F274EC223A20 * Borland Schedules Q4 and Year End 2004 Conference Call and Webcast Borland today announced that its fourth quarter and year end 2004 teleconference and simultaneous Webcast is scheduled to begin at 2:30 p.m. Pacific Time, on Tuesday 1st February 2005. http://www.tmcnet.com/usubmit/2005/Jan/1106470.htm * Firebird Database Readies SMP Release Firebird developers are due to do an alpha release of version 2.0 of the open source database later this month and have completed work on SMP support, which is due to be released in late spring. http://news.zdnet.co.uk/software/developer/0,39020387,39183292,00.htm Otros / Sitios misceláneos ========================== * New BDN Feature: Community Calendar At the BorCon 2004 closing session, one of the new BDN applications launched was a community calendar, code named EventCentral. Any BDN member can use EventCentral to post events of interest to Borland customers anywhere around the world. Events must be approved by a sysop to be publicly visible. http://community.borland.com/article/0,1410,32936,00.html * CodeFez Blogs Blogs by Charlie Calvert, Julian Bucknall, Lino Tadros, Nick Hodges and Steve Teixeira. Topics include software development, Delphi and other Borland tools. http://www.codefez.com/Default.aspx?tabid=79&newsType=NewsListing * PGD DogFight Game Programming Competition DelphiGamer.com recently relauched and will soon be known as "Pascal Game Development" or PGD for short. To coincide with the relaunch, a themed game programming competition has been announced. http://www.pgd.netstarweb.com/viewtopic.php?t=1747 ________________________________________________________________________ Irongut's Delphi Pages Dedicada a la programación con Borland Delphi y Kylix. Tenemos artículos sobre programación, noticias Borland y Delphi, código fuente y componen- tes para usar en sus aplicaciones y más. http://www.paranoia.clara.net/ ________________________________________________________________________ ¡Tú puedes ayudarnos! Por favor danos una mano y ayúdanos a llegar a los 20.000 suscriptores en los próximos meses. Una forma en que puedes ayudarnos es enviando este enlace a tus amigos: http://www.latiumsoftware.com/es/pascal/index.php boletin-pascal-subscribe@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://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E http://www.programmingpages.com/?r=latiumsoftwarecomenpascal http://top100borland.com/in.php?who=20 http://top200.jazarsoft.com/delphi/rank.php3?id=latium Por favor vota. Son sólo unos segundos para ti que REALMENTE pueden hacer la diferencia. Necesitamos tu ayuda para poder continuar. ________________________________________________________________________ Si no has recibido el archivo con el código fuente completo de los ejemplos que se presentan en este boletín, puedes descargarlo de la siguiente dirección: http://www.latiumsoftware.com/descarga/p0053.zip ________________________________________________________________________ Página principal: http://www.latiumsoftware.com/es/pascal/index.php Página del grupo: http://espanol.groups.yahoo.com/group/boletin-pascal/ Para suscribirse / apuntarse: boletin-pascal-subscribe@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 la licencia y la ausencia de garantía que puedes leer en la página http://www.latiumsoftware.com/es/legal.php Allí también encontrarás una nota sobre marcas registradas. Te animamos a que redistribuyas este boletín, siempre y cuando lo hagas en forma completa (incluyendo la información de copyright), sin modificaciones y de manera gratuita. Los artículos son copyright de sus respectivos autores y se reproducen aquí con el permiso de los mismos. ________________________________________________________________________ Latium Software http://www.latiumsoftware.com/es/index.php Irongut's Delphi Pages http://www.paranoia.clara.net/ Copyright 2005 by Ernesto De Spirito + Dave Murray. All rights reserved. ________________________________________________________________________ |
Los ejemplos completos de código fuente de este número están disponibles para descargar.
![]() |
¿Errores? ¿Omisiones? ¿Comentarios? Por favor contáctanos!






