非実在ファイルをエクスプローラにD&Dする
自アプリからエクスプローラへのドラッグ&ドロップにおいて、ファイルシステムやシェル名前空間上に存在しないデータをやりとりする方法があります。それがCFSTR_FILECONTENTSとCFSTR_FILEDESCRIPTORの組み合わせです。ともにMSDNライブラリのShell Clipboard Formatsで説明されています。
これをエクスプローラにドロップすると、ドロップ先にファイルが作成されます。これには、圧縮ファイルの中身を取り出したり、インターネット上からD&D時にダウンロードしたりするなどといった使い道があります。
さて、これについて、Visual C++のネイティブコード (Windows API/ATL/WTL)、Windows Forms、WPFのそれぞれでサンプルコードを書いてみました。それぞれGistに置いてあります。Windows FormsとWPFは自分でIDataObjectを実装しなくて良いので、とてもすっきりしたコードになっています。
それぞれ、IStream (SHCreateMemStream)やSystem.IO.Stream (System.IO.MemoryStream)に書かれているデータがドロップ先のファイルの中身になります。
FD_UNICODEはWindows Vistaからであることに注意してください。Windows XPを対象にし、FD_UNICODEを使わない場合、FILEGROUPDESCRIPTORAを使ってマルチバイト文字でファイル名を指定することになります。
どれもFILEGROUPDESCRIPTORではファイル名しか指定していませんが、実際にはほかにもいくつかメタデータを指定できます(MSDNライブラリ参照: FILEDESCRIPTOR structure (Windows))。
なお、Windows Forms版とWPF版を作るにあたっては、OutlookDataObject.csが以下の点で参考になりました。
- DataObjectでのデータ形式にはCFSTR_定数がそのまま使えそうであること。
- バイト列を扱うにはSystem.IO.Streamを使用すれば良いこと。
逆に、ファイルをドラッグ&ドロップで受け取るアプリケーションは、CF_HDROP以外にも対応することを検討していただけると幸いです。CFSTR_FILECONTENTSとCFSTR_FILEDESCRIPTORのほか、ファイルやフォルダっぽいものとしてCFSTR_SHELLIDLISTなどもあります。
2015年6月27日追記:ネイティブ版のコードにおいて、CreateFormatEnumerator関数を使うようにするなどの変更を行いました。
スポンサード リンク |