These fixes make WinMX (my favorite windows fileshareing program) behave. The problem was that the program called SetItemState during the Custom Draw phase of items. SetItemState results in an Invalidate Rect which causes an Infinite redraw loop. So do not invalidate the rect while drawing. Additionally implement GetSubItemRect and a quick change to notifications sent for OwnerData items. -aric
Index: dlls/comctl32/listview.c =================================================================== RCS file: /home/wine/wine/dlls/comctl32/listview.c,v retrieving revision 1.126 diff -w -u -r1.126 listview.c --- dlls/comctl32/listview.c 11 Apr 2002 17:31:45 -0000 1.126 +++ dlls/comctl32/listview.c 13 May 2002 01:45:43 -0000 @@ -158,6 +158,7 @@ WPARAM charCode; /* Added */ INT nSearchParamLength; /* Added */ WCHAR szSearchParam[ MAX_PATH ]; /* Added */ + BOOL bIsDrawing; } LISTVIEW_INFO; /* @@ -236,6 +237,7 @@ static BOOL LISTVIEW_GetItemBoundBox(HWND, INT, LPRECT); static BOOL LISTVIEW_GetItemPosition(HWND, INT, LPPOINT); static LRESULT LISTVIEW_GetItemRect(HWND, INT, LPRECT); +static LRESULT LISTVIEW_GetSubItemRect(HWND, INT, INT, INT, LPRECT); static INT LISTVIEW_GetItemWidth(HWND); static INT LISTVIEW_GetLabelWidth(HWND, INT); static LRESULT LISTVIEW_GetOrigin(HWND, LPPOINT); @@ -2746,9 +2748,10 @@ if ((itm.state & lpLVItem->stateMask) != (lpLVItem->state & lpLVItem->stateMask)) { - /* send LVN_ITEMCHANGING notification */ - if (!listview_notify(hwnd, LVN_ITEMCHANGING, &nmlv)) - { + /* + * As per MSDN LVN_ITEMCHANGING notifications are _NOT_ sent + * by LVS_OWERNDATA list controls + */ if (lpLVItem->stateMask & LVIS_FOCUSED) { if (lpLVItem->state & LVIS_FOCUSED) @@ -2772,9 +2775,9 @@ rcItem.left = LVIR_BOUNDS; LISTVIEW_GetItemRect(hwnd, lpLVItem->iItem, &rcItem); + if (!infoPtr->bIsDrawing) InvalidateRect(hwnd, &rcItem, TRUE); } - } return TRUE; } return FALSE; @@ -2863,6 +2866,7 @@ { rcItem.left = LVIR_BOUNDS; LISTVIEW_GetItemRect(hwnd, lpLVItem->iItem, &rcItem); + if (!infoPtr->bIsDrawing) InvalidateRect(hwnd, &rcItem, TRUE); } } @@ -3910,6 +3914,7 @@ DWORD cdmode; RECT rect; + infoPtr->bIsDrawing = TRUE; LISTVIEW_DumpListview (infoPtr, __LINE__); GetClientRect(hwnd, &rect); @@ -3945,6 +3950,8 @@ if (cdmode & CDRF_NOTIFYPOSTPAINT) LISTVIEW_SendCustomDrawNotify(hwnd, CDDS_POSTPAINT, hdc, rect); + + infoPtr->bIsDrawing = FALSE; } @@ -6050,6 +6057,42 @@ return bResult; } + +static LRESULT LISTVIEW_GetSubItemRect(HWND hwnd, INT nItem, INT nSubItem, INT +flags, LPRECT lprc) +{ + UINT uView = GetWindowLongW(hwnd, GWL_STYLE) & LVS_TYPEMASK; + INT count; + + TRACE("(hwnd=%x, nItem=%d, nSubItem=%d lprc=%p)\n", hwnd, nItem, nSubItem, + lprc); + + if (!(uView & LVS_REPORT)) + return FALSE; + + if (flags & LVIR_ICON) + { + FIXME("Unimplemented LVIR_ICON\n"); + return FALSE; + } + else + { + LISTVIEW_GetItemRect(hwnd,nItem,lprc); + count = 0; + while (count<(nSubItem-1)) + { + lprc->left += LISTVIEW_GetColumnWidth(hwnd,count); + count ++; + } + + lprc->right = LISTVIEW_GetColumnWidth(hwnd,(nSubItem-1)) + + lprc->left; + + } + return TRUE; +} + + /*** * DESCRIPTION: * Retrieves the width of a label. @@ -8000,6 +8043,7 @@ infoPtr->hwndEdit = 0; infoPtr->pedititem = NULL; infoPtr->nEditLabelItem = -1; + infoPtr->bIsDrawing = FALSE; /* get default font (icon title) */ SystemParametersInfoW(SPI_GETICONTITLELOGFONT, 0, &logFont, 0); @@ -9469,8 +9513,8 @@ return LISTVIEW_GetStringWidthT(hwnd, (LPCWSTR)lParam, TRUE); case LVM_GETSUBITEMRECT: - FIXME("LVM_GETSUBITEMRECT: unimplemented\n"); - return FALSE; + return LISTVIEW_GetSubItemRect(hwnd, (UINT)wParam, ((LPRECT)lParam)->top, + ((LPRECT)lParam)->left, (LPRECT)lParam); case LVM_GETTEXTBKCOLOR: return LISTVIEW_GetTextBkColor(hwnd);