|
Bei der transparenten Anzeige einer Bitmap, werden alle Bits einer Bitmap mit Ausnahme der Bits, die eine festgelegte Farbe haben, auf den Zielkontext übertragen. An den Stellen, an denen die transparente Farbe vorliegt, bleibt der bisherige Inhalt des Zielkontextes erhalten.
Als transparente Farbe kann jede beliebige verwendet werden. Sinnvollerweise legt man die Bitmap jedoch so an, daß eine Hintergrundfarbe, die im Vordergrund nicht vorkommt, als transparent gesetzt werden kann.
Die Funktion TransparentBlt() kopiert die Bitmap hBitmap in den durch hdcDest bezeichneten Ausgabekontext unter Beachtung der transparenten Farbe colorTransparent. Wird in hPal eine Palette für die Bitmap übergeben, so wird diese benutzt; der Parameter kann jedoch auch NULL sein.
nXDest und nYDest legen die linke obere Ecke im Zielkontext hdcDest für die Ausgabe fest, nWidth und nHeight die Breite bzw. Höhe des Zielrechtecks.
Der Offset in die Quellbitmap, ab dem die Bitmap kopiert werden soll, wird durch die linke obere Ecke nXSrc und nYSrc spezifiziert.
| Lösung |
void TransparentBlt(
HDC hdcDest,
int nXDest, int nYDest,
int nWidth, int nHeight,
HBITMAP hBitmap,
int nXSrc, int nYSrc,
COLORREF colorTransparent,
HPALETTE hPal )
{
CDC dc, memDC, maskDC, tempDC;
dc.Attach( hdcDest );
maskDC.CreateCompatibleDC(&dc);
CBitmap maskBitmap;
Die Funktion TransparentBlt() verwendet drei Ausgabekontexte. Die Source-Bitmap wird zunächst in tempDC kopiert, um dann in den zweiten Kontext, den Speicherkontext memDC, kopiert zu werden. maskDC ist der dritte Kontext, der eine monochrome Bitmap enthält, und nur dazu verwendet wird, den Vordergrund aus der Quellbitmap herauszumaskieren.
CBitmap* pOldMemBmp = NULL;
CBitmap* pOldMaskBmp = NULL;
HBITMAP hOldTempBmp = NULL;
memDC.CreateCompatibleDC(&dc);
tempDC.CreateCompatibleDC(&dc);
CBitmap bmpImage;
bmpImage.CreateCompatibleBitmap( &dc, nWidth, nHeight );
pOldMemBmp = memDC.SelectObject( &bmpImage );
Wird in hPal eine gültige Farbpalette übergeben und unterstützt der Zielkontext Paletten, wird die Palette in den Zielkontext selektiert. Als letztes Argument wird der Funktion SelectPalette() FALSE übergeben. Dies zeigt an, daß die Palette eine Vordergrundpalette ist und die Farben exakt angezeigt werden sollen. Würde hier TRUE spezifiziert, so würden die Farben der logischen Palette auf die nächstliegenden Farben gemappt, die bereits in der physikalischen Palette enthalten sind. Der abschließende Aufruf von RealizePalette() aktiviert die Palette, die zusätzlich auch in den memDC selektiert wird, so daß die Farben der Bitmap korrekt gemappt werden.
if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE && hPal )
{
::SelectPalette( dc, hPal, FALSE );
dc.RealizePalette();
::SelectPalette( memDC, hPal, FALSE );
}
hOldTempBmp = (HBITMAP) ::SelectObject( tempDC.m_hDC, hBitmap );
memDC.BitBlt(0,0,nWidth, nHeight, &tempDC, nXSrc, nYSrc,
SRCCOPY);
Als nächstes wird die monochrome Maskenbitmap aus der Quellbitmap erzeugt. Hierzu wird die API-Funktion BitBlt() verwendet, um die Farbbitmap so in eine monochrome Bitmap zu kopieren, daß anschließend alle Pixel mit der Hintergrundfarbe weiß sind. Dazu wird die transparente Farbe mittels SetBkColor() als Hintergrundfarbe gesetzt. Alle übrigen Pixel, die nicht die Hintergrundfarbe besitzen, werden schwarz.
maskBitmap.CreateBitmap( nWidth, nHeight, 1, 1, NULL );
pOldMaskBmp = maskDC.SelectObject( &maskBitmap );
memDC.SetBkColor( colorTransparent );
Maske anhand des memDC Kontextes erzeugen:
maskDC.BitBlt(0, 0, nWidth, nHeight,
&memDC, 0, 0, SRCCOPY );
Liegt die Maskenbitmap vor, können die Quell- und Zielbitmap modifiziert werden, um die endgültige Bitmap zu erhalten. Dazu werden zum einen der Hintergrund und zum anderen der Vordergrund ausmaskiert und dann die Bitmaps zur Zielbitmap zusammenkopiert. Der Hintergrund in memDC wird dazu auf schwarz gesetzt. Der RC-Code SRCPAINT führt dann dazu, daß alle Farben außer schwarz kopiert werden, während schwarz als transparent behandelt wird:
memDC.SetBkColor(RGB(0,0,0));
memDC.SetTextColor(RGB(255,255,255));
memDC.BitBlt(0, 0, nWidth, nHeight, &maskDC, 0, 0, SRCAND);
Analog dazu wird der Vordergrund ausmaskiert...
dc.SetBkColor(RGB(255,255,255));
dc.SetTextColor(RGB(0,0,0));
dc.BitBlt(nXDest, nYDest, nWidth, nHeight, &maskDC,
0, 0, SRCAND);
... und anschließend Vorder- und Hintergrund kombiniert.
dc.BitBlt(nXDest, nYDest, nWidth, nHeight, &memDC,
0, 0, SRCPAINT);
Abschließend sind noch einige Aufräumarbeiten nötig.
| Funktion TransparentBlt |