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