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_ONITEMSTATEICON0x08として表示されます-これはなぜですかLVHT_ABOVE? #defineこれが私の誤解の鍵かもしれません。

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 とフラグを返すというあいまいな効果があります。LVHT_NOWHERE項目インデックスとフラグには -1 が必要です。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 に答える