Eric Grange ha puesto a la disposición pública un Snapshot del estado del desarrollo de GLScene al dia 10 de mayo del 2006.
Como puntos destacables están el que en este snapshot viene el paquete de instalación tanto para Delphi 2006 como para Lazarus, cabe mencionar que se han hecho grandes avances en el desarrollo sobre Lazarus. Creo que esto va a potenciar bastante el uso de Lazarus para aplicaciones gráficas.
En lo particular yo aún encuentro un poco "molesto" el trabajo con Lazarus, el ide aún me parece un tanto inestable y de comportamientos erráticos... me ha pasado por la cabeza iniciar una aplicación real de gestión sobre este IDE pero hasta ahora lo que he visto que se ha hecho me parece muy modesto en comparación con las posibilidades que ofrece Delphi.
En fin, larga vida a Lazarus!! pero que sea una vida de verdadero aprovechamiento, ojalá no se quede como el hermanito "wanabe" de Delphi.
mayo 13, 2006
mayo 04, 2006
Extendiendo la VCL sin usar herencia ni registrando componentes nuevos
Es común que de repente estemos tentados a instalar fulano componente porque hace X monería, el problema con eso es que si nos viciamos en esa practica, llevar los fuentes de nuestro proyecto a otra máquina tiene el inconveniente de que hay que instalar todos estos componentes antes de poder compilar la primera línea de código.
Existen algunas practicas que permiten variar el comportamiento de los componentes que trae Delphi por defecto sin hacer derivaciones de las clases registradas, lo cual permite que sin instalar nada en el IDE tengamos el resultado que deseamos. Una de esas técnicas la describo un poco en el artículo Alternativas a los Skins y es la técnica de las clases sobrepuestas, pero en Delphi 2006 esta no es la única opción... existe una técnica mas estilizada y que se apega más a las buenas costumbres orientadas a objetos.
En BDS 2006 y desde Delphi 8 existe una extensión del lenguaje de Object Pascal llamada Class Helpers esta nueva característica nos permite definir nuevos comportamientos para alguna clase previamente definida de manera natural y su práctica nos ofrece muchos beneficios. Vamos a un ejemplo:
Muchos de nosotros usamos la funcion Trim() de Delphi que elimina los espacios en blanco al principio y al final de una cadena, y solemos usarla en controles como el caso del TEdit con código como este:
Pero, ¿no sería mas claro y elegante que el control Edit1 tuviera un método Ajustar() que hicera eso directamente sobre el control?, veamos como implementariamos eso, primero definimos la clase que servira como ayudante de la clase TEdit.
He llamado a la clase auxiliar TMiEdit ya que en esta técnica la clase auxiliar no tiene que llevar el mismo nombre de la clase a la que estamos ayudando, y ahora definimos el método nuevo:
Observen que como esta clase es una ayudante de TEdit puedo acceder a las propiedades de la misma clase TEdit, en este caso la propiedad Text, ahora para hacer uso del nuevo método no tengo que crear nuevas instancias solo usar un objeto común de la clase TEdit de este modo:
Pero tambien se pueden modificar métodos de la clase afectada, por ejemplo si quisieramos hacer que al llamar al método Clear del TEdit este en vez de poner una cadena nula pusiera por defecto un cero, hariamos algo como esto:
En este caso estamos sobrecargando el método Clear pero al ser este un método re-definido en la clase ayudante se toma este último por defecto.
Esto suele sernos útil en casos donde por ejemplo tenemos que ajustar controles como el TDBGrid para que soporte la ruedita del ratón, o para que cambie de casilla con la tecla Enter, o para Editar campos Memo en las celdas, etc... usando el control TDBGrid de toda la vida.
Las limitaciones que tiene esta técnica son que desde las clases ayudantes no se puede tener acceso a propiedades o métodos declarados como estrictamente privados o estrictamente protegidos, asi como tampoco permite la definición de datos adicionales, es decir que no se pueden declarar variables de campos en estas clases auxiliares; lo único que se permite es que se púeden definir variables de clase (una nueva característica tambien), es decir variables que serán comunes a todas las instancias de la clase ayudada, esto es útil para por ejemplo poder llevar la cuenta de cuantas instancias de X clase se han creado y de alguna manera implementar variantes del patrón de diseño singleton sobrecargando el constructor de la clase.
Existen algunas practicas que permiten variar el comportamiento de los componentes que trae Delphi por defecto sin hacer derivaciones de las clases registradas, lo cual permite que sin instalar nada en el IDE tengamos el resultado que deseamos. Una de esas técnicas la describo un poco en el artículo Alternativas a los Skins y es la técnica de las clases sobrepuestas, pero en Delphi 2006 esta no es la única opción... existe una técnica mas estilizada y que se apega más a las buenas costumbres orientadas a objetos.
En BDS 2006 y desde Delphi 8 existe una extensión del lenguaje de Object Pascal llamada Class Helpers esta nueva característica nos permite definir nuevos comportamientos para alguna clase previamente definida de manera natural y su práctica nos ofrece muchos beneficios. Vamos a un ejemplo:
Muchos de nosotros usamos la funcion Trim() de Delphi que elimina los espacios en blanco al principio y al final de una cadena, y solemos usarla en controles como el caso del TEdit con código como este:
Edit1.Text := Trim(Edit1.Text);
Pero, ¿no sería mas claro y elegante que el control Edit1 tuviera un método Ajustar() que hicera eso directamente sobre el control?, veamos como implementariamos eso, primero definimos la clase que servira como ayudante de la clase TEdit.
TMiEdit = class helper for TEdit
public
procedure Ajusta;
end;
He llamado a la clase auxiliar TMiEdit ya que en esta técnica la clase auxiliar no tiene que llevar el mismo nombre de la clase a la que estamos ayudando, y ahora definimos el método nuevo:
procedure TMiEdit.Ajusta;
begin
Text := Trim(Text);
end;
Observen que como esta clase es una ayudante de TEdit puedo acceder a las propiedades de la misma clase TEdit, en este caso la propiedad Text, ahora para hacer uso del nuevo método no tengo que crear nuevas instancias solo usar un objeto común de la clase TEdit de este modo:
procedure TForm2.Button1Click(Sender: TObject);
begin
Edit1.Ajusta;
end;
Pero tambien se pueden modificar métodos de la clase afectada, por ejemplo si quisieramos hacer que al llamar al método Clear del TEdit este en vez de poner una cadena nula pusiera por defecto un cero, hariamos algo como esto:
TMiEdit = class helper for TEdit
public
procedure Clear; overload;
end;
procedure TMiEdit.Clear;
begin
Text := '0';
end;
begin
Edit1.Clear;
end;
En este caso estamos sobrecargando el método Clear pero al ser este un método re-definido en la clase ayudante se toma este último por defecto.
Esto suele sernos útil en casos donde por ejemplo tenemos que ajustar controles como el TDBGrid para que soporte la ruedita del ratón, o para que cambie de casilla con la tecla Enter, o para Editar campos Memo en las celdas, etc... usando el control TDBGrid de toda la vida.
Las limitaciones que tiene esta técnica son que desde las clases ayudantes no se puede tener acceso a propiedades o métodos declarados como estrictamente privados o estrictamente protegidos, asi como tampoco permite la definición de datos adicionales, es decir que no se pueden declarar variables de campos en estas clases auxiliares; lo único que se permite es que se púeden definir variables de clase (una nueva característica tambien), es decir variables que serán comunes a todas las instancias de la clase ayudada, esto es útil para por ejemplo poder llevar la cuenta de cuantas instancias de X clase se han creado y de alguna manera implementar variantes del patrón de diseño singleton sobrecargando el constructor de la clase.
abril 24, 2006
Delphi SpeedUp for BDS
Andreas Hausladen ha implementado un plugin que acelera el desempeño del IDE de Delphi, está disponible para su uso desde la versión 5 hasta la 10 (BDS2006) de Delphi.
Aqui está el instalador del plugin, pero creo que aún más interesante es el poder acceder al código fuente del que se pueden aprender enormidades, estos fuentes estan comprimidos en formato 7Zip.
Este plugin esta basado en las librerias FastCode y FastMove, echandoles un ojo puede uno ver el portento de trabajo en ensamblador que se le ha dedicado. Yo lo he instalado en BDS2006 y si he notado un incremento en el desempeño del IDE, ya me dirán si es un común en todas las configuraciones.
Aqui está el instalador del plugin, pero creo que aún más interesante es el poder acceder al código fuente del que se pueden aprender enormidades, estos fuentes estan comprimidos en formato 7Zip.
Este plugin esta basado en las librerias FastCode y FastMove, echandoles un ojo puede uno ver el portento de trabajo en ensamblador que se le ha dedicado. Yo lo he instalado en BDS2006 y si he notado un incremento en el desempeño del IDE, ya me dirán si es un común en todas las configuraciones.
marzo 07, 2006
Alternativas a los skins
Existen muchos y muy variadas herramientas en el mercado que permiten hacer cosas bastante llamativas con las interfaces de los programas, VCLSkin, SuiSkin, entre otros con sus ventajas y desventajas entre ellos
Algunos usan sus propios componentes, es decir su propio TEditSkineado, TPanelEskineado, etc, el problema con eso es que obviamente cuando los usas te obligas a reescribir tu aplicacion o al menos pasarle un experto que cambie los nombres de las clases de los controles que ahora serán del nuevo tipo; y tambien con eso ya te estasjodiendo comprometiendo de alguna manera con ese proveedor de la herramienta, pues algunas características que ofrezcan estos componentes no se encontrarán en las clases genéricas.
Otros como VCLSkin son mas flexibles, con solo poner un simple componente en tu formulario principal te cambia la apariencia de la aplicación por completo, abarcando incluso cuadros de dialogo y demás chunches propios de windows
Aqui vamos a discutir una alternativa al uso de estas herramientas que son de pago (aunque algunas realmente valen lo que cuestan si la apariencia es tan importante para ti), y lo haremos usando una técnica ancestral que nos provee Delphi y a la que se le llama "Clases Sobrepuestas". Es increible cuanto mejora la apariencia de una ventana tan solo usando colores agradables y redondeando las esquinas de los componentes contenedores, aqui va el ejemplo vamos a estudiar como hacer que esto en diseño:

se vea en ejecución como esto:

Sin usar componentes de terceros y sin tener que cambiar los componentes que ahora estas usando en tu aplicación común y corriente de Delphi.
La idea es muy simple, vamos a hacer una unidad que será la que pongas al final de la sección uses de tu forma en la parte de la interfase; ahora, esto es importante, la unidad que contenga las clases sobrepuestas debe ser la última en la lista del uses, sino podria no funcionar el truco, por lo menos no para las clases que esten contenidas en las unidades que se encuentren despues de la nuestra.
Primero creamos una nueva unidad llamada GTPaneles.pas, y definamos algunos parámetros configurables al gusto de cada quien...
la constante CnstArco definirá que tan pronunciados queremos que sean los arcos de las esquinas redondeadas, las siguientes dos constantes definen los colores que tendrán los botones en los estados normal y cuando estan presionados, y por último definimos un valor para diferenciar a aquellos componentes a los que no quisieramos que se les aplique el proceso de "embellecimiento", esta técnica la usa VCLSkin, donde si a algun panel no quisieras que se le aplique el Skin solo basta con poner el valor 99 en la propiedad Tag de dicho componente.
Para ejemplificar el trabajo lo haremos con la clase TPanel, y mostraremos la parte mas simple del asunto, aqui hacemos la sobreposición de la clase:
Definamos un par de procedimientos genéricos que usaremos despues en la implementacion de los métodos de las clases sobrepuestas:
Este procedimiento borra el fondo donde se ha de dibujar el control y prepara el terreno para dibujar nuestra obra de arte.
Este otro dibuja ya formalmente los rectangulos redondeados de modo que de la perspectiva 3D.
Despues de eso solo basta con codificar la nueva versión del método Paint del componente mandando a llamar a los dos métodos que ya vimos:
Para el caso de los botones y los TGroupBoxes el procedimiento es similar con la variante de desplegar el texto o el caption del componente en cuestión, e incluso se puede hacer una variante que dibuje tambien los Glyphs de los botones, pero yo por lo menos mi versión la he dejado hasta ahi; si alguien continua con este desarrollo hagamelo saber. También sobre BDS 2006 se pueden hacer uso de los nuevos eventos OnMouseEnter y OnMouseLeave para dar más efectos a los componentes.
En la sección de archivos de este blog esta disponible para descargar un demo completo de lo aqui explicado, seguro que con un poco mas de dedicación se puede ampliar la unidad para que soporte mas clases y con mejor apariencia.
Algunos usan sus propios componentes, es decir su propio TEditSkineado, TPanelEskineado, etc, el problema con eso es que obviamente cuando los usas te obligas a reescribir tu aplicacion o al menos pasarle un experto que cambie los nombres de las clases de los controles que ahora serán del nuevo tipo; y tambien con eso ya te estas
Otros como VCLSkin son mas flexibles, con solo poner un simple componente en tu formulario principal te cambia la apariencia de la aplicación por completo, abarcando incluso cuadros de dialogo y demás chunches propios de windows
Aqui vamos a discutir una alternativa al uso de estas herramientas que son de pago (aunque algunas realmente valen lo que cuestan si la apariencia es tan importante para ti), y lo haremos usando una técnica ancestral que nos provee Delphi y a la que se le llama "Clases Sobrepuestas". Es increible cuanto mejora la apariencia de una ventana tan solo usando colores agradables y redondeando las esquinas de los componentes contenedores, aqui va el ejemplo vamos a estudiar como hacer que esto en diseño:
se vea en ejecución como esto:
Sin usar componentes de terceros y sin tener que cambiar los componentes que ahora estas usando en tu aplicación común y corriente de Delphi.
La idea es muy simple, vamos a hacer una unidad que será la que pongas al final de la sección uses de tu forma en la parte de la interfase; ahora, esto es importante, la unidad que contenga las clases sobrepuestas debe ser la última en la lista del uses, sino podria no funcionar el truco, por lo menos no para las clases que esten contenidas en las unidades que se encuentren despues de la nuestra.
Primero creamos una nueva unidad llamada GTPaneles.pas, y definamos algunos parámetros configurables al gusto de cada quien...
const
CnstArco = 35;
CnstBotonNormal = clMoneyGreen;
CnstBotonPress = clGray;
CnstTagDisable = 99;
la constante CnstArco definirá que tan pronunciados queremos que sean los arcos de las esquinas redondeadas, las siguientes dos constantes definen los colores que tendrán los botones en los estados normal y cuando estan presionados, y por último definimos un valor para diferenciar a aquellos componentes a los que no quisieramos que se les aplique el proceso de "embellecimiento", esta técnica la usa VCLSkin, donde si a algun panel no quisieras que se le aplique el Skin solo basta con poner el valor 99 en la propiedad Tag de dicho componente.
Yo suelo utilizar la propiedad Tag de los componentes para algunos trucos al nivel de la interface de las aplicaciones, si ese es tu caso tambien tendrías que hacer algunos malabares para que esto no te ocasione problemas
Para ejemplificar el trabajo lo haremos con la clase TPanel, y mostraremos la parte mas simple del asunto, aqui hacemos la sobreposición de la clase:
TPanel = class(ExtCtrls.TPanel)
protected
procedure Paint; override;
end;
Definamos un par de procedimientos genéricos que usaremos despues en la implementacion de los métodos de las clases sobrepuestas:
Este procedimiento borra el fondo donde se ha de dibujar el control y prepara el terreno para dibujar nuestra obra de arte.
procedure QuitarFondo(Control: TControl; Dest: TCanvas);
var
SaveIndex: Integer;
DC: HDC;
Position: TPoint;
begin
with Control do
begin
if Parent = nil then
Exit;
DC := Dest.Handle;
SaveIndex := SaveDC(DC);
{$IFDEF PDJ_2}
GetViewportOrgEx(DC, @Position);
{$ELSE}
GetViewportOrgEx(DC, Position);
{$ENDIF}
SetViewportOrgEx(DC, Position.X - Left,
Position.Y - Top, nil);
IntersectClipRect(DC, 0, 0, Parent.ClientWidth,
Parent.ClientHeight);
Parent.Perform(WM_ERASEBKGND, Integer(DC), Integer(0));
Parent.Perform(WM_PAINT, Integer(DC), Integer(0));
RestoreDC(DC, SaveIndex);
end;
end;
Este otro dibuja ya formalmente los rectangulos redondeados de modo que de la perspectiva 3D.
procedure DibujaRedondeado(const C: TCanvas; R1:
TRect; Color: TColor);
var R2: TRect;
begin
//Guardamos el Rectangulo original
R2 := R1;
with C do
begin
Pen.Width := 1;
//Dibujamos la sombra
inc(R1.left, Pen.Width);
inc(R1.top, Pen.Width);
pen.Color := clbtnhighlight;
Brush.Style := bsSolid;
Brush.Color := Color;
RoundRect(R1.Left, r1.top, r1.Right, r1.Bottom,
CnstArco, CnstArco);
pen.Color := color;
Brush.Style := bsclear;
inc(R1.left, Pen.Width);
inc(R1.top, Pen.Width);
RoundRect(R1.Left, r1.top, r1.Right, r1.Bottom,
CnstArco, CnstArco);
//Dibujamos la base...
pen.Color := clBlack;
Brush.Style := bsclear;
r1 := R2; //Recuperamos el rectangulo original...
RoundRect(R1.Left, r1.top, r1.Right, r1.Bottom,
CnstArco, CnstArco);
Brush.Style := bsSolid;
end;
end;
Despues de eso solo basta con codificar la nueva versión del método Paint del componente mandando a llamar a los dos métodos que ya vimos:
procedure TPanel.Paint;
begin
if (Tag <> CnstTagDisable) then
begin
QuitarFondo(Self, Canvas);
DibujaRedondeado(Canvas, GetClientRect, Color);
end else inherited;
end;
Para el caso de los botones y los TGroupBoxes el procedimiento es similar con la variante de desplegar el texto o el caption del componente en cuestión, e incluso se puede hacer una variante que dibuje tambien los Glyphs de los botones, pero yo por lo menos mi versión la he dejado hasta ahi; si alguien continua con este desarrollo hagamelo saber. También sobre BDS 2006 se pueden hacer uso de los nuevos eventos OnMouseEnter y OnMouseLeave para dar más efectos a los componentes.
En la sección de archivos de este blog esta disponible para descargar un demo completo de lo aqui explicado, seguro que con un poco mas de dedicación se puede ampliar la unidad para que soporte mas clases y con mejor apariencia.
¿cuestion de inspiración??
Hay quienes tienen la idea de que esto de la programación es muchas veces cuestión de "momentos", que existen esas horas en que algún ser divino toca tu conciencia y es cuando vienen los más grandes portentos de creatividad en la resolución de un problema o del diseño de alguna aplicación que traia dando tantas vueltas en la cabeza; vaya que es crear un arte...
Esto que algunos llaman suerte creo que esta más bien orientado a la inspiración... pero tambien esa inspiración pudiera estar conllevada con el ambiente, la situación social, economico, familiar que el susodicho programador haya tenido en su momento. Porque es bien sabido que por mas brillante que suela uno ser, en un momento de aflicción o sobrecogimiento no se rinde igual, ni fluyen las ideas con tanta facilidad como cuando todo en la vida es miel sobre hojuelas.
Seria bueno que se comentara aqui que tanto piensan que influye realmente el entorno en el desempeño de un programador, que tanto influye el tener un buen sueldo, una buena esposa (porque no?), minimos problemas en general para tener un destacable desempeño creativo.
Ahora que si a inspiraciones vamos, yo debo declararme como un fan de la música de trova y en mi opinión es una música de inspiración sublime. Para muestra un botón, aqui está un fragmento de una canción de "El Mago" Abel Velasquez, ya me dirán si esto no es inspiración; son palabras que muchas veces no sabe uno a ciencia cierta como decir, descritas de la manera mas sublime, asi que tomen nota... con dedicación especial para mi chaparra...
Esto que algunos llaman suerte creo que esta más bien orientado a la inspiración... pero tambien esa inspiración pudiera estar conllevada con el ambiente, la situación social, economico, familiar que el susodicho programador haya tenido en su momento. Porque es bien sabido que por mas brillante que suela uno ser, en un momento de aflicción o sobrecogimiento no se rinde igual, ni fluyen las ideas con tanta facilidad como cuando todo en la vida es miel sobre hojuelas.
Seria bueno que se comentara aqui que tanto piensan que influye realmente el entorno en el desempeño de un programador, que tanto influye el tener un buen sueldo, una buena esposa (porque no?), minimos problemas en general para tener un destacable desempeño creativo.
Ahora que si a inspiraciones vamos, yo debo declararme como un fan de la música de trova y en mi opinión es una música de inspiración sublime. Para muestra un botón, aqui está un fragmento de una canción de "El Mago" Abel Velasquez, ya me dirán si esto no es inspiración; son palabras que muchas veces no sabe uno a ciencia cierta como decir, descritas de la manera mas sublime, asi que tomen nota... con dedicación especial para mi chaparra...
Suscribirse a:
Entradas (Atom)