ツリーコントロールの右クリック

[戻る]
Nezu 2010/05/13(木) 15:02:57
たびたびすみませんが、お願いします。

ツリーコントロールのアイテムを右クリックしたときに、
右クリックしたアイテム名を取得したいのですが、うまくいきません。


下記のように右クリックされたアイテムが、最下層のアイテムだった場合
アイテム名を取得するようにしたいのですが、
GetItemText()で空が返ってきてしまいます。
それどころか、最下層アイテムの判別もすべて通ってしまいます。

左クリック処理にまったく同じ処理を書いてみましたが、うまくいきました。
ご存じの方、ご教授ください。

void CHogeDlg::OnNMRclickTreeCtrl(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTREEVIEW pNMTreeView    = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    
    // 最下層のアイテムか?
    if(pNMTreeView->itemNew.cChildren != 0)
    {
        *pResult = 0;
        return;
    }    

    // 選択アイテム名
    CString strSelect = m_TreeCtrl.GetItemText(pNMTreeView->itemNew.hItem);
}

環境 2003 MFC

aetos 2010/05/13(木) 18:02:34
http://msdn.microsoft.com/en-us/library/bb773484(VS.85).aspx
pNMHDR を LPNMTREEVIEW にキャストしても大丈夫なようには見えませんけど。

アイテムの取得には CTreeCtrl::HitTest とか使うんじゃないかな。

ロマ 2010/05/13(木) 20:47:01
正式にはaetosさんが書いている通り、HitTestを使うべきですが、

HTREEITEM hItem = GetNextItem(TVGN_DROPHILITE);
if(!hItem)  // 選択項目を右クリックした場合は、TVGN_DROPHILITEでは取れない
  hItem = GetNextItem(TVGN_CARET);
これで、どういう訳か、うまくいきます(xp)。

Nezu 2010/05/14(金) 09:16:31
返信ありがとうございます。

aetosさん、ロマさん、それぞれの方法を試してみました。

HitTestを使った場合
void CHoge::OnNMRclickTree(NMHDR *pNMHDR, LRESULT *pResult)
{
    CPoint pt;
    GetCursorPos(&pt);
    ScreenToClient(&pt);

    UINT uFlag;
     HTREEITEM item = m_Tree.HitTest(pt, &uFlag);
    m_Tree.SelectItem(item);

    // 選択アイテム名
    CString strSelect = m_Tree.GetItemText(item); ←空が返る
}
取得できません。どこか悪いのでしょうか?

TVGN_DROPHILITEを使った場合、
正常に取得できました。
ただ、これを採用して良いか迷います。
やはり正式な方法(HisTest)のほうが良いでしょうか?

maru 2010/05/14(金) 11:37:50
人に聞く前に確かめるべきことがあると思うけど。
    GetCursorPos(&pt);   // 取得した座標はただしいか?
    ScreenToClient(&pt); // 変換した座標は正しいか?

    HTREEITEM item = m_Tree.HitTest(pt, &uFlag);
    // 取得できたitemは正しいか? uFlag の値は?

ちなみにメッセージが発行された時のマウスの位置はGetMessagePos関数で取得します。

> TVGN_DROPHILITEを使った場合、
> 正常に取得できました。
> ただ、これを採用して良いか迷います。
> やはり正式な方法(HisTest)のほうが良いでしょうか?
マイクロソフトのドキュメントに記載されていないやりかたで出来たとしても、
何の保証もないと思いますが。

ryo 2010/05/14(金) 12:30:15
CTreeCtrlって、右クリックした段階で
アイテム選択されていませんでしたっけ?

aetos 2010/05/14(金) 13:29:48
> ScreenToClient(&pt); // 変換した座標は正しいか?

正しくないですねぇ。

Nezu 2010/05/14(金) 13:45:24
皆さま、ありがとうございます。

m_Tree.ScreenToClient(&pt);
とすることで右クリックしたアイテムを取得することができました。
ありがとうございました。

Nezu 2010/05/14(金) 15:38:47
[[解決]]
か・い・け・つ

ロマ 2010/05/14(金) 15:53:48
maruさん
> マイクロソフトのドキュメントに記載されていないやりかたで出来たとしても、
> 何の保証もないと思いますが。

ryoさん
> CTreeCtrlって、右クリックした段階で
> アイテム選択されていませんでしたっけ?


msdnの説明が変ですね。

Default Tree-View Control Message Processing
 WM_RBUTTONDOWN 
  Checks to see if an item was clicked and a drag operation was begun. 
  If the operation has begun, it sends a TVN_BEGINRDRAG notification 
  message to the parent window and highlights the drop target. Otherwise, 
  it sends an NM_RCLICK notification message to the parent window. There 
  is no return value. 

実際には、WM_RBUTTONDOWNでDROPHILITEがつき、
TVN_BEGINDRAGでDROPHILITEが消えます。

エクスプローラのTreeViewは、なぜか、このDefaultProcessingを使わず、
TVM_HITTEST-->TVM_SELECTITEM(TVGN_DROPHILITE)の順で処理しているようです。

....! 2010/05/16(日) 09:33:23
マウス操作による右クリックは対応出来たかも知れんが、
「Shift+F10」等のキーボードからの操作は問題無く対応出来てる?

古いスレッドには追加発言できません。