Gtk#のウィジェットにファイルをドラッグ&ドロップで渡します。
受け取る種類を指定しておくと、ドロップしたときにDragDataReceivedシグナルが発生します。ファイルは "text/uri-list" です。URIで渡されるため、ローカル名に変換が必要です。
using System; using System.Text; using Gtk; class MainClass { public static void Main () { Application.Init (); var win = new Window ("Test DnD") { DefaultSize = new Gdk.Size (100, 100) }; win.DeleteEvent += (o, args) => { Application.Quit (); args.RetVal = true; }; var vbox = new VBox (false, 5); var label = new Label (); var text = new TextView (); vbox.Add (label); vbox.Add (text); win.Add (vbox); var targets = new [] { new TargetEntry ("text/uri-list", TargetFlags.OtherApp, 0) }; Drag.DestSet (label, DestDefaults.All, targets, Gdk.DragAction.Copy); Drag.DestSet (text, 0, targets, Gdk.DragAction.Copy); label.DragDataReceived += HandleDragDataReceived; text.DragDataReceived += HandleDragDataReceived; win.ShowAll (); Application.Run (); } static void HandleDragDataReceived (object o, DragDataReceivedArgs args) { Console.WriteLine (args.Time); var uris = Encoding.ASCII.GetString (args.SelectionData.Data) .Replace ("\r", "").Replace ("\0", "").Trim ().Split ('\n'); foreach (var s in uris) { var uri = new Uri (s); if (uri.IsFile) Console.WriteLine (uri.LocalPath); } } }
注意点
Drag.DestSet() はLabelとTextViewで挙動が異なります。Labelでは2番目の引数にDestDefaults.Allを指定する必要があります。しかしTextViewでDestDefaults.Allを指定するとなぜか2度イベントが通知され、Windowsでは2回目の通知で妙なファイルが渡されます(Xでは1回目と同じ)。そのためゼロを指定しておく必要があります。
【追記】WindowsではLabelにDestDefaults.Dropを指定してもドロップを受け付けますが、Xでははじかれました。
これはC言語からGTK+を直接使用しても同じ結果となりました。GTK+本来の挙動だと思われます。
C言語で同じコードを書いてみると、改めてGtk#が薄いラッパーだと思いました。