次の方法で共有


ファイル選択ダイアログにてフォルダも選択したい

質問

2014年2月17日月曜日 12:18

はじめまして、お世話になります。

C;;の経験が浅いため、デザイナーなどの面でMFCより取り組みやすいと考え、

CLR(CLI)にて開発しております。

とある画面でファイル/フォルダを選択したいのですが、

ファイル選択ダイアログではフォルダを選択した際に、フォルダ内に移動してしまいます。

実現したい内容としては以下の通りです。

●ファイルを選択する

●フォルダも選択する

●複数選択もあり得る

選択するファイル/フォルダは同一ディレクトリ内のみです。

インタフェース的にはOpenFileDialogが理想的です。

標準のOpenFileDialogは継承できないため

色々参考にしつつCommonDialogの拡張を試しておりますが、上手く行っていない状況です。

よろしくお願いいたします。

すべての返信 (7)

2014年2月17日月曜日 16:02 ✅回答済み

MokuMoku015さん、こんばんは。

標準的なOpenFileDialog(CFileDialog)でフォルダ選択はできません。

WindowsShellのSHBrowseForFolderでは、フォルダ選択もファイル選択もできますが、同時選択ができません。(BIF_BROWSEINCLUDEFILES オプション)

ですので、OpenFileDialogのユーザーインターフェースで、

  • ファイル選択
  • フォルダ選択
  • 複数選択

を成し遂げるためには、独自の実装を行わないとだめだとおもいます。

Vista以降の新しいファイルダイアログの場合、次のようなコードでフォルダ選択とファイル選択を「切り替える」ことができます。

// エラー処理省略します。

IFileDialog *pifd = NULL;
IShellItem *psi = NULL;
DWORD dwOptions = 0;
TCHAR* pszPath = NULL;

CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pifd));
pifd->GetOptions(&dwOptions);

// この一行をなくすとファイル選択になります。この行があるとフォルダ選択になります。
pifd->SetOptions(dwOptions | FOS_PICKFOLDERS);

pifd->Show(NULL);

pifd->GetResult(&psi);

// pszPathに選択したファイル、あるいはフォルダへのパスが入ります。
psi->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &pszPath);

psi->Release();
pifd->Release();

2014年2月18日火曜日 4:18 ✅回答済み

>ありがとうございます。アプリはFormを使用しています。
>となると、シェルは利用しないほうが良いということですね。

Formを使っているのであれば、APIを直接利用するよりもラップして使いやすくしている FolderBrowseDialog の利用をお勧めします。

ということです。

内部的にはSHBrowseForFolder を呼び出しているので、結果としては同じ動作になりますが、シェル固有のメモリ操作を必要としない分楽に利用ができます。

>ファイルと同階層のフォルダも選択したい、または複数選択したい、という感じです。

異なるフォルダにある複数のファイルを選択する機能は、OpenFileDialog にもあります。

Multiselect プロパティがそれです。

異なるフォルダのファイルも選択可能ですが(ただし、ファイル選択するためにかなり高度なユーザー操作を要求されます)、選択できるのはあくまでもファイルであり、フォルダを選択することはできません(バッファサイズの関係もあるため、どの程度選択できるのか?については、実験してみないとわかりません)。

また、FolderBrowserDialogのほうは、そもそも複数選択する仕組みが用意されていません。

一応、代案も。

ファイルやフォルダの選択にエクスプローラからのドロップや、コピー&ペーストを可能にするというのはどうでしょう?

とっちゃん@わんくま同盟, Microsoft MVP for Visual C;; (Oct 2005-) http://blogs.wankuma.com/tocchann/


2014年2月18日火曜日 1:36

にゃにゃお様

おはようございます。

ご回答ありがとうございます。

>標準的なOpenFileDialog(CFileDialog)でフォルダ選択はできません。

FileDialogという名称のとおり、フォルダは選べないのですね。

>SHBrowseForFolderでは、フォルダ選択もファイル選択もできますが、同時選択ができません。

こちらで同時選択もできたら良かったのですが…。

使用環境にXPも考えているため、切り替えは使えないかもしれません。

取り急ぎ、記載していただいたコードを試してみます。

1回のダイアログでファイル/フォルダを全て取得するのが厳しいようなので、ファイル選択、フォルダ選択を分けることも考えています。

引き続き、よろしくお願いいたします。


2014年2月18日火曜日 2:36

C;;/CLI で WinForms を使っているのであれば、SHBrowseForFolder API を利用するのではなく、FolderBrowserDialog の利用を検討することをお勧めします。

ただし、アプリが、WPF アプリの場合はこの限りではありません。もっともWPFアプリをXPで動かすと、動作が緩慢(本来OSのサポートがあるはずの部分でサポートが入らないため)になるので、お勧めできませんが。。。

それと、XPも対象となっているので、にゃおにゃおさんが提示してくださった、Vista以降のファイルダイアログを利用したフォルダ選択は使えません(XPまでのファイルダイアログにはその仕組みがないため)。

ところで、ファイルとフォルダを同時に選択したいというのはどういう状況なのでしょう?

ファイルを選択すると必ずフルパスになります(フォルダ+ファイル名)。

これを、フォルダ部分とファイル名部分に分けて取り込みたいということでしょうか?

それとも、ファイル(フルパス)と、同時に別のフォルダも選択したいということでしょうか?

もし、フルパスを分解したいというのであれば、System.IO.Path クラスを使って、分解することができます。

そうではないという場合は残念ですが現行のWindowsで、フルパス+別のフォルダを同時に選択という機能はありませんので、自前でそういうダイアログを作るか、ファイルを選択、フォルダを選択をそれぞれ行うかのいずれかになります。

とっちゃん@わんくま同盟, Microsoft MVP for Visual C;; (Oct 2005-) http://blogs.wankuma.com/tocchann/


2014年2月18日火曜日 3:40

とっちゃん様

ありがとうございます。アプリはFormを使用しています。

となると、シェルは利用しないほうが良いということですね。

>ファイルとフォルダを同時に選択したいというのはどういう状況なのでしょう?

アップロード機能を作成しております。

フォルダ選択の場合はフォルダ配下全てを、ファイル選択の場合は対象ファイルのみをアップロードします。

ファイルと同階層のフォルダも選択したい、または複数選択したい、という感じです。

私のスキル的に自作のダイアログを用意するのは厳しそうです。

ファイル選択とフォルダ選択を分けるのが無難ということですね…。


2014年2月18日火曜日 7:43

とっちゃん様

ありがとうございます。

>Formを使っているのであれば、APIを直接利用するよりもラップして使いやすくしている FolderBrowseDialog の利用をお勧めします。

そういうことでしたか、失;いたしました。

>ファイルやフォルダの選択にエクスプローラからのドロップや、コピー&ペーストを可能にするというのはどうでしょう?

ドラック&ドロップを試してみました。

フォルダ/ファイルを同時に選択でき、尚且つフルパスを取得できました。

この方法で検討を進めようと思います。

進展がありましたら、報告させていただきます。


2014年2月25日火曜日 7:20

>にゃにゃお様、とっちゃん様

お二方ともに、回答ありがとうございました。

簡単に拡張できないのは残念でしたが、用途に合わせて使い分けるべきだと再認識できました。

とっちゃん様に提示して頂いたドロップでのパス取得の方向で進めております。

今回はこれにて解決とさせて頂きます。m(_ _)m