カタバミさんのプログラミングノート

日曜プログラマーがプログラミング関係のメモを記録するブログです。

C#であるAndroid端末のファイルのドロップ処理を実装する場合の注意

動作確認環境:Windows 10 64ビット、Microsoft Visual Studio 2019、C# 7.3

本文

あるAndroid機種はメーカーの公開するドライバをインストールすることでエクスプローラーで内部および外部ストレージを操作できますが、ドラッグ&ドロップ処理の実装は通常のファイル・フォルダと異なっています。そのため、C#では通常のファイルと同様にData.GetData(DataFormats.FileDrop)でファイルパスの一覧を取得することができません。

具体的にはデスクトップの通常のファイル・フォルダと特殊フォルダ、あるAnrdoid機種の外部ストレージ・内部ストレージ、フォルダ・テキストファイルのドラッグ&ドロップ時の動作は次表の通りです。

場所デスクトップあるAnrdoid機種
項目通常フォルダ通常テキストファイル特殊フォルダ*1ストレージ*2フォルダ・テキストファイル
可能な操作
 Copy
 Move
 Link
フォーマット*3
 DragContext
 DragImageBits
 DragSourceHelperFlags
 FileContents
 FileDrop
 FileGroupDescriptorW
 FileName
 FileNameW
 InShellDragLoop
 Preferred DropEffect
 Shell IDList Array
 UsingDefaultDragImage
 WPD NSE
 WPD NSE PnPDevicePath
 WPD NSE StoragePUID
 WPD Storage Attributes
  • WPDはおそらくWindows Portable Device。

FileDropフォーマットが存在しないことに対する対処

あるAndroid端末ではドロップ時の情報(以下、ドロップオブジェクト)にFileDropフォーマットが設定されないため、Data.GetData(DataFormats.FileDrop)は失敗します。これは特殊なファイル・フォルダ(オブジェクト)にはファイルシステム上のパスが存在しないために発生しています。Data.GetData("Shell IDList Array")を使用することでアイテムIDリスト(LPITEMIDLIST)の配列であるCIDA構造体を取得することができ、これとWin32 APIを組み合わせることで表示名(ファイル名として表示される名前)などを取得・設定することができます。

docs.microsoft.com

DragOverイベントハンドラにおけるData.Effect設定の注意

あるAndroid端末はDaagOverイベントハンドラのData.AllowedEffectにCopy | Moveを設定します。したがって、Effectにこれ以外の値、例えばLinkを設定した場合、カーソルは禁止マークとなり、DragDropイベントも発生しません。特別な対応が不要であればAllowedEffectを設定しておくことで回避できます。

参考

docs.microsoft.com

*1:PC、ゴミ箱、コントロールパネル

*2:内部ストレージおよび外部ストレージ

*3:Data.GetFormats(true)で取得。自動変換フォーマットを含む。