Neuzeichnen vieler Bitmaps
-
Hallo, mal wieder ich
und mal wieder ein eigentlich simples aber für mich komisches Problem.
Der Code erklärt sich ja im Prinzip von selbst.
Ich habe eine große Bitmap als Hintergrund und eine kleine (Kugel) die sich nun
über die große Bitmap bewegt. Das ganze ja demzufolge in einer Schleife.
Die Kugelbewegt sich zwar, wird aber nicht von der alten Position gelöscht.
Das heißt, ich sehe die Bewegungsspur der Bitmap. Oder muss ich noch sowas wie FillRect() verwenden?PAINTSTRUCT ps; HDC Bildhdc; Bildhdc = BeginPaint (hWnd, &ps); HDC Bufferhdc, Kugelhdc; Bufferhdc = CreateCompatibleDC(Bildhdc); Kugelhdc = CreateCompatibleDC(Bildhdc); HBITMAP HBMP_OldBuffer = (HBITMAP) SelectObject(Bufferhdc, HBMP_Buffer); HBITMAP HBMP_OldKugel = (HBITMAP) SelectObject(Kugelhdc, HBMP_Kugel); TransparentBlt(Bufferhdc, X, Y, 16, 16, Kugelhdc, 0, 0, 16, 16, RGB(255,0,255)); BitBlt(Bildhdc, 0, 0, 400, 350, Bufferhdc, 0, 0, SRCCOPY); SelectObject(Bildhdc, HBMP_OldBuffer); SelectObject(Bildhdc, HBMP_OldKugel); DeleteDC(Bufferhdc); DeleteDC(Kugelhdc); EndPaint( hWnd, &ps );
-
Oder muss ich noch sowas wie FillRect() verwenden?
Ja, du musst den gesammten Zeichnungsbereich clearen. Dann hast du aber ein neues Problem: Es flackert und verursacht Augenkrebs
. Ich empfehle aus eigener Erfahrung, einen Backbuffer zu verwenden, in den Du zeichnest. Dort kopierst du den Hintergrund und dann die Kugel rein. Nachher malst du den Backbuffer mit BitBlt auf den Haupt-HDC und clearst ihn dann. So flackerts nicht mehr. Hab mal ein kleines ping-pong geschrieben, dass die Grafikausgabe so realisierte... Auf ner 1.47GhZ Maschine hatte ich ca. 17fps :p .mfg
-
Ich habe mir noch einen neuen hdc als Backpuffer angelegt.
Danach hab ich ein CreateCompatibleDC(Backbuffer) gemacht.Wenn ich nun mit Bitblt da etwas rein kopiere, dann wird mir ja noch nichts angezeigt, muss ich den zusätzlich noch initialisieren?
-
Hmm... nein. Wenn du in den Backbuffer gemalt hast, musst du ihn selbst malen, also BitBlt mit dem wirklichen Ziel und dem Backbuffer als Source anwenden. Erst dann wird etwas angezeigt. Darum geht es doch...
-
Ich habe diesen Teil jetzt so, ich kann das auch schwer erklären.
Zumindest wird hier nichts angezeigt. Ich habe bestimmt was mit der Reihenfolge durcheinander gebracht.[cpp]
HBITMAP HBMP_OldBuffer = (HBITMAP) SelectObject(Bufferhdc, HBMP_Buffer);
HBITMAP HBMP_OldKugel = (HBITMAP) SelectObject(Kugelhdc, HBMP_Kugel);FillRect(myBufferhdc,&rc,NULL);
BitBlt(myBufferhdc, 0, 0, 400, 350, Bufferhdc, 0, 0, SRCCOPY);
TransparentBlt(myBufferhdc, X, Y, 16, 16, Kugelhdc, 0, 0, 16, 16, RGB(255,0,255));BitBlt(Bildhdc, 0, 0, 400, 350, myBufferhdc, 0, 0, SRCCOPY);
cpp]Vielleicht ist auch ein Codeschnipsel für mich das beste, denn in der FAQ hab cih wirklich was ansprechendes gefunden
-
Sorry, aber du musst den Backbuffer auf den HDC deines Fensters malen. Wenn das nicht geht, kann ich dir nicht helfen.
-
myBufferhdc = mein Backbuffer
Bildhdc = Frontbuffer.
-
Wo blittest du denn die Hintergrundgrafik ?
(oder ist das etwa HBMP_Buffer ? - Falls ja dann zeichnest du auf das Hintergrundbild, was du aber gar nichts willst ;D)
-
Eben, ich weiß nämlich nicht wie. Aber eine kleine Codezeile wäre ja deshalb nicht schlecht. Wenn ich wüsste, wie ich ein Buffer splitte, in den ich später was reinzeichne, dann hätte ich womöglich auch nicht dieses Problem. Vielleicht könnte mir ja mal jemand eine Codezeile vorgeben.
Das ist eben dieser kleine Ruck, den ich brauche.
-
Falls du noch Probleme mit DoubleBuffering ansich hast: http://c-plusplus.net/forum/viewtopic.php?t=14713
-
Kann man eigentlich in einen HDC zeichnen, in den man vorher nichts reiselektiert hat? Also
HDC IrgendeinHDC, superHDC;
...
IrgendeinHDC = CreateCombatibleBitmap(superHDC);
BitBlt(IrgendeinHDC, 0, 0, 100, 100, usw. ...);
...
-
Alsoo MOOOOOOOOOOOMENT
Jetzt komm ich mir veralbert vor.
Was ist denn der Unterschied zwischen dem Code, den ich ganz am Anfang gepostet habe und dem Link von flenders.
-
z.B. hast du nirgends CreateCompatibleBitmap stehen

-
Vorgehensweise wäre diese:
Backbuffer erzeugen:
o Mit CreateCompatibleDC() quasi die 1. 'Leinwand-Halterung' holen
o Mit CreateCompatibleBitmap() quasi 'Papier' für die 1. Leinwand-Halterung holen
o Mit SelectObject() das 'Papier' in die 1. 'Leinwand-Halterung einsetzen' und das alte 'Papier' das vorher drin war am besten irgendwohin legen...Hintergrundbild zeichnen:
o Mit CreateCompatibleDC() noch eine 'Leinwand-Halterung' holen
o Ein fertiges Bild ('Papier' ;D) mit LoadBitmap(), LoadImage() oder sonstwas holen
o Mit SelectObject() das fertige 'Bild' in die 2. 'Leinwand-Halterung' einsetzen und wieder das was vorher drin war irgendwie sichern
o Jetzt einen Spezialisten holen, der geniale 1:1 Kopien hinkriegt: Mit BitBlt() das Bild in der 2. Leinwandhalterung auf das Bild in der 1. Leinwandhalterung kopieren lassenKugel zeichnen:
o Mit CreateCompatibleDC() eine 3. 'Leinwand-Halterung' holen
o Das fertiges Bild ('Papier' ;D) mit der Kugel via LoadBitmap(), LoadImage() oder sonstwas holen
o Mit SelectObject() das fertige 'Bild' in die 3. 'Leinwand-Halterung' einsetzen und wieder das was vorher drin war irgendwie sichern
o Jetzt einen Spezialisten holen, der geniale 1:1 Kopien mit Transparenz hinkriegt: Mit TransparentBlt() das Bild in der 2. Leinwandhalterung auf das Bild in der 1. Leinwandhalterung kopieren lassenDas ganze darstellen:
o Auf dem Papier in der 1. Leinwand ist jetzt das komplette Bild drin
o Mit BitBlt() jetzt einfach eine 1:1 Kopie auf das Bild in der Leinwand des Fenster machen (BeginPaint() liefert uns ja die 'Leinwand' ;D)...und aufräumen - jeweils für alle 3 erzeugten Leinwände:
o Das Papier aus der Leinwandhalterung nehmen und das was vorher drin war wieder reinpacken (SelectObject())
o Mit DeleteDC() die Leinwandhalterung wieder weg in den Keller packen
o Mit DeleteObject() das voll-bemalte Papier (das mit CreateCompatibleBitmap() erzeugt) in die Mülltonne schmeißen.------
Das soll jetzt nur das Prinzip darstellen
Wenn man das ganze öfter zeichnet macht es natürlich keinen Sinn die Bilder jedesmal neu zu laden und die DCs und die Bitmap im Backbuffer-DC ständig zu erzeugen und dann wieder freizugeben.
Stattdessen wird man die Bilder und den Backbuffer einmal bei WM_CREATE erzeugen/laden und bei WM_DESTROY freigeben. Den Backbuffer müsste man höchstens bei WM_SIZE in der Größe jeweils anpassen...
-
Wow, Danke Leute.
Endlich mal ein Ablaufplan, womit ich was Anfangen kann.
-
echt EDEL, geeky!
-> faq?
-
geeky schrieb:
Stattdessen wird man die Bilder und den Backbuffer einmal bei WM_CREATE erzeugen/laden und bei WM_DESTROY freigeben. Den Backbuffer müsste man höchstens bei WM_SIZE in der Größe jeweils anpassen...
bei WM_CREATE funktioniert
HDC hdcBack = CreateCompatibleDC(hcd);ja noch nicht, weil hdc = BeginPaint()ist, also erst in WM_PAINT erstellt wird.
wie erstellt man also den backBuffer?
-
CreateCompatibleDC(NULL);
...damit erzeugst du einen DC der zum Desktop-DC kompatibel ist
(oder via GetDC() einfach das Fenster-DC holen...)