Nikolay Sivov : comctl32/listview: Improve hittesting a bit.

Alexandre Julliard julliard at winehq.org
Wed Jul 1 09:28:11 CDT 2009


Module: wine
Branch: master
Commit: 84f14a37164f5dd7e8ed7cb65321ac5aa7f9206d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=84f14a37164f5dd7e8ed7cb65321ac5aa7f9206d

Author: Nikolay Sivov <bunglehead at gmail.com>
Date:   Wed Jul  1 00:40:03 2009 +0400

comctl32/listview: Improve hittesting a bit.

---

 dlls/comctl32/listview.c       |   72 +++++++++++++++++++++------------------
 dlls/comctl32/tests/listview.c |   18 +++++++++-
 2 files changed, 55 insertions(+), 35 deletions(-)

diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 7099227..d7a5f97 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -6798,55 +6798,42 @@ static INT LISTVIEW_HitTest(const LISTVIEW_INFO *infoPtr, LPLVHITTESTINFO lpht,
     lpht->iItem = -1;
     if (subitem) lpht->iSubItem = 0;
 
-    if (infoPtr->rcList.left > lpht->pt.x)
-	lpht->flags |= LVHT_TOLEFT;
-    else if (infoPtr->rcList.right < lpht->pt.x)
-	lpht->flags |= LVHT_TORIGHT;
+    LISTVIEW_GetOrigin(infoPtr, &Origin);
+
+    /* set whole list relation flags */
+    if (subitem && infoPtr->uView == LV_VIEW_DETAILS)
+    {
+        /* LVM_SUBITEMHITTEST checks left bound of possible client area */
+        if (infoPtr->rcList.left > lpht->pt.x && Origin.x < lpht->pt.x)
+	    lpht->flags |= LVHT_TOLEFT;
+    }
+    else
+    {
+	if (infoPtr->rcList.left > lpht->pt.x)
+	    lpht->flags |= LVHT_TOLEFT;
+	else if (infoPtr->rcList.right < lpht->pt.x)
+	    lpht->flags |= LVHT_TORIGHT;
+    }
     
     if (infoPtr->rcList.top > lpht->pt.y)
 	lpht->flags |= LVHT_ABOVE;
     else if (infoPtr->rcList.bottom < lpht->pt.y)
 	lpht->flags |= LVHT_BELOW;
 
-    TRACE("lpht->flags=0x%x\n", lpht->flags);
-    if (lpht->flags) return -1;
-
-    lpht->flags |= LVHT_NOWHERE;
-
-    LISTVIEW_GetOrigin(infoPtr, &Origin);
-   
-    /* first deal with the large items */
-    rcSearch.left = lpht->pt.x;
-    rcSearch.top = lpht->pt.y;
-    rcSearch.right = rcSearch.left + 1;
-    rcSearch.bottom = rcSearch.top + 1;
-    
-    iterator_frameditems(&i, infoPtr, &rcSearch);
-    iterator_next(&i); /* go to first item in the sequence */
-    iItem = i.nItem;
-    iterator_destroy(&i);
-   
-    TRACE("lpht->iItem=%d\n", iItem); 
-    if (iItem == -1) return -1;
-
+    /* even if item is invalid try to find subitem */
     if (infoPtr->uView == LV_VIEW_DETAILS && subitem)
     {
-	RECT  bounds, *pRect;
+	RECT *pRect;
 	INT j;
 
-	/* for top/bottom only */
-	bounds.left = LVIR_BOUNDS;
-	LISTVIEW_GetItemRect(infoPtr, iItem, &bounds);
 	opt.x = lpht->pt.x - Origin.x;
-	opt.y = lpht->pt.y;
 
+	lpht->iSubItem = -1;
 	for (j = 0; j < DPA_GetPtrCount(infoPtr->hdpaColumns); j++)
 	{
 	    pRect = &LISTVIEW_GetColumnInfo(infoPtr, j)->rcHeader;
-	    bounds.left  = pRect->left;
-	    bounds.right = pRect->right;
 
-	    if (PtInRect(&bounds, opt))
+	    if ((opt.x >= pRect->left) && (opt.x < pRect->right))
 	    {
 		lpht->iSubItem = j;
 		break;
@@ -6855,6 +6842,25 @@ static INT LISTVIEW_HitTest(const LISTVIEW_INFO *infoPtr, LPLVHITTESTINFO lpht,
 	TRACE("lpht->iSubItem=%d\n", lpht->iSubItem);
     }
 
+    TRACE("lpht->flags=0x%x\n", lpht->flags);
+    if (lpht->flags) return -1;
+
+    lpht->flags |= LVHT_NOWHERE;
+
+    /* first deal with the large items */
+    rcSearch.left = lpht->pt.x;
+    rcSearch.top = lpht->pt.y;
+    rcSearch.right = rcSearch.left + 1;
+    rcSearch.bottom = rcSearch.top + 1;
+
+    iterator_frameditems(&i, infoPtr, &rcSearch);
+    iterator_next(&i); /* go to first item in the sequence */
+    iItem = i.nItem;
+    iterator_destroy(&i);
+
+    TRACE("lpht->iItem=%d\n", iItem);
+    if (iItem == -1) return -1;
+
     lvItem.mask = LVIF_STATE | LVIF_TEXT;
     if (infoPtr->uView == LV_VIEW_DETAILS) lvItem.mask |= LVIF_INDENT;
     lvItem.stateMask = LVIS_STATEIMAGEMASK;
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
index 38155b1..d11d9de 100644
--- a/dlls/comctl32/tests/listview.c
+++ b/dlls/comctl32/tests/listview.c
@@ -2684,7 +2684,16 @@ static void test_hittest(void)
     x = pos.x + 150; /* outside column */
     y = pos.y + (bounds.bottom - bounds.top) / 2;
     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, FALSE, __LINE__);
-    test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, TRUE, TRUE, TRUE, __LINE__);
+    test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
+    /* outside possible client rectangle (to right) */
+    x = pos.x + 500;
+    y = pos.y + (bounds.bottom - bounds.top) / 2;
+    test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, FALSE, __LINE__);
+    test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
+    /* subitem returned with -1 item too */
+    x = pos.x + 150;
+    y = -10;
+    test_lvm_subitemhittest(hwnd, x, y, -1, 1, LVHT_NOWHERE, FALSE, FALSE, TRUE, __LINE__);
     /* parent client area is 100x100 by default */
     MoveWindow(hwnd, 0, 0, 300, 100, FALSE);
     x = pos.x + 150; /* outside column */
@@ -2701,7 +2710,12 @@ static void test_hittest(void)
     x = pos.x + 150; /* outside column */
     y = pos.y + (bounds.bottom - bounds.top) / 2;
     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, FALSE, __LINE__);
-    test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, TRUE, TRUE, TRUE, __LINE__);
+    test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
+    /* outside possible client rectangle (to right) */
+    x = pos.x + 500;
+    y = pos.y + (bounds.bottom - bounds.top) / 2;
+    test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, FALSE, __LINE__);
+    test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
     /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
     himl = ImageList_Create(16, 16, 0, 4, 4);
     ok(himl != NULL, "failed to create imagelist\n");




More information about the wine-cvs mailing list