Entwickler-Ecke

Multimedia / Grafik - Wie kann ich flimmerfrei in den Canvas Zeichnen?


mathias - Mi 12.06.02 21:19
Titel: Wie kann ich flimmerfrei in den Canvas Zeichnen?
Auf einem Canvas mit einem Hintergrundbild werden mehrere Rechtecke flimmerfrei bewegt.

Das Ganze wird in einen Schattenspeicher gezeichnet und nachher mit einem Rutsch in den Canvas kopiert.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Image1: TImage;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
    Bit : TBitmap;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  pos : Array[1..50of TPoint;    // Koordinaten der Objecte

procedure TForm1.Timer1Timer(Sender: TObject);
var
  x, y, i : Integer;
begin                    // Image1 ist das Hintergrundbild
  for x := 0 to Bit.Width div Image1.Width do begin
    for y := 0 to Bit.Height div Image1.Height do begin
      Bit.Canvas.Draw(x * Image1.Width, y * Image1.Height, Image1.Picture.Bitmap);
    end;
  end;
  for i := 1 to 50 do begin
   Inc(pos[ i ].x, 1 + i mod 2);
   Inc(pos[ i ].y, 2 - i mod 2);
   if pos[ i ].x > ClientWidth then pos[ i ].x := -100;
   if pos[ i ].y > ClientHeight then pos[ i ].y := -100;
   Bit.Canvas.Draw(00nil);
   Bit.Canvas.Brush.Color := i * $FFFFFF div 20;
   Bit.Canvas.Rectangle(pos[ i ].x, pos[ i ].y, pos[ i ].x + 100, pos[ i ].y + 100);
  end;
  Canvas.Draw(00, Bit);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i : Integer;
begin
  Timer1.Interval := 1;
  Bit := TBitmap.Create;
  Bit.Width := ClientWidth;
  Bit.Height := ClientHeight;
  for i := 1 to 50 do begin
    pos[ i ].X := Random(ClientWidth);
    pos[ i ].Y := Random(ClientHeight);
  end;
end;

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

end.
:D


alexschultze - Fr 14.06.02 22:50
Titel: Geht doch einfacher !?
Also, wenn man canvas oder images oder sonstwas auf ner Form bewegen will ohne das es flimmert, würde ich es anders angehen.

ich habe auch ewig nach sowas gesucht. Habe immer noch umständliche Codes wie diesen gefundne. z.b. Karten über Form bewegen...

viel einfacher find ich:
<object>.doublebuffered:=true;

Damit wird der zweite Buffer aktiviert und kein flimmern mehr da.
Mit Forms funzt es 100%.
Man muss es immer auf das darunterliegende Objekt (über das bewegt wird) übertragen.

Ich sehe nicht warum die anderen Variante besser sein soll.
Auf Gegenargumente wartend (oder vielleicht auch auf ProArgumente),
alex


mortus - Mi 26.06.02 12:16

duerfte das gleiche wie doublebuffered sein:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
var
    dc,dctmp:HDC;
    bitmap:HBITMAP;
begin
     dc:=GetDC(windowhandle);
     bitmap:=CreateCompatibleBitmap(dc,windowwidth,windowheight);
     dctmp:=CreateCompatibleDC(dc);
     SelectObject(dctmp,bitmap);
     //-->Alles ZEICHNEN
     zeichnen(dctmp);
     //<--Alles ZEICHNEN
     bitblt(dc,0,0,windowwidth,windowheight,dctmp,0,0,srccopy);
     DeleteDC(dctmp);
     DeleteObject(bitmap);
     ReleaseDC(windowhandle,dc);
end;

natuerlich kann man auch alles bei programmstart erzeugen und spaeter wieder freigeben.


alexschultze - Mo 01.07.02 12:58
Titel: gut ;)
gut ;)

aber es ist eben einfacher

alex


Udontknow - Di 02.07.02 11:30

DoubleBuffered:=True reicht manchmal einfach nicht, es kann trotzdem flackern. Genau dann wird es nötig, zuerst seine Zeichenoperationen in ein TBitmap zu packen, und anschliessend mit einem einzigen Draw-Befehl das Resultat auf den Bildschirm zu knallen.


Pit - Di 02.07.02 18:39

Udontknow hat folgendes geschrieben:
DoubleBuffered:=True reicht manchmal einfach nicht, es kann trotzdem flackern.

Soweit so richtig.

Zitat:
Genau dann wird es nötig, zuerst seine Zeichenoperationen in ein TBitmap zu packen, und anschliessend mit einem einzigen Draw-Befehl das Resultat auf den Bildschirm zu knallen.

Was meinst du, was DoubleBuffered macht?

Ein Problem ist, wie es das macht, ein anderes ist, das es nur eine von 3 Flackerursachen beseitigt.

MfG Pit.