PDA

Ver la Versión Completa : Ventana con forma personalizada


Cecil
14-06-2008, 12:52:39
Hola a todos, tengo una duda que hace tiempo que quiero solucionar, y es la siguiente:

Primero mirad la imagen: http://www.usuarios.lycos.es/gatorayosx/formulario-ejemplo.JPG

Bueno, si os fijais, lo que quiero es un formulario personalizado, pero el gran problema es el de las esquinas, que son redondeadas y transparentes. He encontrado un par de ejemplos, pero no funcionan bien, porque lo que quiero esque la ventana funcione normalmente, que se pueda ampliar el formulario, maximizar, etc. Bueno y otro problema es el dichoso parpadeo de las imagenes al redimensionarlas... Agradezco toda ayuda, un saludo.

coso
14-06-2008, 13:59:29
Una sencilla busqueda por el foro ... me dio este (http://www.clubdelphi.com/foros/showthread.php?t=3582&highlight=redondeadas) resultado entre otros.

Cecil
14-06-2008, 14:22:43
Ya realice esa sencilla búsqueda, y encontre ese ejemplo, pero, los bordes se ven demasiado pixelados, y yo necesito poner una imagen con la esquina transparente como en la imagen de mi ejemplo. Muchas gracias por tu respuesta, pero necesito más ayuda. Un saludo!

coso
14-06-2008, 15:06:32
Bueno el antialias es un poquillo mas complicado en delphi 5 y me va bastante lento : / pero el degradado es sencillo. Te pongo un ejemplo y espero q encuentres alguna funcion de antialias con buen rendimiento.


unit degradado;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
f: HRGN;
begin
Form1.Borderstyle := bsNone;
f := CreateRoundRectRgn(
0, // x-coordinate of the region's upper-left corner
0, // y-coordinate of the region's upper-left corner
clientwidth, // x-coordinate of the region's lower-right corner
clientheight, // y-coordinate of the region's lower-right corner
40, // height of ellipse for rounded corners
40); // width of ellipse for rounded corners
SetWindowRgn(Handle,f,True);
end;

procedure TForm1.FormPaint(Sender: TObject);
var
ri,gi,bi : integer;
rf,gf,bf : integer;
pr,pg,pb : double;
r,g,b : integer;
x : integer;
c : TColor;
begin
inherited;

ri := $3F;
gi := $4F;
bi := $70;

rf := 255;
gf := 255;
bf := 255;

pr := (rf - ri) / (2*Width/3);
pg := (gf - gi) / (2*Width/3);
pb := (bf - bi) / (2*Width/3);

c := 0;
for x := 0 to (2*Width div 3) - 1 do
begin
r := ri + round(pr * x);
g := gi + round(pg * x);
b := bi + round(pb * x);

c := RGB(r,g,b);

Canvas.Pen.Color := c;
Canvas.MoveTo(x,0);
Canvas.LineTo(x,Height);
end;

for x := (2*Width div 3) to Width do
begin
Canvas.Pen.Color := c;
Canvas.MoveTo(x,0);
Canvas.LineTo(x,Height);
end;
end;
end.


Saludos

coso
14-06-2008, 16:07:16
Te dejo aqui la ventana con fondo degradado, esquinas redondeadas y antialiasing. De antialias seguro q hay funciones mas buenas por internet. Lo dejo por si alguien quiere cojer la idea.


unit antialias;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure Antialias(Rt : TRect);
procedure Degradado;
procedure FormPaint(Sender: TObject);
function Red(c : TColor) : integer;
function Green(c : TColor) : integer;
function Blue(c : TColor) : integer;
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
Desktop : TControlCanvas;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
f: HRGN;
begin
Desktop := TControlCanvas.Create;

try
Desktop.Handle := GetDC(0);
except
end;

Form1.Borderstyle := bsNone;
f := CreateRoundRectRgn(
0, // x-coordinate of the region's upper-left corner
0, // y-coordinate of the region's upper-left corner
clientwidth, // x-coordinate of the region's lower-right corner
clientheight, // y-coordinate of the region's lower-right corner
40, // height of ellipse for rounded corners
40); // width of ellipse for rounded corners
SetWindowRgn(Handle,f,True);
Left := 40;
Top := 200;
end;

procedure TForm1.Degradado;
var
ri,gi,bi : integer;
rf,gf,bf : integer;
pr,pg,pb : double;
r,g,b : integer;
x : integer;
c : TColor;
begin
ri := 255;
gi := 255;
bi := 255;

rf := $8B;
gf := $9B;
bf := $D1;

pr := (rf - ri) / (2*Height/3);
pg := (gf - gi) / (2*Height/3);
pb := (bf - bi) / (2*Height/3);

c := 0;
for x := 0 to (2*Height div 3) - 1 do
begin
r := ri + round(pr * x);
g := gi + round(pg * x);
b := bi + round(pb * x);

c := RGB(r,g,b);

Canvas.Pen.Color := c;
Canvas.MoveTo(0,x);
Canvas.LineTo(Width,x);
end;

for x := (2*Height div 3) to Height do
begin
Canvas.Pen.Color := c;
Canvas.MoveTo(0,x);
Canvas.LineTo(Width,x);
end;
end;

procedure TForm1.Antialias(Rt : TRect);
var
x,y,i : integer;
r,g,b : longint;
cl : array [0..8] of TColor;
begin
for x := Rt.Left -1 to Rt.Right + 1 do
for y := Rt.Top - 1 to Rt.Bottom + 1 do
begin
r := 0;
g := 0;
b := 0;

cl[0] := desktop.Pixels[Left + x-1,Top + y-1];
cl[1] := desktop.Pixels[Left + x-1,Top + y];
cl[2] := desktop.Pixels[Left + x-1,Top + y+1];

cl[3] := desktop.Pixels[Left + x,Top + y-1];
cl[8] := desktop.Pixels[Left + x,Top + y];
cl[4] := desktop.Pixels[Left + x,Top + y+1];

cl[5] := desktop.Pixels[Left + x+1,Top + y-1];
cl[6] := Desktop.Pixels[Left + x+1,Top + y];
cl[7] := Desktop.Pixels[Left + x+1,Top + y+1];

for i := 0 to 7 do
begin
r := r + Red(cl[i]);
g := g + Green(cl[i]);
b := b + Blue(cl[i]);
end;

r := (r div 8);
g := (g div 8);
b := (b div 8);

Canvas.Pixels[x,y] := RGB(r,g,b);
end;
end;

function TForm1.Red(c : TColor) : integer;
begin
Red := c and $FF;
end;

function TForm1.Green(c : TColor) : integer;
begin
Green := (c and $FF00) div $100;
end;

function TForm1.Blue(c : TColor) : integer;
begin
Blue := (c and $FF0000) div $10000;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
inherited;
Degradado;
Antialias(Rect(0,0,30,30));
Antialias(Rect(Width-30,0,Width,30));
Antialias(Rect(0,Height - 30,30,Height));
Antialias(Rect(Width-30,Height - 30, Width, Height));
Antialias(Rect(0,0,Width,2));
Antialias(Rect(0,0,2,Height));
Antialias(Rect(Width-2,0,Width,Height));
Antialias(Rect(0,Height-2,Width,Height));

end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Desktop.Free;
end;

end.


Saludos

Cecil
14-06-2008, 20:07:27
Mil gracias por tu ayuda, pero el ejemplo del antialiasing no me gusta del todo como realiza el suavizado del borde, pero lo ire tocando hasta dejarlo a mi gusto.
Y bueno, otra cuestión, ¿no existe ninguna forma de poner un pixel en concreto semitransparente?. Un saludo.

coso
14-06-2008, 22:07:20
Bueno, la funcion de antialias que he escrito es una chapucilla rapida :D asi como la del gradiente (bueno esta la uso :), seguro que hay de mejores y mas rapidas (este es un tema ya muy tocado). Si usas mas arriba de delphi 5, deberias tener la propiedad alphablend para conseguir el translucido. Si no, lo que deberias hacer entonces es, tal y como se hace en el antialias, hacer la media aritmetica del color de fondo y del color que quieras pintar. (puedes tb dar un 'peso' a cada valor, el de fondo y el de la form y luego dividir por el total : ej; (3*fondo + 7*form) / 10) . Lo q no se es como conseguir el pixel de fondo, pues el GetDC(0) me da el desktop una vez pintado...y si sustraigo la region no me deja pintar en ella X/ bueno lo dicho seguro q si lo buscas por alla lo encuentras...

saludos