On March 22, 2003 04:21 pm, Vitaliy Margolen wrote: > List view should sent LVN_ODCACHEHINT notification before paint when it's > virtual list (LVS_OWNERDATA style). We were sending it only in OwnerDraw. Indeed. Thanks for the patch. I suggest a slightly different patch, that cleansup the duplication. Does this work for you? ChangeLog Send LVN_ODCACHEHINT notification for LVS_OWNERDATA style in all modes (based on a patch by Vitaliy Margolen). Index: dlls/comctl32/listview.c =================================================================== RCS file: /var/cvs/wine/dlls/comctl32/listview.c,v retrieving revision 1.345 diff -u -r1.345 listview.c --- dlls/comctl32/listview.c 15 Mar 2003 00:05:46 -0000 1.345 +++ dlls/comctl32/listview.c 23 Mar 2003 16:54:05 -0000 @@ -3618,14 +3618,13 @@ * RETURN: * None */ -static void LISTVIEW_RefreshOwnerDraw(LISTVIEW_INFO *infoPtr, HDC hdc) +static void LISTVIEW_RefreshOwnerDraw(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc) { UINT uID = GetWindowLongW(infoPtr->hwndSelf, GWL_ID); HWND hwndParent = GetParent(infoPtr->hwndSelf); POINT Origin, Position; DRAWITEMSTRUCT dis; LVITEMW item; - ITERATOR i; TRACE("()\n"); @@ -3633,26 +3632,11 @@ /* Get scroll info once before loop */ LISTVIEW_GetOrigin(infoPtr, &Origin); - - /* figure out what we need to draw */ - iterator_visibleitems(&i, infoPtr, hdc); - /* send cache hint notification */ - if (infoPtr->dwStyle & LVS_OWNERDATA) - { - RANGE range = iterator_range(&i); - NMLVCACHEHINT nmlv; - - ZeroMemory(&nmlv, sizeof(NMLVCACHEHINT)); - nmlv.iFrom = range.lower; - nmlv.iTo = range.upper - 1; - notify_hdr(infoPtr, LVN_ODCACHEHINT, &nmlv.hdr); - } - /* iterate through the invalidated rows */ - while(iterator_next(&i)) + while(iterator_next(i)) { - item.iItem = i.nItem; + item.iItem = i->nItem; item.iSubItem = 0; item.mask = LVIF_PARAM | LVIF_STATE; item.stateMask = LVIS_SELECTED | LVIS_FOCUSED; @@ -3677,7 +3661,6 @@ TRACE("item=%s, rcItem=%s\n", debuglvitem_t(&item, TRUE), debugrect(&dis.rcItem)); SendMessageW(hwndParent, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis); } - iterator_destroy(&i); } /*** @@ -3692,13 +3675,13 @@ * RETURN: * None */ -static void LISTVIEW_RefreshReport(LISTVIEW_INFO *infoPtr, HDC hdc, DWORD cdmode) +static void LISTVIEW_RefreshReport(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc, DWORD cdmode) { INT rgntype; RECT rcClip, rcItem; POINT Origin, Position; RANGE colRange; - ITERATOR i, j; + ITERATOR j; TRACE("()\n"); @@ -3726,16 +3709,13 @@ if (infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT) j.nSpecial = 0; - /* figure out what we need to draw */ - iterator_visibleitems(&i, infoPtr, hdc); - /* iterate through the invalidated rows */ - while(iterator_next(&i)) + while(iterator_next(i)) { /* iterate through the invalidated columns */ while(iterator_next(&j)) { - LISTVIEW_GetItemOrigin(infoPtr, i.nItem, &Position); + LISTVIEW_GetItemOrigin(infoPtr, i->nItem, &Position); Position.x += Origin.x; Position.y += Origin.y; @@ -3748,10 +3728,10 @@ if (!RectVisible(hdc, &rcItem)) continue; } - LISTVIEW_DrawItem(infoPtr, hdc, i.nItem, j.nItem, Position, cdmode); + LISTVIEW_DrawItem(infoPtr, hdc, i->nItem, j.nItem, Position, cdmode); } } - iterator_destroy(&i); + iterator_destroy(&j); } /*** @@ -3766,26 +3746,21 @@ * RETURN: * None */ -static void LISTVIEW_RefreshList(LISTVIEW_INFO *infoPtr, HDC hdc, DWORD cdmode) +static void LISTVIEW_RefreshList(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc, DWORD cdmode) { POINT Origin, Position; - ITERATOR i; /* Get scroll info once before loop */ LISTVIEW_GetOrigin(infoPtr, &Origin); - /* figure out what we need to draw */ - iterator_visibleitems(&i, infoPtr, hdc); - - while(iterator_prev(&i)) + while(iterator_prev(i)) { - LISTVIEW_GetItemOrigin(infoPtr, i.nItem, &Position); + LISTVIEW_GetItemOrigin(infoPtr, i->nItem, &Position); Position.x += Origin.x; Position.y += Origin.y; - LISTVIEW_DrawItem(infoPtr, hdc, i.nItem, 0, Position, cdmode); + LISTVIEW_DrawItem(infoPtr, hdc, i->nItem, 0, Position, cdmode); } - iterator_destroy(&i); } @@ -3809,6 +3784,7 @@ DWORD cdmode; INT oldBkMode; RECT rcClient; + ITERATOR i; LISTVIEW_DUMP(infoPtr); @@ -3835,19 +3811,35 @@ /* nothing to draw */ if(infoPtr->nItemCount == 0) goto enddraw; + /* figure out what we need to draw */ + iterator_visibleitems(&i, infoPtr, hdc); + + /* send cache hint notification */ + if (infoPtr->dwStyle & LVS_OWNERDATA) + { + RANGE range = iterator_range(&i); + NMLVCACHEHINT nmlv; + + ZeroMemory(&nmlv, sizeof(NMLVCACHEHINT)); + nmlv.iFrom = range.lower; + nmlv.iTo = range.upper - 1; + notify_hdr(infoPtr, LVN_ODCACHEHINT, &nmlv.hdr); + } + if ((infoPtr->dwStyle & LVS_OWNERDRAWFIXED) && (uView == LVS_REPORT)) - LISTVIEW_RefreshOwnerDraw(infoPtr, hdc); + LISTVIEW_RefreshOwnerDraw(infoPtr, &i, hdc); else { if (uView == LVS_REPORT) - LISTVIEW_RefreshReport(infoPtr, hdc, cdmode); + LISTVIEW_RefreshReport(infoPtr, &i, hdc, cdmode); else /* LVS_LIST, LVS_ICON or LVS_SMALLICON */ - LISTVIEW_RefreshList(infoPtr, hdc, cdmode); + LISTVIEW_RefreshList(infoPtr, &i, hdc, cdmode); /* if we have a focus rect, draw it */ if (infoPtr->bFocus) DrawFocusRect(hdc, &infoPtr->rcFocus); } + iterator_destroy(&i); enddraw: if (cdmode & CDRF_NOTIFYPOSTPAINT) -- Dimi.