Strangly, some programs (e.g. emule) depend on having custom draw messages for owner draw listviews. Odd. ChangeLog Generate custom draw notifications for ownerdraw listviews. (Based on a patch by Maxime Bellenge) Reorganize the custom draw code for better reuse. Index: dlls/comctl32/listview.c =================================================================== RCS file: /var/cvs/wine/dlls/comctl32/listview.c,v retrieving revision 1.346 diff -u -r1.346 listview.c --- dlls/comctl32/listview.c 24 Mar 2003 19:28:50 -0000 1.346 +++ dlls/comctl32/listview.c 27 Apr 2003 15:57:13 -0000 @@ -849,21 +849,73 @@ return bResult; } -static void customdraw_fill(NMLVCUSTOMDRAW *lpnmlvcd, LISTVIEW_INFO *infoPtr, HDC hdc, const RECT *rcBounds) +static void customdraw_fill(NMLVCUSTOMDRAW *lpnmlvcd, LISTVIEW_INFO *infoPtr, HDC hdc, + const RECT *rcBounds, const LVITEMW *lplvItem) { ZeroMemory(lpnmlvcd, sizeof(NMLVCUSTOMDRAW)); lpnmlvcd->nmcd.hdc = hdc; lpnmlvcd->nmcd.rc = *rcBounds; lpnmlvcd->clrTextBk = infoPtr->clrTextBk; lpnmlvcd->clrText = infoPtr->clrText; + if (!lplvItem) return; + lpnmlvcd->nmcd.dwItemSpec = lplvItem->iItem; + lpnmlvcd->iSubItem = lplvItem->iSubItem; + if (lplvItem->state & LVIS_SELECTED) lpnmlvcd->nmcd.uItemState |= CDIS_SELECTED; + if (lplvItem->state & LVIS_FOCUSED) lpnmlvcd->nmcd.uItemState |= CDIS_FOCUS; + if (lplvItem->iItem == infoPtr->nHotItem) lpnmlvcd->nmcd.uItemState |= CDIS_HOT; + lpnmlvcd->nmcd.lItemlParam = lplvItem->lParam; } static inline DWORD notify_customdraw (LISTVIEW_INFO *infoPtr, DWORD dwDrawStage, NMLVCUSTOMDRAW *lpnmlvcd) { lpnmlvcd->nmcd.dwDrawStage = dwDrawStage; + if (lpnmlvcd->nmcd.dwItemSpec) lpnmlvcd->nmcd.dwDrawStage |= CDDS_ITEM; return notify_hdr(infoPtr, NM_CUSTOMDRAW, &lpnmlvcd->nmcd.hdr); } +static DWORD notify_prepaint (LISTVIEW_INFO *infoPtr, HDC hdc, NMLVCUSTOMDRAW *lpnmlvcd) +{ + BOOL isSelected = lpnmlvcd->nmcd.uItemState & CDIS_SELECTED; + DWORD cditemmode = notify_customdraw(infoPtr, CDDS_PREPAINT, lpnmlvcd); + + if (cditemmode & CDRF_SKIPDEFAULT) return cditemmode; + + /* apprently, for selected items, we have to override the returned values */ + if (isSelected) + { + if (infoPtr->bFocus) + { + lpnmlvcd->clrTextBk = comctl32_color.clrHighlight; + lpnmlvcd->clrText = comctl32_color.clrHighlightText; + } + else if (infoPtr->dwStyle & LVS_SHOWSELALWAYS) + { + lpnmlvcd->clrTextBk = comctl32_color.clr3dFace; + lpnmlvcd->clrText = comctl32_color.clrBtnText; + } + } + + /* Set the text attributes */ + if (lpnmlvcd->clrTextBk != CLR_NONE) + { + SetBkMode(hdc, OPAQUE); + if (lpnmlvcd->clrTextBk == CLR_DEFAULT) + SetBkColor(hdc, infoPtr->clrTextBkDefault); + else + SetBkColor(hdc,lpnmlvcd->clrTextBk); + } + else + SetBkMode(hdc, TRANSPARENT); + SetTextColor(hdc, lpnmlvcd->clrText); + + return cditemmode; +} + +static inline DWORD notify_postpaint (LISTVIEW_INFO *infoPtr, NMLVCUSTOMDRAW *lpnmlvcd) +{ + return notify_customdraw(infoPtr, CDDS_POSTPAINT, lpnmlvcd); +} + /******** Item iterator functions **********************************/ static RANGES ranges_create(int count); @@ -3504,33 +3556,12 @@ debugrect(&rcBox), debugrect(&rcState), debugrect(&rcIcon), debugrect(&rcLabel)); /* fill in the custom draw structure */ - customdraw_fill(&nmlvcd, infoPtr, hdc, &rcBox); - nmlvcd.nmcd.dwItemSpec = lvItem.iItem; - nmlvcd.iSubItem = lvItem.iSubItem; - if (lvItem.state & LVIS_SELECTED) nmlvcd.nmcd.uItemState |= CDIS_SELECTED; - if (lvItem.state & LVIS_FOCUSED) nmlvcd.nmcd.uItemState |= CDIS_FOCUS; - if (lvItem.iItem == infoPtr->nHotItem) nmlvcd.nmcd.uItemState |= CDIS_HOT; - nmlvcd.nmcd.lItemlParam = lvItem.lParam; + customdraw_fill(&nmlvcd, infoPtr, hdc, &rcBox, &lvItem); if (cdmode & CDRF_NOTIFYITEMDRAW) - cditemmode = notify_customdraw (infoPtr, CDDS_ITEMPREPAINT, &nmlvcd); + cditemmode = notify_prepaint (infoPtr, hdc, &nmlvcd); if (cditemmode & CDRF_SKIPDEFAULT) goto postpaint; - /* apprently, for selected items, we have to override the returned values */ - if (lvItem.state & LVIS_SELECTED) - { - if (infoPtr->bFocus) - { - nmlvcd.clrTextBk = comctl32_color.clrHighlight; - nmlvcd.clrText = comctl32_color.clrHighlightText; - } - else if (infoPtr->dwStyle & LVS_SHOWSELALWAYS) - { - nmlvcd.clrTextBk = comctl32_color.clr3dFace; - nmlvcd.clrText = comctl32_color.clrBtnText; - } - } - /* in full row select, subitems, will just use main item's colors */ if (nSubItem && uView == LVS_REPORT && (infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT)) nmlvcd.clrTextBk = CLR_NONE; @@ -3558,16 +3589,6 @@ /* Don't bother painting item being edited */ if (infoPtr->hwndEdit && nItem == infoPtr->nEditLabelItem && nSubItem == 0) goto postpaint; - /* Set the text attributes */ - if (nmlvcd.clrTextBk != CLR_NONE) - { - SetBkMode(hdc, OPAQUE); - SetBkColor(hdc, nmlvcd.clrTextBk == CLR_DEFAULT ? infoPtr->clrTextBkDefault : nmlvcd.clrTextBk); - } - else - SetBkMode(hdc, TRANSPARENT); - SetTextColor(hdc, nmlvcd.clrText); - /* draw the selection background, if we're drawing the main item */ if (nSubItem == 0) { @@ -3603,7 +3624,7 @@ postpaint: if (cditemmode & CDRF_NOTIFYPOSTPAINT) - notify_customdraw(infoPtr, CDDS_ITEMPOSTPAINT, &nmlvcd); + notify_postpaint(infoPtr, &nmlvcd); return TRUE; } @@ -3618,10 +3639,12 @@ * RETURN: * None */ -static void LISTVIEW_RefreshOwnerDraw(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc) +static void LISTVIEW_RefreshOwnerDraw(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc, DWORD cdmode) { UINT uID = GetWindowLongW(infoPtr->hwndSelf, GWL_ID); HWND hwndParent = GetParent(infoPtr->hwndSelf); + DWORD cditemmode = CDRF_DODEFAULT; + NMLVCUSTOMDRAW nmlvcd; POINT Origin, Position; DRAWITEMSTRUCT dis; LVITEMW item; @@ -3659,7 +3682,18 @@ dis.itemData = item.lParam; TRACE("item=%s, rcItem=%s\n", debuglvitem_t(&item, TRUE), debugrect(&dis.rcItem)); - SendMessageW(hwndParent, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis); + + if (cdmode & CDRF_NOTIFYITEMDRAW) + { + customdraw_fill(&nmlvcd, infoPtr, hdc, &dis.rcItem, &item); + cditemmode = notify_prepaint (infoPtr, hdc, &nmlvcd); + } + + if (!(cditemmode & CDRF_SKIPDEFAULT)) + SendMessageW(hwndParent, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis); + + if (cditemmode & CDRF_NOTIFYPOSTPAINT) + notify_postpaint(infoPtr, &nmlvcd); } } @@ -3800,8 +3834,8 @@ oldClrText = infoPtr->clrText; GetClientRect(infoPtr->hwndSelf, &rcClient); - customdraw_fill(&nmlvcd, infoPtr, hdc, &rcClient); - cdmode = notify_customdraw(infoPtr, CDDS_PREPAINT, &nmlvcd); + customdraw_fill(&nmlvcd, infoPtr, hdc, &rcClient, 0); + cdmode = notify_prepaint(infoPtr, hdc, &nmlvcd); if (cdmode & CDRF_SKIPDEFAULT) goto enddraw; /* Use these colors to draw the items */ @@ -3827,7 +3861,7 @@ } if ((infoPtr->dwStyle & LVS_OWNERDRAWFIXED) && (uView == LVS_REPORT)) - LISTVIEW_RefreshOwnerDraw(infoPtr, &i, hdc); + LISTVIEW_RefreshOwnerDraw(infoPtr, &i, hdc, cdmode); else { if (uView == LVS_REPORT) @@ -3843,7 +3877,7 @@ enddraw: if (cdmode & CDRF_NOTIFYPOSTPAINT) - notify_customdraw(infoPtr, CDDS_POSTPAINT, &nmlvcd); + notify_postpaint(infoPtr, &nmlvcd); infoPtr->clrTextBk = oldClrTextBk; infoPtr->clrText = oldClrText; -- Dimi.