Transparente Farbe wird Schwarz

CodeFatal

Erfahrenes Mitglied
Hi @ all,

hab da mal wieder nen Problem und nen dickes Brett vorm Kopf. Bin schon lange am basteln und testen aber nix klappt mehr.

Ich habe mir soweit möglich die Ergebnisse des folgenden Codes anzeigen lassen und die Bit-Operationen eigentlich auch verstanden (denke ich).

Ausgangssituation:
Will ne Bitmap aus ner Datei laden (klappt)
Will die Transparent in einem Dialogfeld basierenden Dialog darstellen (klappt)
Will die Zoomen können (klappt)
Will die in nem bestimmten Teil des Dialoges darstellen (klappt)
Transparenz an und abschaltbar (klappt)

Soweit so gut.

Fehler auftreten:
Wenn ich keine Transparenz Rechnerei mache ist alles super sobald aber Transparenz mit dazu kommt geht irgendwas schief, sobald ich den dialog invalidiere.
z.B.: wird kurzzeitig von nem anderen Fenster überdeckt oder ausserhalb des Bildschirms bewegt.
Wird die Transparente Fläche dann wieder sichtbar, ist sie nicht mehr Transparent sondern Schwarz. :confused:

Um das Ganze im gesamten zu realisieren, habe ich die Klasse CPaintDC abgeleitet und folgende Funktion hinzugefügt:
Code:
BOOL CMyPaintDC::DrawBitmap(CMyBitmap *pBMap,CRect Zoom, CRect Cut, CDC *pDc, DWORD Flag,COLORREF AlphaColor)//zeichnet Bitmap in DC falls Alpha im Bereich von COLORREF wird Alpha kanal mit berechnet
{
	CBitmap* bmp=NULL;
	CBitmap* oldbmp=NULL;
	CBitmap* oldbmpmask;
	BITMAP *BitmapParam; // Parameter der Bitmaps
	CBitmap CMaskBmp;
	CBitmap *pCBmp;

	CDC dc2,dc2mask;
// --- Speicher-DC für zu zeigendes Bild
	dc2.CreateCompatibleDC(pDc);//Zeichenfläche von CBitmap
// --- Speicher-DC fuer Bitmap-Maske erstellen ---
	dc2mask.CreateCompatibleDC(pDc);//Bitmap für alphamaske
		
	if(bmp)
	{
		pCBmp = pBMap->GetCBitmap();
		// Bitmap-Groesse auslesen
		BitmapParam = pBMap->GetBitmapInfo();
		int m_nTransBmpWidth = BitmapParam->bmWidth;
		int m_nTransBmpHeight = BitmapParam->bmHeight;
		// und geladene Transparent Bitmap auswaehlen
		oldbmp = dc2.SelectObject(bmp);//Bild Original in Speicher laden
		if(AlphaColor>=0 && AlphaColor<=0x00ffffff)//wenn eine gültige AlphaFarbe gesetzt
		{
			// zuerst monochromes (s/w) CBitmap-Objekt in der gleichen
			// Groesse wie eingelesen Bitmap erstellen
			CMaskBmp.CreateBitmap( m_nTransBmpWidth, m_nTransBmpHeight, 1, 1, NULL );
			// und Masken-Bitmap auswaehlen
			oldbmpmask = dc2mask.SelectObject(&CMaskBmp);//jetzt ist in dc2mask eine einheitliche Fläche in der Grösse des Bitmaps Schwarz uninitialisiert
			// --- S/W Bitmap erstellen ----
			dc2.SetBkColor(AlphaColor);
			// geladene Bitmap in monochrome Bitmap umkopieren
			// -> alles ausser Alphafarbe erscheint nun in schwarzer Farbe
			dc2mask.BitBlt(0,0,m_nTransBmpWidth,m_nTransBmpHeight,&dc2,0,0, SRCCOPY );//alles was in dc2 nicht Hintergrund von dc2 entspricht, wird nach dc2mask kopiert, HG von dc2mask ist weiß
			// Aus Orignal-Bitmap Hintergrund entfernen
			dc2.SetBkColor(RGB(255,255,255));//wenn nicht wird Alphafarbe bei oder mit eingerechnet 255 invertieren->0 oder was anderes = was anderes
			// Negativ von S/W Bitmap, HG ist nun schwarz (RGB:0,0,0)
			dc2mask.BitBlt(0,0,m_nTransBmpWidth,m_nTransBmpHeight,NULL,0,0, DSTINVERT );//maske einfach invertieren daher NULL
			// geladene Bitmap mit negativ von S/W-Bitmap verunden
			// --> HG der geladenen Bitmap ist nun schwarz
			dc2.BitBlt(0,0,m_nTransBmpWidth,m_nTransBmpHeight,&dc2mask,0,0, SRCAND );//Alphafarbe ist durch schwarz ersetzt worden bei maske ist alles außer Alphafarbe weiss
			// Mask wieder restaurieren (HG ist weiss = 0xFFFFFF)
			dc2mask.BitBlt(0,0,m_nTransBmpWidth,m_nTransBmpHeight,NULL,0,0, DSTINVERT );//wie oben alles ausser Alphafarbe ist Schwarz
			// Bitmap-Umrisse ausschneiden aus Hintergrund
			// Umrisse der Bitmap aus dem HG ausschneiden
			pDc->SetTextColor(RGB(0,0,0));
			pDc->SetBkColor(RGB(255,255,255));
			pDc->StretchBlt(Zoom.left,Zoom.top,Zoom.Width(),Zoom.Height(),&dc2mask,Cut.left,Cut.top,Cut.Width(),Cut.Height(),SRCAND);//alles was bisher auf dc gezeichnet wurde und die maske -> alles tiefer liegende + "Schatten" von dem was noch kommt
			// Bitmap einkopieren
			// Zum Versuchen: auch einmal diesen Aufruf entfernen
			pDc->StretchBlt(Zoom.left,Zoom.top,Zoom.Width(),Zoom.Height(),&dc2,Cut.left,Cut.top,Cut.Width(),Cut.Height(),SRCPAINT);//alles was bisher auf dc gezeichnet wurde und die maske -> alles tiefer liegende + "Schatten" von dem was noch kommt
			dc2mask.SelectObject(oldbmpmask);
		}
		else//kein Alpha
		{
			pDc->StretchBlt(Zoom.left,Zoom.top,Zoom.Width(),Zoom.Height(),&dc2,Cut.left,Cut.top,Cut.Width(),Cut.Height(),SRCCOPY);//alles was bisher auf dc gezeichnet wurde und die maske -> alles tiefer liegende + "Schatten" von dem was noch kommt
		}

		dc2.SelectObject(oldbmp);
	}
	dc2mask.DeleteDC();
	dc2.DeleteDC();
	return TRUE;
}
Zur Erklärung der Parameter:
CMyBitmap *pBMap - Zeiger auf Daten der Bitmap
CRect Zoom - Rechteck in das von Cut ausgeschnittene Bildpunkte projeziert werden
CRect Cut - Rechteck das aus der Bitmap Bereich ausschneidet (grösser als Bitmap-> Verkleinerung der Anzeige)
CDC *pDc - Zeiger auf das endgültige Ziel Device
DWORD Flag - für spätere Verwendung
COLORREF AlphaColor - Alphafarbe wenn keine farbe gewünscht -1

Ich verwende MFC unter .Net.

Hoffe es gibt hier nen hilfbereiten Menschen, der sich die Mühe macht der Kram einmal durchzu sehen und auch noch feststellt, wo ich den gedanklichen Fehler habe.

Gruss und Danke schon mal für eunre Hilfe
Michael
 
Hallo Michael,

ich habe deinen Code mal schnell in einem Testdialog ausprobiert.
Folgendes war mir unklar bzw. habe ich geändert:

- Ich habe keine Klasse von CPaintDC abgeleitet, sondern die Funktion als Member meines Testdialoges verwendet.
- Da ich die Klasse "CMyBitmap" nicht kenne, habe ich stattdessen mit dem normalen "CBitmap" gearbeitet.
- Die Abfrage "if( bmp )" führt das dazu, das gar nichts geht, soll wahrscheinlich "if( pBMap )" sein?
- Die lokalen Variablen "bmp" und "pCBmp" sind wegen Unterbeschäftigung herausgeflogen.

Hier meine leicht modifizierte Funktion:

Code:
BOOL CTestDlg::rawBitmap(
    CBitmap *pBMap, CRect Zoom, CRect Cut, CDC *pDc, DWORD Flag, COLORREF AlphaColor)
{
    // CBitmap *pBMap      - Zeiger auf Daten der Bitmap
    // CRect Zoom          - Rechteck in das von Cut ausgeschnittene Bildpunkte projeziert werden
    // CRect Cut           - Rechteck das aus der Bitmap Bereich ausschneidet
    //                       (grösser als Bitmap-> Verkleinerung der Anzeige)
    // CDC *pDc            - Zeiger auf das endgültige Ziel Device 
    // DWORD Flag          - für spätere Verwendung
    // COLORREF AlphaColor - Alphafarbe wenn keine farbe gewünscht -1

    CBitmap *oldbmp     = NULL;
    CBitmap *oldbmpmask = NULL;
    BITMAP  BitmapParam; // Parameter der Bitmaps
    CBitmap CMaskBmp;

    CDC dc2,dc2mask;
    
    // --- Speicher-DC für zu zeigendes Bild
    dc2.CreateCompatibleDC(pDc);       //Zeichenfläche von CBitmap
    
    // --- Speicher-DC fuer Bitmap-Maske erstellen ---
    dc2mask.CreateCompatibleDC(pDc);   //Bitmap für alphamaske

    if( pBMap )
    {
        // Bitmap-Groesse auslesen
        pBMap->GetBitmap(&BitmapParam);

        int nTransBmpWidth  = BitmapParam.bmWidth;
        int nTransBmpHeight = BitmapParam.bmHeight;
    
        // und geladene Transparent Bitmap auswaehlen
        oldbmp = dc2.SelectObject(pBMap);//Bild Original in Speicher laden
    
        if( AlphaColor >=0 && AlphaColor <= 0x00ffffff) //wenn eine gültige AlphaFarbe gesetzt
        {
            // zuerst monochromes (s/w) CBitmap-Objekt in der gleichen
            // Groesse wie eingelesen Bitmap erstellen
            
            CMaskBmp.CreateBitmap( nTransBmpWidth, nTransBmpHeight, 1, 1, NULL );
    
            // und Masken-Bitmap auswaehlen
            //jetzt ist in dc2mask eine einheitliche Fläche in der Grösse des Bitmaps Schwarz uninitialisiert
            oldbmpmask = dc2mask.SelectObject(&CMaskBmp);
    
            // --- S/W Bitmap erstellen ----
            dc2.SetBkColor(AlphaColor);
            
            // geladene Bitmap in monochrome Bitmap umkopieren
            // -> alles ausser Alphafarbe erscheint nun in schwarzer Farbe
            
            //alles was in dc2 nicht Hintergrund von dc2 entspricht, wird nach dc2mask kopiert,
            // HG von dc2mask ist weiß
            dc2mask.BitBlt(0, 0, nTransBmpWidth, nTransBmpHeight, &dc2, 0, 0, SRCCOPY );
    
            // Aus Orignal-Bitmap Hintergrund entfernen
            
            //wenn nicht wird Alphafarbe bei oder mit eingerechnet 255 invertieren->
            // 0 oder was anderes = was anderes
            dc2.SetBkColor(RGB(255,255,255));
    
            // Negativ von S/W Bitmap, HG ist nun schwarz (RGB:0,0,0)
            //maske einfach invertieren daher NULL
            dc2mask.BitBlt(0,0,nTransBmpWidth,nTransBmpHeight,NULL,0,0, DSTINVERT );
    
            // geladene Bitmap mit negativ von S/W-Bitmap verunden
            // --> HG der geladenen Bitmap ist nun schwarz
            //Alphafarbe ist durch schwarz ersetzt worden bei maske ist alles außer Alphafarbe weiss
            dc2.BitBlt(0,0,nTransBmpWidth,nTransBmpHeight,&dc2mask,0,0, SRCAND );
    
            // Mask wieder restaurieren (HG ist weiss = 0xFFFFFF)
            //wie oben alles ausser Alphafarbe ist Schwarz
            dc2mask.BitBlt(0,0,nTransBmpWidth,nTransBmpHeight,NULL,0,0, DSTINVERT );
    
            // Bitmap-Umrisse ausschneiden aus Hintergrund
            // Umrisse der Bitmap aus dem HG ausschneiden
            
            // alles was bisher auf dc gezeichnet wurde und die maske -> 
            // alles tiefer liegende + "Schatten" von dem was noch kommt
            pDc->SetTextColor(RGB(0,0,0));
            pDc->SetBkColor(RGB(255,255,255));
            pDc->StretchBlt( Zoom.left,
                             Zoom.top,
                             Zoom.Width(),
                             Zoom.Height(),
                             &dc2mask,
                             Cut.left,
                             Cut.top,
                             Cut.Width(),
                             Cut.Height(),SRCAND);
    
            // Bitmap einkopieren
            // Zum Versuchen: auch einmal diesen Aufruf entfernen
            
            // alles was bisher auf dc gezeichnet wurde und die maske ->
            // alles tiefer liegende + "Schatten" von dem was noch kommt
            pDc->StretchBlt( Zoom.left,
                             Zoom.top,
                             Zoom.Width(),
                             Zoom.Height(),
                             &dc2,
                             Cut.left,
                             Cut.top,
                             Cut.Width(),
                             Cut.Height(),
                             SRCPAINT);
                             
            dc2mask.SelectObject(oldbmpmask);
        }
        else //kein Alpha
        {
            // alles was bisher auf dc gezeichnet wurde und die maske ->
            // alles tiefer liegende + "Schatten" von dem was noch kommt
            pDc->StretchBlt( Zoom.left,
                             Zoom.top,
                             Zoom.Width(),
                             Zoom.Height(),
                             &dc2,
                             Cut.left,
                             Cut.top,
                             Cut.Width(),
                             Cut.Height(),SRCCOPY);
        }

        dc2.SelectObject(oldbmp);
    }
    
    dc2mask.DeleteDC();
    dc2.DeleteDC();
    
    return TRUE;
}


Und hier der Aufruf bei OnPaint():

Code:
CPaintDC dc(this); 

CBitmap bmpDemo;
bmpDemo.LoadBitmap(IDB_BMP_DEMO); //Verwendung einer Resource-Bitmap
// Gezoomt auf doppelte Größe, Rot wird Transparent
rawBitmap(&bmpDemo, CRect(10,10,118,112), CRect(0,0,59,56), &dc, 0, RGB(255,0,0));

CDialog::OnPaint();

In dieser Konstellation übersteht der Dialog problemlos Invalidierungen, ohne irgendwelchen Murks zu zeichen. Warum es bei dir schiefgeht, kann ich daher eigentlich nicht so richtig erklären :confused:
 
Danke für die Hilfe,
Werd das mal vergleichen und bei mir testen.
CMyBitmap macht eigentlich nicht viel anderes als Laden der Bitmap und im Speicherhalten, da ich das öfter machen muss, und sich so der QuellCode doch deutlich reduziert, zumindest wenn man noch dieverse Sicherheitsabfragen einbaut.
Für CMyPaintDC gilt ähnliches. versuche soweit möglich nen Framework aufzubauen und da finde ich es einfach besser, wenn solche Funktionen auf abgeleiteten Klassen beruhen und nicht in einem einzelnen Dialog zufinden sind, bzw in jedem neuen Dialog neu "erfunden" werden müssen. Meines Wissens nach sollte das aber keinen Unterschied machen in der Funktionalität.

Gruss Michael
 
Was ich noch vergessen habe:
Kann die Bitmap nicht einfach aus ner Ressource laden sondern muss die direkt aus der Datei über nen HBITMAP laden. Ist zwar nen Umweg, aber ne andere Möglichkeit aus nem Pfad in ne CBitmap zu packen habe ich leider nicht gefunden.
 
So hab deinen Vorschlag eingebaut.
Der Teil mit if(bmp) sah bei mir schon anderes aus, Hab den Fehler gesehen, nachdem ich gecopied hab, dachte aber ich hatte nach den änderungen nochmals gecopied...

So jetzt aber weiter:
Gute Nachricht: :) Mal mir also ne Chance aus meinen Bock zu finden

Schlechte Nachricht Weiß nicht ganz warum bei mir nicht :confused:
Fürchte das liegt an meiner CMyBitmap

Kleiner Ausschnitt (Diemal aber wirklich so wie bei mir)
Code:
CBitmap* CMyBitmap::GetCBitmap()
{
	return CBitmap::FromHandle(pBitmap);//NULL wenn pBitmap nicht valid, laut MSDN sind die Daten nicht ewig gültig daher mit jedem Invalidate() gerufen
}

BITMAP* CMyBitmap::GetBitmapInfo()
{
	if(pBitmap)
		return &BitmapInfo;//Wird zu load Zeitpunkt gefüllt
	return NULL;
}

//Funktion lädt Bitmap aus Datei in Variable Bitmap altes Bitmap wird gelöscht
BOOL CMyBitmap::LoadBitmap(CString Pfad)
{
	if(pBitmap)
		DeleteObject(pBitmap);

	pBitmap = (HBITMAP)LoadImage(NULL,Pfad,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
	if(!pBitmap)
	{
		MessageBox(NULL,"Konnte \"" + Pfad + "\" nicht laden!","Fehler...",MB_OK);
		pBitmap = NULL;
		ZeroMemory(&BitmapInfo,sizeof(BITMAP));
		Datei.Empty();
		return FALSE;
	}
	Datei = Pfad;

	CBitmap* bmp = GetCBitmap();//Muss sicher nen CBitmap haben, damit BitmapInfo gefüllt werden kann

	if(!bmp)
	{
		MessageBox(NULL,"Konnte CBitmap Element nicht erzeugen!","Fehler...",MB_OK);
		pBitmap = NULL;
		ZeroMemory(&BitmapInfo,sizeof(BITMAP));
		Datei.Empty();
		return FALSE;
	}
	bmp->GetBitmap(&BitmapInfo);
	return TRUE;
}
Ist ja wirklich nicht viel was da passiert, muss den Weg aber gehen, da ich ja zur Laufzeit erst aus ner Datei laden will und noch nicht einmal weiß was, wie groß und überhaupt...

Werd den Fehler mal weiter suchen danke des jetzt funktionierenden Beispiels sollte das ja irgendwie zu schaffen sein...

Gruss Michael
 
Fehler zwar noch nicht gefunden, aber lokalisiert ;)
Nehm ich statt ner vorgeladenen Bitmap MyBitmap.GetCBitmap das nicht mehr. Muss allso die FromHandle-Geschichte von mir falsch verstanden worden sein...
 
So endlich "Erfolg" aber nicht glücklich.
Hab die Klasse CMyBitmap in die Ewigen Jagdgründe geschickt und alles auf CBitmap aufgebaut. Hab vorher wohl die Funktion LoadBitmap übersehen. Die bietet zumindest die Möglichkeit aus Datei zuladen->tut aber nicht obwohl Datei da ist. Kann also noch nen SpeicherProblem sein...
Bei nutzen von "BOOL LoadBitmap( UINT nIDResource)" tritt aber folgendes auf:

rufe ich LoadBitmap nur einmal in OnInitDialog auf und verdecke das Bitmap, wird nur transparente Farbe schwarz -> schon mal besser als alles schwarz

rufe ich loadBitmap in JEDER OnPaint auf klappt es.
Nur mal so zum Verständnis: Wird nicht bei jeder LoadBitmap Speicher allokiert, selbst wenn vorher DeleteObjekt() aufgeufen wird ist das doch ne menge akkerei.

Da ich im Endeffekt viele Bilder laden muss, und zu allem Überfluss auch noch wenig Speicher und Rechenleistung haben werde -> Palm System, wäre mir lieber wenn sich das Handling mit den Bitmaps ungefähr so realisieren liese:

OnInitDialog -> Laden aller Bitmaps AUS DATEI und nicht aus Ressource
OnPaint->Zeichnen der Transparenten Bitmap
Destruktor/ OnClose oder wo auch immer -> Freigeben des Speichers aller Bitmaps

Kann man das nicht irgendwie darauf umbauen?

Gruss Michael
 
CBitmap::LoadBitmap() kann nur aus Resourcen laden (leider). Ansonsten ist mir auch aufgefallen, dass beim einmaligen Laden die erste Ausgabe ok, die folgenden aber statt Transparenz ein geflegtes Schwarz ausgeben.
Mal sehen, ob mir dazu noch was einfällt.
 
CodeFatal hat gesagt.:
Laute meiner MSDN und
http://msdn.microsoft.com/library/d...vcmfc98/html/_mfc_cbitmap.3a3a.loadbitmap.asp (google: CBitmap loadbitmap) kann man auch direkt aus ner Datei laden.
Wo hast du da herausgelesen, dass man auch aus einer Datei laden kann?

Ich habe in meinen alten Sourcen mal noch eine Funktion ausgegraben, die komplett anders als deine funktioniert, aber wenigstens die tranparenten Bereiche nicht "anschwärzt".
Inzwischen arbeite ich eh ausschließlich nur noch mit GDI+, dort lassen sich solche Sachen deutlich einfacher erledigen.

Code:
////////////////////////////
// member Variable    
CBitmap m_bitmap;   
 
////////////////////////////
// in InitDialog
HBITMAP hbm = (HBITMAP)LoadImage( NULL,
                                  _T("test.bmp"),
                                  IMAGE_BITMAP,
                                  0,
                                  0,
                                  LR_LOADFROMFILE );

m_bitmap.Attach(hbm); // Achtung, m_bitmap.Detach() nicht vergessen
                      // wenn der Dialog beendet oder eine neues Bitmap
                      // geladen wird

////////////////////////////                      
// in OnPaint
CPaintDC dc(this); 
DrawTransparent(&dc, &m_bitmap, CRect(10,10,118,112), CRect(0,0,59,56), RGB(255,0,0));

////////////////////////////                      
// Funktionen und Defines

#define _RoundUp(x,y)    ((((x)+((y)-1))/(y))*(y))

void CTestDlg::DrawTransparent(
    CDC *pDC, CBitmap *pBitmap, CRect rcZoom, CRect rcCut, COLORREF crTransparent)
{
    if( !pBitmap )
    {
        return;
    }

    CDC dcMemBgr, dcMemBmp, dcMemSrc;

    dcMemBgr.CreateCompatibleDC(pDC);   // Hintergrund
    dcMemBmp.CreateCompatibleDC(pDC);   // Arbeits-Bitmap
    dcMemSrc.CreateCompatibleDC(pDC);   // Source-Bitmap

    BITMAP bm;
    pBitmap->GetBitmap(&bm);

    // DIB-Bitmaps für Hintergrund und Arbeits-Bitmap erzeugen

    HBITMAP hbmBgr = Create24BPPDIBSection(pDC->GetSafeHdc(), rcZoom.Width(), rcZoom.Height());
    HBITMAP hbmBmp = Create24BPPDIBSection(pDC->GetSafeHdc(), rcZoom.Width(), rcZoom.Height());

    // Hintergrund beschreiben

    CBitmap *pOldBgrBm = dcMemBgr.SelectObject(CBitmap::FromHandle(hbmBgr));
    dcMemBgr.BitBlt(0, 0, rcZoom.Width(), rcZoom.Height(), pDC, rcZoom.left, rcZoom.top, SRCCOPY);

    // Arbeits-Bitmap beschreiben

    CBitmap *pOldTmpBm = dcMemSrc.SelectObject(pBitmap);
    CBitmap *pOldBm    = dcMemBmp.SelectObject(CBitmap::FromHandle(hbmBmp));

    dcMemBmp.StretchBlt( 0,
                         0,
                         rcZoom.Width(),
                         rcZoom.Height(),
                         &dcMemSrc,
                         rcCut.left,
                         rcCut.top,
                         rcCut.Width(),
                         rcCut.Height(),
                         SRCCOPY );
    
    dcMemSrc.SelectObject(pOldTmpBm);

    // Bitmap Parameter ermitteln

    BITMAP bmBgr, bmPic;
    ::GetObject(hbmBgr, sizeof(BITMAP), &bmBgr);
    ::GetObject(hbmBmp, sizeof(BITMAP), &bmPic);

    RGBTRIPLE *lpRgbPic    = (RGBTRIPLE *)bmPic.bmBits;
    RGBTRIPLE *lpRgbBgr    = (RGBTRIPLE *)bmBgr.bmBits;

    // Mit Hintergrund kombinieren und transparente Pixel ausblenden

    for( int nRow = 0; nRow <= bmPic.bmHeight; nRow++ )
    {
        for( int nCol = 0; nCol < bmPic.bmWidth; nCol++ )
        {
            if( RGB(lpRgbPic[nCol].rgbtRed,
                    lpRgbPic[nCol].rgbtGreen,
                    lpRgbPic[nCol].rgbtBlue) != crTransparent )
            {
                lpRgbBgr[nCol].rgbtRed        = lpRgbPic[nCol].rgbtRed;
                lpRgbBgr[nCol].rgbtGreen    = lpRgbPic[nCol].rgbtGreen;
                lpRgbBgr[nCol].rgbtBlue        = lpRgbPic[nCol].rgbtBlue;
            }
        }

        // Jede Zeile eines Bitmap-Arrays wird muss ein geradzahliges
        //  Vielfaches von sizeof(LONG) sein

        int iPicAdd = (_RoundUp(sizeof(RGBTRIPLE) * bmPic.bmWidth, sizeof(LONG)));
        int iBgrAdd = (_RoundUp(sizeof(RGBTRIPLE) * bmBgr.bmWidth, sizeof(LONG)));

        lpRgbPic = (RGBTRIPLE *)((LPBYTE)lpRgbPic + iPicAdd);
        lpRgbBgr = (RGBTRIPLE *)((LPBYTE)lpRgbBgr + iBgrAdd);
    }

    // Ausgeben

    pDC->BitBlt(    rcZoom.left,
                    rcZoom.top,
                    rcZoom.Width(),
                    rcZoom.Height(),
                    &dcMemBgr,
                    0,
                    0,
                    SRCCOPY );


    // Aufräumen

    dcMemBgr.SelectObject(pOldBgrBm);
    dcMemBmp.SelectObject(pOldBm);

    ::DeleteObject(hbmBgr);
    ::DeleteObject(hbmBmp);
}

HBITMAP CTestDlg::Create24BPPDIBSection(HDC hDC, int iWidth, int iHeight)
{
    BITMAPINFO    bmi;
    HBITMAP        hbm;
    LPBYTE        pBits;

    ZeroMemory(&bmi, sizeof(bmi));

    bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth        = iWidth;
    bmi.bmiHeader.biHeight        = iHeight;
    bmi.bmiHeader.biPlanes        = 1;
    bmi.bmiHeader.biBitCount    = 24;
    bmi.bmiHeader.biCompression    = BI_RGB;

    hbm = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (void **)&pBits, NULL, 0);
      
    return hbm;
}
 

Neue Beiträge

Zurück