Selecione um arquivo ou pasta a partir da mesma caixa de diálogo em .NET
-
06-07-2019 - |
Pergunta
Existe uma maneira "fácil" para selecionar um arquivo ou uma pasta a partir da mesma caixa de diálogo?
Em muitos aplicativos que criam I permitir a ambos os arquivos ou pastas como entrada. Até agora eu sempre acabam criando um interruptor para alternar entre janelas de arquivos ou seleção de pastas ou vara com apenas a funcionalidade drag-and-drop.
Uma vez que esta parece uma coisa tão básica I pode imaginar este foi criado antes, mas googling não resulta em muita informação. Portanto, parece que eu teria que começar do zero e criar uma seleção personalizada de diálogo, mas eu prefiro não introduzir quaisquer problemas por reinventar a roda para uma tarefa tão trivial.
Qualquer pessoa alguma dica ou soluções existentes?
Para manter a interface do usuário consistente seria bom se é possível estender o OpenFileDialog (ou o FolderBrowserDialog).
Solução
Tecnicamente, é possível. O diálogo shell usado por FolderBrowseDialog tem a capacidade de voltar os arquivos e pastas. Infelizmente, essa capacidade não é exposto em .NET. Nem mesmo a reflexão pode picar o sinalizador de opção necessário.
Para fazê-lo funcionar, você teria de P / Invoke SHBrowseForFolder () com o sinalizador BIF_BROWSEINCLUDEFILES ativada no BROWSEINFO.ulFlags (valor = 0x4000). A P / Invoke é corajoso, o melhor é copiar e colar o código de outra fonte ou a própria classe FolderBrowseDialog com a ajuda de refletor.
Outras dicas
Com base nas dicas acima eu encontrei algum código de trabalho que usa o diálogo do navegador de pastas padrão no seguinte local: http://topic.csdn.net/t/20020703/05/845468.html
A classe para o navegador de pastas prolongado diálogo
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
O código para implementar o diálogo alargado
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
Você pode usar o OpenFileDialog padrão para selecionar uma pasta. Aqui está um artigo no CodeProject que demonstrou uma maneira de fazê-lo ( http: // www. codeproject.com/KB/dialog/OpenFileOrFolderDialog.aspx ).
Isso já foi feito. Você pode usar FolderBrowserDialogEx - um derivado de re-utilizável do FolderBrowserDialog embutido. Este permite que você digite um caminho, mesmo um caminho UNC. Você pode navegar por pastas ou arquivos + pastas. Você pode navegar para computadores ou impressoras com ele. Com base na built-in FBD, mas ... melhor. Mais flexível. Se você clicar em uma pasta na GUI, o caminho aparece na caixa de texto. Se você digitar um caminho, a pasta fica activatied. Muitas opções de diálogo embutido não tem.
código fonte completo. Livre. MS-Public licença.
código para usá-lo:
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, não há nada no framework .NET que faz isso fora da caixa.
Os diálogos de arquivo .NET derivam CommonDialog :
classes herdadas são obrigados a implementar RunDialog invocando ShowDialog para criar um específico comum caixa de diálogo. classes herdadas pode substituir HookProc para implementar gancho de caixa de diálogo específica funcionalidade.
Todos os construído em diálogos usar a API do shell é que correspondem à sua acção, PrintDialog, OpenFileDialog, SaveFileDialog, etc ...
Você provavelmente tem que construir manualmente essa funcionalidade.
http://www.pinvoke.net/default.aspx/shell32.shbrowseforfolder
aqui é o link gerat se você mudar nesta amostra
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;
para
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE | BIF_BROWSEINCLUDEFILES;
você vai conseguir o que deseja
Se você gostaria de exibir tipos de arquivo única específicos, o seguinte artigo (com código fonte em C #) pode ajudá-lo:
Ele também explica as outras opções que estão disponíveis para "personalizar" o diálogo FolderBrowser,
isso irá permitir que você selecione as pastas usando OpenFileDialog
openFileDialog1.CheckFileExists = false;
openFileDialog1.ValidateNames = false;
O Ookii Diálogos implementar um diálogo do navegador pasta que permitir tanto arquivos ou pastas como entrada, e está disponível para Windows Forms e WPF.
Ookii.Dialogs.Wpf
Ookii.Dialogs.WinForms