Boletín Pascal #16 - 09-FEB-2001
INDICE
1. UNAS PALABRAS DEL EDITOR
2. FORMAS NO RECTANGULARES - Parte II
- INTRODUCCION
- IMPLANTACION BASICA DE "SKINS"
- EL FONDO
- LA FORMA
- PASO A PASO
- LOS CONTROLES
- MAS ALLA
- LO QUE OTROS HACEN
3. FORMAS GRISES CASI INDISTINGUIBLES EN ELEMENTOS DE MENU INHABILITADOS
4. COLOR BUTTON
5. TALLER
6. LICENCIA DE KYLIX
7. ENLACES
________________________________________________________________________
1. UNAS PALABRAS DEL EDITOR
En este número me complace presentar la tan esperada segunda parte del
artículo FORMAS NO RECTANGULARES de Alirio Gavidia, cuya primera parte
fuera publicada en el boletín #13:
http://www.latiumsoftware.com/es/pascal/0013.php
Aprovecho para recordar a los suscriptores que el sorteo de la Librería
JfControls sigue en marcha. Si no lo han hecho aún, observen la demo y
verán que no es ninguna baratija lo que se sortea, sino un producto de
alta calidad que implementa un concepto innovador y que les ayudará a
hacer aplicaciones visualmente atrayentes en un santiamén, además que
está desarrollado por gente de habla hispana que merece nuestro apoyo.
Participar es gratis. Todo lo que tienen que hacer es descargar e
instalar la versión de evaluación de la librería (disponible tanto para
Delphi como para C++ Builder, ambos en versiones 3, 4 y 5) para así
obtener el Key Number (un número único que identifica cada instalación
de la librería) con el que podrán llenar el formulario de inscripción.
Si no quieren instalar la versión de evaluación de la librería, la
última versión de JfSetup le dará el Key Number si instala sólo la demo
(vale la pena verla y no se requiere que la librería esté instalada para
correr el ejecutable). Para más información sobre el sorteo:
http://www.latiumsoftware.com/jfcontrols/index.php?lang=es
A partir del próximo número, este boletín será publicado con los
ejemplos de código fuente adjuntos o "attacheados" que por lo general
tienen menos de 30K.
Saludos,
Ernesto De Spirito
eds2008 @ latiumsoftware.com
________________________________________________________________________
JfControls Lib. Multilenguaje. Multiapariencia. Skins. Privilegios. Más
de 40 componentes integrados y personalizables. Múltiples problemas de
programación resueltos. Administración centralizada de recursos. Para
Delphi 3-2006 y C++ Builder 3-6. http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________
2. FORMAS NO RECTANGULARES - Parte II
Copyright (c) 2001 Alirio Gavidia <alirio@gavidia.org>
Para ver más de mis artículos visite:
Programación Orientada en Delphi
http://www.gavidia.org/pod/
INTRODUCCION
------------
Esta es la segunda parte de un artículo orientado a la utilización de
formas no rectangulares con Delphi bajo Windows. En la parte anterior se
le dio forma no rectangular a un formulario creando un reloj de agujas
como ejemplo. En esta parte se pretende poder crear formularios cuyas
formas se definan desde algún archivo externo a la aplicación. Tal
comportamiento corresponde al muy difundido uso de "Skins". Como ejemplo
"Windows Media Player".
IMPLANTACION BASICA DE "SKINS"
------------------------------
La primera aproximación que aquí presentamos no sólo nos permite definir
el fondo sino además la figura del formulario. En el mercado existe un
componente VCL que hace este trabajo y más. El referido componente VCL
hace uso de dos archivos BMP, el primero con la figura en blanco y negro
y el segundo con el fondo a todo color. Para el presente ensayo se
combinan estas dos características en un sólo archivo, simplemente
tomando el color del primer pixel como color transparente, en realidad
como color que permite definir el límite de la figura (hay una pequeña
diferencia). El resto del dibujo, dentro de la figura, se toma como
fondo del formulario.
Nota: El uso de BMP tiene muchos contras. Los principales: tamaño y
escalabilidad. Del primero quizás la alternativa sería un JPG, pero
el proceso de compresión altera la frontera de la figura generando
colores intermedios y la consecuencia es un frontera difuminada. Por
otro lado están los GIF, pero han sido desterrados de mis rutinas,
librerías y funciones debido a que cierta empresa pretende ahora
cobrar derechos por el uso de los algoritmos de compresión presentes
en los archivos tipo GIF. En cuanto a la escalabilidad, una alternativa
es el uso de Metafile, mejor aún sospecho que los metafiles son
definiciones de regiones completamente análogas a las que se utilizan
aquí. Sin embargo dejaré el estudio de Metafiles para otra ocasión.
Una versión completa de un "Skinner" requiere poder definir el dibujo de
fondo del formulario, su figura así como el de cada control presente.
Nos concentraremos en el formulario dejando de lado los controles.
EL FONDO
--------
En problema del dibujo de fondo es enfrentable de dos maneras a mi
entender. Una es interceptando algún mensaje de Windows para dibujar
sobre el canvas de fondo (como lo hacen algunos controles VCL para
colocar fondos en formularios MDI y No-MDI) y la otra es colocando un
control tipo TImage como el último control en el área cliente del
formulario. Optaré por la última forma porque además será posible hacer
uso de algunos eventos del TImage.
LA FORMA
--------
El problema de la figura reside básicamente en crear un región de
determinada forma. La forma determinante que he asumido es dada a través
de un bitmap. Así que por ejemplo un bitmap consistente en un círculo
azul en un fondo blanco debe generarme un formulario visible como un
círculo. La figura puede ser casi cualquier cosa como el rostro de
Mickey Mouse o la silueta de una araña. Por ello se leerá el bitmap para
generar a partir de él una forma poligonal, eso nos da libertad, pero
elimina en mucho las posibilidades de escalamiento.
PASO A PASO
-----------
En principio el algoritmo va así:
1.- Se ajusta el formulario a las dimensiones del archivo BMP. Esto es
simple. Para ello bastan las siguientes líneas de código:
// Ajustar el área / to Ajust the area
ClientWidth := Image1.Width;
ClientHeight:= Image1.Height;
2.- Se lee el primer punto del formulario y se toma como "transparente".
3.- Se busca el primer punto no "transparente" y a partir de allí se
genera un polígono con la silueta de la parte no "transparente" (ver
GenRegion en el archivo ffigura.pas).
4.- Eliminamos la barra de título (si aún nos estorba). Para ello:
BorderStyle := bsNone; // Titulo estorba / no Title
5.- Cambiamos la figura del formulario conforme al polígono. Para ello
hacemos uso ahora de la rutina "CreatePolygonRgn" y "SetWindowRgn"
(ver ActiveSkin en ffigura.pas). A diferencia del ejemplo de la
primera parte de este artículo, ya no definimos una región elíptica
(circular).
6.- Establecemos desde el TImage los eventos necesarios para el arrastre
de formularios como se hizo en el ejemplo del primer artículo.
Excepto por el tercer punto nada parece en extremo difícil. Para generar
la región poligonal sólo se busca la frontera de la figura, luego se
avanza por toda la orilla de la figura hasta estar en el punto inicial
(o acabar con la memoria, en este caso 1024 puntos). Esta serie de puntos
definen un polígono para generar un región con la función
"CreatePolygonRgn". Luego se utiliza "SetWindowRgn" y ya se tiene el
formulario con la silueta dada. Funciona pero tiene limitaciones:
nuestra figura debe tener una sola frontera, por ello no puede ser una
figura con un agujero en el medio (en todo caso el algoritmo ignorará
el agujero en el medio).
Como de costumbre este artículo va acompañado con un ejemplo para
ilustrar los puntos aquí referidos.
Nota: El algoritmo que sigue la silueta dada en el bitmap es relati-
vamente lento y tosco, sin embargo es mantenible y realiza una
cierta optimización con figuras no muy complejas. Hay un límite dado
que se genera un arreglo en memoria cuando aún no se conoce cuantos
puntos definirán la figura. Queda al usuario el variar este límite a
su conveniencia.
LOS CONTROLES
-------------
El ejemplo adjunto a este artículo contiene además botones con forma. En
modo de diseño son cuadrados pues son de tipo TBitBtn, pero en el evento
OnCreate del formulario se le aplica a cada botón la forma del gráfico
que contiene, de la misma manera que usamos para el formulario en el
procedimiento ActiveSkin:
procedure TForm1.FormCreate(Sender: TObject);
Var
hRegion : Thandle;
Par : Array [0..1024] of TPoint; // Data -> region
Cnt : Integer;
begin
Cnt := GenRegion(Par, BitBtn1.Glyph,
(BitBtn1.Width - BitBtn1.Glyph.Width+1) div 2,
(BitBtn1.Height - BitBtn1.Glyph.Height+1) div 2);
hRegion := CreatePolygonRgn(Par, Cnt, ALTERNATE);
SetWindowRgn(BitBtn1.handle, hRegion, true);
...
Esto demuestra que la definición de regiones funciona más allá de las
ventanas.
MAS ALLA
--------
El problema del tamaño del BMP sigue latente, pero prodríamos empaquetar
el BMP y usarlo empaquetado como hace Winamp. Para este enfoque hay dos
vías: podríamos usar algún algoritmo casi propietario semi-secreto o
poco común (inevitablemente pienso en el Windows Media Player) o algo
como el Zip. Esta última opción tiene la ventaja de que no estamos
restringidos en cuanto a su uso. Pueden encontrar información para saber
como manejarla en el sitio web de Latium Software:
Boletín Pascal #5
http://www.latiumsoftware.com/es/pascal/0005.php
http://www.latiumsoftware.com/es/file.php?id=p05 (código fuente)
Boletín Pascal #6
http://www.latiumsoftware.com/es/pascal/0006.php
http://www.latiumsoftware.com/es/file.php?id=p06 (código fuente)
Si las imágenes son simples, como las que usé en el ejemplo, puede
guardarlas usando 16 colores con compresión RLE 4 (esto puede hacerse
por ejemplo con el viejo y querido Borland Resource Workshop que viene
en el CD de instalación de Delphi).
LO QUE OTROS HACEN
------------------
Deberíamos separar las áreas del formulario en cliente y no cliente, así
como considerar los captions. Eventualmente podríamos usar semi-transpa-
rencias, lo que será cada vez más común (gracias a Steve Jobs por los
favores recibidos, aunque no utilicemos todos una Mac ;)
Por allí hay una librería que considera sombras, animación, morphing y
hasta un lenguaje de scripts, pero van más allá del objetivo de este
artículo.
--------------------------
El código fuente que acompaña este artículo puede descargarse desde:
http://www.latiumsoftware.com/es/file.php?id=p16
________________________________________________________________________
3. FORMAS GRISES CASI INDISTINGUIBLES EN ELEMENTOS DE MENU INHABILITADOS
Por Vladimir S. <shvetadvipa@mtu-net.ru>
Si desea ver consejos y trucos Delphi interesantes vaya con su navegador
a http://www.webmachine.ru/delphi donde encontrará el archivo KULIBA.CHM
por Valentin Ozerov que contiene más de 1.500 trucos y consejos (en
ruso). Ozerov recolectó soluciones de programadores de Rusia y de todo
el mundo, entre las que se encuentran algunas de mis soluciones también.
En una de ellas describo como superar una falla para ciertos elementos
de menú inhabilitados, que es el objeto de este artículo.
Probablemente haya notado que cuando usa imágenes en elementos de menú
y botones en barras de herramientas, éstas se ven como figuras grises
casi indistinguibles cuando dichos componentes están inhabilitados (vea
bmf.gif y btf.gif en el archivo que acompaña este boletín). Una posible
solución a este problema es moficar el código fuente de la VCL (necesita
tener la Edición Empresarial de Delphi para esto). Antes que nada,
busque el fichero ImgList.pas, habitualmente ubicado en la carpeta
${Delphi}\Source\Vcl
donde ${Delphi} es el camino donde instaló Delphi, como por ejemplo
C:\Archivos de programa\Borland\Delphi5
Luego ubique la implementación del método TCustomImageList.DoDraw.
Coméntela (para mantener la versión original por si acaso) y copie el
siguiente código:
procedure TCustomImageList.DoDraw(Index: Integer; Canvas: TCanvas;
X, Y: Integer; Style: Cardinal; Enabled: Boolean);
procedure ScrambleBitmap(var BMP: TBitmap);
const
RMask = $0000FF;
RAMask = $FFFF00;
GMask = $00FF00;
GAMask = $FF00FF;
BMask = $FF0000;
BAMask = $00FFFF;
var
R,C: integer;
Color: LongWord;
begin
with Bmp.Canvas do begin
for C:= 0 to Bmp.Height - 1 do
for R:= 0 to Bmp.Width - 1 do begin
Color:= Pixels[R,C];
if (Color = 0) or (Color = $FFFFFF) then Continue;
if (Color and RMask > $7F) and (Color and RAMask > $0) or
(Color and GMask > $7F00) and (Color and GAMask > $0) or
(Color and BMask > $7F000) and (Color and BAMask > $0)
then
Pixels[R,C]:= $FFFFFF
else
Pixels[R,C]:= 0;
end;
end;
end;
const
ROP_DSPDxax = $00E20746;
var
R: TRect;
DestDC, SrcDC: HDC;
begin
if HandleAllocated then begin
if Enabled then
ImageList_DrawEx(Handle, Index, Canvas.Handle, X, Y, 0, 0,
GetRGBColor(BkColor), GetRGBColor(BlendColor), Style)
else begin
if FMonoBitmap = nil then begin
FMonoBitmap:= TBitmap.Create;
with FMonoBitmap do begin
// Monochrome:= True; commented!!!
Width:= Self.Width;
Height:= Self.Height;
end;
end;
{ Store masked version of image temporarily in FBitmap }
FMonoBitmap.Canvas.Brush.Color:= clWhite;
FMonoBitmap.Canvas.FillRect(Rect(0, 0, Self.Width,
Self.Height));
ImageList_DrawEx(Handle, Index, FMonoBitmap.Canvas.Handle,
0, 0, 0, 0, CLR_DEFAULT, 0, ILD_NORMAL);
ScrambleBitmap(FMonoBitmap); // call patch
R:= Rect(X, Y, X+Width, Y+Height);
SrcDC:= FMonoBitmap.Canvas.Handle;
BitBlt(SrcDC, 0, 0, Width, Height, SrcDC, 0, 0,
DSTINVERT); // add!!!
{ Convert Black to clBtnHighlight }
Canvas.Brush.Color:= clBtnHighlight;
DestDC:= Canvas.Handle;
Windows.SetTextColor(DestDC, clWhite);
Windows.SetBkColor(DestDC, clBlack);
BitBlt(DestDC, X+1, Y+1, Width, Height, SrcDC, 0, 0,
ROP_DSPDxax);
{ Convert Black to clBtnShadow }
Canvas.Brush.Color:= clBtnShadow;
DestDC:= Canvas.Handle;
Windows.SetTextColor(DestDC, clWhite);
Windows.SetBkColor(DestDC, clBlack);
BitBlt(DestDC, X, Y, Width, Height, SrcDC, 0, 0, ROP_DSPDxax);
end;
end;
end;
Ahora debe compilar esta unidad. Esto normalmente se hace copiando el
archivo ImgList.pas en el directorio donde reside su proyecto y luego
compilando el proyecto, produciendo así el archivo ImgList.dcu que debe
mover por ejemplo a la carpeta ${Delphi}\Lib para que aplique a todas
las aplicaciones que compile en el futuro.
Los gráficos que resultan con este parche se ven muchísimo mejor (vea
bmr.gif y btr.gif en el archivo que acompaña este boletín).
________________________________________________________________________
4. COLOR BUTTON
Por Vladimir S. <shvetadvipa@mtu-net.ru>
Cuando lee libros de Charlie Calvert, Tom Swan y otros, puede encontrar
algo como esto "... no puede cambiar el color de un Button o un BitBtn
porque Windows lo dibuja". Bueno... no puede hacerlo, pero si desea muy
mucho hacerlo, sí puede!
Desarrollé un componente ColorBtn. Puede usar cualquier color que quiera
(vea colorbtn.gif en el archivo zip que acompaña este boletín).
Aquí está el código:
unit ColorBtn;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons;
type
TColorBtn = class(TButton)
private
IsFocused: boolean;
FCanvas: TCanvas;
F3DFrame: boolean;
FButtonColor: TColor;
procedure Set3DFrame(Value: boolean);
procedure SetButtonColor(Value: TColor);
procedure CNDrawItem(var Message: TWMDrawItem);
message CN_DRAWITEM;
procedure WMLButtonDblClk(var Message: TWMLButtonDblClk);
message WM_LBUTTONDBLCLK;
procedure DrawButtonText(const Caption: string; TRC: TRect;
State: TButtonState; BiDiFlags: Longint);
procedure CalcuateTextPosition(const Caption: string;
var TRC: TRect; BiDiFlags: Longint);
protected
procedure CreateParams(var Params: TCreateParams); override;
procedure SetButtonStyle(ADefault: boolean); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property ButtonColor: TColor read FButtonColor
write SetButtonColor default clBtnFace;
property Frame3D: boolean read F3DFrame write Set3DFrame
default False;
end;
procedure Register;
implementation
{ TColorBtn }
constructor TColorBtn.Create(AOwner: TComponent);
begin
Inherited Create(AOwner);
FCanvas:= TCanvas.Create;
FButtonColor:= clBtnFace;
F3DFrame:= False;
end;
destructor TColorBtn.Destroy;
begin
FCanvas.Free;
Inherited Destroy;
end;
procedure TColorBtn.CreateParams(var Params: TCreateParams);
begin
Inherited CreateParams(Params);
with Params do Style := Style or BS_OWNERDRAW;
end;
procedure TColorBtn.Set3DFrame(Value: boolean);
begin
if F3DFrame <> Value then F3DFrame:= Value;
end;
procedure TColorBtn.SetButtonColor(Value: TColor);
begin
if FButtonColor <> Value then begin
FButtonColor:= Value;
Invalidate;
end;
end;
procedure TColorBtn.WMLButtonDblClk(var Message: TWMLButtonDblClk);
begin
Perform(WM_LBUTTONDOWN, Message.Keys, Longint(Message.Pos));
end;
procedure TColorBtn.SetButtonStyle(ADefault: Boolean);
begin
if IsFocused <> ADefault then IsFocused:= ADefault;
end;
procedure TColorBtn.CNDrawItem(var Message: TWMDrawItem);
var
RC: TRect;
Flags: Longint;
State: TButtonState;
IsDown, IsDefault: Boolean;
DrawItemStruct: TDrawItemStruct;
begin
DrawItemStruct:= Message.DrawItemStruct^;
FCanvas.Handle:= DrawItemStruct.HDC;
RC:= ClientRect;
with DrawItemStruct do begin
IsDown:= ItemState and ODS_SELECTED <> 0;
IsDefault:= ItemState and ODS_FOCUS <> 0;
if not Enabled then State:= bsDisabled
else if IsDown then State:= bsDown
else State:= bsUp;
end;
Flags:= DFCS_BUTTONPUSH or DFCS_ADJUSTRECT;
if IsDown then Flags:= Flags or DFCS_PUSHED;
if DrawItemStruct.ItemState and ODS_DISABLED <> 0 then
Flags:= Flags or DFCS_INACTIVE;
if IsFocused or IsDefault then begin
FCanvas.Pen.Color:= clWindowFrame;
FCanvas.Pen.Width:= 1;
FCanvas.Brush.Style:= bsClear;
FCanvas.Rectangle(RC.Left, RC.Top, RC.Right, RC.Bottom);
InflateRect(RC, -1, -1);
end;
if IsDown then begin
FCanvas.Pen.Color:= clBtnShadow;
FCanvas.Pen.Width:= 1;
FCanvas.Rectangle(RC.Left, RC.Top, RC.Right, RC.Bottom);
InflateRect(RC, -1, -1);
if F3DFrame then begin
FCanvas.Pen.Color:= FButtonColor;
FCanvas.Pen.Width:= 1;
DrawFrameControl(DrawItemStruct.HDC, RC, DFC_BUTTON, Flags);
end;
end else
DrawFrameControl(DrawItemStruct.HDC, RC, DFC_BUTTON, Flags);
FCanvas.Brush.Color:= FButtonColor;
FCanvas.FillRect(RC);
InflateRect(RC, 1, 1);
if IsFocused then begin
RC:= ClientRect;
InflateRect(RC, -1, -1);
end;
if IsDown then OffsetRect(RC, 1, 1);
FCanvas.Font:= Self.Font;
DrawButtonText(Caption, RC, State, 0);
if IsFocused and IsDefault then begin
RC:= ClientRect;
InflateRect(RC, -4, -4);
FCanvas.Pen.Color:= clWindowFrame;
Windows.DrawFocusRect(FCanvas.Handle, RC);
end;
FCanvas.Handle:= 0;
end;
procedure TColorBtn.CalcuateTextPosition(const Caption: string;
var TRC: TRect; BiDiFlags: Integer);
var
TB: TRect;
TS, TP: TPoint;
begin
with FCanvas do begin
TB:= Rect(0, 0, TRC.Right + TRC.Left, TRC.Top + TRC.Bottom);
DrawText(Handle, PChar(Caption), Length(Caption), TB,
DT_CALCRECT or BiDiFlags);
TS := Point(TB.Right - TB.Left, TB.Bottom - TB.Top);
TP.X := ((TRC.Right - TRC.Left) - TS.X + 1) div 2;
TP.Y := ((TRC.Bottom - TRC.Top) - TS.Y + 1) div 2;
OffsetRect(TB, TP.X + TRC.Left, TP.Y + TRC.Top);
TRC:= TB;
end;
end;
procedure TColorBtn.DrawButtonText(const Caption: string; TRC: TRect;
State: TButtonState; BiDiFlags: Integer);
begin
with FCanvas do begin
CalcuateTextPosition(Caption, TRC, BiDiFlags);
Brush.Style:= bsClear;
if State = bsDisabled then begin
OffsetRect(TRC, 1, 1);
Font.Color:= clBtnHighlight;
DrawText(Handle, PChar(Caption), Length(Caption), TRC,
DT_CENTER or DT_VCENTER or BiDiFlags);
OffsetRect(TRC, -1, -1);
Font.Color:= clBtnShadow;
DrawText(Handle, PChar(Caption), Length(Caption), TRC,
DT_CENTER or DT_VCENTER or BiDiFlags);
end else
DrawText(Handle, PChar(Caption), Length(Caption), TRC,
DT_CENTER or DT_VCENTER or BiDiFlags);
end;
end;
procedure Register;
begin
RegisterComponents('Samples', [TColorBtn]);
end;
end.
Como puede ver no es muy difícil.
Nota: Windows dibuja el botón y ColorBtn lo pinta.
________________________________________________________________________
5. TALLER
En la última edición mostré una forma simple de poner casillas de
verificación para campos lógicos en un DBGrid sin crear un nuevo
componente. Ahora, a todos aquellos que están aprendiendo sobre
creación de componentes y tienen algo de tiempo para esto, me gustaría
proponerles como ejercicio que escriban un descendiente de TDBGrid que
maneje campos lógicos. Incluiré todas las soluciones que reciba en el
archivo adjunto de la primera edición de Marzo de este boletín.
________________________________________________________________________
6. LICENCIA DE KYLIX
Escribo este artículo porque algunos expresaron cierta preocupación por
la licencia dual de CLX, pensando que para distribuir aplicaciones
comercialmente deberían pagar una licencia comercial de CLX aparte de la
licencia de Kylix. Antes de continuar quisiera agradecer a Thomas J.
Theobald (Gerente de Producto - Herramientas RAD - Borland Software
Corporation) por muy amablemente responder mis preguntas acerca de esta
cuestión.
De acuerdo con el CLUF (Contrato de Licencia para el Usuario Final, o
EULA: End-User License Agreement) de la Open Edition de Kylix, todas las
aplicaciones, bibliotecas, paquetes, componentes, etc. que haga con esta
edición deberán ser distribuidos bajo la Licencia Pública General (o
GPL: General Public License). La CLX que vendrá con esta edición de
Kylix también será GPL. Puede encontrar más información sobre esta
licencia en el sitio web de la Free Software Foundation:
http://www.fsf.org/copyleft/gpl.html
También hay disponible una traducción no oficial al español en:
http://www.es.gnu.org/modules/content/index.php?id=8
Por otra parte, la CLX que viene con Kylix Desktop Developer Edition y
Kylix Server Developer Edition se distribuye bajo una licencia dual. Con
estas ediciones uno podrá distribuir sus aplicaciones, bibliotecas,
paquetes, componentes, etc. bajo la GPL o bajo sus propios términos de
licencia (comercial, shareware, beerware, freeware, adware, etc.) sin
tener que pagar ninguna licencia adicional aparte de la licencia de la
edición Desktop o Server de Kylix (U$S 999 y U$S 1,999 respectivamente)
puesto que éstas ya incluyen el precio de la licencia comercial de CLX.
Kylix será licenciado por desarrollador, significando ésto que puede
tener Kylix instalado en muchos ordenadores en tanto que usted sea el
único que use Kylix. Si por ejemplo dos desarrolladores pretenden usar
Kylix, aún si está instalado en la misma máquina y que no hagan uso
simultáneo, tendrán que adquirir dos licencias.
He escuchado a muchos argüir que los precios de las ediciones
comerciales de Kylix son bastante altos, y creo que lo son (para mí por
lo menos), pero tenemos que considerar tres cosas:
1) Debemos entender que Borland tiene que cubrir el costo de desarrollo
de Kylix que llevó mucho más trabajo y tiempo del esperado, o mejor
dicho del originalmente estimado, porque no puede decirse que la
demora sea totalmente inesperada considerando que estamos hablando
de casi todo un desarrollo nuevo en un entorno nuevo como Linux...
2) El precio aún es bueno considerando que con esta herramienta RAD se
podrá entrar a todo un nuevo mercado.
3) La Open Edition estará disponible para descargar gratuitamente (o por
tan sólo U$S 99 por el CD y la documentación impresa) y es bastante
apta para los contratistas independientes que desarrollan soluciones
a medida. El hecho de que tenga que entregar el código fuente y
permitir uso libre del software (copias, modificaciones, etc.) no le
impide cobrar por él. Software libre no es necesariamente software
gratis. Si alguien nos pide que desarrolle o que le haga cambios a
una aplicación GPL, esto no significa que debamos hacerlo gratis!
Podemos cobrar por nuestro trabajo tanto como podamos. También
podemos cobrar por empacar y despachar software GPL, aún si éste no
es nuestro (por ejemplo las distribuciones Linux hacen esto). Además,
distribuir su software como GPL puede ayudarlo a vender sus servicios
como desarrollador independiente porque las compañías ven con buenos
ojos al software GPL dado que no quieren estar atadas a tarifas de
mantenimiento ni verse forzadas a acudir al desarrollador original si
necesitan hacer cambios o agregados al programa. ¿Qué pasaría si
usted ya no tiene más tiempo para esas cosas? Las compañías quieren
la libertad de elegir quién mantendrá y hará posteriores desarrollos
del software que compran. No obstante ello, es bastante probable que
requieran esos servicios de usted, puesto que nadie conocerá una
aplicación mejor que aquel que la desarrolló. Fundamentalmente lo que
quieren es la seguridad de que no dependen de usted, y que eventual-
mente pueden reemplazarlo si alguna vez decide moverse a otras cosas,
o si algo le sucede, o si sienten que les cobra muy caros sus
servicios, o lo que sea...
Personalmente, creo que habrá un antes y un después del lanzamiento de
Kylix... Mi primer pensamiento es que muy pronto Linux se poblará de
aplicaciones de interfaz gráfica muy buenas distribuidas bajo los
términos de la GPL. Principalmente utilidades de configuración y
administración del sistema, y herramientas básicas que harán que Linux
sea más amistoso con el usuario. El software comercial posiblemente
tarde más en llegar, pero supongo que tarde o temprano también estará
allí. La frase "no hay aplicaciones para Linux" será parte del pasado.
Mi segundo pensamiento es que debido a que Linux es gratis, y que la
Kylix Open Edition también será gratis, y dado que la GPL es adecuada
para propósitos educativos, puedo ver ahora mismo la presión de
estudiantes y profesores en el próximo año para incluir la combinación
Linux + Kylix en los planes y programas de estudios de escuelas,
colegios, politécnicos y universidades. Creo que si Kylix no ayuda a
llevar a Linux al siguiente nivel y no consigue más adeptos al lenguaje
Pascal, nada lo hará. Bueno, el tiempo dirá...
________________________________________________________________________
7. ENLACES
* Scalabium
Un sitio bien diseñado con muchos trucos Delphi, ejemplos de código
fuente, componentes, artículos y tutoriales. (En inglés)
http://www.scalabium.com/
________________________________________________________________________
¡TÚ PUEDES AYUDARNOS!
Necesitamos tu ayuda para que este boletín pueda continuar y crecer. Una
forma en que puedes ayudarnos es enviando este enlace a tus amigos:
http://www.latiumsoftware.com/es/pascal/index.php
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, que esperamos en el futuro se traduzca también en un
mayor número de colaboraciones de artículos, trucos, etc.:
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://www.lawebdelprogramador.com/buscar/votar.php?id=615
Por favor vota. Son sólo unos segundos para ti que REALMENTE pueden
hacer la diferencia. Necesitamos tu ayuda para poder continuar.
________________________________________________________________________
Si no has recibido el archivo con el código fuente completo de los
ejemplos que se presentan en este boletín, puedes descargarlo de la
siguiente dirección: http://www.latiumsoftware.com/es/file.php?id=p16
________________________________________________________________________
Página principal: http://www.latiumsoftware.com/es/pascal/index.php
Página del grupo: http://espanol.groups.yahoo.com/group/boletin-pascal/
Para suscribirse / apuntarse: boletin-pascal-subscribe@gruposyahoo.com
Para cancelar / removerse: boletin-pascal-unsubscribe@gruposyahoo.com
Para reportar problemas con la suscripción: eds2008 @ latiumsoftware.com
________________________________________________________________________
Este boletín se provee "TAL Y COMO ESTA", sin garantía de ninguna clase.
Su uso implica la aceptación de nuestros términos de licencia y de la
ausencia de garantía que puedes leer en nuestro sitio web. Allí también
encontrarás una nota sobre marcas registradas. Te animamos a que redis-
tribuyas este boletín, siempre y cuando lo hagas en forma completa
(incluyendo la información de copyright), sin modificaciones y de manera
gratuita. Los artículos son copyright de sus respectivos autores y se
reproducen aquí con el permiso de los mismos.
________________________________________________________________________
Latium Software http://www.latiumsoftware.com/es/index.php
Copyright (c) 2001 por Ernesto De Spirito. Todos los derechos reservados
________________________________________________________________________
|