Flüssige Graphik mit Multimediatimer und doublebuffered Form?



  • Hallo,
    Ich arbeite mit dem C++ Builder 6 und habe das Problem, dass meine bewegte ständig Graphik einfriert.
    Ich benutzte den Multimediatimer und eine doublebuffered Form wie in mehreren
    anderen Beiträgen hier schon beschrieben.
    Sieht auch super aus, aber nur bis zum Hängenbleiben.
    Was mach ich falsch?
    Besten Dank!

    private:	// User declarations
            static void CALLBACK TimerFunction(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
    
    public:		// User declarations
            Graphics::TBitmap* bmp;
            __fastcall TForm1(TComponent* Owner);
            void MMTimerHandler(UINT nIDEvent);
            UINT idEvent;
    
            void __fastcall TForm1::PrepareMeasurement(TObject *Sender);
    

    CPP

    #include <vcl.h>
    #pragma hdrstop
    #include <mmsystem.h>
    #include <windows.h>
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    int x=0;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
      bmp = new Graphics::TBitmap;
      bmp->Width  = 500;
      bmp->Height = 500;
      Form1->DoubleBuffered=true;
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      TIMECAPS tc;
      timeGetDevCaps(&tc, sizeof(TIMECAPS));
      DWORD resolution = 5;
      timeBeginPeriod(resolution);
      idEvent = timeSetEvent(20, resolution, TimerFunction, (DWORD)this, TIME_PERIODIC);
     }
    
    void CALLBACK TForm1::TimerFunction(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
    {
      TForm1* obj = (TForm1*)dwUser;
      obj->MMTimerHandler(wTimerID);
    }
    
    void TForm1::MMTimerHandler(UINT nIDEvent)
    {
       x++;
       Form1->Label1->Caption =x;
       if(x>350)x=0;
       bmp->Canvas->Brush->Color = clSilver;
       bmp->Canvas->Rectangle(0, 0, 1000, 1000);
       bmp->Canvas->Brush->Color = clRed;
       bmp->Canvas->Pen->Width=2;
       bmp->Canvas->Ellipse(100+x, 100, 200+x, 200);
       Form1->PaintBox1->Canvas->Draw(0, 0, bmp);
    }
    


  • Was ist dein Endziel?

    Canvas eignet sich leider nicht für zeitgesteuerte Animationen dafür is es viel zu langsam evtl. wäre die Verwendung von OpenGL angebracht?



  • Hallo,

    die Callback-Funktion, die du verwenden möchtest, ist veraltet (s. hier) und m.E. ausserdem nicht für Grafikaufgaben geeignet.

    Eine Win32-Callbackfunktion sollte/darf kein Member einer Klasse sein. Tipp dazu von embarcadero.
    SetTimer wäre eher das richtige bzw. gleich ein TTimer aus der Komponentenpalette.



  • Danke für die Antworten!

    Stimmt, laut embarcadero darf ichs so nicht machen.
    Der TTimer ist halt etwas ungleichmässig und führt zu recht starkem Ruckeln.
    Ich habs jetzt als Kompromisslösung so gemacht:
    Der Multimediatimer tacktet die Translationsvariable x, der Ttimer gibt die Events zum Zeichnen. Es ist so schon deutlich flüssiger als mit dem TTimer allein.

    Einfach gesagt, möchte ich etwa Laufbänder generieren, die möglichst gleichmässig über den Bildschirm wandern. Nicht für die Börse, sondern für Messwerte.
    Von OpenGL hab ich keine Ahnung, werds mir aber mal anschauen ums vielleicht noch besser hinzukriegen, danke!


Anmelden zum Antworten