我正在尝试确定用户是否点击了列表视图上方或下方/下方。
Listview处于报告模式,具有扩展样式的完整行选择和网格线。
根据LVHITTESTINFO的文档,我无法获得正确的结果。
我的复选框的标题与我主窗口中LVHITTESTINFO中的值相同。
这些是LVHT_ABOVE,LVHT_BELOW,LVHT_NOWHERE,LVHT_TOLEFT,LVHT_TORIGHT和LVHT_ONITEM。
我的目标是检查与hittesting返回的结果具有相同标题的标题。
我已经在主窗口中捕获了鼠标以响应WM_LBUTTONDOWN并在WM_LBUTTONUP处理程序中进行了测试。
这是我编写可在此处发布的最小SSCCE /代码段的最简单方法。
以下是相关代码:
case WM_LBUTTONDOWN:
// reset checkboxes
CheckDlgButton(hWnd, 3000, BST_UNCHECKED);
CheckDlgButton(hWnd, 3100, BST_UNCHECKED);
CheckDlgButton(hWnd, 3200, BST_UNCHECKED);
CheckDlgButton(hWnd, 3300, BST_UNCHECKED);
CheckDlgButton(hWnd, 3400, BST_UNCHECKED);
CheckDlgButton(hWnd, 3500, BST_UNCHECKED);
// capture the mouse
SetCapture(hWnd);
break;
case WM_LBUTTONUP:
{
// extract coordinates
POINT pt = { 0 };
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
// do the hittesting
ClientToScreen(hWnd, &pt);
ScreenToClient(GetDlgItem(hWnd, 2000), &pt);
LVHITTESTINFO lvhti = { 0 };
lvhti.pt = pt;
ListView_HitTest(GetDlgItem(hWnd, 2000), &lvhti);
// check appropriate checkboxes
if ((lvhti.flags & LVHT_ABOVE) == LVHT_ABOVE)
CheckDlgButton(hWnd, 3000, BST_CHECKED);
if ((lvhti.flags & LVHT_BELOW) == LVHT_BELOW)
CheckDlgButton(hWnd, 3100, BST_CHECKED);
if ((lvhti.flags & LVHT_NOWHERE) == LVHT_NOWHERE)
CheckDlgButton(hWnd, 3200, BST_CHECKED);
if ((lvhti.flags & LVHT_ONITEM) == LVHT_ONITEM)
CheckDlgButton(hWnd, 3300, BST_CHECKED);
if ((lvhti.flags & LVHT_TOLEFT) == LVHT_TOLEFT)
CheckDlgButton(hWnd, 3400, BST_CHECKED);
if ((lvhti.flags & LVHT_TORIGHT) == LVHT_TORIGHT)
CheckDlgButton(hWnd, 3500, BST_CHECKED);
// release mouse capture
ReleaseCapture();
}
break;
测试原则:
按以下方式进行测试:单击主窗口客户区,按住鼠标左键,然后将光标拖到项目/上方(或下方)列表视图上。然后我释放调用WM_LBUTTONUP消息的按钮,并检查相应的复选框。
测试结果:
在Windows 7上测试
在Windows XP上测试
重要:
如何调整上述代码以获得正确的测试结果?
如果我的问题的解决方案很复杂并且需要太多的空间和精力来发布,我会对指示和指南感到满意,或者至少有一些链接指向我正确的方向。
如果需要进一步的信息,我会更新我的帖子。
答案 0 :(得分:1)
由于LVHT_ONITEMSTATEICON
和LVHT_ABOVE
具有相同的值,因此您必须查看请求的y
坐标以区分它们。 LVHT_ABOVE
表示命中结果位于客户区上方,因此只能在y
坐标小于零时设置,而LVHT_ONITEMSTATEICON
只能在命中结果打开时设置客户区内的图标。
LVHT_ONITEM...
标志仅在LVHT_ONITEM
不存在时才有意义。 LVHT_ONITEM
表示匹配结果是整个项目的整体,而LVHT_ONITEM...
表示匹配结果是项目的特定部分。
试试这个:
if (((lvhti.flags & LVHT_ABOVE) == LVHT_ABOVE) && (pt.y < 0))
// above the client area ...
...
if ((lvhti.flags & LVHT_ONITEM) == LVHT_ONITEM)
// on an item as a whole...
else
{
if ((lvhti.flags & LVHT_ONITEMICON) == LVHT_ONITEMICON)
// on an item's icon...
if ((lvhti.flags & LVHT_ONITEMLABEL) == LVHT_ONITEMLABEL)
// on an item's text...
if ((lvhti.flags & LVHT_ONITEMSTATEICON) == LVHT_ONITEMSTATEICON)
// on an item's state icon...
}
另外,不要忘记查看ListView_HitTest()
和/或LVHITTESTINFO::iItem
字段的返回值。它们会告诉您列表项索引,如果命中结果不在项目上,则为-1。