diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c index 7099227017d..d7a5f97ee33 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 38155b16b7a..d11d9deef24 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");