Categoría: <span>Delphi</span>

Share Button

A raiz de la última entrada de este blog respecto a crear componentes en un ScrollBox, y el ejemplo que desarrollé para mostrarlo creando un simple visualizador de imágenes y sus minuatura, Salvador (Delphi básico) y yo mismo, nos hemos propuesto crear un componente que permita gestionar estas miniaturas.

La idea inicial, era simplemente recordar y practicar determinados conceptos sobre componentes, pero poco a poco la cosa ha ido tomando forma y el resultado (por ahora en desarrollo todavía) se está tornando bastante interesante.

El componente TPanelMiniaturas está pensado como una colección  (TCollection) de minuaturas (TCollectionItems). Además se complementa con un componente adicional que se encarga de «pintar» las minuaturas en pantalla y que está ligado a cada ítem de la colección. Debe permitir gestionar esas miniaturas en diseño y en ejecución y facilitar al programador métodos para trabajar con ellas.

Podéis ver más imágenes y detalles del diseño del componente en esta entrada de la web de Salvador:  «Panel de miniaturas» y seguir las últimas ideas que se nos van ocurriendo aquí (debate en facebook). Estamos abiertos a cualquier idea y sugerencia, así que si alguien se anima, que «no se corte»…  ;-)

Un saludo.

Componentes Delphi

Share Button

Se trata de un ejemplo sencillo que puede servir a quien esté comenzando con la creación de componentes en runtime y asignación de eventos. En este caso se trata de un visualizador de imágenes, que crea componentes TImage dentro de un TScrollBox, a modo de miniaturas, para luego visualizar esas imágenes en un control TImage a tamaño mayor.


Se utiliza también una TObjectList para almacenbar los objetos (componentes TImage y TPanel) que se van creando en ejecución para posteriormente poder acceder a ellos. Para crear los componentes se utiliza un código com este:

var
  im:TImage;
  i:Integer;
  pnl:TPanel;
begin
 
  // Para cada imagen
  for i := 0 to (imList.Count - 1) do begin
    // Crear el control imagen
    im := TImage.Create(nil);
    // Asignar propiedades
    im.Parent := ScrollBox1;
    im.Height := ScrollBox1.Height;
    im.Width := im.Height;
    im.Top := 0;
    im.Left := ((im.Width + 15{panel} + 4) * i);
    im.Transparent := true;
    im.Align := alLeft;
    im.Stretch := True;
    im.Proportional := True;
 
    // Cargar
    im.Picture.LoadFromFile(imList[i]);
    // vebto OnClick
    im.OnClick := ClickImage;
    // Añadirla a la lista de objetos
    oList.Add(im);
 
    // Separados
    pnl := TPanel.Create(nil);
    pnl.Parent := ScrollBox1;
    pnl.Left := im.Left + 5;
    pnl.Width := 15;
    pnl.Height := im.Height;
    pnl.Align := alLeft;
    pnl.Color := clBlack;
    // Aadirlo a la lista de objetos
    oList.Add(pnl);
 
  end;

Se puede descargar el código completo del ejemplo desde aquí .
Actualizo el contenido en DropBox.
Este ejemplo ha surgido a partir de este hilo en el ClubDelphi.

Otros ejempos útiles sobre el mismo tema, relacionados con este pueden ser «Crear, mover y redimensionar controles en Runtime (IDE)» o «Crear/destruir comp. en Runtime y moverlas con el ratón«.

Un saludo.

Delphi Ejemplos Fácil

Share Button

Hay un ejemplo antiguo en la página en la sección de ejemplos, titulado «Trocear un bitmap en n imágenes a modo de puzle». Hoy ha salido en los foros una pregunta sobre la operación contraria, ¿Cómo unir varios bitmaps (TImage) en una única imagen?

Puede ser algo trivial para los que llevamos un tiempo en esto, pero no tanto para los que empiezan; Reconozco que yo al principio también me liaba con los Canvas, los Rect, los ClientRect y no sabía cual copiar en cada cual.  ;-)

El código para unir cuatro imágenes en una sóla formando un cuadro, es muy sencillo y sería algo así:

var
  ARect:TRect;
  path:string;
begin
 
  // Añadir los 4 canvas a la nueva imagen
  ARect.Left := 0;  ARect.Top := 0; ARect.Right := 48; ARect.Bottom := 48;
  imgDestino.Canvas.CopyRect(ARect, img1.Canvas, img1.ClientRect);
  ARect.Left := 48;  ARect.Top := 0; ARect.Right := 92; ARect.Bottom := 48;
  imgDestino.Canvas.CopyRect(ARect, img2.Canvas, img2.ClientRect);
  ARect.Left := 0;  ARect.Top := 48; ARect.Right := 48; ARect.Bottom := 92;
  imgDestino.Canvas.CopyRect(ARect, img3.Canvas, img3.ClientRect);
  ARect.Left := 48;  ARect.Top := 48; ARect.Right := 92; ARect.Bottom := 92;
  imgDestino.Canvas.CopyRect(ARect, img4.Canvas, img4.ClientRect);
 
  // Path para grabarla a disco
  path := ChangeFileExt(Application.ExeName, '.bmp');
  imgDestino.Picture.SaveToFile(path);
  MessageDlg('Se ha guardado la imagen con el nombre: ' +
             path, mtInformation, [mbOK], 0);

Si en lugar de unirlas formando un cuadro, se quieren unir de otra forma (las 4 en línea, por ejemplo), basta con cambiar las coordenadas de destino.

Si hubiera que cambiar el tamaño final, por ejemplo para reducirlo hasta el de las imágenes originales, se podrían aplicar técnicas de antialiasing al redimensionar.

Descargar ejemplo.

Un saludo.

Delphi Ejemplos

Share Button

Si no os acaba de gustar o no es vuestro estilo, un póster como el de Raquel Welch, que cuelga Andrew Dufresne (Tim Robbins) en la película «Cadena perpetua», o simplemente sois un poco más «frikis» y/o  fans de Delphi, os adjunto este que hoy he visto en «TheRoadToDelphi» y que me ha traído gratos recuerdos.  ;-)

VCL Object Hierarchy

Un saludo.

Delphi Humor OOP

Share Button

Después de un breve tiempo de innacividad, espero en breve volver a publicar de forma más asídua.

Vuelvo a publicar con una escuesta sobre los sistema de Control de Versiones.

Una de las cosas que creo básicas para un programador, cuando uno ya lleva un tiempo en esto y el volumen de código generado empieza a ser grande, es un  buen control de versiones, que además se puede utilizar como backup y repositorio de fuentes. Y ya no sólo cuando se trabaja en grupo, sino a nivel personal.

Para mi, es una de quellas cosas, que una vez que las pruebas, a no puedes «vivir» sin ellas.   ;-)

Os animo a que votéis y déis vuestra opinión.

Un saludo.

Delphi Encuesta

Share Button

He probado algunos sistema de traducción para programas Delphi, entre ellos multiidioma2he de destacar los componentes de TsiLang Component Suite , que me parecen muy buenos y completos.

Estos días necesitaba un paquete gratuíto y revisando páginas y foros he llegado a GNU Gettext for Delphi and C++ Builder. Me parece un paquete muy sencillo de utilizar y por lo que he probado hasta ahora, cómodo y eficaz.

En esta entrada voy a explicar desde cero los pasos que he seguido para conseguir una aplicación multiidioma.

PREPARATIVOS

(1) GNU Gettext

Descargar desde la página «GNU Gettext for Delphi and C++ Builder» el programa de instalación. También se puede encontrar la última versión en SourceForge.

Una vez descargado el ficchero e instalado tendremos lo necesario para generar nuestros ficheros de traducción e integrarlos en el programa.

NOTA: Hay una versión especial compatible con Delphi 2009 que podemos descargar desde aquí, si estamos utilizando esta versión de Delphi..

Si se ha instalado correctamente, nos pedirá reiniciar el sistema.
Una vez instalado, si desde el explorador de Windows pulsamos Click derecho con el ratón sobre una carpeta, nos debería aparecer una nueva opción «Extract Translations to Template«.
generar_traducciones

(2) Poedit for Windows

Necesitaremos una herramienta para poder traducir (ya seamos nosotros o una tercera persona) los ficheros de traducción a los diferentes idiomas. Esto está pensado para que esa posible tercera persona (que puede no tener Dephi instalado)  pueda traducir un fichero sólo con esta herramienta (y el fichero .po como veremos después).

Descargamos el programa desde la página (http://www.poedit.net/) y lo nstalaremos.

Una vez realizados estos dos pasos previos, crearemos un pequeño proyecto de ejemplo donde realizar las pruebas.

Para ello, desde Delphi comenzamos una nueva aplicación y en el formulario generaremos algo similar a esto:

TRADUCCIÓN

(a) Preparar el  proyecto.

Una vez tenemos nuestra aplicación funcionando debemos preparnos para comentar lo necesario para traducción.
(1) Lo primero es añadir la unit gnugettext.pas a nuestro proyecto. Las units que usesn traducciones deberán tenerla en el uses.

NOTA: Si habéis realizado la instalación estandard debería estar en:
«c:\Archivos de programa\dxgettext\gnugettext.pas»

(2) Añadir al OnCreate de nuestros formularios el siguiente código:

// Traducir el formulario
TranslateComponent(Self);

(3) Preparar la estructura de directorios para organizar las traducciones. Dentro del directorio de la aplicación crearemos una carpeta llamada locale y dentro de ella un árbol de directorios similar al que se ve en la imagen.

directorios1

En este ejemplos, yo voy a utilizar 4 idiomas (es, en, fr, ca); Contando que el original va a ser el Español(es) debemos crear la estructura para los otros 3 (inglés, francés y catalán). Nos quedará un arbol de directorios como este:

directorios2

(b) Generar fichero de traducciones (.po)

(1) Para generar el fichero de traducciones del proyecto se debe extraer todas las cadena «traducibles» y almacenarlas en un fichero; Para ello basta con que, desde el explorador de Windows, pulsemos Click derecho sobre la carpeta del proyecto y seleccionemos la opción «Extract Translations to template».
Esto generará un fichero default.po en el directorio de la aplicación.

generar_traducciones

(2) Copiaremos este fichero dentro de los directorios LC_MESSAGES; Tantas copias como directorios tengamos. Después de eso tendremos varios ficheros .po; Uno en el directorio de la aplicación y uno dentro de cada carpeta de traducción:

appdir/appTest.exe
appdir/default.po
appdir/locale/en/LC_MESSAGES/default.po (Traducciones al inglés)
appdir/locale/fr/LC_MESSAGES/default.po (Traducciones al francés)
appdir/locale/ca/LC_MESSAGES/default.po (Traducciones al catalán)
…

(c) Traducir los ficheros.

En este punto ya se pueden abrir cada uno de los ficheros .po y traducirlo utilizando poedit. Una vez abierto el fichero con poedit, veremos una pantalla como esta:


Una vez finalizada la traducción de palabras y cerrado el programa veremos que en cada directorio aparecen 2 ficheros; El  default.po (original) y el de traducción llamado default.mo.
Repetimos esto con todos los ficheros de traducción.

(d) Cómo utilizar las traducciones en nuestro programa

Una vez los ficheros de traducción estén generados, para utilizarlos desde la aplicación añadirenmos el siguiente código a los botones de activación de los idiomas.

botones_idiomas

// para el catalán
UseLanguage('ca');
RetranslateComponent(Self);
 
// para el inglés
UseLanguage('en');
RetranslateComponent(Self);
...

Si ejecutamos la aplicación veremos que al pulsar los botones cambia es aspecto del formulario.

Para finalizar, aun nos queda un detalle, que es, que la cadena que aparece al pulsar el botón «Hola Mundo!»  no aparece traducida.

Para ello utilizaremos la función de traducción  _().
La llamada que actualmente está así:

MessageDlg('Hola', mtInformation, [mbOK], 0);

Pasará a colocarse así:

MessageDlg(_('Hola'), mtInformation, [mbOK], 0);

PASOS FINALES

Con eso nuestro programa debería quedar traducido completamente. Si movemos el EXE y la carpeta locale a cualquier otro sitio veremos que el programa funciona correctamente. Si sólo movemos el EXE, el efecto es que no aparace nada traducido.

Queda un último detalle, que es integrar las traducciones en el EXE, para que todo quede en el ejecutable y no debamos preocuparnos del directorio locale.

integrar_traducciones

Basta con pulsar click derecho sobre el EXE de nuestra aplicación desde el explorador de Windows, Seleccionar la opción «Embeb Translations» y seleccionar los ficheros de traducción que queremos integrar.

integrar_traducciones2

Con esto debería ser todo.

UPDATE: (20/04/2011)

Pues haciendo pruebas he llegado a obtener el mismo proble que comenta Sil en sus comentarios (en mi caso utilizando Delphi XE). Se trata de que al intentar añadir las traducciones al exe se obtiene un error con la referencia: «6637DB2E-62E1-4A60-AC19-C23867046A89».

Revisando por Internet, parece que se solventa sustituyendo unas constantes que hay en gnugettext.pas.

(1) Buscar esta sección en la unit gnugettext.pas:

  // DetectionSignature: used solely to detect gnugettext usage by assemble
  DetectionSignature: array[0..35] of AnsiChar='2E23E563-31FA-4C24-B7B3-90BE720C6B1A';
  // Embedded Header Begin Signature (without dynamic prefix written by assemble)
  BeginHeaderSignature: array[0..35] of AnsiChar='BD7F1BE4-9FCF-4E3A-ABA7-3443D11AB362';
  // Embedded Header End Signature (without dynamic prefix written by assemble)
  EndHeaderSignature: array[0..35] of AnsiChar='1C58841C-D8A0-4457-BF54-D8315D4CF49D';
  // Assemble Prefix (do not put before the Header Signatures!)
  SignaturePrefix: array[0..2] of AnsiChar='DXG'; // written from assemble

(2) Y sustituirlas por estas:

  // DetectionSignature: used solely to detect gnugettext usage by assemble
  DetectionSignature: array[0..35] of AnsiChar='6637DB2E-62E1-4A60-AC19-C23867046A89';
  // Embedded Header Begin Signature (without dynamic prefix written by assemble)
  BeginHeaderSignature: array[0..35] of AnsiChar='';
  // Embedded Header End Signature (without dynamic prefix written by assemble)
  EndHeaderSignature: array[0..35] of AnsiChar='';
  // Assemble Prefix (do not put before the Header Signatures!)
  SignaturePrefix: array[0..16] of AnsiChar='#0#0#0#0#0#0#0#0';//'DXG'; // written from assemble

Con este ambio ha desaparecido el error y se integran perfectamente las traducciones.

Espero que haya sido útil.

Espero comentarios, sugerencias, errores,… y demás.

Delphi Multiidioma

Share Button

Acabo de cerrar la versión 1.8b de la librería GLibWMI.

Nuevos componentes y algunas correciones a errores referentes a propiedades y «leaks» de memoria (los más importantes).

La librería está accesible completa en SourceForge (GLibWMI).

SourceForge

Podéis descargar los fuentes vía SVN desde:

http://glibwmi.svn.sourceforge.net/svnroot/glibwmi/

O también podéis descargar los ficheros desde aquí.

Código Componentes Delphi GLibWMI WMI

Share Button

Acabo de cerrar la versión 1.6 beta.

He subido la versión completa a Sourceforge.  A partir de ahora estará disponible allí completa (fuentes incluídos) con licencia GNU.

En esta última versión se han añadido nuevos componentes, nuevos métodos y corrección de algunos errores.

También se pueden descargar los ficheros desde aquí.

Por supuesto (y como siempre), se aceptan cualquier tipo de comentarios, dudas, sugerencias, críticas,…

ACTUALIZACIÓN: A partir de este momento se pueden descargar los fuentes vía SVN desde:

http://glibwmi.svn.sourceforge.net/svnroot/glibwmi/

Un saludo.

Código Componentes Delphi WMI

Share Button

EProgrammerNotFound :-)

Es el error que muchas veces pienso que debería haber «saltado» en la aplicación, cuando reviso cierto código que debí escribir un día de esos en que mi cabeza está «nublada» (como los días de invierno…).

Pues Voilà!
A partir de la versión 2009 de Delphi ya está disponible y prometo usarla de aquí en adelante en mis nuevos desarrollos… ;-)

¿Que no os lo creéis? Basta con revisar la unit SysUtils.pas

Una imagen para los incrédulos:

Leído en el Blog de Marco Cantù.

Código Delphi Humor Programación

Share Button

Acabo de empaquetar la versión 1.3 (beta) de la librería de componentes GLibWMI, basados en la WMI de Windows.

Básicamente he añadido nuevos componentes y he corregido algunos errores que incluía la demo general. Además he testado la librería en Delphi 2009 sin ningun problema a la hora de compilar. Doy por supesto que en todas las intermedias entre D7 y D2009 fucionará sin problemas.

Los componentes nuevos son:

  • CProcessInfo:  Información acerca de los procesos que hay ejecutándose en el sistema..
  • CServiceInfo:   Información detalleda de los servicios que hay instalados en el sistema..
  • CDesktopMonitorInfo:   Información detallada sobre el monitor o dispositivo de visualización que hay en el sistema.
  • CComputerSystemInfo:   Información acerca del sistema en General.
  • CStartupCommandInfo:    Información acerca de los procesos que se ejecutan automáticamente cuando el usuario hace el Login en el sistema.

<Ver más detalles>

Código Componentes Delphi WMI