Bitmaps
Wie Sie Bitmaps aus Dateien laden und darstellen, das haben Sie schon im Kapitel
GDI erfahren. Bitmaps lassen sich aber auch als Ressource zum Programm hinzufügen.
Der Vorteil dabei ist, dass Sie bei der Weitergabe Ihres Programms die Bitmap-Datei
selbst nicht mehr weitergeben müssen, sondern die Bitmap ist mit ins Programm eingebunden.
Sehen wir uns an, wie Bitmaps als Ressourcen eingebunden werden.
 |
Falls Sie das Beispiel SBmpUser aus der vorherigen
Lektion nicht mehr geöffnet haben, so öffnen Sie dieses zunächst. Im Verzeichnis
99Templates befinden sich zwei Bitmap-Dateien die wir nun einbinden.
Öffnen Sie dazu die Ressourcen-Ansicht und klicken Sie mit der rechten Maustaste
den Eintrag SBmpUser Ressourcen an. Wählen Sie aus dem eingeblendeten
Kontext-Menü den Eintrag Importieren... aus und fügen dann nacheinander
die Dateien OFF.BMP und ON.BMP zur Ressource hinzu. Geben
Sie den neu hinzugefügten Bitmap-Ressourcen die IDs IDB_OFF und IDB_ON. Das
war's dann auch schon. Selbstverständlich können Sie, wenn Sie grafisch begabt
sind, eigene Bitmaps erstellen. Klicken Sie dazu den Ressource-Typ Bitmap
mit der rechten Maustaste an und wählen aus dem Kontext-Menü den Eintrag
Bitmap einfügen aus. Standardmäßig wird dann eine Bitmap mit der Auflösung
48x48 und 16 Farben erstellt. Wollen Sie eine andere Auflösung oder Farbtiefe,
führen Sie einen Doppelklick innerhalb des Editorfensters durch. Daraufhin
wird folgender Dialog eingeblendet:

Hier können Sie dann die ID, die Auflösung, die Farbtiefe und, durch Auswahl
des Tabulators Palette, die Farben einstellen.
|
 |
IDs von Bitmap-Ressourcen sollten mit dem Präfix IDB_xxx beginnen.
Und obwohl wir externe Bitmap-Dateien in die Ressource eingebunden haben, werden
die Bitmaps nachher beim Übersetzen und Linken mit zum Programm dazugebunden |
Um eine Bitmap-Ressource zu laden, steht die CBitmap Methode LoadBitmap(...)
zur Verfügung. Sie erhält als Parameter die ID der zu ladenden Bitmap. Damit Sie
die geladene Bitmap auch ausgeben können, müssen Sie zunächst, wie in der Lektion
Bitmaps und Speicher-DC im Kapitel GDI besprochen, einen Speicher-DC
erstellen und dann das Bitmap-Objekt darin selektieren. Anschließend können Sie
mit Hilfe der CDC Methode BitBlt(...) die Bitmap ausgeben.
 |
Beginnen wir diesen Übungsteil mit dem Laden der Bitmaps und
dem Erstellen des für die Ausgabe notwendigen Speicher-DC. Da diese Schritte
nur einmal durchgeführt werden müssen, bringen wir sie sinnvollerweise wieder
in der Methode OnInitialUpdate(...) unter. Fügen Sie aber der Klasse
CSBmpUserView zuerst folgenden privat Daten hinzu:
CDC *m_pMemDCOff;
CDC *m_pMemDCOn;
CBitmap m_CBmpOff;
CBitmap m_CBmpOn;
bool m_bIsOn; |
Anschließend fügen Sie der Klasse die OnInitialUpdate(...) Methode
hinzu und erweitern deren Code wie folgt:
void CSBmpUserView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: Speziellen Code hier einfügen und/oder Basisklasse aufrufen
// Beide Bitmap aus
Ressource laden
m_CBmpOff.LoadBitmap(IDB_OFF);
m_CBmpOn.LoadBitmap(IDB_ON);
// 2 Speicher-DC erstellen
CDC *pDC = GetDC();
m_pMemDCOff = new CDC;
m_pMemDCOff->CreateCompatibleDC(pDC);
m_pMemDCOn = new CDC;
m_pMemDCOn->CreateCompatibleDC(pDC);
// Beide Bitmaps darin selektieren
m_pMemDCOff->SelectObject(&m_CBmpOff);
m_pMemDCOn->SelectObject(&m_CBmpOn);
// Flag fuer Bitmap-Darstellung
initialisieren
m_bIsOn = false;
// Geliehenen DC auch wieder
freigeben
ReleaseDC(pDC);
} |
Sodann kann die Methode OnDraw(...) angepasst werden. Je nach Zustand
der Membervariable m_bIsOn soll entweder die Bitmap IDB_ON (Speicher-DC
ist m_pMemDCOn) oder IDB_OFF (Speicher-DC ist m_pMemDCOff)
dargestellt werden:
void CSBmpUserView::OnDraw(CDC*
pDC)
{
CSBmpUserDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// ZU ERLEDIGEN: Hier Code zum Zeichnen der ursprünglichen Daten
hinzufügen
// Struktur fuer Bitmap-Kenndaten
BITMAP BmpParam;
// Falls On-Bitmap gezeichnet
werden soll
if (m_bIsOn)
{
m_CBmpOn.GetBitmap(&BmpParam);
pDC->BitBlt(10,10,BmpParam.bmWidth,BmpParam.bmHeight,
m_pMemDCOn,0,0,SRCCOPY);
}
else
{
m_CBmpOff.GetBitmap(&BmpParam);
pDC->BitBlt(10,10,BmpParam.bmWidth,BmpParam.bmHeight,
m_pMemDCOff,0,0,SRCCOPY);
}
} |
Das Toggeln der Membervariable m_bIsOn führen wir in der Methode
OnLButtonDown(...) durch. Wird auf die dargestellte Bitmap geklickt,
so soll diese wechseln. Erweitern Sie hierzu die OnLButtonDown(...)
Methode wie folgt:
void CSBmpUserView::OnLButtonDown(UINT
nFlags, CPoint point)
{
// TODO: Code für die Behandlungsroutine für Nachrichten hier
einfügen und/oder Standard aufrufen
// Hintergrundfarbe des
Fensters auslesen
CDC *pDC = GetDC();
COLORREF BackColor = pDC->GetBkColor();
// Falls Cursor auf Bitmap
zeigt
// (akt. Farbe ungleich Hintergrundfarbe)
if (pDC->GetPixel(point.x,point.y)
!= BackColor)
{
// darzustellende Bitmap wechseln
m_bIsOn = !m_bIsOn;
Invalidate();
return;
}
ReleaseDC(pDC);
// String-Objekte erstellen
....
} |
Übersetzen und starten Sie das Beispiel nun.
|
Wenn Sie mit der linken Maustaste die Bitmap anklicken, so sollte diese wechseln.
Ob eine Bitmap oder der Fensterhintergrund angeklickt wurde, wird durch auswerten
des Farbwertes unterhalb des Cursors festgestellt. Dieses Verfahren funktioniert
natürlich nur dann, wenn innerhalb der Bitmap keine Farben vorkommen die mit dem
Fensterhintergrund identisch sind.
Aber haben Sie sich beim Beenden des Programms auch einmal die Ausgabe in Debuggerfenster
angesehen? Dort werden zwei memory leaks gemeldet, d.h. irgendwo haben
Sie Speicher reserviert und dann aber vergessen, diesen auch wieder freizugeben.
 |
Versuchen Sie selber einmal diesen 'kleinen' Fehler zu beheben.
 |
Aber wenn Sie wollen kann ich Ihnen auch meine Lösung anzeigen. |
Lösung zur Ausgabe von Bitmaps
In der Methode OnInitialUpdate(...) haben wir zum
einen zwei Speicher-DCs reserviert und zum anderen auch noch Bitmaps geladen.
All dies sollte beim Beenden der Anwendung auch wieder freigegeben werden.
In der Regel können Sie in der Methode OnInitialUpdate(...) reservierte
Ressourcen in der Methode OnDestroy(...) wieder freigeben. Fügen
Sie diese Methode noch der Klasse CSBmpUserView wie folgt hinzu:
void CSBmpUserView::OnDestroy()
{
CView::OnDestroy();
// TODO: Code für die Behandlungsroutine für Nachrichten hier
einfügen
// Speicher-DCs
freigeben
delete m_pMemDCOff;
delete m_pMemDCOn;
// Bitmaps freigeben
m_CBmpOff.DeleteObject();
m_CBmpOn.DeleteObject();
} |
Ende der Lösung
|
Übersetzen und starten Sie das Programm. Jetzt sollte alles fehlerfrei funktionieren.
|
Das fertige Beispiel zu dieser und der vorherigen Lektion finden Sie auch unter
07Ressourcen\SBmpUser.
Und damit beenden wir das Thema Bitmap-Ressource und kommen in der nächsten Lektion
zu einer der wichtigsten Ressource, dem Menü.
|