2009-03-10 4 views
3

EDIT: Ich habe eine Prämie angeboten, da ich bezweifle, dass ich sonst irgendwelche Antworten bekommen werde.ImageList Transparenz auf Listenansichten?

In letzter Zeit habe ich mit Listviews gearbeitet und ich habe beschlossen, für jedes Element ein Symbol hinzuzufügen, das angibt, ob es sich um Eingabe oder Ausgabe handelt. Die Symbole hinzufügen in Ordnung, aber sie sind nicht transparent:

Example of icon not being transparent

Wie zu sehen ist, werden die Symbole sind eindeutig nicht transparent. Ich mache zur Zeit so etwas wie diese Last die Symbole:

hImageList = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 2, 2); 
    if (hImageList != NULL) 
    { 
    iIN = ImageList_AddIcon(hImageList, LoadIcon(hInstance, MAKEINTRESOURCE(101))); 
    iOUT = ImageList_AddIcon(hImageList, LoadIcon(hInstance, MAKEINTRESOURCE(102))); 
    } 

Ich habe für ImageList_Create & LoadIcon/LoadImage mit den Flaggen versucht, Messing, aber haben kein Glück gehabt und um ehrlich zu sein habe ich die Ideen ausgehen.

Jede Hilfe wäre sehr willkommen.

+0

Du hast deine Quelle irgendwo für uns zur Verfügung? Ich sehe einige Kommentare, in denen Leute Ihren Code testen. Ich würde es mir gerne ansehen, da ich in diesem Bereich viel gearbeitet habe ... – LarryF

+0

Bitte sehen Sie meine Antwort (Antwort 2) für http: //stackoverflow.com/questions/6893351/transparent-images-in-imimelists-for-listviews/ thread. Olexiy –

Antwort

11

First up, ImageList_ReplaceIcon kopiert die Daten-Symbol, wenn es zu einer Bildliste hinzuzufügen. Also muss der HICON danach veröffentlicht werden.

Als nächstes sind Bildlisten native Bitmaps, keine Symbole. Und die Art und Weise, wie Sie Ihre Imagelist erstellen, macht die Umwandlung von Icon in Bitmap sehr vieldeutig. ILC_COLOR32 impliziert, dass die Bildliste als ein 32-Bit-dib-Abschnitt erstellt werden sollte, der typischerweise Transparenzinformationen über einen eingebetteten Alphakanal enthält. ILC_MASK impliziert stattdessen, dass die internen Bitmaps DDB-Bitmaps sind, wobei die Transparenzinformationen als 1bpp-Maskenbitmap gespeichert sind.

Die schnellste Lösung für Ihr Problem - nehmen Sie zwei Symbole:

  • sie in ein, das ist 32 Pels breit hoch von 16 Ressource einzelner Bitmap Merge. Fülle den Hintergrund mit einer Maskenfarbe: - lila oder so.
  • Erstellen Sie die Bitmap mit ILC_COLOR | ILC_MASK
  • Legen Sie das Bitmap sicher LR_TRANSPARENT nicht zu bedienen ist.
  • Fügen Sie die Bitmap mit ImageList_AddMasked hinzu und übergeben Sie ein COLORREF, das die Maskenfarbe darstellt.

OR, für eine bessere visuelle Wirkung ...

  • Export Ihrer PNG-Daten als 32x16 32bpp Bitmap-Datei Daten vormultipliziert Alphakanal enthält.
  • Erstellen Sie die Bildliste mit dem Wert ILC_COLOR32.
  • LoadImage() mit LR_CREATEDIBSECTION zum Laden der Bitmap als 32bpp dib Abschnitt.
  • Fügen Sie das Bild mit ImageList_Add()

(die letzten Option ist etwas schwierig, wenn die Anzahl von Werkzeugen, die 32-Bit unterstützt das Schreiben aus BMP-Dateien mit ist richtig multiplizierten Alpha-Kanäle vor eher niedrig).


Bearbeitet, um das folgende Codebeispiel hinzuzufügen. Mit Hilfe eines 4bpp Bitmap in der Entwickler-Umgebung erstellt das funktioniert einfach toll: -

HWND hwndCtl = CreateWindowEx(0,WC_LISTVIEW,TEXT("ListView1"),WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL,0,0,cx,cy,hWnd,(HMENU)101,hModule,NULL); 
HBITMAP hbm = (HBITMAP)LoadImage(hModule,MAKEINTRESOURCE(IDB_BITMAP1),IMAGE_BITMAP,0,0,0); 
COLORREF crMask=RGB(255,0,255); 
HIMAGELIST himl = ImageList_Create(16,16,ILC_COLOR|ILC_MASK,2,0); 
ImageList_AddMasked(himl,hbm,crMask); 
ListView_SetImageList(hwndCtl,himl,LVSIL_NORMAL); 
+0

Ich habe die erste Option früher heute versucht und ich hatte das gleiche Problem. Nachdem ich deinen Beitrag gelesen hatte, versuchte ich den zweiten Weg, und es machte keinen Unterschied. Bitte werfen Sie einen Blick darauf: http://pastebin.com/f5617ac8a – Irwin

+0

Wenn Sie ILC \ _MASK | ILC \ _COLOR bereitstellen, wie laden Sie die Bitmap?Sie sollten wahrscheinlich das DIBSECTION-Flag weglassen und beachten, dass das Laden von Bitmaps auf DDB-Oberflächen mit Verlust behaftet ist, so dass ein COLORREF, der die idealen RGB-Werte in der Datei beschreibt, nicht mit den Bildpunkten in der DDB übereinstimmen kann. Verwenden Sie reine Farben. –

+0

... Sie haben es völlig versäumt, die zweite Option zu kommentieren. Außerdem habe ich das Flag LR_CREATEDIBSECTION für die erste Option weggelassen. Meine Maskenfarbe war pink (RGB (255, 0, 255)), also hätte es keine Übereinstimmungen gegeben. – Irwin

0

Sie möchten, dass Ihre Symbole eine Hintergrundfarbe haben, die nirgendwo anders im Symbol verwendet wird, wie ein wirklich hässliches Purpur, und verwenden Sie dann LoadImage (..., LR_LOADTRANSPARENT); Die Fahne sagt, schau dir das erste Pixel bei 0,0 an und mache alles so transparent.

+1

Ich habe dies bereits versucht (mit ersten Pixel als RGB (255, 0, 255)) und zitieren die Dokumentation: LR_LOADTRANSPARENT lädt das Bild nicht transparent. Es erstellt eine undurchsichtige Bildliste, die nur transparent erscheint, weil alle Hintergrundpixel in COLOR_WINDOW geändert wurden. – Irwin

+0

Ah ja, das macht Sinn. Dumme Windows und transparente Icons. –

0

Ihr Code sieht gut aus, ich benutze immer LoadImage anstelle von LoadIcon, aber ich vermute, dass das egal ist. Haben Sie überprüft, dass die Icons tatsächlich transparente Bereiche haben und selbst keinen festen Hintergrund haben?

Meine Anrufe Loadimage wie folgt aussehen:

HICON hIcon = (HICON)LoadImage(hinstResources,MAKEINTRESOURCE(IDI_ICON),IMAGE_ICON,16,16,LR_DEFAULTCOLOR); 
+0

Wie in meinem ursprünglichen Beitrag erwähnt, habe ich bereits mit LoadIcon & LoadImage verstimmt. Ich habe auch versucht, nur die LR_DEFAULTCOLOR-Flagge allein zu verwenden, und es machte keinen Unterschied. Oh und ja, meine Icons sind transparent: http://img12.imageshack.us/img12/6117/reseditxpirc776.png – Irwin

0

hier ... Eine Abbildungsliste, wie vorgeschlagen, machen Sie Ihre Symbole in eine Bitmap, 16 Pixel hoch, um 16 * n lang, wo n = die Anzahl der Symbole ...

Setzen Sie die Hintergrundfarbe auf 255, 0, 255, wie Sie es getan haben.

Dann laden Sie es, und es in die Bildliste hinzufügen, wie ich hier tat:

m_ImageList.Create(16, 16, ILC_COLOR16 | ILC_MASK, 7, 1); 
CBitmap bm; 
bm.LoadBitmap(IDB_SUPERTREEICONS); 
m_ImageList.Add(&bm, RGB(255, 0, 255)); 
GetTreeCtrl().SetImageList(&m_ImageList, TVSIL_NORMAL); 

Natürlich ist dies in MFC geschrieben wurde, aber wie Sie wissen, es ist nur ein Wrapper für Win32 ..

Außerhalb von diesem müssen Sie zu einem benutzerdefinierten Zeichensteuerelement gehen, in dem Sie das Symbol über den Hintergrund zeichnen, auf dem das Symbol gerade sitzt. Es gibt keine magische "transparente" Farbe, die ich kenne, in irgendeiner dieser Steuerungen.

Im Falle eines benutzerdefinierten ziehen, müssen Sie Code verwenden, wie folgt aus:

#define TRANSPARENT_COLOR (255,0,255) 

UINT iBitmap = IDB_ICON_UP 
CDC *dc = GetDC(); 
int x = 0, y = 0; 

    CDC *pDisplayMemDC = new CDC; 
    CDC *pMaskDC = new CDC; 
    CDC *pMemDC = new CDC; 
    CBitmap *pBitmap = new CBitmap; 
    CBitmap *pMaskBitmap = new CBitmap; 
    CBitmap *pMemBitmap = new CBitmap; 
    int cxLogo, cyLogo; 
    BITMAP bm; 

    pBitmap->LoadBitmap(iBitmap); 
    pDisplayMemDC->CreateCompatibleDC(dc); 
    CBitmap *pOldBitmap = (CBitmap *)pDisplayMemDC->SelectObject(pBitmap); 

    pBitmap->GetObject(sizeof(bm), &bm); 
    cxLogo = bm.bmWidth; 
    cyLogo = bm.bmHeight; 

    pMaskBitmap->CreateBitmap(cxLogo, cyLogo, 1, 1, NULL); 
    pMaskDC->CreateCompatibleDC(dc); 
    CBitmap *pOldMask = (CBitmap *)pMaskDC->SelectObject(pMaskBitmap); 
    COLORREF oldBkColor = pDisplayMemDC->SetBkColor(TRANSPARENT_COLOR); 
    pMaskDC->BitBlt(0, 0, cxLogo, cyLogo, pDisplayMemDC, 0, 0, SRCCOPY); 

    pMemBitmap->CreateCompatibleBitmap(dc, cxLogo, cyLogo); 
    pMemDC->CreateCompatibleDC(dc); 
    CBitmap *pOldMem = (CBitmap *)pMemDC->SelectObject(pMemBitmap); 

    pMemDC->BitBlt(0, 0, cxLogo, cyLogo, dc,   x, y, SRCCOPY); 
    pMemDC->BitBlt(0, 0, cxLogo, cyLogo, pDisplayMemDC, 0, 0, SRCINVERT); 
    pMemDC->BitBlt(0, 0, cxLogo, cyLogo, pMaskDC,  0, 0, SRCAND); 
    pMemDC->BitBlt(0, 0, cxLogo, cyLogo, pDisplayMemDC, 0, 0, SRCINVERT); 
     dc->BitBlt(x, y, cxLogo, cyLogo, pMemDC,  0, 0, SRCCOPY); 

    delete pMemDC->SelectObject(pOldMem); 
    delete pMemDC; 

    delete pMaskDC->SelectObject(pOldMask); 
    delete pMaskDC; 

    delete pDisplayMemDC->SelectObject(pOldBitmap); 
    delete pDisplayMemDC; 

Dieser Code wo entscheidet das Symbol zu zeichnen, und macht eine Momentaufnahme des Hintergrunds, schafft eine Maske für die Symbol, und dann zeichnet es über den Hintergrund, so dass es einen völlig transparenten Hintergrund ...

Hoffnung, die etwas hilft. Wenn nicht, erkläre bitte ausführlicher, was du zu erreichen versuchst und was du siehst oder was du nicht siehst ...