2010-01-14 52 views
2

我想在用戶右鍵單擊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的 - 這是爲什麼?這可能是我誤解的關鍵。

回答

4

我認爲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

1

我有類似的問題,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)) { 
... 
    } 
}