comctl32: listview: compute the state icon rect in GetItemMetrics (fixes bug #7527)

Mikołaj Zalewski mikolaj at zalewski.pl
Tue Mar 13 12:47:37 CDT 2007


A recent patch changed the GetItemMetrics. After it the state icon rect 
is computed by moving the icon rect. This works fine if the icon and 
state icon are of the same size but fails if e.g. there is no icon. My 
patch adds a separate rect for the state icon in GetItemMetrics and 
computes it's corner by moving the icons corner but then uses the 
correct height and width. I'm not sure if this is correct for large icon 
style (I'd expect the state icon to be centered verticaly) but it works 
fine for the most common case of LVS_REPORT or LVS_SMALLICON with 
checkboxes. I'd also expect this is what the previous patch intended to do.
-------------- next part --------------
From cd2bfd9830480989b74016385e5c38a17cb99db1 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Miko=C5=82aj_Zalewski?= <mikolaj at zalewski.pl>
Date: Mon, 12 Mar 2007 22:39:59 +0100
Subject: [PATCH] comctl32: listview: compute the state icon rect in GetItemMetrics

---
 dlls/comctl32/listview.c |   50 ++++++++++++++++++++++++++-------------------
 1 files changed, 29 insertions(+), 21 deletions(-)

diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 113845d..c07cd2b 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -1886,10 +1886,11 @@ static void LISTVIEW_GetItemOrigin(LISTVIEW_INFO *infoPtr, INT nItem, LPPOINT lp
  * [I] lpLVItem : item to compute the measures for
  * [O] lprcBox : ptr to Box rectangle
  *                Same as LVM_GETITEMRECT with LVIR_BOUNDS
- * [0] lprcSelectBox : ptr to State icon rectangle
+ * [0] lprcSelectBox : ptr to select box rectangle
  *  		  Same as LVM_GETITEMRECT with LVIR_SELECTEDBOUNDS
  * [O] lprcIcon : ptr to Icon rectangle
  *                Same as LVM_GETITEMRECT with LVIR_ICON
+ * [O] lprcStateIcon: ptr to State Icon rectangle
  * [O] lprcLabel : ptr to Label rectangle
  *                Same as LVM_GETITEMRECT with LVIR_LABEL
  *
@@ -1898,7 +1899,7 @@ static void LISTVIEW_GetItemOrigin(LISTVIEW_INFO *infoPtr, INT nItem, LPPOINT lp
  */
 static void LISTVIEW_GetItemMetrics(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem,
 				    LPRECT lprcBox, LPRECT lprcSelectBox,
-				    LPRECT lprcIcon, LPRECT lprcLabel)
+				    LPRECT lprcIcon, LPRECT lprcStateIcon, LPRECT lprcLabel)
 {
     UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
     BOOL doSelectBox = FALSE, doIcon = FALSE, doLabel = FALSE, oversizedBox = FALSE;
@@ -1917,7 +1918,7 @@ static void LISTVIEW_GetItemMetrics(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVI
     }
     if (lprcSelectBox) doSelectBox = TRUE;
     if (lprcLabel) doLabel = TRUE;
-    if (doLabel || lprcIcon) doIcon = TRUE;
+    if (doLabel || lprcIcon || lprcStateIcon) doIcon = TRUE;
     if (doSelectBox)
     {
         doIcon = TRUE;
@@ -1942,9 +1943,9 @@ static void LISTVIEW_GetItemMetrics(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVI
     Box.top = 0;
     Box.bottom = infoPtr->nItemHeight;
 
-    /************************************************************/
-    /* compute ICON bounding box (ala LVM_GETITEMRECT)          */
-    /************************************************************/
+    /******************************************************************/
+    /* compute ICON bounding box (ala LVM_GETITEMRECT) and STATEICON  */
+    /******************************************************************/
     if (doIcon)
     {
 	LONG state_width = 0;
@@ -1983,6 +1984,16 @@ static void LISTVIEW_GetItemMetrics(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVI
 	}
 	if(lprcIcon) *lprcIcon = Icon;
 	TRACE("    - icon=%s\n", wine_dbgstr_rect(&Icon));
+
+        /* TODO: is this correct? */
+        if (lprcStateIcon)
+        {
+            lprcStateIcon->left = Icon.left - state_width;
+            lprcStateIcon->right = Icon.left;
+            lprcStateIcon->top = Icon.top;
+            lprcStateIcon->bottom = lprcStateIcon->top + infoPtr->iconSize.cy;
+            TRACE("    - state icon=%s\n", wine_dbgstr_rect(lprcStateIcon));
+        }
      }
      else Icon.right = 0;
 
@@ -2144,7 +2155,7 @@ static void LISTVIEW_GetItemBox(LISTVIEW_INFO *infoPtr, INT nItem, LPRECT lprcBo
 	lvItem.stateMask = LVIS_FOCUSED;
 	lvItem.state = (lvItem.mask & LVIF_TEXT ? LVIS_FOCUSED : 0);
     }
-    LISTVIEW_GetItemMetrics(infoPtr, &lvItem, lprcBox, 0, 0, 0);
+    LISTVIEW_GetItemMetrics(infoPtr, &lvItem, lprcBox, 0, 0, 0, 0);
 
     OffsetRect(lprcBox, Position.x + Origin.x, Position.y + Origin.y);
 }
@@ -3714,7 +3725,7 @@ static BOOL LISTVIEW_DrawItem(LISTVIEW_INFO *infoPtr, HDC hdc, INT nItem, INT nS
     WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' };
     static const WCHAR szCallback[] = { '(', 'c', 'a', 'l', 'l', 'b', 'a', 'c', 'k', ')', 0 };
     DWORD cdsubitemmode = CDRF_DODEFAULT;
-    RECT* lprcFocus, rcSelect, rcBox, rcIcon, rcLabel;
+    RECT *lprcFocus, rcSelect, rcBox, rcIcon, rcLabel, rcStateIcon;
     NMLVCUSTOMDRAW nmlvcd;
     HIMAGELIST himl;
     LVITEMW lvItem;
@@ -3743,10 +3754,11 @@ static BOOL LISTVIEW_DrawItem(LISTVIEW_INFO *infoPtr, HDC hdc, INT nItem, INT nS
     lprcFocus = infoPtr->bFocus && (lvItem.state & LVIS_FOCUSED) ? &infoPtr->rcFocus : 0;
 
     if (!lprcFocus) lvItem.state &= ~LVIS_FOCUSED;
-    LISTVIEW_GetItemMetrics(infoPtr, &lvItem, &rcBox, &rcSelect, &rcIcon, &rcLabel);
+    LISTVIEW_GetItemMetrics(infoPtr, &lvItem, &rcBox, &rcSelect, &rcIcon, &rcStateIcon, &rcLabel);
     OffsetRect(&rcBox, pos.x, pos.y);
     OffsetRect(&rcSelect, pos.x, pos.y);
     OffsetRect(&rcIcon, pos.x, pos.y);
+    OffsetRect(&rcStateIcon, pos.x, pos.y);
     OffsetRect(&rcLabel, pos.x, pos.y);
     TRACE("    rcBox=%s, rcSelect=%s, rcIcon=%s. rcLabel=%s\n",
         wine_dbgstr_rect(&rcBox), wine_dbgstr_rect(&rcSelect),
@@ -3783,8 +3795,7 @@ static BOOL LISTVIEW_DrawItem(LISTVIEW_INFO *infoPtr, HDC hdc, INT nItem, INT nS
 	{
 	     TRACE("uStateImage=%d\n", uStateImage);
 	     ImageList_Draw(infoPtr->himlState, uStateImage - 1, hdc,
-	         rcIcon.left - infoPtr->iconStateSize.cx,
-	         rcIcon.top, ILD_NORMAL);
+	         rcStateIcon.left, rcStateIcon.top, ILD_NORMAL);
 	}
     }
 
@@ -5645,19 +5656,19 @@ static BOOL LISTVIEW_GetItemRect(LISTVIEW_INFO *infoPtr, INT nItem, LPRECT lprc)
     switch(lprc->left)
     {
     case LVIR_ICON:
-	LISTVIEW_GetItemMetrics(infoPtr, &lvItem, NULL, NULL, lprc, NULL);
+	LISTVIEW_GetItemMetrics(infoPtr, &lvItem, NULL, NULL, lprc, NULL, NULL);
         break;
 
     case LVIR_LABEL:
-	LISTVIEW_GetItemMetrics(infoPtr, &lvItem, NULL, NULL, NULL, lprc);
+	LISTVIEW_GetItemMetrics(infoPtr, &lvItem, NULL, NULL, NULL, NULL, lprc);
         break;
 
     case LVIR_BOUNDS:
-	LISTVIEW_GetItemMetrics(infoPtr, &lvItem, lprc, NULL, NULL, NULL);
+	LISTVIEW_GetItemMetrics(infoPtr, &lvItem, lprc, NULL, NULL, NULL, NULL);
         break;
 
     case LVIR_SELECTBOUNDS:
-	LISTVIEW_GetItemMetrics(infoPtr, &lvItem, NULL, lprc, NULL, NULL);
+	LISTVIEW_GetItemMetrics(infoPtr, &lvItem, NULL, lprc, NULL, NULL, NULL);
         break;
 
     default:
@@ -5719,12 +5730,12 @@ static BOOL LISTVIEW_GetSubItemRect(LISTVIEW_INFO *infoPtr, INT nItem, LPRECT lp
     switch(lprc->left)
     {
     case LVIR_ICON:
-	LISTVIEW_GetItemMetrics(infoPtr, &lvItem, NULL, NULL, lprc, NULL);
+	LISTVIEW_GetItemMetrics(infoPtr, &lvItem, NULL, NULL, lprc, NULL, NULL);
         break;
 
     case LVIR_LABEL:
     case LVIR_BOUNDS:
-	LISTVIEW_GetItemMetrics(infoPtr, &lvItem, lprc, NULL, NULL, NULL);
+	LISTVIEW_GetItemMetrics(infoPtr, &lvItem, lprc, NULL, NULL, NULL, NULL);
         break;
 
     default:
@@ -6203,7 +6214,7 @@ static INT LISTVIEW_HitTest(LISTVIEW_INFO *infoPtr, LPLVHITTESTINFO lpht, BOOL s
     if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return -1;
     if (!infoPtr->bFocus) lvItem.state &= ~LVIS_FOCUSED;
 
-    LISTVIEW_GetItemMetrics(infoPtr, &lvItem, &rcBox, NULL, &rcIcon, &rcLabel);
+    LISTVIEW_GetItemMetrics(infoPtr, &lvItem, &rcBox, NULL, &rcIcon, &rcState, &rcLabel);
     LISTVIEW_GetItemOrigin(infoPtr, iItem, &Position);
     opt.x = lpht->pt.x - Position.x - Origin.x;
     opt.y = lpht->pt.y - Position.y - Origin.y;
@@ -6215,9 +6226,6 @@ static INT LISTVIEW_HitTest(LISTVIEW_INFO *infoPtr, LPLVHITTESTINFO lpht, BOOL s
     TRACE("rcBounds=%s\n", wine_dbgstr_rect(&rcBounds));
     if (!PtInRect(&rcBounds, opt)) return -1;
 
-    rcState = rcIcon;
-    OffsetRect(&rcState, -infoPtr->iconStateSize.cx, 0);
-
     if (PtInRect(&rcIcon, opt))
 	lpht->flags |= LVHT_ONITEMICON;
     else if (PtInRect(&rcLabel, opt))
-- 
1.4.4.2


More information about the wine-patches mailing list