Device Contexts speichern?
-
Ich habe in der MSDN unter CWnd::GetDC folgendes gelesen:
Since only five common device contexts are available at any given time [...]
.
Stimmt das wirklich? Also, wenn ich Grafik auf dem Bildschirm ausgeben will, speichere ich pro Bild immer eine CDC- und eine CBitmap-Variable (Nur CDC speichern und CBitmap bloß lokal für den Ladevorgang aufrufen, geht nicht, dann stürzt er irgendwann ab.) und trotzdem zeigt er alle an.
Ist meine Vorgehensweise dennoch falsch? Sollte ich lieber nur die CBitmap-Variable speichern und den Device Context bei jedem Ladevorgang neu erstellen und danach wieder löschen? Aber wie soll man dann die Bilder manipulieren? Wenn ich da zum Beispiel während der Laufzeit mit SetPixel raufmale. Das geht ja nur über den DC. Wie kann ich das auch dauerhaft speichern?Ich würde mich sehr freuen, wenn mir jemand sagen könnte, welche Art der Bildspeicherung am üblichsten ist.
-
Mehrere Bilder ein DC, das was du manipulieren willst, lädst du in den DC und fertig. Wenn ein anderes Bild dran ist, lädst du das andere Bild rein. usw
-
Since only five common device contexts are available at any given time [...]
-
Mehrere Bilder ein DC, das was du manipulieren willst, lädst du in den DC und fertig. Wenn ein anderes Bild dran ist, lädst du das andere Bild rein. usw
Aber was ist, wenn ich die Manipulationen dauerhaft speichern will? Nehmen wir an, ich habe eine vorgegebene Bitmapdatei mit einer Spielfigur. Nun will ich aber, daß sie keine rote, sondern eine grüne Mütze hat. Dazu würde ich einfach einmal am Anfang alle Pixel mit CDC::GetPixel abklappern und bei entsprechendem Rückgabewert die Farbe mit CDC::SetPixel setzen. Wenn ich das jetzt so mache:
//In der Klassendefinition der Dialogfeldklasse: CBitmap m_bmpBild; //In OnInitDialog: CClientDC dc(this); CDC dcBild; BITMAP bm; m_bmpBild.LoadBitmap (IDB_SPRITE); m_bmpBitmap.GetBitmap (&bm); dcBild.CreateCompatibleDC (&dc); dcBild.SelectObject (&m_bmpBild); for (int nX=0; nX<bm.bmWidth; nX++) for (int nY; nY<bm.bmHeight; nY++) if (dcBild.GetPixel (nX, nY)==RGB (255, 0, 0)) dcBild.SetPixel (nX, nY, RGB (0, 255, 0));
dann ist das Bild doch nicht in der Variable m_bmpBild geändert oder erliege ich da einem Irrtum? Leider kann ich momentan nicht selbst nachgucken, weil ich im Moment kein Visual C++ zur Verfügung habe. Aber wenn ich richtig liege, wäre das ein Problem, denn es gibt keine Manipulationsmethoden in der CBitmap-Klasse.
-
Wenn du ein CBitmap in den CDC lädst, wirken sich alle Änderungen auf dein CBitmap aus, sonst hätte das ja keinen Sinn. Falls deine Mütze durchgehend in einem Rotton ist, schau dir mal Fill-Methoden an *gg* alles schon da
-
[quote="NES-Spieler"]
//In der Klassendefinition der Dialogfeldklasse:
CBitmap m_bmpBild;//In OnInitDialog:
CClientDC dc(this);
CDC dcBild;
BITMAP bm;
CBitmap oldbmp;m_bmpBild.LoadBitmap (IDB_SPRITE);
m_bmpBitmap.GetBitmap (&bm);dcBild.CreateCompatibleDC (&dc);
oldbmp = dcBild.SelectObject (&m_bmpBild);In einem CDC kannst du über SelectObject jederzeit ein neues draw Object selecten. Bei dem Select wird dir das alte Object zurückgegeben. Einfach bei mehreren Objecten(Schachspiel, usw.) das zurückgegbene Object in einem Objectarray speichern.
codeman
-
Wenn du ein CBitmap in den CDC lädst, wirken sich alle Änderungen auf dein CBitmap aus, sonst hätte das ja keinen Sinn.
Aha. Das wußte ich nicht.
Falls deine Mütze durchgehend in einem Rotton ist, schau dir mal Fill-Methoden an *gg* alles schon da
Beziehen die sich nicht nur auf Rechtecke? FillRect, FillSolidRect etc.
Was ich noch gern wissen würde: In einem Tutorial (www.henkessoft.de/C++/MFC/mfc_einsteigerbuch_kapitel9.htm) werden lokale DCs am Ende immer wieder in ihren Anfangszustand zurückversetzt:
CDC dcBild; CBitmap bmpBild; CBitmap *pbmpAltesBild; //... pbmpAltesBild=dcBild.SelectObject (&bmpBild); //... //Ganz am Ende: dcBild.SelectObject (pbmpAltesBild);
Hat das irgendeine praktische Relevanz? O.k., der DC wird wieder zurückversetzt. Vergleichbar mit dem Zurücksetzen eines Zeigers auf NULL, nachdem ich mit delete den Speicherbereich gelöscht habe. (Was zwar ganz nett ist, aber real betrachtet nicht wichtig, wenn es sich um einen lokalen Zeiger handelt und die Funktion danach sowieso schließt.) Also: Ist es aus irgendwelchen Gründen notwendig (Memory Leaks oder was weiß ich) oder ist das nur der persönliche Stil des Autors?
An codeman:
Wieso sollte ich die jeweils zurückgegebenen Werte speichern? Das sind ja letztendlich auch nur die Bilder, die ich selbst kurz vorher da reingeladen habe, das heißt, ich besitze die Variable bereits.
-
NES-Spieler schrieb:
Sollte ich lieber nur die CBitmap-Variable speichern und den Device Context bei jedem Ladevorgang neu erstellen und danach wieder löschen? Aber wie soll man dann die Bilder manipulieren? Wenn ich da zum Beispiel während der Laufzeit mit SetPixel raufmale. Das geht ja nur über den DC. Wie kann ich das auch dauerhaft speichern
1.)Deshalb nur die BITMAP speichern, weil das deine Referenz zu deinem Speicherbereich ist, nicht der DC. Er stellt, wenn du so willst nur den Kontainer für deine Bitmap(und noch ein paar andere schen
)
2.)Bilder manipulirst du über den DC, jedoch in dem Speicherbereich des BITMAPS. Somit findet jede veränderung in der BITMAP statt und nicht im DC.
3.)Wenn du wärend der Laufzeit Pixel manipulierst, tust du das in dem BITMAP-Speicher, den du dann dauerhaft speichern kannst. Darum auch der Vorschlag alles Bitmaps von dir in diesem Array zu speichern, da du die Referenzen auf den manipulierten Speicher und die manipulirten Daten im Speicher erhältst und zu gegebener Zeit wieder neu laden, oder speichern kannst.
codeman
-
O.k., vielen Dank für Deine zusätzlichen Informationen.
Jetzt müßte ich noch wissen, wie es sich mit dem verhält, was ich oben zum Schluß erfragt habe: Ist es nötig, den DC vor dem Löschen (bzw. vor dem Ende seines Gültigkeitsbereichs) wieder in den Ursprungszustand zurückzuversetzen, indem ich beim ersten SelectObject den Rückgabewert speichere und ihm den am Ende nochmal übergebe? Oder braucht man das nicht?
-
Der Rückgabewert des SelectObjects ist ein Object(z.B CBitmap) das in dem DC Selected war bevor das neue Selected wird. Ist noch kein Object selectiert und du machst den ersten SelectObject, brauchst du ihn nicht wieder zurückstellen. Falls aber ein Object selected war und du willst im Anschluss mit diesem wieder weiterarbeiten, musst du es schon wieder mit SelectObject einstellen.
Also DC's musst du nur dann wieder zurüstellen, wenn du dein altes Object wieder selectiert haben willst.
codeman
-
O.k., ich hab alles ausprobiert und es hat geklappt. Vielen Dank für Eure Hilfe.