GDI+ - Gezeichnetes für spätere Verwendung speichern
-
Hallo zusammen,
ich beginne im Moment mit GDI+ Programmierung um ein kleines Plottool zu erstellen.
Die ersten Schritte waren soweit auch ganz ok, nun bin ich an der Stelle angekommen, an der ich ein "Zoom-Rechteck" zeichnen möchte.
Dieses Rechteck soll dabei immer mit dem Mauszeiger wachsen. Das heißt bei geänderter Mauszeigerposition soll das alte, z.B. kleinere Rechteck nciht mehr angezeigt werden, sondern nur noch das neue Rechteck.
Ich würde mir nun gern die ganzen Rechnungen sparen, die ich machen muss um den eigentlichen Plot darzustellen. Das Bild existiert ja bereits. Ich weiß nur nicht so recht, wie ich darauf zugreifen kann.
Ziel ist also, das letzte gezeichnete Fensterbild zu speichern um das dann immer wieder neu als Hintergrund zu nutzen, wenn ich mein Zoom-Rechteck zeichne.
Ich habe schon einiges gesucht aber bin leider bisher immer nur gescheitert.
Mein Programm arbeitet wie folgt:
onPaint(hdc):this->hdcMem = CreateCompatibleDC(hdc);
const int nMemDC = SaveDC(hdcMem);
HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
SelectObject(hdcMem, hBitmap);
Graphics graphics(hdcMem);Auf dieses graphics Objekt führe ich nun meine ganzen Zeichenmethoden aus bis ich fertig binund kopiere das dann nachher wieder in das original hdc wegen doubleBuffering:
BitBlt(hdc, left, top, width, height, hdcMem, left, top, SRCCOPY);
RestoreDC(hdcMem, nMemDC);
this->_nMemDC = nMemDC;Ich hoffe nun, dass ich in irgendeiner Weise das hdcMem Objekt speichern kann( weil hier sollten ja alle gezeichneten Informationen drin stecken?) um dieses im als neues Hintergrundbild einfach so zu verwenden, ohne vorher wieder meine Berechnungen durchführen zu müssen.
Ist das irgendwie möglich? Ich habe bisher leider noch nicht den richtigen Weg gefunden..
Ich möchte wie gesagt immer wieder auf das letzte berechnete Ausgangsbild aufsetzen und nicht auf das aktuell dargestellt Bild, da ich dieses ersetzen möchte.
Ich hoffe ich habe es einigermaßen verständlich rübergebracht, falls mir jemand helfen kann wäre ich SEHR dankbar;)
Viele Dank schon mal im Voraus
Grüße
torettoCPP
-
Du verwendest doch schon BitBlt, d.h. genau dieselbe Funktion kannst du doch für das Plot-Bitmap verwenden, um dann nachträglich das Zoom-Rechteck darüber zu zeichnen.
-
Danke für die Rückmeldung, soweit bin ich leider noch nicht gekommen..
Ich würde nun gern in irgendeiner Weise wieder auf das alte Bitmap zugreifen können, weiß allerdings nicht wie.
Im 1. Durchgang mache ich alles so wie oben beschrieben und das Bild wird gezeichnet.
In meiner Klasse speichere ich hdcMem und hBitmap.Beim 2. Zeichnen möchte ich nun auf mein gespeichertes Bild zugreifen und das wieder genauso zeichnen, allerdings bleibt mein Fenster weiß und ohne Inhalt.
Ich mache das zur Zeit so:
SelectObject(this->hdcMem, this->hBitmap);
BitBlt(hdc, left, top, width, height, this->hdcMem, left, top, SRCCOPY);Fehlt hier noch eine Funktion?
Ich dachte, in hdcMem sollten ja noch alle Informationen drinstecken (die Zeichnung eben).
Das Graphics Objekt, mit dem ich im 1. Durchlauf alles gezeichnet habe, ist allerdings nicht mehr vorhanden, muss das auch gespeichert werden? Sind hier die Zeicheninformationen enthalten oder im hdcMem?Mein Ziel ist das alte Bild wieder 1:1 so herstellen zu können.
-
Das eigentliche Bild ist natürlich in hBitmap (welches du mittels CreateCompatibleBitmap erzeugt hast) enthalten und dies solltest du daher nicht löschen. Ansonsten poste mal den relevanten Teil deines bisherigen Codes (und benutze dafür die Code-Tags hier im Forum ;-).
-
ah ok danke, das war mein Fehler, hatte es schon in meiner Klasse angelegt, aber dann vergessen den Klassenmember zu nutzen
Evtl noch zwei Verständnisfragen, dazu erstmal der relevante Code:
void onPaint(hdc) { if(neuBerechnenUndZeichnen) { //für DOUBLE BUFFERING //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ this->hdcMem = CreateCompatibleDC(hdc); const int nMemDC = SaveDC(hdcMem); this->hBitmap = CreateCompatibleBitmap(hdc, width, height); SelectObject(hdcMem, hBitmap); //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //Grafikobjekt erzeugen Graphics graphics(hdcMem); //Farben als Konstanten / Makros SolidBrush back(Color(220,220,220)); graphics.FillRectangle(&back, this->left, this->top, this->width, this->height); // weitere Zeichnungen..... RECT rcClip; GetClipBox(hdc, &rcClip); left = rcClip.left; top = rcClip.top; width = rcClip.right - rcClip.left; height = rcClip.bottom - rcClip.top; BitBlt(hdc, left, top, width, height, hdcMem, left, top, SRCCOPY); RestoreDC(hdcMem, nMemDC); this->_nMemDC = nMemDC; } else { // gespeichertes Bild Zeichnen SelectObject(this->hdcMem, this->hBitmap); BitBlt(hdc, left, top, width, height, this->hdcMem, left, top, SRCCOPY); } }
So funktioniert es nun :-). Aber noch zwei Fragen:
Wenn ich allerdings die Zeile 34 "SelectObject(this->hdcMem, this->hBitmap);" auskommentiere funktioniert es nicht mehr.
In der MSDN Doku steht zur SelectObject Funktion:
"This function selects an object into a specified device context. The new object replaces the previous object of the same type. "
--> Ich dachte aber, dass hBitmap schon in hdcMem enthalten ist?Wenn nur folgenden BEfehl benutze fuktioniert es ebenfalls nicht:
SelectObject(hdc, this->hBitmap);Ich dachte so kann es auch funktionieren, weil ich auf dem anderen Weg ja das gleiche mit hdcMem mache und danach eine 1:1 Kopie in hdc erstelle, was nachher dargestellt wird. Wieso kann ich SelectObject nicht direkt auf hdc anwenden?
Danke!
Grüße
torettoCPP
-
Hallo nochmals,
da ich selber auch nicht so der WinAPI-Experte bin (bzw. das schon einige Jährchen zurückliegt), solltest du besser direkt im WinAPI-Unterforum nachfragen.
Ansonsten habe ich noch folgenden Artikel gefunden: http://www.codeproject.com/Articles/224754/Guide-to-Win32-Memory-DC