Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Gráficos (https://www.clubdelphi.com/foros/forumdisplay.php?f=8)
-   -   BitBtl vs Draw (https://www.clubdelphi.com/foros/showthread.php?t=36759)

Deiv 23-10-2006 15:45:13

BitBtl vs Draw
 
¿Por que los 2 códigos del TTimmer trabajan de diferente forma?

Código Delphi [-]
 
procedure TForm1.FormCreate(Sender: TObject);
begin
   G:= TBitMap.Create;
   G.LoadFromFile(getcurrentdir+'/molecule14.bmp');
   G.TransparentColor:=G.Canvas.Pixels[1,1];
   G.Transparent:= True;
   G.TransparentMode:= tmFixed;
end;

Opción 1 :
Código Delphi [-]
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Canvas.Brush.Color := clBtnFace;
  Canvas.FillRect(Rect(10+i-2, 10, 10+I, 10+G.Height)); //clear old small rect
  Bitblt(Canvas.Handle, 10 + i, 10, G.Width, G.Height, G.Canvas.Handle, 0, 0, SRCCOPY);
  i:=i+2;
end;

Opción 2 :
Código Delphi [-]
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Canvas.Brush.Color := clBtnFace;
  Canvas.FillRect(Rect(10+i-2, 10, 10+I, 10+G.Height)); //clear old small rect
  Canvas.Draw(10+i,10,G);
  i:=i+2;
end;
En un principio cuando no había que transparentar el BitMap cualquier opción valía (BitBtl o Draw) pero cuando intenté transparentar en TForm1.FormCreate, BitBtl no hace nada, y Draw INTENTA transparentar, pero ocurre un efecto especial (adjunto el Archivo) al evento OnMouseMove: al principio transparenta su parte izquierda y luego se completa como era el BitMap originalmente (solo la izquierda) y la derecha está transparentado.

1.- ¿A que se debe todo este efecto con Draw?
2.- ¿Como hacer funcionar el transparente con BitBtl?

Neftali [Germán.Estévez] 23-10-2006 16:18:52

1 Archivos Adjunto(s)
Creo que en parte puede ser problema de que el fondo de la imagen no es uniforme.
Prueba con esta imagen y esta línea:

Código Delphi [-]
Bitblt(Canvas.Handle, 10 + i, 10, G.Width, G.Height, G.Canvas.Handle, 0, 0, MERGECOPY);

Deiv 23-10-2006 16:56:25

Ok, en este momento no tengo Delphi lo revisaré en casa, pero que hay con:
Cita:

1.- ¿A que se debe todo este efecto con Draw?



en la opción 2?

seoane 23-10-2006 18:54:39

Respuesta 1
El efecto se produce porque al dibujar una imagen lo haces sobre la anterior, y las partes transparentes dejan ver los restos de la anterior, de esta manera al ir moviendo la imagen los restos de las imágenes anteriores terminan llenando toda la parte izquierda de la imagen.

Respuesta 2
La función Bitblt es una api que copia un bloque de pixeles de un Device Context a otro, le trae sin cuidado las propiedades del objeto TBitmap. Por eso no hace caso de la propiedad Transparent.

Posible solución:
La solución pasa por usar el método Draw y borrar los restos de la imagen anterior antes de dibujar la actual, además de usar un buffer para evitar el parpadeo. Nos quedaría algo así en el evento del timer:
Código Delphi [-]
procedure TForm1.Timer1Timer(Sender: TObject);
var
  Buffer: TBitmap;
begin
  Canvas.Brush.Color:= clBtnFace;
  Buffer:= TBitmap.Create;
  try
    Buffer.Canvas.Brush.Color:= Canvas.Brush.Color;
    Buffer.Width:= G.Width + 2;
    Buffer.Height:= G.Height + 2;
    Buffer.Canvas.Draw(2,2,G);
    Canvas.Draw(i+10,10,Buffer);
  finally
    Buffer.Free;
  end;
  inc(i,2);
end;

Deiv 23-10-2006 22:43:53

1 Archivos Adjunto(s)
He aplicado la nueva imagen de Neftali, su código, y el BitBtl ahora si trabaja bien con el transparente.

Y tal como mencioné un post anterior: Con el Draw (y esta nueva imagen inclusive) no pasa nada, ahora me pareciera que recorriera un "Cometa" al dibujar, inclusive he intentado con DoubleBuffered:=true; y nada

Estoy en un Cafe Internet en este momento y voy leyendo el Post de Seoane (no tengo Delphi a mano), me parece algo sólido lo que explica, lo probaré mas un rato, de todas maneras quería que compartieran "mi cometa"... es decir mi aplicación en la cual se ve ese efecto, es interesante, lo pueden observar.

Deiv 24-10-2006 18:55:03

Adjunto en este post para los que no tienen Delphi a mano un archivo BMP capturado de mi aplicación cuando se mueve "mi cometa"

Cita:

Respuesta 2
La función Bitblt es una api que copia un bloque de pixeles de un Device Context a otro, le trae sin cuidado las propiedades del objeto TBitmap. Por eso no hace caso de la propiedad Transparent.
Ahora que leo con mayor atención, entonces? ¿Como el código de Néftali hace funcionar el transparente en el BitBtl?


Código Delphi [-]
Bitblt(Canvas.Handle, 10 + i, 10, G.Width, G.Height, G.Canvas.Handle, 0, 0, MERGECOPY);

Como dije anteriormente trabaja el BitBtl y transparenta.

¿Como explicar eso???

seoane 24-10-2006 20:28:09

Cita:

Empezado por Deiv

Como dije anteriormente trabaja el BitBtl y transparenta.

¿Como explicar eso???

No querido Deiv, no transparenta. Y si crees que transparenta deberías comprarte un monitor nuevo :D Lo que hace Bitbtl con la opción MERGECOPY es combinar pixel a pixel con el fondo utilizando la operación booleana AND, como el fondo de la imagen que te paso Neftali es de color blanco al realizar la operación AND el color resultante es el del fondo del formulario (a AND 1 = a), pero si te fijas el resto de colores de la imagen se ven también alterados. De hecho aunque la propiedad Transparent estuviese a FALSE, se obtendría el mismo resultado, porque como ya dije antes, aunque no me creyeras ;) ,al bitbtl le trae sin cuidado.

Neftali [Germán.Estévez] 25-10-2006 11:10:49

Como bien te han dicho el código que te pasé no transparenta, simplemente que usando el color adecuado, evita los problemas.

Deiv 27-10-2006 02:21:13

Gracias muchachos, aunque no crean de tiempo sali de duda (casi un año) cuando en un hilo pregunté de otra forma: Evitar parpadeo de imagen Aquí ahora está mas claro, gracias a los Genios como Uds. los novatos salimos de dudas.

Deiv 23-01-2007 15:05:36

Hola amigos!

Con motivos de dar estética a mi Aplicación en cuanto a seleccionar una opción, necesito mostrar unas 15 imágenes en un Área de mi Form (superior) en constante movimiento de derecha a izquierda y viceversa, las imágenes tendrán un único tamaño de 100 x 150 pixels, dicha Área tendrá la dimensión de 600 x 200 pixels (donde quepan 5 imágenes separadas). Definiendo que el área será dividida por el medio (300 pixels) de un "Contenedor" deseo al evento OnMouseMove que si el puntero del Mouse se encuentra en la izquierda de este "contenedor" las imágenes deben moverse en sentido contrario (a la derecha), que si el puntero del Mouse se encuentra en la derecha las imágenes deben moverse a la izquierda, y finalmente que si el puntero del Mouse sale del área contenedora las imágenes deben dejar de moverse.

Mis preguntas:
- ¿Cuál "contenedor" (Área) para las imágenes sugieren?: TForm, TPanel, TPaintBox? otro?
- ¿Cómo mostrar las imágenes en ese "contenedor"?: Por código con TImageList, en varias TImage? otro?

En este hilo me enseñaron a mover UNA imagen, lo que no me doy cuenta es como cargar ahora VARIAS imágenes y lograr ese mismo efecto.
Gracias anticipadas.

Deiv 29-01-2007 15:10:15

Hola amigos,
¿No me encuentran alguna sugerencia? no me doy cuenta cómo cargar varias imágenes, con una era fácil como dije, pero con varias??
Deiv


La franja horaria es GMT +2. Ahora son las 15:07:42.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi