2017年6月14日水曜日

VB Folder 選択ダイアログに思う

Folder Dialog での 特殊フォルダの動きが変です。
少し前迄の MyComputer が機能していなかったのは解消されていますが、Win10 v1703 b15063.332
MyMusic やら MyPictures やら MyDocuments 等のものを出そうとすると一筋縄では行きません。
どうやら、Microsoft さま は Form でのサポートに混乱があるとも思えて来ます。
MyMusic やら MyPictures やら MyDocuments 等 は過去の遺産と化すのでしょうか ... 。


Form を止めて WPF に遷りなさい と言う事でしょうか?。
いいえ、WPF には 標準の Folder Dialog は存在しませんし ... 。

現状での問題は MyMusic やら MyPictures やら MyDocuments 等 を扱うと Folder Dialog が機能し難い と言う事。

そして、これ迄の経緯を踏まえれば、今後も、確実に動くのは Default 値の Desktop のみと考えて置いた方が良いかも です。
確かに、現在、MyComputer を Root に設定すれば、動いてはくれますが、 また何時、方針変換があるか分かりません。
そこで、どうしたら、以前の様に、特殊フォルダを扱えるか考えて見ました。

確実なのは、先ず、選択肢に 必ず Desktop を残して置く方法です。
これなら、ユーザーは、最悪、候補を展開して目的のものに辿り着けますから。

次に、特殊フォルダは、上で書いたユーザーの行動を再現させます。
つまり、確実な Root から 階層を辿る 手段を模写しましょう。
具体的には、
Root Me.FolderBrowserDialog1.RootFolder を Desktop 若しくは MyComputer にして置き、
Current の Me.FolderBrowserDialog1.SelectedPath を Environment.SpecialFolder の列挙体にします。
そして、 .Show する前に、 キーを送ります。
Tab + Tab + Right キーです。
Tab + Tab で TreeView を選ばせ、 Right で候補を展開させます。
これで、 特殊フォルダ が展開された状態で Dialog が開いて来ます。

正常に表示されるものにキー送信は不要ですので、条件分岐で処理します。
一応、 各候補項目で表示を合わせる為に、Tab + Tab を送って置きますね。.


尚、どうせ書くなら、色々なケースを試そうと思って、Network 等も入れた処、大苦戦!。
結局、 Internet の情報に救われたのですが、
My 系のもの も これを応用して 行けそうです。  いえ、行けません でした。
分かっていないのは怖いですね。  他の My 系のものは この手法でも やはり 駄目です ... 。

そして、取り敢えず、形にすると、 今度は、続けて Dialog を開いた時の挙動に ... ? が。
USB メモリ等の Removable な Folder を選ぶと、次回に表示を持ち越さないのです ... 。

振り出しに戻る ... と。
でも、固定ディスク は 何も無かったかの如く 持ち越してくれます。

一体、どうなってるのだろう ... 。


やはり、 Folder Dialog は 鬼門 です。


さて、 Code 。

前回の投稿 VB OS に左右される関数 Environment.SpecialFolder (CODE) を手直しします。

Public Class Form1

    Private serchedPathPC As String = ""

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        With Me.ComboBoxRoot.Items
            .Add("Pictures")
            .Add("Documents")
            .Add("Computer")
            .Add("Computer_1stDrv")
            .Add("Desktop")
            .Add("DesktopDir")
            .Add("Network")
        End With
        Me.ComboBoxRoot.SelectedIndex = 2
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Select Case Me.ComboBoxRoot.Text
            Case "Pictures"
                Me.FolderBrowserDialog1.RootFolder = Environment.SpecialFolder.Desktop
                Me.FolderBrowserDialog1.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
                SendKeys.Send("{TAB}{TAB}{Right}")
            Case "Documents"
                Me.FolderBrowserDialog1.RootFolder = Environment.SpecialFolder.Desktop
                Me.FolderBrowserDialog1.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
                SendKeys.Send("{TAB}{TAB}{Right}")
            Case "Computer"
                Me.FolderBrowserDialog1.RootFolder = Environment.SpecialFolder.MyComputer
                SendKeys.Send("{TAB}{TAB}")
            Case "Computer_1stDrv"
                Me.FolderBrowserDialog1.RootFolder = Environment.SpecialFolder.MyComputer
                'Me.FolderBrowserDialog1.SelectedPath = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"   '"PC" Selected (Win10) (Win7=Computer)
                If serchedPathPC = "" Then
                    Me.FolderBrowserDialog1.SelectedPath = Environment.GetEnvironmentVariable("SystemDrive")    '"C:" Drive Selected Mostly
                Else
                    Me.FolderBrowserDialog1.SelectedPath = serchedPathPC    'Notice: Remobvable Drive Can Not Show!
                End If
                SendKeys.Send("{TAB}{TAB}")
            Case "Desktop"
                Me.FolderBrowserDialog1.RootFolder = Environment.SpecialFolder.Desktop
                SendKeys.Send("{TAB}{TAB}")
            Case "DesktopDir"
                Me.FolderBrowserDialog1.RootFolder = Environment.SpecialFolder.DesktopDirectory
                SendKeys.Send("{TAB}{TAB}")
            Case "Network"
                'https://www.codeproject.com/Articles/20547/How-to-Browse-Network-Folders-using-Folder-Dialog
                Dim type As Type = Me.FolderBrowserDialog1.[GetType]
                'Get Fieldinfo For Rootfolder
                Dim fieldInfo As Reflection.FieldInfo = _
                    type.GetField("rootFolder", _
                    Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)
                'Set The Value For Folder Dialog Using DirectCast
                '18 = Network Neighborhood, The Root
                fieldInfo.SetValue(Me.FolderBrowserDialog1, _
                      DirectCast(18, Environment.SpecialFolder))
                SendKeys.Send("{TAB}{TAB}")
            Case Else
                Me.FolderBrowserDialog1.RootFolder = Environment.SpecialFolder.MyComputer
                SendKeys.Send("{TAB}{TAB}")
        End Select
        Me.FolderBrowserDialog1.Description = "Select Directory  on " & Me.ComboBoxRoot.Text
        Me.FolderBrowserDialog1.ShowDialog()
        Me.TextBoxPath.Text = IIf(Me.FolderBrowserDialog1.SelectedPath.Length = 3, _
                                  Me.FolderBrowserDialog1.SelectedPath, _
                                  Me.FolderBrowserDialog1.SelectedPath & "\")
        If Me.ComboBoxRoot.Text = "Computer_1stDrv" Then
            serchedPathPC = Me.FolderBrowserDialog1.SelectedPath
        End If
    End Sub

End Class

あ~、 どうすりゃ いいんだろぅ ... 。
OS の更新挙動に振り廻される この仕組み。



0 件のコメント:

コメントを投稿