From 2c7435a469f66bffc0d164ec0383be8d28982afe Mon Sep 17 00:00:00 2001 From: Catalin Date: Tue, 28 Feb 2017 16:03:49 +0200 Subject: [PATCH] Fix wxListCtrl::HitTest() --- src/msw/listctrl.cpp | 70 ++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp index 54bbef9225..62ad1af893 100644 --- a/src/msw/listctrl.cpp +++ b/src/msw/listctrl.cpp @@ -1780,35 +1780,53 @@ wxListCtrl::HitTest(const wxPoint& point, int& flags, long *ptrSubItem) const flags = 0; - if ( hitTestInfo.flags & LVHT_ABOVE ) - flags |= wxLIST_HITTEST_ABOVE; - if ( hitTestInfo.flags & LVHT_BELOW ) - flags |= wxLIST_HITTEST_BELOW; - if ( hitTestInfo.flags & LVHT_TOLEFT ) - flags |= wxLIST_HITTEST_TOLEFT; - if ( hitTestInfo.flags & LVHT_TORIGHT ) - flags |= wxLIST_HITTEST_TORIGHT; - - if ( hitTestInfo.flags & LVHT_NOWHERE ) - flags |= wxLIST_HITTEST_NOWHERE; - - // note a bug or at least a very strange feature of comtl32.dll (tested - // with version 4.0 under Win95 and 6.0 under Win 2003): if you click to - // the right of the item label, ListView_HitTest() returns a combination of - // LVHT_ONITEMICON, LVHT_ONITEMLABEL and LVHT_ONITEMSTATEICON -- filter out - // the bits which don't make sense - if ( hitTestInfo.flags & LVHT_ONITEMLABEL ) + // test whether an actual item was hit or not + if ( hitTestInfo.flags == LVHT_ONITEMICON ) { - flags |= wxLIST_HITTEST_ONITEMLABEL; - - // do not translate LVHT_ONITEMICON here, as per above + flags = wxLIST_HITTEST_ONITEMICON; } - else + // note a bug in comctl32.dll: + // 1) in report mode, when there are 2 or more columns, if you click to the + // right of the first column, ListView_HitTest() returns LVHT_ONITEM + // (LVHT_ONITEMICON|LVHT_ONITEMLABEL|LVHT_ONITEMSTATEICON). + else if ( hitTestInfo.flags & LVHT_ONITEMLABEL ) { - if ( hitTestInfo.flags & LVHT_ONITEMICON ) - flags |= wxLIST_HITTEST_ONITEMICON; - if ( hitTestInfo.flags & LVHT_ONITEMSTATEICON ) - flags |= wxLIST_HITTEST_ONITEMSTATEICON; + flags = wxLIST_HITTEST_ONITEMLABEL; + } + // note another bug in comctl32.dll: + // 2) LVHT_ONITEMSTATEICON and LVHT_ABOVE have the same value. However, the + // former (used for the checkbox when LVS_EX_CHECKBOXES is used) can + // only occur when y >= 0, while the latter ("above the control's client + // area") can only occur when y < 0. + else if ( (hitTestInfo.flags == LVHT_ONITEMSTATEICON) && point.y >= 0 ) + { + flags = wxLIST_HITTEST_ONITEMSTATEICON; + } + else if ( hitTestInfo.flags == LVHT_NOWHERE ) + { + flags = wxLIST_HITTEST_NOWHERE; + } + + if ( flags ) // any flags found so far couldn't be combined with others + return item; + + // outside an item, values could be combined + if ( (hitTestInfo.flags & LVHT_ABOVE) && point.y < 0 ) // see second MS bug + { + flags = wxLIST_HITTEST_ABOVE; + } + else if ( hitTestInfo.flags & LVHT_BELOW ) + { + flags = wxLIST_HITTEST_BELOW; + } + + if ( hitTestInfo.flags & LVHT_TOLEFT ) + { + flags |= wxLIST_HITTEST_TOLEFT; + } + else if ( hitTestInfo.flags & LVHT_TORIGHT ) + { + flags |= wxLIST_HITTEST_TORIGHT; } return item;