AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Schnell wiederholt in PaintBox zeichnen (Bitblt)
Thema durchsuchen
Ansicht
Themen-Optionen

Schnell wiederholt in PaintBox zeichnen (Bitblt)

Ein Thema von BenjaminH · begonnen am 26. Okt 2009 · letzter Beitrag vom 1. Nov 2009
Antwort Antwort
Seite 1 von 2  1 2      
BenjaminH

Registriert seit: 14. Okt 2004
Ort: Freiburg im Breisgau
713 Beiträge
 
Turbo Delphi für Win32
 
#1

Schnell wiederholt in PaintBox zeichnen (Bitblt)

  Alt 26. Okt 2009, 20:31
Hallo,
ich zeichne bei meinem BeatDetector in ganz kurzen Intervallen das Spektrum.
Der Timer ist der aus MMSystems
timer := timeSetEvent(25, 25, @UpdateFreq, 0, TIME_PERIODIC); Im Timer findet folgendes statt:
Delphi-Quellcode:
Spectrum:TBitmap;

BitBlt(MainForm.PaintBox1.Canvas.Handle, 0, 0, spectrum.width, Spectrum.height,spectrum.Canvas.Handle, 0, 0, SRCCOPY);
Jetzt passiert folgendes:
  • Nach einiger Zeit bleibt das Spektrum stehen(unter XP später, unter Win 7/Vista früher)
  • Blende ich jetzt die PaintBox aus und wieder ein, so funktioniert das Spektrum unter XP wieder.
    Unter Win 7/Vista dagegen ist es dann ganz verschwunden, die PaintBox ist also durchsichtig.

Allerdings habe ich durch zwischenzeitliches Speichern der Bitmap Spectrum erkannt, das diese durchgehend weitergezeichnet wird. Einzig das übertragen in die PaintBox scheint nicht zu funktionieren.

Kann irgendjeman dieses Verhalten erklären und mir einen Tipp geben, wie ich das beheben kann?
Vielen Dank!
Viele Grüße,
Benjamin
Benjamin
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#2

Re: Schnell wiederholt in PaintBox zeichnen (Bitblt)

  Alt 26. Okt 2009, 20:37

Hm, schwer zu sagen das kann viele Ursachen haben.

Wie zeichnest du auf das Bitmap und oder erstellst du irgend etwas was du nicht frei gibst ?

PS.: Die Paintbox kann man auch weg lassen und direkt auhc den Canvas der Form zeichnen.
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
BenjaminH

Registriert seit: 14. Okt 2004
Ort: Freiburg im Breisgau
713 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: Schnell wiederholt in PaintBox zeichnen (Bitblt)

  Alt 26. Okt 2009, 21:03
Zeichen ich direkt auf die Form passiert dasselbe.
Ich habe mit FastMM geprüft, ob ich irgendwas nicht freigebe. Offensichtlich nicht.
Die einzigen Sachen die ich nutze sind FillRect und LineTo.
Benjamin
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#4

Re: Schnell wiederholt in PaintBox zeichnen (Bitblt)

  Alt 27. Okt 2009, 11:09
Kannst du die Zeichenrout. hier mal zeigen ?
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.024 Beiträge
 
Delphi 12 Athens
 
#5

Re: Schnell wiederholt in PaintBox zeichnen (Bitblt)

  Alt 27. Okt 2009, 11:27
Wenn ich mich recht erinnere, muss das Zeichnen in die PaintBox im OnPaint-Event erfolgen, da die PaintBox keinen Speicher für den Zeicheninhalt bereitstellt.

In deinem Fall sollte im Timer-Ereignis lediglich PaintBox.Invalidate aufgerufen werden, während der BitBlt-Befehl im OnPaint der Paintbox stehen sollte.
Uwe Raabe
  Mit Zitat antworten Zitat
BenjaminH

Registriert seit: 14. Okt 2004
Ort: Freiburg im Breisgau
713 Beiträge
 
Turbo Delphi für Win32
 
#6

Re: Schnell wiederholt in PaintBox zeichnen (Bitblt)

  Alt 27. Okt 2009, 14:09
Zitat von Uwe Raabe:
Wenn ich mich recht erinnere, muss das Zeichnen in die PaintBox im OnPaint-Event erfolgen, da die PaintBox keinen Speicher für den Zeicheninhalt bereitstellt.
Das ist zwar richtig, in dem Fall aber glaube ich leider irrelevant. Zwar "erinnert" sich die PaintBox nicht mehr an ihren Inhalt, wenn sie einmal geleert wurde, das ist aber egal, weil sie 40 mal pro Sekunde neu befüllt wird.

Die Zeichenroutine sieht so aus:
Delphi-Quellcode:
procedure paintSpectrum;
var
  i: Integer;
  y: Integer;
  sc:INteger; //Skalierung;
  b0,b1:Integer;
  rect:TRect;
  avg:Single;
begin
  //Fläche schwarz machen
  Rect.Left:=0;
  Rect.Top:=0;
  Rect.Right:=Spectrum.Width+1;
  Rect.Bottom:=Spectrum.Height+1;
  with Spectrum.Canvas do
  begin
    brush.Color:=clBlack;
    FillRect(Rect);
  end;
  
  //Jedes Band zeichnen
  b1:=1;
  for i := 0 to Bands - 1 do
  begin
    //Breite des Bandes
    b0:=b1-1;
    b1:=Trunc(Power(2, i * 10.0 / (BANDS - 1)));

    //Skalierungsfaktor
    sc:=10 + b1 - b0;

    //Wert des Bandes(skaliert)
    Y := Trunc((sqrt(MainForm.BandHistory[i,MainForm.Histposition-1] / log10(SC)) * 1.7 * Spectrum.Height) - 4);

    //Band zeichnen
    Rect.Left:=trunc(i*spectrum.width/bands);
    Rect.Top:=spectrum.Height-y;
    Rect.Right:=trunc((i+1)*spectrum.width/bands);
    Rect.Bottom:=spectrum.Height;
    with Spectrum.Canvas do
    begin
      //Ausgewähltes Band in Gelb, sonst grün
      if i=MainForm.SelectedBand then
        Brush.Color:=clYellow
      else
        Brush.Color:=clGreen;
      FillRect(Rect);
    end;
  
    //Durchschnitt des Bandes
    avg:=MainForm.AverageBandEnergy(MainForm.BandHistory[i]);
     
    //Durchschnittswert des Bandes einzeichnen
    Y := Trunc((sqrt(avg / log10(SC)) * 1.7 * Spectrum.Height) - 4);
    Spectrum.Canvas.Pen.Color:=clRed;
    Spectrum.Canvas.MoveTo(Rect.Left,Spectrum.Height-Y);
    Spectrum.Canvas.LineTo(Rect.Right,Spectrum.Height-Y);

    //Schwellwert einzeichnen
    Y :=Trunc((sqrt(avg*MainForm.DetectingFactor / log10(SC)) * 1.7 * Spectrum.Height) - 4);
    Spectrum.Canvas.Pen.Color:=clYellow;
    Spectrum.Canvas.MoveTo(Rect.Left,Spectrum.Height-Y);
    Spectrum.Canvas.LineTo(Rect.Right,Spectrum.Height-Y);
  end;
  //Auf Zeichenfläche übertragen
  BitBlt(MainForm.PaintBox1.Canvas.Handle, 0,0,spectrum.width,Spectrum.height,spectrum.Canvas.Handle, 0,0,SRCCOPY);
end;
Benjamin
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#7

Re: Schnell wiederholt in PaintBox zeichnen (Bitblt)

  Alt 27. Okt 2009, 14:28
Ich kann mir vorstellen, dass der Timer sich hier quasi selbst überholt, die Zeichenroutine also ab und an noch zugange ist wenn schon der nächste Callback kommt. Das staut sich dann zusammen. Du könntest also einen Skip-Frame-Mechanismus einbauen: Kling moppig, wäre aber einfach nur das Abschalten der Reaktion auf den Timer wenn gerade gezeichnet wird.

Ein anderer Ansatz wäre es das zeichnen ähnlich wie in Spielen zu machen: Im Application.Idle Event. Um dabei nicht 100% CPU Last reinzubraten kann man mittels eines FPS Counters die FPS quasi künstlich drosseln. Timer sind zum Zeichnen immer so eine Sache, und selten eine gute

Edit: Ein dritter Weg wäre noch ein separater Zeichenthread der sich immer wieder mit Sleep(0) in der Dauerschleife "klein" hält. Auch hier wäre eine manuelle FPS-Begrenzung sinnvoll, und das letztliche Zeichnen auf den Zielcanvas sollte Synchronized gemacht werden.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
BenjaminH

Registriert seit: 14. Okt 2004
Ort: Freiburg im Breisgau
713 Beiträge
 
Turbo Delphi für Win32
 
#8

Re: Schnell wiederholt in PaintBox zeichnen (Bitblt)

  Alt 27. Okt 2009, 14:48
Zitat von Medium:
Ich kann mir vorstellen, dass der Timer sich hier quasi selbst überholt, die Zeichenroutine also ab und an noch zugange ist wenn schon der nächste Callback kommt. Das staut sich dann zusammen. Du könntest also einen Skip-Frame-Mechanismus einbauen: Kling moppig, wäre aber einfach nur das Abschalten der Reaktion auf den Timer wenn gerade gezeichnet wird.
Das hab ich mal versucht. War aber nix.

Über die anderen Möglichkeiten muss ich mir mal Gedanken machen.
Was ist denn groß der Unterschied zwischen dem Zeichnen im Timer und dem im OnIdle Event/eigenem Thread? In beiden Fällen wird doch regelmäßig gezeichnet, nur dass das beim Timer eben in festen Intervallen ist, oder?
Benjamin
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.024 Beiträge
 
Delphi 12 Athens
 
#9

Re: Schnell wiederholt in PaintBox zeichnen (Bitblt)

  Alt 27. Okt 2009, 14:54
Das mit dem Sich-Selbst-Überholen des Timers kannst du mit dem OnPaint-Ansatz ebenfalls lösen.
Uwe Raabe
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#10

Re: Schnell wiederholt in PaintBox zeichnen (Bitblt)

  Alt 27. Okt 2009, 15:03
Auch hier wieder ein Offscreenbitmap basteln und in einem Timer etc. auf dieses Bitmap zeichnen lassen.
Das/die Bitmaps dann in der Paintbox zeichnen.

Spectrum ist eine PaintBox ?

Ich pers. verwende keine PaintBox, ist mir zu "dumm".


Beispiel:
Delphi-Quellcode:
implementation

{$R *.dfm}

const
  VisXOffset = 50;
  VisYOffset = 40;

procedure TForm1.FormCreate(Sender: TObject);
begin
  bmp := TBitmap.Create;
  bmp.Width := 200;
  bmp.Height := 80;
  bmp.Canvas.Brush.Color := clBlack;

  RenderVisDone := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if RenderVisDone and ASSIGNED(bmp) then
  begin
    RenderVis;
    bitblt(Canvas.Handle, VisXOffset, VisYOffset, bmp.Width, bmp.Height,
      bmp.Canvas.Handle, 0, 0, SRCCOPY);
  end;
end;

procedure TForm1.RenderVis;
var
  i: integer;
  gt: Cardinal;
begin
  RenderVisDone := False;
  bmp.Canvas.FillRect(bmp.Canvas.ClipRect);

  for i := 0 to bmp.Width div 4 - 1 do
  begin
    gt := GetTickCount;
    Windows.SetPixel(bmp.Canvas.Handle, i*4, round(bmp.Height div 2 + sin(gt/250+i)*15), RGB(255, 0, 0));
    Windows.SetPixel(bmp.Canvas.Handle, i*4, round(bmp.Height div 2 + sin(gt/500-i)*20), RGB(128, 128, 255));
  end;

  RenderVisDone := True;
end;

end.
Man kann sich das auch in eine Classe bauen bzw. formen.


//Edit: Delphicodehighlightdingenbumensfehlfunktionskorrek tur ..
Angehängte Dateien
Dateityp: zip demo_949.zip (204,8 KB, 30x aufgerufen)
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:03 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz