Here is a picture of my program:
As you can see, the icons aren't transparent, simply white. This is problematic, because I've coded the list-view to alternate colors and the white looks very ugly on grey.
Right now, I'm using a bitmap with a pink background for the icons, and using the pink color as a mask. Here's the code for my HIMAGELIST:
hImageList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, ICON_COUNT, 0);
if (hImageList != NULL)
{
HBITMAP hBitmap = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_ICONS));
if (hBitmap != NULL)
{
ImageList_AddMasked(hImageList, hBitmap, RGB(0xFF, 0, 0xFF)); // pink mask
DeleteObject(hBitmap);
}
ImageList_SetBkColor(hImageList, CLR_NONE);
}
ListView_SetImageList(hWnd, hImageList, LVSIL_SMALL);
Here is the code for the list-view's Custom Draw (the alternating colors)
LRESULT WhiteFlagUI::PaintListView(__in HWND hwndListView, __in LPARAM lParam)
{
LPNMLVCUSTOMDRAW lpListDraw = reinterpret_cast<LPNMLVCUSTOMDRAW>(lParam);
switch (lpListDraw->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
return (CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYSUBITEMDRAW);
break;
case (CDDS_PREPAINT | CDDS_ITEM):
{
RECT rect;
if (ListView_GetSubItemRect(hwndListView, lpListDraw->nmcd.dwItemSpec, lpListDraw->iSubItem, LVIR_BOUNDS, &rect))
{
COLORREF color;
// determine color
if (lpListDraw->nmcd.uItemState & CDIS_SELECTED)
color = RGB(157, 173, 215);
else if (lpListDraw->nmcd.dwItemSpec % 2)
color = RGB(240, 240, 240);
else
color = RGB(255, 255, 255);
// paint
HBRUSH hBrush = CreateSolidBrush(color);
if (hBrush != NULL)
{
FillRect(lpListDraw->nmcd.hdc, &rect, hBrush);
DeleteObject(hBrush);
}
// return color info
lpListDraw->clrTextBk = color;
return CDRF_NEWFONT;
}
}
break;
}
return CDRF_DODEFAULT;
}
Quite frankly, I'm completely lost as to how to approach this. Does anyone have any ideas?
I found a bit of a hack around this problem. If you set the background image to a blank white bitmap using ListView_SetBkImage it will force the icons to draw transparently. Unfortunately, doing this causes NM_CUSTOMDRAW to ignore the background color set with CDRF_NEWFONT. To get around it, call FillRect to fill background of the item in CDDS_ITEMPREPAINT and return CDRF_DODEFAULT or CDRF_NEWFONT if you are changing the foreground color as well.
I was faced with this problem as well. I've solved it by adding SetBkColor(RGB(...)) where RGB(...) alternates from foreground color to background one in the custom draw procedure. I use 16x16 4b BMP with white background. Instead of using FillRect(), I set clrTextBk too. The last works for texts. As I see from my experiments with CListCtrl, function SetBkColor() sets background color for icons only and does not for text (I found nothing about this in docs).
All this works only for non-empty items. To draw empty rows with this style, I override OnEraseBkgnd() notification function. For fully empty list, simple rectangles are drawn.
I hope this will help
Olexiy