Listview K3

Dimitrie O. Paun dpaun at rogers.com
Thu Oct 3 23:41:41 CDT 2002


ChangeLog
  Fix large item focus handling for virtual listviews.
  Since at most _one_ item can have the focus at any time,
  we can maintain one such rectangle per list, rather than
  per item. This is both more efficient, and works for
  LVS_OWNERDATA listviews as well.

--- dlls/comctl32/listview.c.K2	Thu Oct  3 23:51:46 2002
+++ dlls/comctl32/listview.c	Fri Oct  4 00:22:58 2002
@@ -102,7 +102,6 @@
   INT iIndent;
   POINT ptPosition;
   BOOL valid;
-  RECT rcLastDraw;
 } LISTVIEW_ITEM;
 
 typedef struct tagRANGE
@@ -151,6 +150,7 @@
   BOOL bFocus;
   INT nFocusedItem;
   RECT rcFocus;
+  RECT rcLargeFocus;            /* non-empty when a large item in ICON mode has focus */
   DWORD dwStyle;		/* the cached window GWL_STYLE */
   DWORD dwLvExStyle;		/* extended listview style */
   HDPA hdpaItems;
@@ -2454,80 +2454,6 @@
 }
 
 
- /***
-  * DESCRIPTION:          [INTERNAL]
-  * Sets rectangle that the item was last drawn at.
-  *
-  * PARAMETER(S):
-  * [I] HWND : window handle
-  * [I] INT : item index
-  * [I] LPRECT : coordinate information
-  *
-  * RETURN:
-  *   SUCCESS : TRUE
-  *   FAILURE : FALSE
-  */
-static BOOL LISTVIEW_SetItemDrawRect(LISTVIEW_INFO *infoPtr, INT nItem, LPRECT lpRect)
-{
-  BOOL bResult = FALSE;
-  HDPA hdpaSubItems;
-  LISTVIEW_ITEM *lpItem;
-
-  TRACE("(hwnd=%x,nItem=%d,rect=(%d,%d)-(%d,%d))\n",
-	infoPtr->hwndSelf, nItem,
-	lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
-
-  if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lpRect != NULL))
-  {
-    if ((hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem)))
-    {
-      if ((lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0)))
-      {
-        bResult = TRUE;
-        lpItem->rcLastDraw = *lpRect;
-      }
-    }
-  }
-  return bResult;
-}
-
- /***
-  * DESCRIPTION:          [INTERNAL]
-  * Gets rectangle that the item was last drawn at.
-  *
-  * PARAMETER(S):
-  * [I] HWND : window handle
-  * [I] INT : item index
-  * [O] LPRECT : coordinate information
-  *
-  * RETURN:
-  *   SUCCESS : TRUE
-  *   FAILURE : FALSE
-  */
-static BOOL LISTVIEW_GetItemDrawRect(LISTVIEW_INFO *infoPtr, INT nItem, LPRECT lpRect)
-{
-  BOOL bResult = FALSE;
-  HDPA hdpaSubItems;
-  LISTVIEW_ITEM *lpItem;
-
-  if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lpRect != NULL))
-  {
-    if ((hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem)))
-    {
-      if ((lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0)))
-      {
-        bResult = TRUE;
-        if (lpRect) *lpRect = lpItem->rcLastDraw;
-	TRACE("(hwnd=%x,nItem=%d,rect=(%d,%d)-(%d,%d))\n",
-	      infoPtr->hwndSelf, nItem,
-	      lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
-      }
-    }
-  }
-  return bResult;
-}
-
-
 /***
  * Tests wheather the item is assignable to a list with style lStyle 
  */
@@ -2827,30 +2753,18 @@
     /* redraw item, if necessary */
     if (bResult && !infoPtr->bIsDrawing)
     {
-	RECT rcOldItem={0,0,0,0};
-
 	if (oldFocus != infoPtr->nFocusedItem && infoPtr->bFocus)
-	    LISTVIEW_ToggleFocusRect(infoPtr);
-
-	/* Note that ->rcLastDraw is normally all zero, so
-	 * no second InvalidateRect is issued.
-	 *
-	 * However, when a large icon style is drawn (LVS_ICON),
-	 * the rectangle drawn is saved in rcLastDraw. That way
-	 * the InvalidateRect will invalidate the entire area drawn
-	 *
-	 * FIXME: this is not right. We have already a ton of rects,
-	 *        we have two functions to get to them (GetItemRect,
-	 *        and GetItemMeasurements), and we introduce yet
-	 *        another rectangle with setter/getter functions!!!
-	 *        This is too much. Besides, this does not work
-	 *        correctly for owner drawn control...
-	 */
-	if ((oldFocus >= 0) && (oldFocus < GETITEMCOUNT(infoPtr)))
 	{
-	    LISTVIEW_GetItemDrawRect(infoPtr, oldFocus, &rcOldItem);
-	    if(!IsRectEmpty(&rcOldItem))
-		LISTVIEW_InvalidateRect(infoPtr, &rcOldItem);
+	    LISTVIEW_ToggleFocusRect(infoPtr);
+	    /* Note that ->rcLargeFocus is normally all zero, so
+	     * no second InvalidateRect is issued.
+	     *
+	     * However, when a large icon style is drawn (LVS_ICON),
+	     * the rectangle drawn is saved in rcLastDraw. That way
+	     * the InvalidateRect will invalidate the entire area drawn
+	     */
+	   if (!IsRectEmpty(&infoPtr->rcLargeFocus))
+		LISTVIEW_InvalidateRect(infoPtr, &infoPtr->rcLargeFocus);
 	}
 	LISTVIEW_InvalidateItem(infoPtr, lpLVItem->iItem);
     }
@@ -3266,6 +3180,7 @@
    * that the background is complete
    */
   rcFocus = rcLabel;  /* save for focus */
+  SetRectEmpty(&infoPtr->rcLargeFocus);
   if ((uFormat & DT_NOCLIP) || (lvItem.state & LVIS_SELECTED))
   {
       /* FIXME: why do we need this??? */
@@ -3276,7 +3191,7 @@
       DeleteObject(hBrush);
 
       /* Save size of item drawing for next InvalidateRect */
-      LISTVIEW_SetItemDrawRect(infoPtr, nItem, &rcFullText);
+      infoPtr->rcLargeFocus = rcFullText;
       TRACE("focused/selected, rcFocus=%s\n", debugrect(&rcFocus));
   }
   /* else ? What if we are losing the focus? will we not get a complete




More information about the wine-patches mailing list