none
エクスプローラからデスクトップ上のアイコンにドラッグ&ドロップを受け付け RRS feed

  • 質問

  •  

    エクスプローラからデスクトップ上のアイコンにドラッグ&ドロップを受け付け
    かつ、そのオブジェクト(この場合ファイルのパス)を配列として受け取りたい?

    まずイベントは
    private void Form1_Load(object sender, EventArgs e)
    でよいのだろうか?

    受け取りは
    e.Effect = DragDropEffects.Copy;
    string[] s_fileName = (string[])e.Data.GetData(DataFormats.FileDrop, false);  // ドロップされたファイルの名称が配列で渡される

    これではエラーです。当然だDragEnterイベントではないのだから、下のイベントの中なら正しく動作する。
    private void Form1_DragEnter(object sender, DragEventArgs e)
    デスクトップ上のアイコンにドラッグ&ドロップした時は上記のイベントは発生しない。

    色々と調べてみたものの以下のところにしか行き着きません。
    http://www.atmarkit.co.jp/fdotnet/csharptips/003dragdrop/003dragdrop.html

    ご教授をお願いいたします。

    2009年8月17日 2:43

回答

  • デスクトップ上のアイコンというのは,ショートカットまたは.exe本体のアイコンのことだと仮定しますが,よいでしょうか。

    この場合,起動時の引数という形でファイルの一覧は渡されてきます。
    なので,Mainメソッドの引数になります。
    Mainメソッドが,
    void Main ()
    または
    int Main ()
    のようになっている場合は,引数に
    string[] args
    を加えてください。

    デバッグ時は,プロジェクトのプロパティから,デバッグタブにあるコマンドライン引数に,ファイル名を指定することで同等にことができます。
    • 回答としてマーク 若葉 2009年8月18日 6:24
    2009年8月17日 3:22
  • main ではなく Main です。このメソッドは Program.cs 内に既に定義されているはずです(デフォルトでは引数なしのはず)。

    なお、Main の引数として渡されるほか、Environment クラスの CommandLine プロパティや GetCommandLineArgs メソッドでも取得できます。
    • 回答としてマーク 若葉 2009年8月18日 6:24
    2009年8月17日 6:41
  • Form1 のコンストラクタで、Form1 のメンバー変数にコピーしてあげればよいはずです。メンバー名と引数名が同じなので this を使って、
    this.s_FileName = s_FileName;

    としてあげれば良いのではないでしょうか。メンバーの s_FileName はあらかじめ new しておく必要はないです。(上書きするので)
    もし s_FileName を加工するのでオリジナルを残したいということであれば、同じくコンストラクタのタイミングでメンバー変数を new して値をコピーしてあげればよいです。
    args.Length の値はすでに送られています。Form1 のコンストラクタ内で、s_FileName.Length で参照できると思います。
    • 回答としてマーク 若葉 2009年8月18日 6:25
    2009年8月18日 1:04

すべての返信

  • デスクトップ上のアイコンというのは,ショートカットまたは.exe本体のアイコンのことだと仮定しますが,よいでしょうか。

    この場合,起動時の引数という形でファイルの一覧は渡されてきます。
    なので,Mainメソッドの引数になります。
    Mainメソッドが,
    void Main ()
    または
    int Main ()
    のようになっている場合は,引数に
    string[] args
    を加えてください。

    デバッグ時は,プロジェクトのプロパティから,デバッグタブにあるコマンドライン引数に,ファイル名を指定することで同等にことができます。
    • 回答としてマーク 若葉 2009年8月18日 6:24
    2009年8月17日 3:22
  •  

    YuOさん、
    以下のファイルをディスクトップ上に放り出しただけです。
    .....\Release\WindowsFormsApplication1.exe

    ディスクトップ上のデバッグはまだよく分かりませんので各通過点にメッセージを出してみました。
    以下ではドロップ&ドラッグの時"mainを通過"のメッセージが出ません。

    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public class ArgsTest
            {
                public static void main(String[] args)
                {
                    MessageBox.Show("mainを通過");
                    if (args.Length < 1)
                    {
                        MessageBox.Show("ドロップ&ドラッグでは引数の数がおかしいです");
                    }
                    string[] s_fileName = (string[])args;
                    MessageBox.Show(s_fileName[0].ToString());
                    MessageBox.Show(s_fileName[1].ToString());
                }
            }
            public Form1()
            {
                InitializeComponent();
                MessageBox.Show("Form1を通過");
            }
            private void Form1_Load(object sender, EventArgs e)
            {
                MessageBox.Show("Form1_Loadを通過");
            }
        }
    }

    コンソールアプリケーションのではないので??です。

    2009年8月17日 6:35
  • main ではなく Main です。このメソッドは Program.cs 内に既に定義されているはずです(デフォルトでは引数なしのはず)。

    なお、Main の引数として渡されるほか、Environment クラスの CommandLine プロパティや GetCommandLineArgs メソッドでも取得できます。
    • 回答としてマーク 若葉 2009年8月18日 6:24
    2009年8月17日 6:41
  • Hongliangさん、ありがとうございます。
    Program.csが何で存在しているのか分からず今まで放って置きました。
    Mainはシステムとホームとの接着剤的役目ですね。
    Main内変数s_fileNameにはオブジェクトを受け取れましたが
    Form1内変数s_FileNameへ送る所がまだできていません。
    通常の関数・サブルーチンと同じようにしてみましたがどうやら別の方法でないと駄目だと言っているようです。

    出来ることなら
    args.Length変数の値もForm1内に送りたいですし、
    MainとForm1との共通の変数の定義が出来ればいちいち送る必要も無い訳で...
    その辺の詳しいテクニックをご指導ください。
    以下はMainとForm1のテストコードです。

    namespace WindowsFormsApplication1
    {
        static class Program
        {
            /// <summary>
            /// アプリケーションのメイン エントリ ポイントです。
            /// </summary>
            [STAThread]
            static void Main(String[] args)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                MessageBox.Show("Mainを通過");

                string[] s_fileName = Environment.GetCommandLineArgs();
               
                if (args.Length > 0)
                {
                    MessageBox.Show(s_fileName[0].ToString());
                    MessageBox.Show(s_fileName[1].ToString());
                }  
                else
                {
                    MessageBox.Show("ドロップ&ドラッグされなかった");
                }
                Application.Run(new Form1(s_fileName));
            }
        }
    }

    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private string[] s_FileName = new String[30];  // 配列変数作業領域、編集するファイルのパス

            public Form1(string[] s_FileName)
            {
                InitializeComponent();
                MessageBox.Show("Form1を通過");
            }
            private void Form1_Load(object sender, EventArgs e)
            {
                MessageBox.Show("Form1_Loadを通過");
                if (s_FileName[0] != null)                //ドロップ&ドラッグされるとメッセージを出す
                {
                MessageBox.Show(s_FileName[0].ToString());
                MessageBox.Show(s_FileName[1].ToString());
                }
            }
        }
    }

    2009年8月18日 0:28
  • Form1 のコンストラクタで、Form1 のメンバー変数にコピーしてあげればよいはずです。メンバー名と引数名が同じなので this を使って、
    this.s_FileName = s_FileName;

    としてあげれば良いのではないでしょうか。メンバーの s_FileName はあらかじめ new しておく必要はないです。(上書きするので)
    もし s_FileName を加工するのでオリジナルを残したいということであれば、同じくコンストラクタのタイミングでメンバー変数を new して値をコピーしてあげればよいです。
    args.Length の値はすでに送られています。Form1 のコンストラクタ内で、s_FileName.Length で参照できると思います。
    • 回答としてマーク 若葉 2009年8月18日 6:25
    2009年8月18日 1:04
  • 若葉さん自身で書いていますが、 Environment.GetCommandLineArgs(); なら、プログラム内のどこからでも呼び出しできます。
    #コメントの最初のほうにあったのは、Main( string[] args ) の args を使えばいいのでは?です。

    なので、コンストラクタパラメータで渡すなどよりは、チェックの必要があるところで、Environment.GetCommandLineArgs() を呼び出せばいいのでは?


    わんくま同盟,Microsoft MVP for Visual C++(Oct 2005-) http://blogs.wankuma.com/tocchann/
    2009年8月18日 2:19



  • YuOさん、Hongliangさん、totojoさん、ありがとうございます。

    this.s_FileName = s_FileName; と同一変数名にすると何やら「同一変数になっていのす...置き換えますか?」が出るので
    s_fileName = s_FileName; と単純に private string[] s_fileName に入れてみました。
    s_fileName及びi_fileName_indexは様々なイベントで使いたいのでイベント間共通変数が良いと思います。
    MainとForm1と全てのイベント間、共通の変数の定義が出来れば最良ですが

    Form1を以下のようにしました。何となくこれて動いてくれているようです。
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private string[] s_fileName = new String[30];  // 配列変数作業領域、編集するファイルのパス
            private int i_fileName_index = 0;                // 編集するファイルのパスのインデックス
            public Form1(string[] s_FileName)
            {
                MessageBox.Show("Form1に進入");
                InitializeComponent();
                s_fileName = s_FileName;
                i_fileName_index = s_FileName.Length;
                MessageBox.Show(i_fileName_index.ToString());
                if (i_fileName_index == 2)
                {
                    MessageBox.Show(s_fileName[0].ToString());
                    MessageBox.Show(s_fileName[1].ToString());
                }
                MessageBox.Show("Form1を出る");
            }
            private void Form1_Load(object sender, EventArgs e)
            {
                MessageBox.Show("Form1_Loadを通過");
            }
        }
    }

    私にとっては全てが新しい事ばかりで新鮮さを感じています。また、学ぶことが楽しくなって来ています。大変ありがとうございました。

    とっちゃんさん、
    > Environment.GetCommandLineArgs(); なら、プログラム内のどこからでも呼び出しできます。
    そうなんですか!!
    後日試してみます。取り合えずご返事まで、結果をまた書き込み致します。

    2009年8月18日 6:23


  • とっちゃんさん、ありがとうございます。
    public Form1(string[] args) の中に
    s_fileName = Environment.GetCommandLineArgs(); を記述してみましたが
    ドロップ&ドラッグのファイルの一覧は受け取れませんでした。
    起動したプログラムのパスのみ受け取れます。
    public Form1() とするとargs.Length;が受け取れなくなります。
    やーー、難しくてワクワク・・・
    やはりMainのところで全てのイベント間、共通の変数の定義が出来ればと思いますが?

    2009年8月18日 7:34
  • GetCommandLineArgs は、string[] を返します。
    が、Main( string[] args ) とは、違って、[0] の部分に、実行ファイル名が入ります。結果的に1つずれているという部分に着目する必要があるかと。
    このあたりは、デバッガなどでブレークして変数を覗いてみるなどして、どういうものがどういう形で送られてくるのか?を確認するとよいと思いますよ。

    あと、ヘルプも積極的に活用しましょう。

    このあたりのことが書かれていますし、Environment.GetCommandLineArgs のドキュメントのサンプルコードなどは、どういうものが渡ってくるのかがよくわかるように書かれていますよ。


    わんくま同盟,Microsoft MVP for Visual C++(Oct 2005-) http://blogs.wankuma.com/tocchann/
    2009年8月18日 7:39