web-dev-qa-db-ja.com

.NETの同じダイアログからファイルまたはフォルダを選択します

同じダイアログからファイルORフォルダを選択する「簡単な」方法はありますか?

私が作成する多くのアプリでは、ファイルまたはフォルダーの両方を入力として許可しています。今までは、ファイルまたはフォルダの選択ダイアログを切り替えるスイッチを作成するか、ドラッグアンドドロップ機能のみを使用していた。

これは基本的なことのように思われるので、これは以前に作成されたものだと想像しますが、グーグルを使用しても多くの情報は得られません。だから私はゼロから始めてカスタム選択ダイアログを作成する必要があるようですが、そのような些細なタスクのためにホイールを再発明することで問題を導入することはしません。

誰かヒントや既存の解決策はありますか?

UIの一貫性を保つには、OpenFileDialog(またはFolderBrowserDialog)を拡張できると便利です。

31
barry

技術的には可能です。 FolderBrowseDialogで使用されるシェルダイアログには、ファイルとフォルダの両方を返す機能があります。残念ながら、その機能は.NETでは公開されていません。リフレクションすら必要なオプションフラグを突くことができません。

これを機能させるには、BROWSEINFO.ulFlagsでBIF_BROWSEINCLUDEFILESフラグをオンにしてSHBrowseForFolder()をP/Invokeする必要があります(値= 0x4000)。 P/Invokeはザラザラしているので、コードを another source またはReflectorの助けを借りてFolderBrowseDialogクラス自体からコピーして貼り付けるのが最善です。

12
Hans Passant

上記のヒントに基づいて、次の場所にある標準のフォルダーブラウザーダイアログを使用するいくつかの機能するコードを見つけました: http://topic.csdn.net/t/20020703/05/845468.html

拡張されたフォルダブラウザダイアログのクラス

Imports System   
Imports System.Text   
Imports System.Windows.Forms   
Imports System.Runtime.InteropServices   

Public Class DirectoryDialog 
    Public Structure BROWSEINFO 
        Public hWndOwner As IntPtr 
        Public pIDLRoot As Integer 
        Public pszDisplayName As String 
        Public lpszTitle As String 
        Public ulFlags As Integer 
        Public lpfnCallback As Integer 
        Public lParam As Integer 
        Public iImage As Integer 
    End Structure 

    Const MAX_PATH As Integer = 260

    Public Enum BrowseForTypes As Integer 
        Computers = 4096 
        Directories = 1 
        FilesAndDirectories = 16384 
        FileSystemAncestors = 8 
    End Enum 

    Declare Function CoTaskMemFree Lib "ole32" Alias "CoTaskMemFree" (ByVal hMem As IntPtr) As Integer 
    Declare Function lstrcat Lib "kernel32" Alias "lstrcat" (ByVal lpString1 As String, ByVal lpString2 As String) As IntPtr 
    Declare Function SHBrowseForFolder Lib "Shell32" Alias "SHBrowseForFolder" (ByRef lpbi As BROWSEINFO) As IntPtr 
    Declare Function SHGetPathFromIDList Lib "Shell32" Alias "SHGetPathFromIDList" (ByVal pidList As IntPtr, ByVal lpBuffer As StringBuilder) As Integer 
    Protected Function RunDialog(ByVal hWndOwner As IntPtr) As Boolean 

        Dim udtBI As BROWSEINFO = New BROWSEINFO() 
        Dim lpIDList As IntPtr 
        Dim hTitle As GCHandle = GCHandle.Alloc(Title, GCHandleType.Pinned) 
        udtBI.hWndOwner = hWndOwner 
        udtBI.lpszTitle = Title 
        udtBI.ulFlags = BrowseFor 
        Dim buffer As StringBuilder = New StringBuilder(MAX_PATH) 
        buffer.Length = MAX_PATH 
        udtBI.pszDisplayName = buffer.ToString() 
        lpIDList = SHBrowseForFolder(udtBI) 
        hTitle.Free() 
        If lpIDList.ToInt64() <> 0 Then 
            If BrowseFor = BrowseForTypes.Computers Then 
                m_Selected = udtBI.pszDisplayName.Trim() 
            Else 
                Dim path As StringBuilder = New StringBuilder(MAX_PATH) 
                SHGetPathFromIDList(lpIDList, path) 
                m_Selected = path.ToString() 
            End If 
            CoTaskMemFree(lpIDList) 
        Else 
            Return False 
        End If 
        Return True 
    End Function 

    Public Function ShowDialog() As DialogResult 
        Return ShowDialog(Nothing) 
    End Function 

    Public Function ShowDialog(ByVal owner As IWin32Window) As DialogResult 
        Dim handle As IntPtr 
        If Not owner Is Nothing Then 
            handle = owner.Handle 
        Else 
            handle = IntPtr.Zero 
        End If 
        If RunDialog(handle) Then 
            Return DialogResult.OK 
        Else 
            Return DialogResult.Cancel 
        End If 
    End Function 

    Public Property Title() As String 
        Get 
            Return m_Title 
        End Get 
        Set(ByVal Value As String) 
            If Value Is DBNull.Value Then 
                Throw New ArgumentNullException() 
            End If 
            m_Title = Value 
        End Set 
    End Property

    Public ReadOnly Property Selected() As String 
        Get 
            Return m_Selected 
        End Get 
    End Property 

    Public Property BrowseFor() As BrowseForTypes
        Get 
            Return m_BrowseFor 
        End Get 
        Set(ByVal Value As BrowseForTypes) 
            m_BrowseFor = Value 
        End Set 
    End Property 

    Private m_BrowseFor As BrowseForTypes = BrowseForTypes.Directories 
    Private m_Title As String = "" 
    Private m_Selected As String = "" 

    Public Sub New() 
    End Sub
End Class 

拡張ダイアログを実装するコード

Sub Button1Click(ByVal sender As Object, ByVal e As EventArgs)
    Dim frmd As DirectoryDialog = New DirectoryDialog()
    ' frmd.BrowseFor = DirectoryDialog.BrowseForTypes.Directories   
    ' frmd.BrowseFor = DirectoryDialog.BrowseForTypes.Computers   
    frmd.BrowseFor = DirectoryDialog.BrowseForTypes.FilesAndDirectories   
    frmd.Title = "Select a file or a folder"    
    If frmd.ShowDialog(Me) = DialogResult.OK Then   
        MsgBox(frmd.Selected)   
    End If   
End Sub
7
barry

完了しました。 FolderBrowserDialogEx -組み込みのFolderBrowserDialogの再利用可能な派生物を使用できます。これにより、UNCパスも含め、パスを入力できます。フォルダー、またはファイル+フォルダーを参照できます。それを使用してコンピューターまたはプリンターを参照できます。組み込みFBDに基づいていますが、...優れています。より柔軟。 GUIでフォルダーをクリックすると、パスがテキストボックスに表示されます。パスを入力すると、フォルダがアクティブになります。組み込みダイアログにはないオプションがたくさんあります。

完全なソースコード。自由。 MS-Publicライセンス。

FolderBrowserDialogEx

それを使用するコード:

     var dlg1 = new Ionic.Utils.FolderBrowserDialogEx();
     dlg1.Description = "Select a folder to extract to:";
     dlg1.ShowNewFolderButton = true;
     dlg1.ShowEditBox = true;
     //dlg1.NewStyle = false;
     dlg1.SelectedPath = txtExtractDirectory.Text;
     dlg1.ShowFullPathInEditBox = true;
     dlg1.RootFolder = System.Environment.SpecialFolder.MyComputer;

     // Show the FolderBrowserDialog.
     DialogResult result = dlg1.ShowDialog();
     if (result == DialogResult.OK)
     {
         txtExtractDirectory.Text = dlg1.SelectedPath;
     }
5
Cheeso

標準のOpenFileDialogを使用してフォルダーを選択できます。これを行う方法を示したCodeProjectの記事を次に示します( http://www.codeproject.com/KB/dialog/OpenFileOrFolderDialog.aspx )。

5
stankovski

http://www.pinvoke.net/default.aspx/Shell32.shbrowseforfolder

このサンプルで変更した場合、ここにgeratリンクがあります

  bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;

for

  bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE | BIF_BROWSEINCLUDEFILES;

あなたはあなたが望むものを得るでしょう

1
Araym

私の知る限り、.NETフレームワークには、これをそのまま使用するものは何もありません。

.NETファイルダイアログは CommonDialog から派生します。

継承されたクラスは、ShowDialogを呼び出して特定の共通ダイアログボックスを作成することにより、RunDialogを実装する必要があります。継承されたクラスは、HookProcをオーバーライドして、特定のダイアログボックスのフック機能を実装できます。

1
Mitch Wheat

すべての組み込みダイアログは、そのアクションに対応するシェルAPI、PrintDialog、OpenFileDialog、SaveFileDialogなどを使用します。

ほとんどの場合、この機能を手動で構築する必要があります。

1
Tom Anderson

特定のファイルタイプのみを表示する場合は、次の article (C#のソースコードを使用)が役立ちます。

http://www.codeproject.com/KB/Shell/csdoesshell1.aspx?fid=14137&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26

また、FolderBrowserダイアログを「カスタマイズ」するために使用できる他のオプションについても説明します。

0
barry

Ookii Dialogsは、ファイルまたはフォルダーの両方を入力として許可するフォルダーブラウザーダイアログを実装し、WindowsフォームおよびWPF。

enter image description here

Ookii.Dialogs.Wpf

https://github.com/caioproiete/ookii-dialogs-wpf


Ookii.Dialogs.WinForms

https://github.com/caioproiete/ookii-dialogs-winforms

0
Caio Proiete

これにより、OpenFileDialogを使用してフォルダーを選択できます

        openFileDialog1.CheckFileExists = false;
        openFileDialog1.ValidateNames = false;
0
Jason P