HitTest按预期工作

问题描述:

我想在用户右键单击CListCtrl中的项目时显示上下文菜单。我的代码如下:HitTest按预期工作

void DatastoreDialog::OnContextMenu(CWnd *pWnd, CPoint pos) 
{ 
    // Find the rectangle around the list control 
    CRect rectMainArea; 
    m_itemList.GetWindowRect(&rectMainArea); 
    // Find out if the user right-clicked the list control 
    if(rectMainArea.PtInRect(pos)) 
    { 
     LVHITTESTINFO hitTestInfo; 
     hitTestInfo.pt = pos; 
     hitTestInfo.flags = LVHT_ONITEM; 
     m_itemList.HitTest(&hitTestInfo); 
     if (hitTestInfo.flags & LVHT_NOWHERE) 
     { 
      // No item was clicked 
     } 
     else 
     { 
      MyContextHandler(hitTestInfo) 
     } 
    } 
} 

当我实际运行代码时,无论我在哪里点击;在一个项目上,在CListCtrl的空白处,在对话框的任何其他位置(通过删除第一个if语句); hitTestInfo.flags设置为48,如果我正确阅读this,则表示“在整个CListCtrl的右侧下方”。当我第一次检查它是否在CListCtrl中时,这并没有什么意义。

那么我有一个不正确的假设吗?我的代码不正确?我错过了什么吗?

作为一个可能相关,或许不是,奖金问题,既LVHT_ONITEMSTATEICONLVHT_ABOVE#define d为0x08的 - 这是为什么?这可能是我误解的关键。

我认为HitTest()需要在客户端坐标中的位置。自从我上次做这件事以来已经有一段时间了,但将屏幕坐标传递到客户端窗口命中测试例程是没有意义的。在hitTestInfo.pt = pos;之前加m_itemList.ScreenToClient(&pos);,看看是否有帮助。

此外,请注意OnContextMenu()可能不是您正在寻找的调用。它被调用以响应(默认)shift-f10。 WM_CONTEXTMENU的文档(在对角地阅读它时,我不记得它是如何工作的,从我上次做的时候开始)不太清楚在这种情况下'pos'的内容是什么;你可能需要做一个明确的GetCursorPos()来处理这种情况。或者只是在WM_RBUTTONDOWN中显示你的上下文。

+0

非常感谢!我还会研究WM_RBUTTONDOWN事情 - 你说得对,它导致上下文菜单显示不正确。 – Smashery 2010-01-15 00:42:35

+0

如果只有我可以投你两次:-) – Smashery 2010-01-15 00:54:54

+1

Pos的传递给OnContextMenu将(-1,-1)我相信,在Shift-F10或专用菜单键的情况下。 – 2013-12-17 22:00:09

我有类似的问题,HitTest列表控制。 即使在标题上发生点击,它也会影响返回项目0和LVHT_ONITEM标志 。对于一个标志,人们可以预期项目 index和LVHT_NOWHERE。 我通过使用头控件的HitTest解决了这个问题。这是如何:



UINT uFlags = 0; 
CHeaderCtrl* pHdr = m_list.GetHeaderCtrl(); 
if (!pHdr) return; // sanity 
HDHITTESTINFO hitTestInfo = {0}; 
hitTestInfo.pt = ptClient; 
int iItem = pHdr->HitTest(&hitTestInfo); 
if ((iItem != -1) && ((HHT_ONHEADER | HHT_ONDIVIDER) & hitTestInfo.flags)) { 
    // this is header control menu 
    CWnd::OnContextMenu(pWnd, point); 
} 
else if (HHT_BELOW & hitTestInfo.flags) { 
    CXTMenu Menu; 
    // this is list view control menu 
    if (Menu.LoadMenu(IDR_LIST_CONTEXT)) { 
... 
    } 
}