2 Grafiken Kombinieren (Übereinanderlegen) in MFC (CBitmap / HIcon)

Kanisterkopp

Grünschnabel
Hallo, Community!
Ich hoffe ihr nehmt es mir nicht übel, dass mein erster Beitrag eine Frage ist.;)
Nachdem mich CodeProject und Co. leider nicht weitergeholfen haben, wollte ich hier mal um Rat bitten...

Ich Arbeite zur Zeit an einem MFC Projekt das eine ClistCtrl benötigt eine CImagelist um die Icons/Symbole zu "verwalten".
Jetzt stehe ich vor dem Problem zwei Grafiken zu "kombinieren". Der Zweck ist weitere Ansicht. Dazu habe ich eine CImageList die Grafiken in der Größe 128x128 schluckt.

Diese soll nun einen variable Hintergrundgrafik beinhalten (sind in den Resourcen vorhanden) über die ein Symbol (bekommt man per WINAPI) gelegt werden soll.

Die Bilder liegen im Programmcode als CBitmap und HIcon vor.. das Endresultat hätte mich am liebsten in einem CBitmap damit ich es wieder problemlos zu CImageList hinzufügen kann.

Habe schon einige Beispiele gesehen um ein Bitmap in ein anderes zu Kopieren aber leider hilft mir das nicht weiter.
Zudem kommt auch noch die unterschiedliche Größe der Ausgangsbilder dazu.
So solls sein
 
Hallo,

ich könnte mir folgende Vorgensweise vorstellen:

- Zeichne beide Grafiken in jeweils einen eigenen Speicher-Devicekontext.
- Mit "GetPixel" kannst du dir dann die Pixel des Icons aus dem einen Devicekontext holen und mit "SetPixel" an die gewünschte Position des anderen Devicekontexts (vom Hintergrundbitmap) schreiben.
- Den Inhalt des Speicher-Devicekontextes vom Hintergrundbitmap kannst du dann wieder in die Imagelist packen

Statt mit "GetPixel/SetPixel" könnte man auch mit "BitBlt" das Icon mit einem Rutsch auf auf das Hintergrundbitmap kopieren. Allerdings klappt das so nicht mit evt. im Icon vorhandenen transparenten Bereichen. Bei "GetPixel/SetPixel" lässt man die betreffenden Pixel (ist ja immer eine ganz bestimmte Farbe) einfach aus. Da das Icon nicht groß ist, fällt die mäßige Performance von "GetPixel/SetPixel" auch nicht ins Gewicht

Gruß
MCoder
 
Hey, danke für die schnelle Antwort ;) Ich werde mich erstmal an dem Versuch über Get/Set Pixel versuchen.
Nur das Vorgehen mit Device Context ist mir noch nicht ganz klar..
wenn ich das ganze Richtig verstanden haben...
Code:
CClientDC dc(0); //Device Context erstellen
CDC memDC; //Speicher Device Context 
memDC.CreateCompatibleDC(&dc);

CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dc, 128, 128); //Device Context zuweisen
memDC.SelectObject(&bitmap);

int size = bmp.bmWidthBytes * bmp.bmHeight;

int *buf = new int[size];
bitmap.GetBitmapBits(size, buf); //Pixel Des Hintergrund in Array laden

for(......) //Pixel manipulieren 
bitmap.SetBitmapBits(size,buf);
Geht vielleicht auch noch schneller als jedes mal GetPixel separat aufzurufen.
 
Zuletzt bearbeitet:
Hallo,

nimm besser "GetDIBits" als "GetBitmapBits"; Letzteres ist noch ein Relikt aus der 16-Bit Ära. Ich habe deswegen "Get/SetPixel" vorgeschlagen, weil die Pixelmanipulation in dem erhaltenen Puffer nicht ganz ohne ist. Die Organisation der Pixeldaten hängt z.B. noch von der Farbtiefe ab.

Gruß
MCoder
 
Sooo mittlerweile bin ich auch zu einer einfachen Lösung gekommen die bestimmt auch performanter ist, als einzelnen Pixel zu setzten.
Code:
{
//Bild laden
LSICON TypeIcon = GetExtIcon(szExt);
CBitmap cEmtpy;
cEmtpy.LoadBitmap(MAKEINTRESOURCE(240));
HBITMAP hBitmap = (HBITMAP) cEmtpy;
	
CDC dc;
dc.CreateCompatibleDC(p_ListView->GetDC());
CBitmap *pOldBmp = dc.SelectObject(&cEmtpy);
dc.DrawIcon(48,48,TypeIcon.hLarge); #1
dc.SelectObject(pOldBmp);

CBitmap* pCBitmap = CBitmap::FromHandle(hBitmap);
int id = m_WMThumbnails.Add(pCBitmap, RGB(0, 0, 0));

return id;
}
Die Bilder werden jetzt übereinander gesetzt, das einzige Problem (#1) ist wenn das untere Bild 32Bit Farbtiefe hat (mit Alpha) bleibt die Stelle an der das Icon erscheinen soll leer = bzw Transparent.
Ich gehe davon aus das das Icon eine andere Farbtiefe hat und es daher zu diesem Problem kommt.

Mit einem Hintergrundbild ohne Alpha Channel passt alles perfekt. Vielleicht noch jemand ne Idee das Problem hinzubekommen? :)


EDIT: Jetzt wird alles richtig gezeichnet! Vielen dank für die Hilfe ;)

EDIT2: Leider scheint es doch abhängig davon zu sein, was für ein ICON gezeichnet werden soll.. bei *.doc klappt bsp. alles *.tif hingegen bleiben leer.
 
Zuletzt bearbeitet:
Nur ein Versuch. Vielleicht kommst du weiter, wenn du das Icon nicht direkt auf den Devicekontext des Bitmaps kopierst, sondern beide Grafiken auf einen anderen Devicekontext bringst. Mit "CreateCompatibleBitmap()" solltest ein Bitmap mit geringerer Farbtiefe (24 Bit) erhalten, was im Ergebnis (vielleicht) weniger Probleme machen könnte.
C++:
// ...

CDC dcBM;
dcBM.CreateCompatibleDC(p_ListView->GetDC());
CBitmap *pOldBmp = dcBM.SelectObject(&cEmtpy);

CDC dc;
dc.CreateCompatibleDC(p_ListView->GetDC());
dc.CreateCompatibleBitmap(p_ListView->GetDC(), 128, 128);

dc.BiBlt(0, 0, 128, 128, &dcBM, 0, 0, SRCCPY);
dc.DrawIcon(48,48,TypeIcon.hLarge);

// ...
Gruß
MCoder
 

Neue Beiträge

Zurück