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