おせわになります、さらやと申します。
(いきなりの長文、失礼します。)
VS2005 C++, MFC不使用でダイアログアプリを作成しています。
(開発/ターゲットとも、OSはXPです。)
現在SHBrowseForFolder()を使用して、フォルダ選択のダイアログを
表示しているのですが、このダイアログで「+」をクリックして
アイテムを展開したというイベントを捕らえたいと思っていますが、
うまく捕らえることができなくて、困っています。
ツリービューなのでTVM_EXPANDが飛んでいるのだろうと
ツリービューやフォルダ選択ダイアログをサブクラス化して
見たのですが、捕らえられません。
(SPY++で見ても、飛んでいるように見えません。)
また、ネットを検索していてWM_NOTIFYで通知されるという
記述を見かけたため、下記のように記述してみましたが
捕まえることができません。
(フォルダ選択ダイアログのプロシージャ、ツリービューのプロシージャ
両方で試してみましたが、捕まえられませんでした。)
------(ソース抜粋(一部略) ここから)-------------
NMHDR* pnmhdr;
case WM_NOTIFY:
pnmhdr=(NMHDR*)lParam;
switch(pnmtv->hdr.code){
case TVN_ITEMEXPANDED:
::MessageBox(hdlg,"TVN_ITEMEXPANDED","WM_NOTIFY",MB_OK);
break;
case TVM_EXPAND:
::MessageBox(hdlg,"TVM_EXPAND","WM_NOTIFY",MB_OK);
break;
}
break;
------(ソース抜粋 ここまで)-------------
参考書やMSDNライブラリも見てみましたが、TVM_EXPANDの使い方は
見つかるものの、捕まえる方法は見つけることができませんでした。
ちなみに、自分でTreeView_Expand()を発行してアイテムを展開したときは、ツリービューのプロシージャにTVM_EXPANDが飛んできていました。
私の実装方法がまずいのか、そもそもの考え方が間違っているのかすら
わからなくなって困っております。
なにか、ヒントだけでもいただければと思い、質問させていただきました。
よろしくお願いいたします。
> ツリービューやフォルダ選択ダイアログをサブクラス化して
フォルダ選択ダイアログのプロシージャで
> case TVN_ITEMEXPANDED:
TVN_ITEMEXPANDEDW にしてみ。
> TVM_EXPAND
基本的に、頭が TVM となっているのは「ツリービューに対して命令する時に使用されるメッセージ識別子」で、
頭が TVN となっているのは「ツリービューからのイベント発生を通知する時に使用される識別子」。
※ 厳密に言えば、TVN は WM_NOTIFY で使用される通知コードなんで実際は全く別物
> ツリービューなのでTVM_EXPANDが飛んでいるのだろうと
他者がツリービューに対して「アイテムを展開したい」と思った時は、命令をしないとツリービュー
には伝わらないので命令する(TVM_EXPAND を飛ばす)必要がある。
けど、ツリービュー自身が「アイテムを展開したい」と思った時は別に命令(TVM_EXPAND を飛ばす)
なんてしなくても良いよね。普通に展開(例えば item_expand_仮() 関数を実行等)しても良い。
なので「アイテムを展開」を知る手段として TVM_EXPAND を当てにするよりは、素直に
TVN_ITEMEXPANDED / TVN_ITEMEXPANDING を利用した方が良いかと。
> TVM_EXPANDの使い方は見つかるものの、捕まえる方法は
一応書いておくと、ツリービューのプロシージャで
LRESULT CALLBACK WindowProc (HWND, UINT uMsg, WPARAM LPARAM) {
// 提示ソースのように WM_NOTIFY 内じゃない
if (uMsg == TVM_EXPAND) { }
}
とすれば(TVM_EXPAND が投げられているなら)捕獲可能なハズ。
gak さん
丁寧な返信、ありがとうございます。
>TVN_ITEMEXPANDEDW にしてみ。
試してみます!(すみません、今、手元に開発環境がないところに
いるので、試すのが明日になってしまいます。。。)
>基本的に、頭が TVM となっているのは「ツリービューに対して命令する時に使用されるメッセージ識別子」で、
>頭が TVN となっているのは「ツリービューからのイベント発生を通知する時に使用される識別子」。
すみません、私のやりたいことを正しく書けていませんでした。
申し訳ありません。
今回の実装では、「展開を察知して、場合によっては展開させない」ことが
最終目的でして、展開される前に阻止するには、TVM_EXPANDを捕まえて
破棄してやればよいのでは、と考えたため、TVMを捕まえようと
していました。
(TVN系のメッセージなら、名前からしてTVN_ITEMEXPANDINGが
「展開した」ではなく「展開しようとしている」なのかと思って
フォルダ選択ダイアログのWM_NOTIFY内で捕まえようとしてみましたが、
これも捕まえることができず、動きを確認することができませんでした。)
>一応書いておくと、ツリービューのプロシージャで
>LRESULT CALLBACK WindowProc (HWND, UINT uMsg, WPARAM LPARAM) {
> // 提示ソースのように WM_NOTIFY 内じゃない
> if (uMsg == TVM_EXPAND) { }
>}
>とすれば(TVM_EXPAND が投げられているなら)捕獲可能なハズ
これも試したのですが、捕まえられませんでした。
こちらからTreeView_Expandマクロを発行したときは捕まえられましたので
やはり、gakさんのおっしゃるとおり、ツリービューが自分を操作するのに
いちいちメッセージ飛ばしたりしないんですね。
コントロールが動くためにはすべてメッセージが絡むと思っていました。
勉強になりました。
自分の中でとても納得してしまったので、「解決」にしたいところなのですが、
明日TVN_ITEMEXPANDEDWを試してみたいので、また書き込みをさせてください。
gakさん、ありがとうございました。
gak さんに教えていただいたTVN_ITEMEXPANDEDW で、
見事に捕捉することができました!!!
TVN_ITEMEXPANDINGもW付きにすることで捕らえることができ、
無事目的の実装ができそうです。
(TVN_ITEMEXPANDINGを破棄しても、展開を阻止できるのですね。)
SHBrowseForFolder()の内部ではユニコードでメッセージが
飛んでいるのですね。
大変勉強になりました。
gakさん、本当にありがとうございました。
ツイート | ![]() |