Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Gráficos (https://www.clubdelphi.com/foros/forumdisplay.php?f=8)
-   -   Evitar el refresco de un TImage como fondo de un form (https://www.clubdelphi.com/foros/showthread.php?t=38412)

gluglu 14-12-2006 00:46:30

Evitar el refresco de un TImage como fondo de un form
 
Hola compañeros del foro !

Tengo una imagen de fondo en un TImage en un form. También tengo iconos sobre la misma imagen que logro mover y cambiar de sitio en tiempo de ejecución.

Pero mi problema es que cada vez que muevo el icono, me provoca un refresco indeseado de la imagen que resulta en un 'flickeo' de la imagen de fondo bastante desagradable.

Habrá manera de evitar ese 'flickeo' de la imagen de fondo mientras estoy ejecutando la operación de movimiento de mi icono ?

Muchas gracias por vuestra ayuda. ;)

seoane 14-12-2006 00:59:53

Cita:

Empezado por gluglu
Habrá manera de evitar ese 'flickeo' de la imagen de fondo mientras estoy ejecutando la operación de movimiento de mi icono ?

Pues eso depende de la versión de delphi que tengas, si el formulario dispone de la propiedad DoubleBuffered bastara con ponerla a TRUE y el parpadeo desaparecerá. Por ejemplo, en el OnCreate del formulario:
Código Delphi [-]
procedure TForm1.FormCreate(Sender: TObject);
begin
  DoubleBuffered:= TRUE;
end;

Si por el contrario, no dispones de esa propiedad por tratarse de una versión antigua de delphi no te quedara mas remedio que crear tu internamente un buffer y manejar todos los gráficos tu mismo por código. Aunque no se si te compensara tanto trabajo.

gluglu 14-12-2006 01:21:25

Gracias Domingo !

Qué rapidez ! :D Ya lo he probado.

Por cierto, nuestro estimado compañero David en su momento me permitió crear mi avatar con la versión de Delphi y la base de datos que utilizo, ... y en ella se vé que estoy utilizando Delphi 9 :o , o en este caso más avanzado, Delphi 2006, en su versión VCL.net

Con el DobleBuffered := True funciona bien el 'no' refresco del TImage de fondo, aunque se refresca al final del todo y aun se nota el 'flickeo'.

Lo que pasa es que en el caso de poner la propiedad DobleBuffered a verdadero, no me muestra el movimiento del icono que estoy moviendo, con lo cual el efecto tampoco es el deseado, porque hasta que no dejo de mover el ratón, no se muestra la posición en la que he dejado el icono.

Por lo tanto, no me sirve esta opción.

Lo raro, y es por lo que inicié este hilo, es que con cualquier otro form creado como MDIChild, que es mi caso, al moverlo no me produce el dichoso parpadeo, pero con un icono posicionado (y moviéndolo) sobre el mismo form principal, si que se me dá el parpadeo. :mad:

seoane 14-12-2006 01:26:47

A lo mejor lo que esta "fallando" es el código que utilizas para mover el icono. Si pudieras poner un poco de código, le echábamos un vistazo.

gluglu 14-12-2006 01:35:49

El icono, y dos labels asociados, los muevo con los eventos OnMouseDown, OnMouseMove y OnMouseUp :

Código Delphi [-]
procedure TMainform.Icon01MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Dragging  := True;
  DragPoint := Point(X, Y);
end;
 
procedure TMainform.Icon01MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if Dragging then begin
    Icon01.Left   := Icon01.Left + X - DragPoint.X;
    Icon01.Top    := Icon01.Top  + Y - DragPoint.Y;
    Label01a.Left := Icon01.Left - 34;
    Label01a.Top  := Icon01.Top  + 34;
    Label01b.Left := Icon01.Left - 34;
    Label01b.Top  := Icon01.Top  + 48;
  end;
end;
 
procedure TMainform.Icon01MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Dragging := False;
end;

El TImage tiene cargada una imagen JPG, y la propiedad Strech := True, con el TImagen ocupando todo el fondo del form MDIForm principal, con la propiedad Align := alClient;

seoane 14-12-2006 01:51:24

Yo para hacer esto, suelo emplear un código parecido, aunque uso solo un evento. Por ejemplo, aquí tengo una imagen que ocupa todo el formulario (Streach:= TRUE; Align:= alClient; ) y otra mas pequeña que es la que muevo. En el evento OnMouseMove de esta última coloco los siguiente:

Código Delphi [-]
procedure TForm1.Image2MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  P: TPoint;
begin
  GetCursorPos(P);
  if ssLeft in Shift then
  begin
    Image2.Top:= Image2.Top + P.Y - AnteriorP.Y;
    Image2.Left:= Image2.Left + P.X - AnteriorP.X;
  end;
  AnteriorP:= P;
end;

Siendo AnteriroP una variable declarada de la siguiente manera:
Código Delphi [-]
TForm1 = class(TForm)
    Image1: TImage;
    Image2: TImage;
    procedure Image2MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    AnteriorP: TPoint;      // < -- Aqui esta declarada
  public
    { Public declarations }
  end;

Este ejemplo, una vez coloca la propiedad DoubleBuffered a TRUE no muestra ningún tipo de parpadeo, y la imagen 2 se puede mover perfectamente.

gluglu 14-12-2006 02:22:52

Pues estimado amigo Domingo, ... me sigue sin funcionar como yo pretendo. Es correcto que tal y como indicaba antes, mientras estoy moviendo el cursor, la imagen no se actualiza, y por lo tanto no parpadea. Pero es que en mi caso, con Delphi 2006 al menos, tampoco me va mostrando el movimiento 'de arrastre' del icono que estoy moviendo. Por lo que hasta que no para el ratón, no me muestra el icono en la posición actual del ratón, y en ese momento también me vuelve a repintar la imagen de fondo.

Si muevo el ratón muy despacio, algo así como dudando donde voy a situar el icono, cada vez que para el movimiento del ratón, me redibuja el icono en esa posición, y también como decia arriba, la imagen de fondo. Lo que sigue provocando el molesto parpadeo al mover el ratón muy despacio.

Además, con el DoubleBuffered a True, entiendo que la imagen se carga en memoria, y el consumo de la misma aumenta. Con una imágen pequeña entiendo no haya problema, pero con una imagen grande, en buena resolución, como fondo de pantalla, el consumo de memoria puede ser considerable.

En el caso concreto que estoy probando, la imagen ocupa entre 300 y 500K, y es en concreto un fondo de Windows Vista que he cogido de aqui, que por cierto me parecen bastante bonitos y espectaculares algunos. ;)

http://www.flickr.com/photos/brajesh...7594389648659/

seoane 14-12-2006 02:37:34

Pues es verdad, no estaba teniendo en cuenta que tu form es un fsMDIForm. En ese caso aparecen todos esos efectos que mencionas, que no aparecen cuando el formulario es normal. A lo mejor alguien con mas experiencia en ese tipo de formularios te puede explicar ese comportamiento tan extraño.

En cuanto a la propiedad DoubleBuffered. Lo único que hace es que el formulario a la hora de dibujarse, no lo haga cada objeto directamente, si no que se dibujan en un buffer intermedio y luego este se dibuja de una sola vez en la pantalla. No queda nada a mayores cargado en memoria, si es eso lo que te preocupaba.

gluglu 14-12-2006 11:49:20

Pues tienes toda la razón. Si el formulario no es MDI funciona todo correctamente, incluso sin DoubleBuffered := True.

Pero claro, mi formulario es MDI y mi aplicación está concebida de esa manera.

Si alguien más sabe algo acerca de ello, lo agradezco.

De momento lo que he hecho, y para que no quede tan mal, es que al iniciar el movimiento del ratón con el icono, desactivo el TImage poniendo la propiedad Visible := False, y cuando suelto el botón, de nuevo vuelvo a ponerlo visible. Al menos a mi me parece que de esta manera queda mejor. Lo que provoca que el usuario esté moviendo el icono sobre un fondo normal.

Muchas gracias de todos maneras, Domingo.

Deiv 15-12-2006 15:34:51

Hola,
No tengo mucha experiencia en gráficos y/o en programación pero recordé que hace tiempo atrás había leido algo al respecto del hilo y te paso las direcciones, donde quizá puedas hallar respuesta a tus preguntas, son artículos que se encuentra en GRUPO ALBOR, y la idea de Ian Marteens:

1.- Cómo conseguir una imagen como fondo de un formulario
2.- Imagen de fondo en un formulario MDI

Ojalá te sirvan de algo
Un saludo
Deiv

Edito: No encuentro esa página en ALBOR, entonces estaba en la sección Trucos, ahora no lo encuentro, de todas maneras te envío 2 archivos adjuntos que grabé hace tiempo, es lo mismo.

Deiv 18-12-2006 23:31:25

Hola,
¿Te sirvió la información?, no?, ya que Yo también estoy pensando más adelante hacer algo parecido al tuyo, me informarías si esos ejemplos te ayudaron y ver la forma de implementar en los mios?
Un saludo

gluglu 19-12-2006 16:26:31

Gracias Deiv por tu información.

He intentado implementarla, pero a primeras me encuentro con que el método Forms.MakeObjectInstance no lo tengo disponible. Para mayor información digo que estoy utilizando Delphi 2006 VCL.Net

No sé si existe algún sustituto para implementarla.

El código correspondiente a los ejemplos que mandaste es :
Código Delphi [-]
procedure TForm1.FormShow(Sender: TObject); 
...
// Obtener la dirección de nuestro procedimiento de ventana 
Proc_Cliente := Forms.MakeObjectInstance(ClienteWindowProc);
...
...
//############################################################################
// RUTINA : ClienteWindowProc(Messages::TMessage &Message) 
// 
// ACCIÓN : Sub-clasifica el procedimiento de mensajes del área cliente con 
//          el objeto de pintar en el mismo (mensaje 'WM_ERASEBKGND'). 
//############################################################################
procedure TForm1.ClienteWindowProc(var Message: Messages.TMessage);
....

javisuco 08-01-2007 16:26:11

Repintado del control TImage.
 
Estimado gluglu:

Este es uno de los principales problemas que tiene Delphi, el otro es el de las Fuentes Grandes (La interfaz se estropea seleccionando fuentes grandes).

Yo hace muchos años detecté este problema y es..... Tatán..... si te fijas en el código del control TImage cada vez que un objeto se mueve sobre su canvas, se producen dos eventos:

- Invalidate.
- Repaint (Esto es, el parpadeo).

Para ello, no tienes más remedio que crearte un nuevo control copiando el código del TImage que está accesible y cortar la actualización cuando un objeto pasa por encima de el.

Espero te sirva de algo.


La franja horaria es GMT +2. Ahora son las 01:21:09.

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