2

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

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,如果我没看错的,它的意思是“在整个 CListCtrl 的下方和右侧”。当我第一次检查它是否在 CListCtrl 中时,这真的没有意义。

那么我在某处有不正确的假设吗?我的代码不正确吗?我错过了什么吗?

作为一个可能相关的,或者可能不相关的,BONUS QUESTION,两者LVHT_ONITEMSTATEICONLVHT_ABOVE都是#define0x08 - 为什么会这样?这可能是我误解的关键。

4

2 回答 2

4

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

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

于 2010-01-14T13:18:36.963 回答
1

HitTest我对列表控制有类似的问题。LVHT_ONITEM即使在标题上发生单击,它也具有返回项目 0 和标志的模糊效果。人们会期望 -1 用于项目索引和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)) {
...
    }
}
于 2011-04-06T15:10:18.523 回答