« 絶対 | トップページ | 押しちゃうよ »

2020年7月14日 (火)

フォルダ選択ダイアログ

梅雨らしい雨の降り方は、今日で終わり?

朝は、豪雨というほどではなかったけれど、結構強めの雨が降った。

お昼前に雨は上がり、太陽が出た。

 

VB.netで、どうして標準でこの機能を提供していないのだろう?と思うものがある。

それは、フォルダ選択ダイアログである。

VB.netでは、「FolderBrowserDialog」を使って、フォルダ選択ダイアログを表示する。

これがめちゃくちゃ扱いづらい!

階層が深いと、クリック、クリック、クリック、・・・とずーっと辿っていかないといけない。

ソフトによっては、ファイル選択ダイアログと同じようなフォルダ選択ダイアログを使っているものもある。

これであれば、いちいちクリックし続けなくても、パスを丸ごとコピペすれば、一気にその場所まで行くことが出来る。

VB.netでは、上記のダイアログしか提供されていないのに、どうしてそういうダイアログを提供しているソフトがあるのだろう?と不思議だった。

疑問は解決。

VB.netでは標準でそういうのは提供されていないけれど、外部DLLを読み込んで、それを表示しているようだ。

NuGetパッケージマネージャーから、「windowsapicodepack」とでも入力すれば、色々と出てくる。

有名なのは、次の2つ。

Aybeという人が作った「WindowsAPICodePack-Core」「WindowsAPICodePack-Shell」。DLLファイルは2つ。

もう一つは、Microsoftが提供している「Microsoft.WindowsAPICodePack-Core」「Microsoft.WindowsAPICodePack-Shell」。DLLファイルは3つ。

どちらも複数ファイルで、ファイルサイズが数百KB。

そういうライブラリから、色んな機能を抽出して使うならまだしも、フォルダ選択ダイアログのためだけにそれらを使うというのはなぁ、と思った。

もしかしたら、フォルダ選択ダイアログだけに特化したものがあるのでは?と思って探してみると、あった!

BetterFolderBrowser」というものがそれ。

比較的最近にも更新されているので、問題ないと思う。

これであれば、DLLファイルは一つだし、サイズはたったの13KB!

これはいい!

ライブラリをインポートして、下記のサンプルのように定義し、呼び出す。

Imports WK.Libraries.BetterFolderBrowserNS

Private Sub Test()
    Dim bfb = New BetterFolderBrowser()
    bfb.Title = "Select a folder..."
    bfb.Multiselect = True
    bfb.RootFolder = System.Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)

    If bfb.ShowDialog() = DialogResult.OK Then
       MsgBox(bfb.SelectedFolder)
    End If
End Sub

すると、他のソフトでも見られた、フォルダ選択ダイアログが出てくる。

これの面白いところは、複数フォルダを選択出来るというところ。

「.Multiselect」を「True」にすればいい。
データは、「.SelectedFolders」にし、これが配列になっているので、ループして取り出せばいい。

これを取り込めば、フォルダ選択ダイアログの使い勝手が良くなる。

ただ、こういうのって、もう一般的だったりするのだから、VB.netで標準装備してほしいと思う。

裏技的に、ファイル選択ダイアログ「OpenFileDialog」をフォルダ選択ダイアログのようにして使うやり方もある。

OpenFileDialog でフォルダを指定する [ WinForms ] - Qiita

Private Sub Test()
    Dim fbd = New OpenFileDialog()
    fbd.FileName = "SelectFolder"
    fbd.Filter = "Folder|."
    fbd.CheckFileExists = False

    If fbd.ShowDialog() = DialogResult.OK Then
        MsbBox(System.IO.Path.GetDirectoryName(fbd.FileName))
    End If
End Sub

やっていることは、ファイルを非表示にして、フォルダだけを表示している。
ダミーで、ファイル名を「SelectFolder」というものにして、そこから、フォルダのパスを取得。

試してみたけれど、DLLを全く使わないのが一番のメリット。

動作は「概ね」OK。

「概ね」OKなのは、親フォルダを選択し、それを得たい場合はちょっと融通が利かない。
親の親を選択しておかないと、それを得られないのである。

一度選択したものは、非選択に出来ない。
それを一旦クリアするために、親の親を選択する必要性がある。

言葉だとわかりづらいけれど、やってみればわかるでしょう。

個人で使う場合は、それを頭に入れて使えばいいけれど、一般の人が使うとなると、混乱を招きかねない。

ということで、一般の人にも使ってもらうことを考えると、「BetterFolderBrowser」を使うのが無難なようだ。

 

12月10日(木)追記。

この記事、ちょこちょこ覗かれているようなので、新たな情報を追記。

フォルダ選択ダイアログにこだわり続け、探しに探して、更にいいものを見つけた。

世の中、すごい人が一杯いるねぇ。

まずは、上記のOpenFileDialogと同様に、ちょっとした修正で、フォルダ選択ダイアログのように使うやり方。

なんとまぁ、SaveFileDialogを使うというもの!

c# - How do I Use OpenFileDialog to select files or paths - Stack Overflow

このページの一番下に書かれている。

OpenFileDialogとSaveFileDialog、同じように思えて、同じ動きをしないという不思議。(笑)

作ってみればわかるけれど、明らかに、SaveFileDialogの方が、よりフォルダ選択に相応しいのがわかる。

フォルダの再選択も普通。

ここに書かれているものをもうちょっと工夫すれば、よりよくなると思う。

難点は、ボタンが「保存」のまま、そして、どういう訳か、URLのショートカットキーのファイルだけが表示される。

それを選択すると、「上書きしますか?」と聞かれる時がある。
OKを押しても実害はないけれど、ちょっと気持ち悪いかもしれない。

でも、総合的に見て、OpenFileDialogよりはるかにいいし、9割以上、許容可能な出来だと思う。

処理としては、replaceを2回しているところがあるけれど、そこは「IO.Path.GetDirectoryName(path)」で問題ない。
これできちんとパスを取得してくれる。

面白いハッキングだし、OpenFileDialogと動きが違うというのを知ることが出来て面白い。

次は、IFileOpenDialogを利用したフォルダ選択ダイアログ。

上記では、外部DLLを読み込みするものを紹介した。

これらは、

その1
GitHub - Jack-M-Code/FolderBrowserDialog: Visual Studio 2017 default FolderBrowserDialog not practical The component will be overridden

その2
「まともな」フォルダ選択ダイアログ(Vista以降) - 簡単に FileOpenDialog を実装してみる - Qiita

その3
Trying to open a file dialog using the new IFileDialog and IFileOpenDialog interfaces in C# with minimal code - Stack Overflow

その4
OpenFolderDialog – Medo's Home Page

どれも外部DLL化されておらず、ソースだけがあり、Class化されている。
その1とその2はほぼ同じ作りで、ちょこっとだけ違っている。
その3は、Vista-style folder pickerを使ったものとのこと。その4は、その3に近いやり方。
その1やその2とは違ったアプローチになっている。

C#で書かれているので、C#なら、そのまま使える(はず)。
僕は、VB.NETなので、変換を掛けてみた。
全てきちんと変換が掛からなかったので、ところどころ修正。

その1のソースの下の方の関数やEnumの変数は全て使われているわけではないようなので、不要なものは削除してもいいかも。

その2のソース、「If Not hr.Equals(0) Then Return System.Windows.Forms.DialogResult.Abort」がうまく機能していないらしく、前者と同じ「 If hr <> 0 Then Return DialogResult.Abort」に変えたらちゃんと動いた。
これは、VB.NETのソース。

その3は、変換後のVB.NETのソースをところどころ修正。

もうお腹一杯だったので(苦笑)、その4はVB.NETに変換せず、C#のままコンパイルして動作確認。

VB.NETに変換するにはちょっと手間がいるけれど、どれもちゃんと動くではないか!
大掛かりな修正、変更ではないのに、ちゃんとフォルダ選択ダイアログになっている。

動き、見た目、そのまんま、フォルダ選択ダイアログである。
また、4つとも、見た目に差異は感じない。

Visual Studio標準で何とかしたいという人は、SaveFileDialogのハッキング、外部DLLは使いたくない人で、Class化して、ちゃんとしたフォルダ選択ダイアログにしたい人は、これらを使わせてもらうといいだろう。

これでフォルダ選択ダイアログに関しては、言うことなしになると思う。

|

« 絶対 | トップページ | 押しちゃうよ »

パソコン・インターネット」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




« 絶対 | トップページ | 押しちゃうよ »