Hinzufügen einer Bitmap zu einer CImageList
-
Hi,
beim Versuch eine Bitmap in eine CImageList einzufügen, kommt es zu einer unhandled exception.
Zunächst mal mein Code:
CImageList imageList; CBitmap* ptestBitmap; ptestBitmap = (CBitmap*)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1),IMAGE_BITMAP,32, 32, LR_DEFAULTCOLOR); imageList.Create(32, 32, ILC_COLOR, 0, 40); imageList.Add(ptestBitmap, RGB(0,0,0)); //(*)
In Zeile (*) erfolgt also folgender Aufruf:
_AFXCMN_INLINE int CImageList::Add(CBitmap* pbmImage, COLORREF crMask) { ASSERT(m_hImageList != NULL); return AfxImageList_AddMasked(m_hImageList,(HBITMAP)pbmImage->GetSafeHandle(), crMask); }
Und dabei geht
_AFXWIN_INLINE HGDIOBJ CGdiObject::GetSafeHandle() const { return this == NULL ? NULL : m_hObject; }
in die Hose.
Kann mir jemand erklären, was ich hier falsch mache?
-
LoadImage gibt doch ein HANDLE(HBITMAP) auf eine Bitmap zurück, und kein CBitmap*
also mußt du das HANDLE erst in ein CBitmap-Object "Importieren".vieleicht mit CBitmap::FromHandle()
Gruß Matthias
-
So tritt der Fehler nicht mehr auf, danke für den Hinweis!
(Komischerweise hat dieser Cast von HANDLE auf CBitmap* an anderer Stelle problemlos funktioniert.)Allerdings komme ich jetzt mit diesem CBitmap::FromHandle nicht ganz klar
Habe das so ausgebessert:
CImageList imageList; CBitmap* ptestBitmap; HBITMAP hBitmap; hBitmap = (CBitmap*)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1),IMAGE_BITMAP,32, 32, LR_DEFAULTCOLOR); ptestBitmap->FromHandle(hBitmap); // ptestBitmap = CBitmap::FromHandle(hBitmap) imageList.Create(32, 32, ILC_COLOR, 0, 40); imageList.Add(ptestBitmap, RGB(0,0,0)); //(*)
Allerdings tauchen die "Bildchen" in meinem CListControl anschließend nicht auf.
Wie oben beschrieben hatte ich es zuvor an anderer Stelle ebenfalls mit einem solchen Cast probiert und die Bilder wurden angezeigt (allerdings kein CListControl). Als ich das jetzt entsprechend korrigiert habe, sind die Bilder dort ebenfalls verschwunden...In der MSDN heißt es bei CBitmap::FromHandle():
MSDN schrieb:
If a CBitmap object is not already attached to the handle, a temporary CBitmap object is created and attached. This temporary CBitmap object is valid only until the next time the application has idle time in its event loop, at which time all temporary graphic objects are deleted. Another way of saying this is that the temporary object is only valid during the processing of one window message.
Habe ich hier noch etwas zu beachten. Wie verknüpfe ich denn das Bitmap zuvor schon mit einem Handle? Habe es mit Attach(hBitmap) probiert, das ändert aber nichts.
Bin ziemlich ratlos...
-
?!
CImageList imageList; CBitmap bitmap; bitmap.LoadBitmap(MAKEINTRESOURCE(IDB_BITMAP1)); imageList.Create(32, 32, ILC_COLOR, 0, 40); imageList.Add(&bitmap, RGB(0,0,0)); //(*)
oder
CImageList imageList; CBitmap* pBitmap = CBitmap::FromHandle(::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1),IMAGE_BITMAP,32, 32, LR_DEFAULTCOLOR)); imageList.Create(32, 32, ILC_COLOR, 0, 40); imageList.Add(pBitmap, RGB(0,0,0)); //(*)
-
Sorry, das war natürlich ein ganz cleverer Beitrag von mir, weil ich in meinem Posting genau das nicht ausgebessert habe, was ich ausbessern wollte. Also noch einmal:
CImageList imageList; CBitmap* ptestBitmap; HBITMAP hBitmap; hBitmap = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1),IMAGE_BITMAP,32, 32, LR_DEFAULTCOLOR); ptestBitmap->FromHandle(hBitmap); // ptestBitmap = CBitmap::FromHandle(hBitmap) imageList.Create(32, 32, ILC_COLOR, 0, 40); imageList.Add(ptestBitmap, RGB(0,0,0)); //(*) CListCtrl* lc = (CListCtrl*) GetDlgItem(IDC_LIST); lc->SetImageList(&imageList, LVSIL_SMALL); lc->InsertItem(0, _T("Testitem"), 0);
@(D)Evil:
Obiges sollte doch jetzt deiner zweiten Variante entsprechen, oder? Der Cast des Return-Wertes von ::LoadImage() auf HBITMAP ist allerdings erforderlich, weil ::LoadImage() ein HANDLE liefert, CBitmap::FromHadle() aber ein HBITMAP nimmt.Das Problem bleibt aber das bereits beschriebene, auch wenn ich deinen Code exakt übernehme (abgesehen von dem Cast des Return-Wertes von ::LoadImage() auf HBITMAP): die Bilder tauchen in dem ListControl nicht auf und ich verstehe nicht, woran das liegen kann...
(Dass ich Bitmaps aus Resourcen auch mit CBitmap::LoadBitmap() laden kann, ist mir klar, allerdings lässt ::LoadImage() eine Skalierung auf die gewüschte Größe zu und das kriege ich über LoadBitmap() nicht hin. Oder gibt es eine Möglichkeit ein CBitmap-Objekt nachträglich zu skalieren?)
-
Inzwischen funktioniert es
Vielleicht zur Aufklärung:
1.)
CImageList muss offensichtlich dynamisch erzeugt werden2.)
Die in CImageList::Create() angegebene Größe (die ersten beiden Parameter, hier: 32, 32) muss mit der der hinzuzufügenden Bitmap(s) übereinstimmen.
Wahrscheinlich die Weisheit schlechthin, erklärt aber auch, warum die Bitmaps mittels ::LoadImage() geladen und entsprechend skaliert werden sollten, (falls es nicht doch eine andere Möglichkeit gibt ;))
3.)
Beim Aufruf von CListCtrl::SetImageList() muss offensichtlich als Image-List-Typ LVSIL_NORMAL angegeben werden, wenn man Bitmaps verwendet.Hier nochmal der Code:
CImageList* pImageList = new CImageList; ASSERT(pImageList != 0); pImageList->Create(32, 32, ILC_COLOR32, 0, 40); CBitmap* pBitmap = CBitmap::FromHandle((HBITMAP)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1),IMAGE_BITMAP,32, 32, LR_DEFAULTCOLOR)); pImageList->Add(ptestBitmap, RGB(0,0,0)); CListCtrl* lc = (CListCtrl*) GetDlgItem(IDC_LIST); lc->SetImageList(pImageList, LVSIL_NORMAL); lc->InsertItem(0, _T("Testitem"), 0);
Vielen habe ich jetzt vermutlich nichts Neues erzählt, aber vielleicht gibt es ja welche, die sich genauso blöd anstellen wie ich. Und diejenigen, denen das ohnehin schon immer alles klar war, hätten ja schließlich antworten können :p
Und falls es doch noch etwas zu korrigieren gibt: bitte, gerne!