Выберите файл или папку в том же диалоговом окне в .NET.
-
06-07-2019 - |
Вопрос
Есть ли «простой» способ выбрать файл ИЛИ папку из одного и того же диалогового окна?
Во многих приложениях, которые я создаю, я разрешаю использовать как файлы, так и папки в качестве входных данных.До сих пор я всегда создавал переключатель для переключения между диалоговыми окнами выбора файлов или папок или придерживался только функции перетаскивания.
Поскольку это кажется такой простой вещью, я предполагаю, что это было создано раньше, но поиск в Google не дает большого количества информации.Похоже, мне придется начать с нуля и создать собственный диалог выбора, но я предпочитаю не создавать никаких проблем, изобретая велосипед для такой тривиальной задачи.
Есть ли у кого-нибудь какие-нибудь советы или существующие решения?
Чтобы обеспечить единообразие пользовательского интерфейса, было бы неплохо расширить OpenFileDialog (или FolderBrowserDialog).
Решение
Технически это возможно. Диалоговое окно оболочки, используемое FolderBrowseDialog, может возвращать как файлы, так и папки. К сожалению, эта возможность не предоставляется в .NET. Даже отражение не может поставить нужный флаг опции.
Чтобы это работало, вам нужно выполнить P / Invoke SHBrowseForFolder () с включенным флагом BIF_BROWSEINCLUDEFILES в BROWSEINFO.ulFlags (значение = 0x4000). P / Invoke является жестким, лучше всего скопировать и вставить код из другой источник или сам класс FolderBrowseDialog с помощью Reflector.
Другие советы
На основе приведенных выше советов я нашел несколько рабочих кодов, в которых используется стандартное диалоговое окно просмотра папок, по следующему адресу: 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, но ... лучше. Более гибкий. Если щелкнуть папку в графическом интерфейсе, путь появится в текстовом поле. Если вы введете путь, папка будет активирована. Много опций, которых нет во встроенном диалоге. Р>
Полный исходный код. Свободно. MS-Public License.
Код для его использования:
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 Framework нет ничего такого, что могло бы сделать это «из коробки». Р>
. Диалоги файлов .NET происходят от CommonDialog а>: р>
Унаследованные классы необходимы для
реализовать RunDialog, вызвав
ShowDialog для создания определенного общего
диалоговое окно. Унаследованные классы могут
переопределить HookProc для реализации
конкретный диалог диалогового окна
функциональность. р>
Все встроенные диалоговые окна используют API-интерфейсы оболочки, соответствующие их действию, PrintDialog, OpenFileDialog, SaveFileDialog и т. д.
Скорее всего, вам придется вручную создавать эту функцию.
Если вы хотите отображать только определенные типы файлов, выполните следующие действия: статья (с исходным кодом на C #) может помочь вам:
Здесь также объясняются другие параметры, доступные для " настройки " диалоговое окно FolderBrowser,
это позволит вам выбирать папки, используя OpenFileDialog
openFileDialog1.CheckFileExists = false;
openFileDialog1.ValidateNames = false;
А Диалоги оокии реализовать диалог браузера папок, который позволяет использовать как файлы, так и папки в качестве входных данных и доступен для Windows Forms и WPF.
Ookii.Dialogs.Wpf
Ookii.Dialogs.WinForms