Oxygen! This one optimizes things, as we make now exactly 1 query (GetItem) per item when drawing, whereas before we were making 2 (one in Draw.*Item, one in GetItemMeasures). We also no longer make a call to GetOrigin for every item. We're quickly approaching a theoretical optimum while drawing! :))) ChangeLog Use GetItemMetrics instead of GetItemMeasures when drawing. --- dlls/comctl32/listview.c.O1 Fri Oct 11 00:55:43 2002 +++ dlls/comctl32/listview.c Fri Oct 11 01:19:56 2002 @@ -1402,7 +1402,7 @@ BOOL doState = FALSE, doIcon = FALSE, doLabel = FALSE, oversizedBox = FALSE; RECT Box, State, Icon, Label; - ERR("(lpLVItem=%s)\n", debuglvitem_t(lpLVItem, TRUE)); + TRACE("(lpLVItem=%s)\n", debuglvitem_t(lpLVItem, TRUE)); /* Be smart and try to figure out the minimum we have to do */ if (lprcBounds) @@ -3157,17 +3157,18 @@ * [I] infoPtr : valid pointer to the listview structure * [I] hdc : device context handle * [I] nItem : item index + * [I] pos : item position in client coordinates * [I] cdmode : custom draw mode * * RETURN: * Success: TRUE * Failure: FALSE */ -static BOOL LISTVIEW_DrawItem(LISTVIEW_INFO *infoPtr, HDC hdc, INT nItem, DWORD cdmode) +static BOOL LISTVIEW_DrawItem(LISTVIEW_INFO *infoPtr, HDC hdc, INT nItem, POINT pos, DWORD cdmode) { WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' }; DWORD cditemmode = CDRF_DODEFAULT; - RECT* lprcFocus, rcSelect, rcBox, rcIcon, rcLabel; + RECT* lprcFocus, rcSelect, rcBox, rcState, rcIcon, rcLabel; NMLVCUSTOMDRAW nmlvcd; LVITEMW lvItem; @@ -3186,7 +3187,11 @@ /* now check if we need to update the focus rectangle */ lprcFocus = infoPtr->bFocus && (lvItem.state & LVIS_FOCUSED) ? &infoPtr->rcFocus : 0; - if (!LISTVIEW_GetItemMeasures(infoPtr, nItem, &rcBox, NULL, &rcIcon, &rcLabel)) return FALSE; + if (!LISTVIEW_GetItemMetrics(infoPtr, &lvItem, &rcBox, NULL, &rcState, &rcIcon, &rcLabel)) return FALSE; + OffsetRect(&rcBox, pos.x, pos.y); + OffsetRect(&rcState, pos.x, pos.y); + OffsetRect(&rcIcon, pos.x, pos.y); + OffsetRect(&rcLabel, pos.x, pos.y); customdraw_fill(&nmlvcd, infoPtr, hdc, &rcBox, &lvItem); if (cdmode & CDRF_NOTIFYITEMDRAW) @@ -3197,9 +3202,6 @@ if (infoPtr->himlState) { UINT uStateImage = (lvItem.state & LVIS_STATEIMAGEMASK) >> 12; - RECT rcState = rcBox; - - rcState.left += infoPtr->iconSize.cx * lvItem.iIndent; if (uStateImage) ImageList_Draw(infoPtr->himlState, uStateImage - 1, hdc, rcState.left, rcState.top, ILD_NORMAL); @@ -3242,17 +3244,18 @@ * [I] infoPtr : valid pointer to the listview structure * [I] hdc : device context handle * [I] nItem : item index + * [I] pos : item position in client coordinates * [I] cdmode : custom draw mode * * RETURN: * Success: TRUE * Failure: FALSE */ -static BOOL LISTVIEW_DrawLargeItem(LISTVIEW_INFO *infoPtr, HDC hdc, INT nItem, DWORD cdmode) +static BOOL LISTVIEW_DrawLargeItem(LISTVIEW_INFO *infoPtr, HDC hdc, INT nItem, POINT pos, DWORD cdmode) { WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' }; DWORD cditemmode = CDRF_DODEFAULT; - RECT rcBounds, rcIcon, rcLabel, *lprcFocus; + RECT rcBox, rcState, rcIcon, rcLabel, *lprcFocus; NMLVCUSTOMDRAW nmlvcd; LVITEMW lvItem; UINT uFormat; @@ -3271,10 +3274,15 @@ /* now check if we need to update the focus rectangle */ lprcFocus = infoPtr->bFocus && (lvItem.state & LVIS_FOCUSED) ? &infoPtr->rcFocus : 0; - - if (!LISTVIEW_GetItemMeasures(infoPtr, nItem, NULL, &rcBounds, &rcIcon, &rcLabel)) return FALSE; + + if (!lprcFocus) lvItem.state &= ~LVIS_FOCUSED; + if (!LISTVIEW_GetItemMetrics(infoPtr, &lvItem, &rcBox, NULL, &rcState, &rcIcon, &rcLabel)) return FALSE; + OffsetRect(&rcBox, pos.x, pos.y); + OffsetRect(&rcState, pos.x, pos.y); + OffsetRect(&rcIcon, pos.x, pos.y); + OffsetRect(&rcLabel, pos.x, pos.y); - customdraw_fill(&nmlvcd, infoPtr, hdc, &rcBounds, &lvItem); + customdraw_fill(&nmlvcd, infoPtr, hdc, &rcBox, &lvItem); if (cdmode & CDRF_NOTIFYITEMDRAW) cditemmode = notify_customdraw (infoPtr, CDDS_ITEMPREPAINT, &nmlvcd); if (cditemmode & CDRF_SKIPDEFAULT) goto postpaint; @@ -3286,10 +3294,8 @@ if (infoPtr->himlState) { UINT uStateImage = (lvItem.state & LVIS_STATEIMAGEMASK) >> 12; - INT x = rcIcon.left - infoPtr->iconStateSize.cx + 10; - INT y = rcIcon.top + infoPtr->iconSize.cy - infoPtr->iconStateSize.cy + 4; if (uStateImage > 0) - ImageList_Draw(infoPtr->himlState, uStateImage - 1, hdc, x, y, ILD_NORMAL); + ImageList_Draw(infoPtr->himlState, uStateImage - 1, hdc, rcState.left, rcState.top, ILD_NORMAL); } /* draw the icon */ @@ -3495,7 +3501,10 @@ if (rgntype == COMPLEXREGION && !RectVisible(hdc, &rcItem)) continue; if (j == 0) - LISTVIEW_DrawItem(infoPtr, hdc, i.nItem, cdmode); + { + POINT pos = { rcItem.left, rcItem.top }; + LISTVIEW_DrawItem(infoPtr, hdc, i.nItem, pos, cdmode); + } else LISTVIEW_DrawSubItem(infoPtr, hdc, i.nItem, j, rcItem, lpCols[j].align, cdmode); } @@ -3532,8 +3541,10 @@ while(iterator_next(&i)) { if (!LISTVIEW_GetItemListOrigin(infoPtr, i.nItem, &Position)) continue; + Position.x += Origin.x; + Position.y += Origin.y; - LISTVIEW_DrawItem(infoPtr, hdc, i.nItem, cdmode); + LISTVIEW_DrawItem(infoPtr, hdc, i.nItem, Position, cdmode); } iterator_destroy(&i); } @@ -3568,14 +3579,23 @@ continue; if (!LISTVIEW_GetItemListOrigin(infoPtr, i.nItem, &Position)) continue; - LISTVIEW_DrawLargeItem(infoPtr, hdc, i.nItem, cdmode); + Position.x += Origin.x; + Position.y += Origin.y; + LISTVIEW_DrawLargeItem(infoPtr, hdc, i.nItem, Position, cdmode); } iterator_destroy(&i); /* draw the focused item last, in case it's oversized */ if (LISTVIEW_GetItemMeasures(infoPtr, infoPtr->nFocusedItem, &rcBox, 0, 0, 0) && RectVisible(hdc, &rcBox)) - LISTVIEW_DrawLargeItem(infoPtr, hdc, infoPtr->nFocusedItem, cdmode); + { + if (LISTVIEW_GetItemListOrigin(infoPtr, infoPtr->nFocusedItem, &Position)) + { + Position.x += Origin.x; + Position.y += Origin.y; + LISTVIEW_DrawLargeItem(infoPtr, hdc, infoPtr->nFocusedItem, Position, cdmode); + } + } } /***