DragEventArgs eとComTypes.IDataObject型
DragDropイベントなどで使用されるe.Data
はSystem.Windows.Forms.IDataObject型ですが、System.Runtime.InteropServices.ComTypes.IDataObject型(以下ComTypes.IDataObject型)へ明示的に変換することができます。このComTypes.IDataObject型を使用することで通常のe.Data
では隠されたフォーマット形式等を参照することができます。
以下に具体的なコードを示します。Form1はDragDragが有効なフォームで複数行テキストボックスTextBox1が1つ存在します。実行してフォームの枠にエクスプローラーからファイルをドロップするとドロップデータに含まれるフォーマットの形式一覧をテキストボックスに表示します。
using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; using ComTypes = System.Runtime.InteropServices.ComTypes; namespace WindowsFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_DragOver(object sender, DragEventArgs e) { e.Effect = DragDropEffects.All; } private void Form1_DragDrop(object sender, DragEventArgs e) { var obj = (ComTypes.IDataObject)e.Data; var buffer = new StringBuilder(); var enumerator = obj.EnumFormatEtc(ComTypes.DATADIR.DATADIR_GET); var fmts = new ComTypes.FORMATETC[1]; const int S_OK = 0; while (enumerator.Next(1, fmts, null) == S_OK) { var fmt = fmts[0]; buffer.AppendLine($"{fmt.cfFormat.ToString("X4")} \"{ClipboardUtility.GetClipboardFormatName(fmt.cfFormat)}\""); } textBox1.Text = buffer.ToString(); } } public static class ClipboardUtility { private const int ERROR_INSUFFICIENT_BUFFER = 122; public static class NativeMethods { [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int GetClipboardFormatNameW(uint format, StringBuilder lpszFormatName, int cchMaxCount); } public static string GetClipboardFormatName(short format) { var buffer = new StringBuilder(); for (int l = 256; ; l += 256) { var copied = NativeMethods.GetClipboardFormatNameW( (uint)format, buffer, l); if (Marshal.GetLastWin32Error() == 0) return buffer.ToString(0, copied); if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER) return null; } } } }
出力の具体例
デスクトップのファイル・フォルダおよびGoogle ChromeのURLまたは選択範囲(文字列)をドロップした場合の出力例を示します。
デスクトップのファイル・フォルダ(PC等の特殊項目含まず)
C0DA "Shell IDList Array" TYMED_HGLOBAL C213 "DragImageBits" TYMED_HGLOBAL C0E9 "DragContext" TYMED_ISTREAM C214 "DragSourceHelperFlags" TYMED_HGLOBAL C0E8 "InShellDragLoop" TYMED_HGLOBAL 000F "" TYMED_HGLOBAL C006 "" TYMED_HGLOBAL C007 "" TYMED_HGLOBAL
デスクトップのファイル・フォルダ(PC等の特殊項目含む)
C0DA "Shell IDList Array" TYMED_HGLOBAL C0E3 "Preferred DropEffect" TYMED_HGLOBAL C213 "DragImageBits" TYMED_HGLOBAL C0E9 "DragContext" TYMED_ISTREAM C214 "DragSourceHelperFlags" TYMED_HGLOBAL C0E8 "InShellDragLoop" TYMED_HGLOBAL
Google Chrome 64ビット (68.0.3440.75)のURL(HTTPS)
C0E9 "DragContext" TYMED_ISTREAM C213 "DragImageBits" TYMED_HGLOBAL C347 "text/x-moz-url" TYMED_HGLOBAL C0DE "FileGroupDescriptorW" TYMED_HGLOBAL C07B "FileContents" TYMED_HGLOBAL C0EE "UniformResourceLocatorW" TYMED_HGLOBAL C0E7 "UniformResourceLocator" TYMED_HGLOBAL 000D "" TYMED_HGLOBAL 0001 "" TYMED_HGLOBAL
Google Chrome 64ビット (68.0.3440.75)の選択範囲(文字列のみ)
C0E9 "DragContext" TYMED_ISTREAM C213 "DragImageBits" TYMED_HGLOBAL C344 "chromium/x-renderer-taint" TYMED_HGLOBAL 000D "" TYMED_HGLOBAL 0001 "" TYMED_HGLOBAL C0E2 "" TYMED_HGLOBAL C1DC "" TYMED_HGLOBAL
データフォーマット(クリップボードフォーマット)形式の数値と文字列
データフォーマットはクリップボードフォーマットと共通で管理されており、4バイトの数値または文字列へのポインタです。数値から名前を取得するにはWin32 APIのGetClipboardFormatNameW(A)関数を使用することができます。クリップボードデータの形式については公式ドキュメントを参照してください。
2021/3/10:この記事は別のブログで投稿した記事を移動したものです。