Entwickler-Ecke

Windows API - Flackern beim Zeichnen auf Desktop


supersass1 - Do 20.09.07 10:51
Titel: Flackern beim Zeichnen auf Desktop
hallo,

ich habe folgenden Code:

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:
procedure TForm1.Timer2Timer(Sender: TObject);
var
  DesktopDC: HDC;
  DesktopCanvas: TControlCanvas;
mi,mj:integer;
k:real;
begin
if Timer2.Interval = 1 then timer2.Interval := 20;
mbla := mbla+1;
mj := trunc(sin((mbla / 180) * Pi)*500+500);
Label5.Caption:=IntToStr(mbla);
Label6.Caption:=FloatToStr(mj);


 //bildschirm refreshen, verantwortlich fürs flackern

  randomize;
  DesktopDC := GetDC(0);
  if DesktopDC = 0 then
  begin
    //Hier Fehlerbehandlung einfügen
  end
  else
  try
    DesktopCanvas := TControlCanvas.Create;
    try
      DesktopCanvas.Handle := DesktopDC;
          DesktopCanvas.Brush.Style := bsSolid;
          DesktopCanvas.Brush.Color:=RGB(255,0,50);
          DesktopCanvas.Pen.Color:=RGB(255,0,50);
          DesktopCanvas.Ellipse(0,0,mj,mj);
    finally
      DesktopCanvas.Free;
    end;
  finally
    ReleaseDC(0, DesktopDC);
  end;


end;

procedure TForm1.Button11Click(Sender: TObject);
begin
Timer2.Enabled := true;
mbla:=0; // golbal definiert

end;


Der Code erzeugt einen roten Kreis, der immer größer wird.
Doch leider flackert das Bild ganz schön dolle.
Vermutlich ist dies dran schuld:
Zitat:
RedrawWindow(0, nil, 0, RDW_UPDATENOW or RDW_ALLCHILDREN or RDW_INVALIDATE or RDW_ERASE or RDW_INTERNALPAINT);

gibt es eine bessere Lösung?


Vielen Dank :)


Delete - Do 20.09.07 10:57

Zeichne auf ein Bitmap im Speicher un kopiere das dann auf den Desktop bei Bedarf.


supersass1 - Do 20.09.07 11:00

user profile iconLuckie hat folgendes geschrieben:
Zeichne auf ein Bitmap im Speicher un kopiere das dann auf den Desktop bei Bedarf.


Ja du kannst gut reden, ich versteh nicht viel was du sagst, zumindest fehlst mir bei der Umsetzung.

Wie kann ich was auf ein Bitmap zeichnen? Und wie kann ich das ganze da noch auf dem Desktop zeichnen, und noch millisekündlich aktualisieren?


bms - Do 20.09.07 11:04

Was für einen Zweck hat das Programm? Ich frage deshalb weil die Line eine Farbe hat. Muß das sein? Also welchen Zweck hat das Programm? Wenn Farbe nicht notwendig ist, dann könntest du z.B. mit Xor arbeiten. In diesem Fall bräuchtest du nicht refreshen, sondern mit einem erneuten Zeichnen den Desktop wieder in den Ausgangszustand bringen.

Alternativ kannst du ein Cliping bereich berechnen. Das Refresh würde dann nur da ausgeführt wo sich der Kreis befindet. Das ist aber etwas kompliziert, aber letztendlich die sauberste Lösung.


bms - Do 20.09.07 11:06

user profile iconsupersass1 hat folgendes geschrieben:
user profile iconLuckie hat folgendes geschrieben:
Zeichne auf ein Bitmap im Speicher un kopiere das dann auf den Desktop bei Bedarf.


Ja du kannst gut reden, ich versteh nicht viel was du sagst, zumindest fehlst mir bei der Umsetzung.

Wie kann ich was auf ein Bitmap zeichnen? Und wie kann ich das ganze da noch auf dem Desktop zeichnen, und noch millisekündlich aktualisieren?


Tut mir leid, wenn du nicht programmieren kannst, wieso versuchst du gleich auf dem Desktop zu zeichnen? Lerne erst das nötigste und setzt dich erst dann an das Programm drann.


supersass1 - Do 20.09.07 11:06

user profile iconbms hat folgendes geschrieben:


Alternativ kannst du ein Cliping bereich berechnen. Das Refresh würde dann nur da ausgeführt wo sich der Kreis befindet. Das ist aber etwas kompliziert, aber letztendlich die sauberste Lösung.


Das klingt doch interessant.

Ja ich muss Farbe verwenden. Nein, das Programm hat keinen Sinn, ich möchte lediglich die Funktionen des Zeichnens "erkunden". Ich habe mir als Ziel gesetzt, bewegende Körper mit Farbeffekten zu füllen. Evtl später daraus 3D Objekte machen.


bms - Do 20.09.07 11:19

Wieso nutzt du dann den Desktop? Der Desktop ist nicht zum Zeichnen da. Man kann auf den Desktop zeichnen, aber das ist eher die Ausnahme und eigentlich ist es nur dem Betriebssystem vorbehalten. Du hast dein Fenster und in dem Solltest du arbeiten.

Ein Tipp, guck dir Canvas an. Canvas ist die Leinwand auf der du zeichnen kannst. Jedes Formular hat seine Canvas-Leinwand, z.B. Form1.Canvas. Guck dir dann was TCanvas so alles an Möglichkeiten bietet. Wahrscheinlich hast du dein Beispiel aus irgendeiner FAQ Seite, aber der Desktop ist nur für die Profis an die auch wissen was die damit machen wollen.

Dein Beispiel würde dann in etwa so aussehen:


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:
procedure TForm1.Timer2Timer(Sender: TObject);
var
  DesktopDC: HDC;
  DesktopCanvas: TControlCanvas;
  mi,mj:integer;
  k:real;
begin
  if Timer2.Interval = 1 then timer2.Interval := 20;
  mbla := mbla+1;
  mj := trunc(sin((mbla / 180) * Pi)*500+500);
  Label5.Caption:=IntToStr(mbla);
  Label6.Caption:=FloatToStr(mj);


    //bildschirm refreshen, verantwortlich fürs flackern
    randomize;

    Canvas.Brush.Style := bsSolid;
    Canvas.Brush.Color:=RGB(255,0,50);
    Canvas.Pen.Color:=RGB(255,0,50);
    Canvas.Ellipse(0,0,mj,mj);

end;

procedure TForm1.Button11Click(Sender: TObject);
begin
  Timer2.Enabled := true;
  mbla:=0; // golbal definiert
end;


supersass1 - Do 20.09.07 11:23

Ja aber so wie du es eben gepostet hast, wird quasi immer nur draufgezeichnet, sodass man die Bewegung gar nicht sieht. Also muss man auch das "eigene" Fenster refreshen.

Letztendlich möcht ich aber gerne auf dem Dekstop zeichnen, wenn ich eh refreshen muss, spielt es keine Rolle ob im eingenen Fenster oder nicht.


bms - Do 20.09.07 11:37

Ach herrje, willst du auf dem Desktop zeichnen weil du keine Ahnung von der Materie hast oder weil es wirklich auf dem Desktop sein muss? Wie ich dir schon gesagt habe ist das Desktop für das Betriebssystem da. Das Betriebssystem managt dann die einzelnen Programme und stellt jedem der Programme sein eigenes Fenser zu Verfügung in dem jedes Programm zeichnen kann was er will. Wenn du auf dem Desktop zeichnest, dann kann das Ergebnis jede Zeit vom System überschreiben werden. Du hast weniger Kontrolle.

Wärst du ein Profi, ich hätte gesagt, daß du schon weißt was du tust, aber deine Antwort auf Luckie Bemerkung zeigt, daß du keine Ahnung hast was du da tust. Du weißt nichtmal wie du auf einem Bitmap zeichnen kannst und begibst dich gleich an den Desktop. Natürlich könne ich dir weiter helfen, aber ich hab keine Lust einem zu helfen der stur am Unsinn hält und dadurch auch dem Helfenden mehr Arbeit mach als es nötig ist.


supersass1 - Do 20.09.07 11:46

Okay, dass sehe ich ein.
Ich habe es, wie du gesagt hast, in Form versuchst, aber da flackert es auch.

Ich versuche es nun im eigenen Fenster, aber benötige dennoch Hilfe, wärest du bereit mir dabei zu helfen?

Danke :)


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure TForm1.Timer1Timer(Sender: TObject);
var
mj:integer;
begin
  if Timer1.Interval = 1 then timer1.Interval := 10;
  mbla := mbla+1;
  mj := trunc(sin((mbla / 180) * Pi)*100+100);


    Image1.Canvas.Brush.Style := bsSolid;
    Image1.Canvas.Brush.Color:=RGB(255,0,50);
    Image1.Canvas.Pen.Color:=RGB(255,0,50);
    Image1.Canvas.Ellipse(200-mj,200-mj,mj,mj);


end;


Das Soll ein Kreis sein, der immer größer und kleiner wird, er bleibt aber groß, welch nicht refresht wird..


Delete - Do 20.09.07 12:07

http://www.michael-puff.de/Developer/Artikel/2003_2005/WieWindowsFunktioniert.shtml
Ganz am Ende vom Artikel ist ein Beispiel, wie man das mit einem Bitmap im Speicher macht. Der Rest sollte aber auch für dich interessant sein.


bms - Do 20.09.07 13:11

Etwas allgemeines zu Delphi. Delphi ist keine Multimediaprogrammiersprache. Du kannst zwar auch sehr vieles mit Delphi machen, aber dann wird es kompliziert. Noch komplizierter wird es nur wenn du auf dem Desktop direkt arbeitest. Wenn es dir also drum geht etwas Multimedia zu programmieren, dann wäre z.B. Flash die richtige Programmiersprache. Wenn es aber Delphi sein soll und du sowieso irgendwann 3D programmieren willst, dann solltest du es vielleicht gleich richtig machen und 3D programmieren. Ich bin da nicht auf dem neusten Stand was aktuell das beste ist um 3D zu programmieren, aber die anderen wissen es. Der Vorteil ist, daß das Ergebnis unheimlich schnell verarbeit würde, da du auf DirectX zugreifen würdest. Das ist andere Tachnik als Canvas. Wenn du noch nicht soweit gehen willst, dann bleibt dir nur Canvas übrig. Nur wie gesagt ist Canvas nicht dafür gedacht Multimedia darzustellen. Es ist etwas langsammer und man muß alle Möglichkeiten ausnutzen.

Um dein Problem mit dem Kreis effizient zu lösen müßtest du mit Clipping-Bereichen arbeiten. Das funktioniert einfach so: du erstellst eine Maske mit Bereichen die gezeichnet werden können. Alles außerhalb des Bereichs kann in der Zeit nicht überzeichnet werden. Auch wenn du es versuchst. Zeichnen kannst du nur im Clipping Bereich. Dadurch, daß der Clipping bereich in der Regel kleiner als das ganze Fenster ist, wird hier sehr viel Zeit gespart. Es ist effizient. Das Betriebssystem arbeitet auch so. Das Problem ist nur, daß Delphi selbst in der Hinsicht nichts anbietet. Man muß hier auf die Windows-Api ausweichen. Und einfach ist es auch nicht, aber erlernbar. Guck dir also am besten die Funktionen die mit Clipping und Regionen zu tun haben. Auf jeden Fall ist das nichts um so innerhalb von paar Minuten zu erlernen. Aber wenn man es nach paar Tagen drauf hat, kann man sehr viel schneller zeichnen.

Etwas langsamer, aber auch einfacher geht es wenn du mit zwei oder drei Bitmaps arbeitest.


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:
var
  Form1: TForm1;
  mbla: Integer;

implementation

{$R *.DFM}

var
  Bmp1, Bmp2: TBitmap;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Bmp1 := TBitmap.Create;
  Bmp2 := TBitmap.Create;
end;

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

procedure TForm1.Timer1Timer(Sender: TObject);
var
mj:integer;
begin
  if Timer1.Interval = 1 then timer1.Interval := 10;
  mbla := mbla+1;
  mj := trunc(sin((mbla / 180) * Pi)*100+100);

    Bmp2.Canvas.Draw(0, 0, Bmp1); // Zuerst Hintergrund von Bmp1 nach Bmp2 kopieren

    Bmp2.Canvas.Brush.Style := bsSolid;
    Bmp2.Canvas.Brush.Color:=RGB(255,0,50);
    Bmp2.Canvas.Pen.Color:=RGB(255,0,50);
    Bmp2.Canvas.Ellipse(200-mj,200-mj,mj,mj); // etwas auf Bmp2 zeichnen

    Image1.Picture.Bitmap.Canvas.Draw(0, 0, Bmp2); // Bmp2 nach Image1 kopieren
    //Durch das kopieren gibt es kaum flakern, allerdinsg kostet das Kopieren Zeit.
    //Bei sowas einfachem merkt man es nicht. Bei einem Spiel würde es ruckeln.
end;

procedure TForm1.Button11Click(Sender: TObject);
begin

  try
    with Image1.Picture do
    begin
      // Hintergrung in Image1 laden. Pfad kann abweichen bei anderen Computern
      Bitmap.LoadFromFile('c:\windows\web\wallpaper\Grüne Idylle.bmp');

      //Bitmap.Width := Image1.Width;
      //Bitmap.Height := Image1.Height;

      Bmp1.Assign(Bitmap);
      Bmp2.Assign(Bitmap);

      Bmp1.Canvas.Draw(0, 0, Bitmap); // Bitmap-Hintergrung  vom Image1 sichern
      // Wenn Hintergrund nicht nötig, dann kann man sich auch Bmp1 schenken
    end;

    Timer1.Enabled := true;
    mbla:=0; // golbal definiert

  finally

  end;
end;


Der Nachteil beim Arbeiten mit zwei bis drei Bitmaps ist, daß das Ganze seine Zeit kostet. Flackern wird es zwar nicht mehr, aber unter Umständen ruckeln.

Das Beispiel oben lädt zuerst ein Hintergrundbild "Grüne Idylle.bmp" in Image1, damit es nicht so grau ist. Dieses Hintergrundbild wird dann in Bmp1 gesichert. Bei jedem Durchlauf wird zuerst Bmp1 ins Bmp2 kopiert. Damit wird der alte Inhalt von Bmp2 überschrieben. Dann wird etwas in Bmp2 gezeichnet. Das Ergebnis wird ins Image1 kopiert.

Würde man sich Bmp2 sparen und Bmp1 direkt ins Image1 kopieren und direkt auf Image1 zeichen, dann würde das Bild flackern, denn es gäbe eine Kurzen Augenblick in dem das Bmp1 bild ohne die Zeichnung (hier roter Kreis) sichtbar wäre. Das Auge würde es merken und es würde flackern. Indem man aber es über Bmp2 macht, kopiert man bereits das fertige Bild ins Image1. Das merkt das Auge kaum.


supersass1 - Do 20.09.07 13:36

user profile iconLuckie hat folgendes geschrieben:
http://www.michael-puff.de/Developer/Artikel/2003_2005/WieWindowsFunktioniert.shtml
Ganz am Ende vom Artikel ist ein Beispiel, wie man das mit einem Bitmap im Speicher macht. Der Rest sollte aber auch für dich interessant sein.


vielen Dank schonmal, ein wenig ruckeln tut es immer noch.

Aber nun eine andere Frage, warum kann ich kein Kreis erzeugen, sondern nur ein Quadrat?


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:
procedure DrawPicture(c1:integer=0;c2:integer=0;c3:integer=0;c4:integer=0);
var
  Canvas    : TCanvas;
  Bitmap    : TBitmap;

begin
  begin
    Bitmap := TBitmap.Create();
    try
      Bitmap.Canvas.Brush.Color:=RGB(255,0,50);
      Bitmap.Canvas.Brush.Style:=bsSolid;
      Bitmap.Canvas.Pen.Width:=5;
      Bitmap.Canvas.Ellipse(c1,c2,c3,c4);
        Bitmap.Height := c3;
        Bitmap.Width := c4;

        Canvas := TCanvas.Create();

          Canvas.Draw(0,0, Bitmap);
        finally
          Canvas.Free;
        end;
      finally
      end;
    finally
      Bitmap.Free;
    end;
  end;
end;


procedure TForm1.Timer1Timer(Sender: TObject);
var
mj:integer;
begin
  if Timer1.Interval = 1 then timer1.Interval := 10;
  mbla := mbla+1;
  mj := trunc(sin((mbla / 180) * Pi)*100+100);
   DrawPicture(200-mj,200-mj,mj,mj);
   RedrawWindow(0, nil, 0, RDW_UPDATENOW or RDW_ALLCHILDREN or RDW_INVALIDATE or RDW_ERASE or RDW_INTERNALPAINT);


end;
end.


bms - Do 20.09.07 13:51

Eine Frage, programmierst du deine Beispiele selbst oder suchst du sie dir im Internet?


supersass1 - Do 20.09.07 13:56

Ich programmier sie selber.
Aber natürlich schau ich im internet, um zu gucken WIE es überhaupt geht, woher sollt ich es sonst wissen?

Also warum wird kein Kreis angezeigt?


jaenicke - Do 20.09.07 14:12

Weil du nicht das Canvas des Formulars benutzt, sondern ein neues Objekt erzeugst. Das ist aber keiner sichtbaren Zeichenfläche zugeordnet. ;-)
Wenn du DrawPicture als Prozedur innerhalb des Formulars deklarierst, dann kannst du direkt Canvas benutzen ohne dafür eine Variable zu deklarieren oder es neu zu erzeugen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
TForm1 = class(TForm)
  Timer1: TTimer;
  ...
private
  procedure DrawPicture(c1:integer=0;c2:integer=0;c3:integer=0;c4:integer=0);
public
end;

...

procedure TForm1.DrawPicture(c1:integer=0;c2:integer=0;c3:integer=0;c4:integer=0);


// EDIT:
Dein try..finally stimmt irgendwie nicht, erstens brauchst du gar keins, wenn der Quelltext stimmt, zweitens hast du nur ein try aber dreimal finally...
Die Exception dürfte genau sein, dass Canvas keiner Zeichenfläche zugeordnet ist.


supersass1 - Do 20.09.07 14:29

user profile iconjaenicke hat folgendes geschrieben:

// EDIT:
Dein try..finally stimmt irgendwie nicht, erstens brauchst du gar keins, wenn der Quelltext stimmt, zweitens hast du nur ein try aber dreimal finally...
Die Exception dürfte genau sein, dass Canvas keiner Zeichenfläche zugeordnet ist.


Ja ich hab von meinem Code nur das nötigste Rausgeschnitten, dabei muss das passiert sein.

So, hier ist der Code beabreitet mit TForm1.DrawPicture... aber dennoch sehe ich nur ein bewegendes Viereck, keinen Kreis.


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:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure DrawPicture(c1:integer=0;c2:integer=0;c3:integer=0;c4:integer=0);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
    mbla:Integer;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
Timer1.Enabled := false;
end;

procedure TForm1.DrawPicture(c1:integer=0;c2:integer=0;c3:integer=0;c4:integer=0);
var
  DC        : HDC;
  Canvas    : TCanvas;
  Bitmap    : TBitmap;

begin
  begin
    Bitmap := TBitmap.Create();
    try
      Bitmap.Canvas.Brush.Color:=RGB(255,0,50);
      Bitmap.Canvas.Brush.Style:=bsSolid;
      Bitmap.Canvas.Pen.Width:=5;
      Bitmap.Canvas.Ellipse(c1,c2,c3,c4);
        Bitmap.Height := c3;
        Bitmap.Width := c4;
      
      DC := GetWindowDC(GetForegroundWindow());

      try
        Canvas := TCanvas.Create();
        try

          Canvas.Handle := DC;

          Canvas.Draw(0,0, Bitmap);
        finally
          Canvas.Free;
        end;
      finally
        ReleaseDC(0, DC);
      end;
    finally
      Bitmap.Free;
    end;
  end;
end;


procedure TForm1.Timer1Timer(Sender: TObject);
var
mj:integer;
begin
  if Timer1.Interval = 1 then timer1.Interval := 10;
  mbla := mbla+1;
  mj := trunc(sin((mbla / 180) * Pi)*100+100);
   DrawPicture(200-mj,200-mj,mj,mj);
   RedrawWindow(0, nil, 0, RDW_UPDATENOW or RDW_ALLCHILDREN or RDW_INVALIDATE or RDW_ERASE or RDW_INTERNALPAINT);


end;


procedure TForm1.Button1Click(Sender: TObject);
begin
if (Timer1.Enabled = false) then Timer1.Enabled := true else Timer1.Enabled := false;
end;

end.


Delete - Do 20.09.07 15:19

Sollte das so was werden? Demo im Anhang.


bms - Do 20.09.07 15:20

user profile iconsupersass1 hat folgendes geschrieben:
Ich programmier sie selber.
Aber natürlich schau ich im internet, um zu gucken WIE es überhaupt geht, woher sollt ich es sonst wissen?

Also warum wird kein Kreis angezeigt?


Ich frage deshalb, weil Teile deines Codes hochwertig sind, also viel Hintergrundwissen erfordern, andere wiederum wie die eines absoluten Anfängers sind. Deshalb weiß ich nicht an welches Stelle ich helfen soll.

Ich wollte schon fragen welchen Sinn der obere Code hat bis ich weiter unten gelesen habe, daß du nur Teile davon veröffentlicht hat. Trotzdem glaube ich, daß du keine Ahnung hast was du da machst. Vor allem die Flags bei RedrawWindow sind zum Teil Unsinn. Und auch wenn, so wird es immer flackern. Ich weiß nicht wo man dir helfen soll, welcher Code also von dir ist und welchen du nur kopiert ist.

Zu deiner Frage. Das Rechteck ist deswegen da, weil du die Bitmap genauso breit machst wie der Kreis breit sein soll. Das Rechteck ist die Grenze der Bitmap. Und da der Kreis größer ist als die Bitmap, sieht man immer nur das Rechteck.


bms - Do 20.09.07 15:25

user profile iconLuckie hat folgendes geschrieben:
Sollte das so was werden? Demo im Anhang.


Glaube ich nicht, denn ein funktionierendes Beispiel in der Art habe ich bereits oben vor zwei Stunden gepostet. Er will es auf jeden Fall auf dem Desptop haben und es soll sich über refreshen des Desktops löschen.


bms - Do 20.09.07 15:32

user profile iconbms hat folgendes geschrieben:
Zu deiner Frage. Das Rechteck ist deswegen da, weil du die Bitmap genauso breit machst wie der Kreis breit sein soll. Das Rechteck ist die Grenze der Bitmap. Und da der Kreis größer ist als die Bitmap, sieht man immer nur das Rechteck.


Ups, kleiner Fehler von mir. Der Grund ist, daß du zuerst auf einer Bitmap mit den Abmessungen 0 x 0 etwas zeichnest und erst dann die Breite und Höhe setzt. Da kommt nichts raus. Verschiebe die beiden Zeilen nach oben:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
    Bitmap := TBitmap.Create();
    try
        Bitmap.Height := c3;
        Bitmap.Width := c4;

      Bitmap.Canvas.Brush.Color:=RGB(255,0,50);
      Bitmap.Canvas.Brush.Style:=bsSolid;
      Bitmap.Canvas.Pen.Width:=5;
      Bitmap.Canvas.Ellipse(c1,c2,c3,c4);


Trotzdem wird es unheimlich flackern.


supersass1 - Do 20.09.07 15:43

Doch für den Anfang ist das schonmal hilfreich. Ich werde mir deinen Code anschauen und daraus lernen.

@bms: ja z.b. dies Redraw habe ich aus dem Internet, ich weiß halt keine bessere Möglichkeit um zu refreshen. Aber grundsätzlich kannst du davon ausgehen, dass es von mir ist, zumindest dass ich weiß, warum ich jenen Code habe.


Delete - Do 20.09.07 15:48

Hast du dir mein Beispielprogramm mal angesehen?


jaenicke - Do 20.09.07 15:48

Die Frage ist vor allem, was das werden soll. Wenn das zum Beispiel ein Bildschirmschoner sein soll (weil was anderes fällt mir eigentlich nicht ein, wo man etwas quer über die anderen Fenster schreibt und die anderen Fenster darunter sichtbar bleiben müssen), dann ginge das sehr viel besser (mit weniger flackern).


supersass1 - Do 20.09.07 15:52

ich möchte lediglich die Funktionen testen.

Deshlalb werde ich mir den Code von Luckie noch einmal genauer anschauen.
Ja ich habe dein Beispiel program gesehn.


bms - Fr 21.09.07 01:18

user profile iconsupersass1 hat folgendes geschrieben:
ich möchte lediglich die Funktionen testen.

Deshlalb werde ich mir den Code von Luckie noch einmal genauer anschauen.
Ja ich habe dein Beispiel program gesehn.


Wenn man lediglich die Funktionen testen will, dann informiert man sich über die Funktionen. Man kommt nicht mit einem Beispiel das so schlecht programmiert ist, daß es kaum eine Steigerung gibt. Und eine Steigerung gibt es kaum. Das Ganze flackert so stark, daß man Angst hat epileptische Anfälle zu bekommen. Es spricht nichts dagegen die API Funktionen kennen zu lernen, aber dann lernt man sie vorher und gibt den Anderen nicht das Gefühl, daß der ganze Code aus Copy&Paste zusammengestellt ist. Letztendlich bist du selbst schuld wenn irgendwann keiner mehr Lust hat dir weiter zu helfen. Denn helfen tut man gerne, aber dann soll bitte derjenige mit dem Problem die beste und einfachte Lösung anstreben. Du tust es nicht. Trotz zwei sauberen Lösungen kommst du immer noch mit Desktop an und verwendest Codeteile von denen du keine Ahnung hast was sie letztendlich bewirken.


Delete - Fr 21.09.07 09:46

user profile iconsupersass1 hat folgendes geschrieben:
ich möchte lediglich die Funktionen testen.

Aber dazu legt man sich nicht unnötig Hürden in den Weg. Wenn ich Zeichenfunktionen kennen lernen will, dann teste ich sie auf dem eigenen Fenster über das ich die volle Kontrolle habe und nicht gleich in irgendwelchen fremden Fenstern oder gar auf dem Desktop.