VC6、MFCダイアログベースで製作しています。
ツリーコントロール内で、右クリックポップアップメニューを表示しようとしているのですが、右クリックと左クリックの違いがわからず困っています。
例えば、ルートが選択状態(点線囲い)かつフォーカスが当たっているとします。そこで、その子アイテムを左クリックすると、そのクリックしたアイテムが選択状態かつフォーカスがあたります。しかし、右クリックをすると、アイテムにフォーカスがあたるのですが選択状態(点線囲い)はルートにあります。そのため、GetSelectedItemではルートを取得してしまいます。
このような場合、どのような記述あるいはメンバを使えばよいのでしょうか?どうか、ご教授お願いいたします。
右クリックしたときに、カーソル座標から、カーソルの下にあるアイテムを取得して、そっちを選択状態にしちゃうとか。
シャノンさん、ご返答ありがとうございます。
シャノンさんのご指導通りできました。しかし、わざわざ、
GetCursorPosでマウスの絶対座標、
m_tree.GetWindowRectでツリーの絶対座標
を出して、引き算で相対座標を求め、HitTestを使いました。
なんか効率が悪いような気がします。こんなことしなくてもすぐにツリー内の相対座標を出す方法はあるのでしょうか?
MapWindowPoints を使って、2つの座標を変換できます。
GetCursorPos はスクリーン座標なので、これを m_tree のクライアント座標に変換するには
POINT pt;
::GetCursorPos( &pt );
::MapWindowPoints( HWND_DESKTOP, m_tree.m_hWnd, &pt, 1 );
とします。
注意すべきは、CWnd のメンバではない、グローバルな MapWindowPoints を使うこと。
そうでないと、本来はスクリーン座標である pt を、親ウィンドウのクライアント座標と解釈されてしまいます。
これで、多少はエレガントになるかもしれませんが、いかがでしょうか?
ツリーコントロールのクライアント座標を一発で、かつ簡単に取得する方法は、たぶんありません。
ツリーコントロールをサブクラス化して WM_RBUTTONDOWN を捕まえればできるかもしれませんが、現行の引き算の方がまだ簡単かと思います。
#NM_RCLICK がクライアント座標を提供してくれればいいのに、と思う昨今。
シャノンさん、大変お世話になります。
MapWindowPoints!?すばらしいですね、これ。
やはり、プログラムはスマートの方が気持ちがいいです。
またひとついいものを覚えさせていただきました。
毎回、シャノンさんにご教授していただいて、大変感謝しております。
プログラムを行う学科に進めばよかった、と思う昨今。
ScreenToClient()でできませんか?
今回の用途に限っては、ScreenToClient でもいいですね。
より特化した関数と言うことで、そっちを使うべきでしょうか。
好みの問題のような気もしますが。
MapWindowPoints の方が汎用性がありますし、覚えて置いて損はないです。
2つのウィンドウのクライアント座標系で RECT 型を相互変換するのに ClientToScreen と ScreenToClient を左上と右下にそれぞれ適用していたりするのをたまに見ますが…MapWindowPoints なら一発ですし。
ツイート | ![]() |