ツリーコントロールでフォーカスのあるアイテムを取得するには?

解決


TM  2004-08-25 13:55:26  No: 54303

VC6、MFCダイアログベースで製作しています。

ツリーコントロール内で、右クリックポップアップメニューを表示しようとしているのですが、右クリックと左クリックの違いがわからず困っています。

例えば、ルートが選択状態(点線囲い)かつフォーカスが当たっているとします。そこで、その子アイテムを左クリックすると、そのクリックしたアイテムが選択状態かつフォーカスがあたります。しかし、右クリックをすると、アイテムにフォーカスがあたるのですが選択状態(点線囲い)はルートにあります。そのため、GetSelectedItemではルートを取得してしまいます。

このような場合、どのような記述あるいはメンバを使えばよいのでしょうか?どうか、ご教授お願いいたします。


シャノン  2004-08-25 18:28:50  No: 54304

右クリックしたときに、カーソル座標から、カーソルの下にあるアイテムを取得して、そっちを選択状態にしちゃうとか。


TM  2004-08-25 23:20:04  No: 54305

シャノンさん、ご返答ありがとうございます。

シャノンさんのご指導通りできました。しかし、わざわざ、

GetCursorPosでマウスの絶対座標、
m_tree.GetWindowRectでツリーの絶対座標

を出して、引き算で相対座標を求め、HitTestを使いました。

なんか効率が悪いような気がします。こんなことしなくてもすぐにツリー内の相対座標を出す方法はあるのでしょうか?


シャノン  2004-08-25 23:46:41  No: 54306

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 がクライアント座標を提供してくれればいいのに、と思う昨今。


TM  2004-08-26 00:02:55  No: 54307

シャノンさん、大変お世話になります。

MapWindowPoints!?すばらしいですね、これ。
やはり、プログラムはスマートの方が気持ちがいいです。
またひとついいものを覚えさせていただきました。

毎回、シャノンさんにご教授していただいて、大変感謝しております。
プログラムを行う学科に進めばよかった、と思う昨今。


瀬戸っぷ  2004-08-26 07:01:21  No: 54308

ScreenToClient()でできませんか?


シャノン  2004-08-26 09:32:14  No: 54309

今回の用途に限っては、ScreenToClient でもいいですね。
より特化した関数と言うことで、そっちを使うべきでしょうか。
好みの問題のような気もしますが。

MapWindowPoints の方が汎用性がありますし、覚えて置いて損はないです。
2つのウィンドウのクライアント座標系で RECT 型を相互変換するのに ClientToScreen と ScreenToClient を左上と右下にそれぞれ適用していたりするのをたまに見ますが…MapWindowPoints なら一発ですし。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加