同じダイアログからファイルORフォルダを選択する「簡単な」方法はありますか?
私が作成する多くのアプリでは、ファイルまたはフォルダーの両方を入力として許可しています。今までは、ファイルまたはフォルダの選択ダイアログを切り替えるスイッチを作成するか、ドラッグアンドドロップ機能のみを使用していた。
これは基本的なことのように思われるので、これは以前に作成されたものだと想像しますが、グーグルを使用しても多くの情報は得られません。だから私はゼロから始めてカスタム選択ダイアログを作成する必要があるようですが、そのような些細なタスクのためにホイールを再発明することで問題を導入することはしません。
誰かヒントや既存の解決策はありますか?
UIの一貫性を保つには、OpenFileDialog(またはFolderBrowserDialog)を拡張できると便利です。
技術的には可能です。 FolderBrowseDialogで使用されるシェルダイアログには、ファイルとフォルダの両方を返す機能があります。残念ながら、その機能は.NETでは公開されていません。リフレクションすら必要なオプションフラグを突くことができません。
これを機能させるには、BROWSEINFO.ulFlagsでBIF_BROWSEINCLUDEFILESフラグをオンにしてSHBrowseForFolder()をP/Invokeする必要があります(値= 0x4000)。 P/Invokeはザラザラしているので、コードを another source またはReflectorの助けを借りてFolderBrowseDialogクラス自体からコピーして貼り付けるのが最善です。
上記のヒントに基づいて、次の場所にある標準のフォルダーブラウザーダイアログを使用するいくつかの機能するコードを見つけました: 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
完了しました。 FolderBrowserDialogEx -組み込みのFolderBrowserDialogの再利用可能な派生物を使用できます。これにより、UNCパスも含め、パスを入力できます。フォルダー、またはファイル+フォルダーを参照できます。それを使用してコンピューターまたはプリンターを参照できます。組み込みFBDに基づいていますが、...優れています。より柔軟。 GUIでフォルダーをクリックすると、パスがテキストボックスに表示されます。パスを入力すると、フォルダがアクティブになります。組み込みダイアログにはないオプションがたくさんあります。
完全なソースコード。自由。 MS-Publicライセンス。
それを使用するコード:
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;
}
標準のOpenFileDialogを使用してフォルダーを選択できます。これを行う方法を示したCodeProjectの記事を次に示します( http://www.codeproject.com/KB/dialog/OpenFileOrFolderDialog.aspx )。
http://www.pinvoke.net/default.aspx/Shell32.shbrowseforfolder
このサンプルで変更した場合、ここにgeratリンクがあります
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;
for
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE | BIF_BROWSEINCLUDEFILES;
あなたはあなたが望むものを得るでしょう
私の知る限り、.NETフレームワークには、これをそのまま使用するものは何もありません。
.NETファイルダイアログは CommonDialog から派生します。
継承されたクラスは、ShowDialogを呼び出して特定の共通ダイアログボックスを作成することにより、RunDialogを実装する必要があります。継承されたクラスは、HookProcをオーバーライドして、特定のダイアログボックスのフック機能を実装できます。
すべての組み込みダイアログは、そのアクションに対応するシェルAPI、PrintDialog、OpenFileDialog、SaveFileDialogなどを使用します。
ほとんどの場合、この機能を手動で構築する必要があります。
特定のファイルタイプのみを表示する場合は、次の article (C#のソースコードを使用)が役立ちます。
また、FolderBrowserダイアログを「カスタマイズ」するために使用できる他のオプションについても説明します。
Ookii Dialogsは、ファイルまたはフォルダーの両方を入力として許可するフォルダーブラウザーダイアログを実装し、WindowsフォームおよびWPF。
Ookii.Dialogs.Wpf
Ookii.Dialogs.WinForms
これにより、OpenFileDialogを使用してフォルダーを選択できます
openFileDialog1.CheckFileExists = false;
openFileDialog1.ValidateNames = false;