2008年12月26日金曜日

[VC++] VC++で複数コントロールに対する個別のドラッグアンドドロップを受け付ける方法

やたら細かいネーミング。汗


D&D対応のサンプルはWebでも色々あるんだけど。
あのやり方だと、ウィンドウのどこにドロップしても同じになってしまう。


たとえばこんなウィンドウ。


この二つのエディットボックスがそれぞれD&Dを受け付けるようにしたいときの方法。
あくまで一つの方法ですけど。一番簡単なので使っています。


作成環境はVC++6.0なので、.NETとはウィンドウの構成とかはかなり違いますが、基本的に仕組みは同じはず。


まず、リソースエディタでエディットボックスをD&D対応にします。

リソースエディタを起動して、



各対象アイテムの拡張スタイルで「ドラッグドロップを許可」にチェックをつけます。



次に、ウィンドウ画面上でクラスウィザードを表示。



オブジェクトIDでウィンドウのIDを選択すると、PreTranslateMessageという関数名が表示されます。
これをダブルクリックして、下の「メンバ関数」に追加された、PreTranslateMessage関数をダブルクリック。

ソースファイルが開きます。画面が黒いのはほっといてください。


この関数(PreTranslateMessage)は、ウィンドウに飛んでくるすべてのメッセージが実行される前に必ず通る場所です。

なので、ここでメッセージを取得すれば、ウィンドウに飛んでくるほぼすべてのメッセージを取得できます。いじりようによってはウィンドウを閉じられなくも出来る強力な関数ですのでご注意を。


ここに、こんなソースを挿入します。



処理を簡単に箇条書き。
  1. 受け取ったメッセージがWM_DROPFILESの場合
  2. wParamに格納されているパス名データを解析用APIに渡してファイル名を取得
  3. hwndに格納されているメッセージ送信先IDを、対象の2つのEditBoxのID情報と比較し、該当するEditBoxにパス情報を書き込む

と言うものです。

DragQueryFileというAPIは、ファイルの名前を指定したバッファに書き込んでくれる解析用APIです。

これでファイルをD&Dすると、各エディットボックスにファイル名が設定されますよ。