Last Updated 2004/10/12
Programming Tips Visual C++ MFC ドラッグアンドドロップ  索 引 
ドラッグ中のイメージ
2004/10/12

エクスプローラのツリービューコントロールのように,アイテムのドラッグイメージ(淡い色で表示される)を,自分のアプリケーションのクライエントエリアだけでなく,デスクトップやマイコンピュータ上でも表示させる.
(OLE機能付きで)

エクスプローラやマイコンピュータ,ごみ箱など,それぞれ別のアプリケーションのように見えるが,実は「Windows 95」という大きなアプリケーションの1つにすぎない.
だから,ツリービューコントロールのドラッグイメージは,デスクトップ上のどこに持っていってもちゃんと表示される.しかし,ワードパットやペイント上にドラッグするとドラッグイメージは消えて,デフォルトのOLEドラッグカーソルだけになる.それは,ワードパットやペイントはエクスプローラから見れば別アプリケーションだからである.

このようなドラッグのインタフェースを自分のプログラムで実現させるとなると,ツリービュークラスにOLEを実装しなければならない.
(注:ツリービューコントロールのドラッグイメージは,CImageList::DragEnter() の第1引数を NULL にしてやるとディスプレイ上のどこでも表示させる事ができる)

通常ツリービューコントロールのドラッグ中の処理は WM_MOUSEMOVE メッセージの中で行うが,ビュークラスに COleDropSource() を実装して,DoDragDrop() を呼ぶと WM_MOUSEMOVE メッセージが一切来なくなる.

OLEでのドラッグ中のカーソルイメージを変更するには COleDropSource クラスの OnBeginDrag(),GiveFeedback(),QueryContinueDrag() メンバ関数を実装する必要があり,この中の GiveFeedback() 関数が WM_MOUSEMOVE メッセージに代わる物となる.
だから,GiveFeedback() の中でカーソルイメージを変更する.
ツリービューコントロールの WM_MOUSEMOVE ハンドラ時にやろうとする処理を,この GiveFeedback() の中でやる事になる.具体的には,関数コールという形になり,COleDropSource::OnBeginDrag() の CWnd へのポインタを使用する.

そうすれば,ツリービューのアイテムをドラッグすると,そのドラッグイメージが自分のクライエントエリアから出てもちゃんと表示されるし,OLEのドラッグ&ドロップ機能も果たしてくれる.

ただし,1つだけ制限がある.
GiveFeedback() 関数が呼ばれるのは,ドラッグ中のマウスカーソルがOLEのドロップ・ターゲットを実装しているアプリ上にある時だけだという事だ.
だから,スクリーン上のどこでもツリービューのドラッグイメージをマウスカーソルに付随させる事は,どうしてもできない.
GiveFeedback() が呼ばれない時はどうしようもないからである.

逃げ道として,ドロップターゲットを実装していないウィンドウ上にさしかかった最初の1回だけ GiveFeedback() 関数の引数に DROPEFFECT_NONE がくる.
この時に,ドラッグイメージを消してやればよい.そうすれば,マウスカーソルはデフォルトOLEカーソルの「駐車禁止マーク」だけになる.
そして再び,ドロップ・ターゲットを実装しているウィンドウ上にマウスカーソルが来れば,また GiveFeedbak() 関数が呼ばれ,その引数に DROPEFFECT_COPY などが来るので,再度ドラッグイメージを表示してやればよい.


参照
ファイルのドロップ
前後のTips
ドラッグ中のイメージ

DSS ProgrammingTipsCGI Ver2.01