Как настроить OpenFileDialog для выбора папок?

251

В VS .NET, когда вы выбираете папку для проекта, отображается диалоговое окно, которое выглядит как OpenFileDialog или SaveFileDialog, но настроено на прием только папок. С тех пор как я увидел это, я хотел знать, как это делается. Я знаю о FolderBrowserDialog, но мне никогда не нравился этот диалог. Он начинается слишком мало и не позволяет мне воспользоваться возможностью набрать путь.

Я почти уверен, что сейчас нет способа сделать это из .NET, но мне так же любопытно, как вы делаете это из неуправляемого кода. Если не считать полного переопределения диалога с нуля, как вы модифицируете диалог, чтобы иметь такое поведение?

Я также хотел бы повторить, что я знаю о FolderBrowserDialog, но иногда мне не нравится его использовать, в дополнение к искреннему любопытству, как настроить диалог таким образом. Указание мне просто использовать FolderBrowserDialog помогает мне поддерживать постоянный интерфейс, но не удовлетворяет мое любопытство, поэтому оно не считается ответом.

Это не специфичная для Vista вещь; Я видел этот диалог начиная с VS .NET 2003, поэтому его можно использовать в Win2k и WinXP. Это не вопрос «я хочу знать, как правильно это сделать», а вопрос «мне было любопытно, так как я впервые хотел сделать это в VS 2003». Я понимаю, что в файловом диалоге Vista есть возможность сделать это, но он работает в XP, поэтому я знаю, что они что- то сделали, чтобы заставить его работать. Специфичные для Vista ответы не являются ответами, потому что Vista не существует в контексте вопроса.

Обновление: Я принимая ответ Скотта Вишневски, потому что она поставляется с рабочим образцом, но я думаю , что Серж заслуживает похвалы за указывая на диалоговые настройки (который, по общему признанию противный из .NET , но это делает работу) и Марк Рэнс для выяснить , что MS наверное накатил собственный диалог для этой задачи.

OwenP
источник
7
просто простое решение от codeproject codeproject.com/Articles/44914/… [ключом к получению OpenFileDialog для выбора файлов и папок является установка для свойств ValidateNames и CheckFileExists значения false (dialog.ValidateNames = false; dialog.CheckFileExists = false) и установите для FileName какое-то специальное ключевое слово, чтобы убедиться, что папки выбраны (dialog.FileName = "Выбор папки";).]
Riju
3
Отправить это как ответ, он сделал работу для моего проекта.
CigarDoug
@Riju dialog.FileName = "Folder Selection"должен быть dialog.FileName = "Folder Selection."с завершающим периодом? во всяком случае, я не могу заставить его работать в powershell по второму щелчку «Открыть» в любом случае. Он продолжает говорить, что файл не найден, хотя CheckFileExists предположительно является ложным
ComradeJoecool
нвм, в настройках powershell dialog.CheckFileExists = 0вместо false решил мою проблему
ComradeJoecool
Вы пробовали Ookii Dialogs для WPF ?
С. Аугусто Проиете

Ответы:

57

У меня есть диалог, который я написал, называется диалог OpenFileOrFolder, который позволяет вам открыть папку или файл.

Если вы установите для его значения AcceptFiles значение false, то он будет работать только в режиме принятия папки.

Вы можете скачать исходники с GitHub здесь

Скотт Вишневски
источник
4
Очень интересно и определенно так сложно, как я рассчитывал. Есть ли возможность комментировать и указывать, что он делает? Это, наряду с другими комментариями, заставляет меня поверить, что MS, вероятно, просто развернула свой собственный диалог.
OwenP
1
Я получаю следующую ошибку при попытке построить ваше решение ... к сожалению, c ++ не является одной из моих сильных сторон ... Ошибка 1 не может открыть включаемый файл 'afxres.h'.
Игнасио Солер Гарсия
1
@SoMoS и другие с такой же проблемой: в файле WindowsFormsApplication1.csproj отредактируйте строку 100 так, чтобы она соответствовала вашей настройке. В моем случае мне пришлось изменить «9.0» на «10.0» (дважды) и удалить «(x86)» (дважды).
Ренни Пит
2
Я скачал код (zip) и обнаружил файл .h (C), и скомпилировал с ошибкой, например, не могу открыть включаемый файл «sal.h».
Лэй Ян
2
Это решение также не работает на VS2010 и VS2017!
AleX_
49

Вы можете использовать FolderBrowserDialogEx - повторно используемую производную от встроенного FolderBrowserDialog. Этот позволяет вам ввести путь, даже путь UNC. Вы также можете просматривать компьютеры или принтеры с ним. Работает так же, как встроенный FBD, но ... лучше.

(РЕДАКТИРОВАТЬ: я должен был указать, что этот диалог может быть установлен для выбора файлов или папок.)

Полный исходный код (один короткий модуль C #). Свободно. 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;
}
Cheeso
источник
7
Извините, если я обиделась, просто неприятно задавать вопрос и говорить: «Я хочу эту конкретную вещь, а не эти другие вещи», и люди с радостью предлагают незапрошенную вещь. Я хотел диалог браузера файлов, а не диалог браузера папок.
OwenP
15
Если сформулировать вопрос, мне кажется, что он запрашивает диалог выбора папки - разве это не так? Во всяком случае, это именно то, что я искал +1
Тим
Однозначно лучший ответ на данный момент
Василь Попов
1
Это не меняет того факта, что ответ по-прежнему является ответом только по ссылке. Показывать, как использовать код, размещенный на стороннем ресурсе, перестает быть полезным, когда эта ссылка тоже становится временно или постоянно недоступной. Правила существуют по определенной причине, и этот вклад противоречит этим правилам.
Инспектируемый
1
Я посмотрел на этот ответ, и он явно не ссылается на сторонний ресурс. Так что «любой ответ» явно неверен. Если вы чувствуете, что я слишком остро реагирую, возможно, вам стоит поднять вопрос в мета, чтобы обсудить правила. Я не буду Я просто применю их.
Инспектируемое
48

Существует пакет кода Windows API. У него много вещей, связанных с оболочкой, включая CommonOpenFileDialogкласс (в Microsoft.WindowsAPICodePack.Dialogsпространстве имен). Это идеальное решение - обычный открытый диалог с отображением только папок.

Вот пример того, как его использовать:

CommonOpenFileDialog cofd = new CommonOpenFileDialog();
cofd.IsFolderPicker = true;
cofd.ShowDialog();

К сожалению, Microsoft больше не поставляет этот пакет, но несколько человек неофициально загрузили двоичные файлы в NuGet. Один пример можно найти здесь . Этот пакет - просто материал для оболочки. Если вам это нужно, у того же пользователя есть несколько других пакетов, которые предлагают больше функциональности, присутствующих в оригинальном пакете.

Кен Уэйн ВандерЛинде
источник
1
Я не знал, что это в Windows API Code Pack - спасибо за указание на это.
Патрик Клаг
10
Класс CommonOpenFileDialog существует только в Windows Vista или более поздней версии, поэтому будет возникать исключение в старых операционных системах
Rachel
1
Подскажите, пожалуйста, как ссылаться на Windows API Code Pack?
Джефф
1
Архивная галерея была удалена. или так ссылка говорит .. Может ли это быть новым местом для этого?
По умолчанию
3
Кстати, класс CommonOpenFileDialog находится в пространстве имен Microsoft.WindowsAPICodePack.Dialogs (мне понадобилось время, чтобы его найти).
Моргб
35

Пакет Ookii.Dialogs содержит управляемую оболочку вокруг нового диалогового окна браузера папок (в стиле Vista). Это также изящно ухудшается на старых операционных системах.

Кристиан Клаузер
источник
2
Круто, это открытый исходный код в стиле BSD!
Роман Старков
7
Единственная проблема в том, что я не позволю мне использовать профиль клиента .net Framework в качестве цели.
Кугель
2
Очень хорошее решение. Это, на мой взгляд, лучший ответ. Именно то, что я искал с 3 лет.
Самуил
1
Еще одна проблема с этим решением: оно не позволяет пользователю вставлять несуществующий путь. Младший, сравнительно, но все же жаль.
Роман Старков
1
Лучший практический ответ для тех, кому нужен OpenFileDialogдиалог с папкой -style.
аква
27

Для этого лучше использовать FolderBrowserDialog.

using (FolderBrowserDialog dlg = new FolderBrowserDialog())
{
    dlg.Description = "Select a folder";
    if (dlg.ShowDialog() == DialogResult.OK)
    {
        MessageBox.Show("You selected: " + dlg.SelectedPath);
    }
}
Райан Фарли
источник
9
Я знаю, что лучше использовать FolderBrowserDialog. Мне любопытно, как это было сделано независимо. В любом случае FolderBrowserDialog воняет во многих отношениях; даже в Vista нет панели мест. Забавно, как если бы это было лучше MS до сих пор избегал этого в 3 версиях VS.
OwenP
24
FolderBrowserDialog имеет много проблем с удобством использования. Я бы не стал вносить это в приложение. Смотрите мой пост для диалога, который имеет гораздо лучшее удобство использования
Скотт Вишневски
6
FolderBrowserDialog не позволяет: - вводить / вставлять полные пути в текстовое поле внизу - использовать панель «Избранные ссылки» в Vista - использовать поиск в Vista
decasteljau
89
FolderBrowserDialog - действительно ужасная часть пользовательского интерфейса.
Маккенир
32
Серьезно, люди, ПОЖАЛУЙСТА, перестаньте вставлять этот раздражающий диалог в ваши приложения. Это ОЧЕНЬ ПЛОХОЙ пользовательский интерфейс, как подчеркивалось в предыдущих комментариях.
Роман Старков
23

После нескольких часов поисков я нашел этот ответ на leetNightShade в виде рабочего раствора .

Я верю, что есть три вещи, которые делают это решение намного лучше, чем все остальные.

  1. Это просто в использовании. Требуется только включить два файла (которые в любом случае можно объединить в один) в вашем проекте.
  2. Он возвращается к стандартному FolderBrowserDialog при использовании на XP или более старых системах.
  3. Автор дает разрешение на использование кода для любых целей, которые вы считаете нужными.

    Там нет лицензии как таковой, так как вы можете взять и сделать с кодом, что вы будете.

Загрузите код здесь .

Алекс Эссильфи
источник
@MattDavis: я подтвердил, что он работает на .NET Framework 4.0 (как стандартный, так и клиентский профиль). Просто убедитесь, что к вашему проекту добавлены и FolderSelectDialog.cs, и Reflector.cs. Одна вещь, хотя ... вы работаете на Windows 8? Я тестировал на компьютере Win7.
Алекс Эссильфи
@ Алекс Эссильфи, ты прав. Должно быть, я сделал что-то не так, втянув это в свой проект. Я удалю свой предыдущий комментарий для ясности.
Мэтт Дэвис
Пробежался по нескольким вариантам и подумал, что это лучший. Рекомендуя.
Jaded
Работал в windows 10 для меня. Хорошее простое решение
Дэвид Уилтон
должны уважать отказоустойчивость в старых системах
Mike M
17

Точное Audio Copy работает таким образом на Windows XP. Отображается стандартный диалог открытия файла, но поле имени файла содержит текст «Имя файла будет игнорироваться».

Просто угадайте здесь, но я подозреваю, что строка вводится в элемент управления редактирования поля со списком каждый раз, когда в диалог вносятся существенные изменения. Пока поле не пустое, а флажки диалогового окна не проверяют наличие файла, диалоговое окно можно закрыть в обычном режиме.

Изменить: это намного проще, чем я думал. Вот код на C ++ / MFC, вы можете перевести его в среду по вашему выбору.

CFileDialog dlg(true, NULL, "Filename will be ignored", OFN_HIDEREADONLY | OFN_NOVALIDATE | OFN_PATHMUSTEXIST | OFN_READONLY, NULL, this);
dlg.DoModal();

Редактировать 2: Это должен быть перевод на C #, но я не бегло говорю на C #, поэтому не стреляйте в меня, если он не работает.

OpenFileDialog openFileDialog1 = new OpenFileDialog();

openFileDialog1.FileName = "Filename will be ignored";
openFileDialog1.CheckPathExists = true;
openFileDialog1.ShowReadOnly = false;
openFileDialog1.ReadOnlyChecked = true;
openFileDialog1.CheckFileExists = false;
openFileDialog1.ValidateNames = false;

if(openFileDialog1.ShowDialog() == DialogResult.OK)
{
    // openFileDialog1.FileName should contain the folder and a dummy filename
}

Изменить 3: Наконец, посмотрел на фактическое диалоговое окно в Visual Studio 2005 (у меня не было доступа к нему ранее). Это не стандартный диалог открытия файла! Если вы проверите окна в Spy ++ и сравните их со стандартным открытым файлом, вы увидите, что структура и имена классов не совпадают. Если вы внимательно посмотрите, вы также можете заметить некоторые различия между содержимым диалогов. Мой вывод заключается в том, что Microsoft полностью заменила стандартный диалог в Visual Studio, чтобы дать ему такую ​​возможность. Мое решение или что-то подобное будет как можно ближе, если только вы не захотите написать свое собственное с нуля.

Марк Рэнсом
источник
17

Хорошо, позвольте мне попытаться соединить первую точку ;-) Немного поигравшись с Spy ++ или Winspector, вы увидите, что текстовое поле Папка в расположении проекта VS является настройкой стандартного диалога. Это не то же самое поле, что и текстовое поле имени файла в стандартном диалоговом окне, например в блокноте.

Оттуда, я полагаю, VS скрывает текстовые поля / комбинированные списки имен файлов и типов файлов и использует собственный шаблон диалога, чтобы добавить свою собственную часть внизу диалога.

РЕДАКТИРОВАТЬ: Вот пример такой настройки и как это сделать (в Win32. Не .NET):

m_ofn - это структура OPENFILENAME, которая лежит в основе диалогового окна файла. Добавьте эти 2 строки:

  m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEDIALOG_IMPORTXLIFF);
  m_ofn.Flags |= OFN_ENABLETEMPLATE;

где IDD_FILEDIALOG_IMPORTXLIFF - это пользовательский шаблон диалога, который будет добавлен внизу диалога. Смотрите часть в красном ниже. (источник: apptranslator.com )альтернативный текст

В этом случае настраиваемая часть - это только метка + гиперссылка, но это может быть любой диалог. Он может содержать кнопку ОК, которая позволит нам проверить выбор папки.

Но как мы избавимся от некоторых элементов управления в стандартной части диалога, я не знаю.

Более подробно в этой статье MSDN .

Серж Вотье
источник
1
Это звучит как некоторые объяснения, которые я слышал в прошлом, но я никогда не видел демонстрацию концепции. Есть ли в документации MSDN прохождение по этому поводу?
OwenP
10

Вы можете создать подкласс файлового диалога и получить доступ ко всем его элементам управления. У каждого есть идентификатор, который можно использовать для получения дескриптора окна. Затем вы можете показать и скрыть их, получать от них сообщения об изменениях выбора и т. Д. И т. Д. Все зависит от того, сколько усилий вы хотите предпринять.

Мы сделали это, используя поддержку классов WTL, и настроили диалог файлов, включив в него панель пользовательских мест и подключаемые представления COM.

MSDN предоставляет информацию о том, как сделать это с помощью Win32, эта статья CodeProject содержит пример , а эта статья CodeProject предоставляет пример .NET .

Джефф Йейтс
источник
10

Вы можете использовать такой код

  • Фильтр скрытия файлов
  • Имя файла скрыть первый текст

Для расширенного скрытия текстового поля для имени файла вам нужно взглянуть на OpenFileDialogEx

Код:

{
    openFileDialog2.FileName = "\r";
    openFileDialog1.Filter = "folders|*.neverseenthisfile";
    openFileDialog1.CheckFileExists = false;
    openFileDialog1.CheckPathExists = false;
}
Аврам
источник
Просто и это то, что мне нужно для Windows 7+
Хао Нгуен
Кроме того, OFN_NOVALIDATE требуется для флагов
Гоблин Алхимик
5

Я полагаю, что вы на Vista используете VS2008? В этом случае я думаю, что опция FOS_PICKFOLDERS используется при вызове диалогового окна файла Vista IFileDialog . Я боюсь, что в .NET-коде это потребовало бы большого количества грубого P / Invoke-кода взаимодействия, чтобы начать работать.

Дункан Смарт
источник
1
Vista , конкретные; Я впервые увидел это на VS 2003 на Windows XP.
OwenP
2

Первое решение

Я разработал это как очищенную версию диалога выбора папки в стиле .NET Win 7 Биллом Седдоном из lyquidity.com (у меня нет никакой принадлежности). (Я узнал о его коде из другого ответа на этой странице ). Я написал свой собственный, потому что его решение требует дополнительного класса Reflection, который не нужен для этой целевой цели, использует управление потоком на основе исключений, не кэширует результаты своих вызовов отражений. Обратите внимание, что вложенный статический VistaDialogкласс таков, что его статические переменные отражения не пытаются заполняться, если Showметод никогда не вызывается. Он возвращается к диалоговому окну до Vista, если не в достаточно высокой версии Windows. Должно работать в Windows 7, 8, 9, 10 и выше (теоретически).

using System;
using System.Reflection;
using System.Windows.Forms;

namespace ErikE.Shuriken {
    /// <summary>
    /// Present the Windows Vista-style open file dialog to select a folder. Fall back for older Windows Versions
    /// </summary>
    public class FolderSelectDialog {
        private string _initialDirectory;
        private string _title;
        private string _fileName = "";

        public string InitialDirectory {
            get { return string.IsNullOrEmpty(_initialDirectory) ? Environment.CurrentDirectory : _initialDirectory; }
            set { _initialDirectory = value; }
        }
        public string Title {
            get { return _title ?? "Select a folder"; }
            set { _title = value; }
        }
        public string FileName { get { return _fileName; } }

        public bool Show() { return Show(IntPtr.Zero); }

        /// <param name="hWndOwner">Handle of the control or window to be the parent of the file dialog</param>
        /// <returns>true if the user clicks OK</returns>
        public bool Show(IntPtr hWndOwner) {
            var result = Environment.OSVersion.Version.Major >= 6
                ? VistaDialog.Show(hWndOwner, InitialDirectory, Title)
                : ShowXpDialog(hWndOwner, InitialDirectory, Title);
            _fileName = result.FileName;
            return result.Result;
        }

        private struct ShowDialogResult {
            public bool Result { get; set; }
            public string FileName { get; set; }
        }

        private static ShowDialogResult ShowXpDialog(IntPtr ownerHandle, string initialDirectory, string title) {
            var folderBrowserDialog = new FolderBrowserDialog {
                Description = title,
                SelectedPath = initialDirectory,
                ShowNewFolderButton = false
            };
            var dialogResult = new ShowDialogResult();
            if (folderBrowserDialog.ShowDialog(new WindowWrapper(ownerHandle)) == DialogResult.OK) {
                dialogResult.Result = true;
                dialogResult.FileName = folderBrowserDialog.SelectedPath;
            }
            return dialogResult;
        }

        private static class VistaDialog {
            private const string c_foldersFilter = "Folders|\n";

            private const BindingFlags c_flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
            private readonly static Assembly s_windowsFormsAssembly = typeof(FileDialog).Assembly;
            private readonly static Type s_iFileDialogType = s_windowsFormsAssembly.GetType("System.Windows.Forms.FileDialogNative+IFileDialog");
            private readonly static MethodInfo s_createVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("CreateVistaDialog", c_flags);
            private readonly static MethodInfo s_onBeforeVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("OnBeforeVistaDialog", c_flags);
            private readonly static MethodInfo s_getOptionsMethodInfo = typeof(FileDialog).GetMethod("GetOptions", c_flags);
            private readonly static MethodInfo s_setOptionsMethodInfo = s_iFileDialogType.GetMethod("SetOptions", c_flags);
            private readonly static uint s_fosPickFoldersBitFlag = (uint) s_windowsFormsAssembly
                .GetType("System.Windows.Forms.FileDialogNative+FOS")
                .GetField("FOS_PICKFOLDERS")
                .GetValue(null);
            private readonly static ConstructorInfo s_vistaDialogEventsConstructorInfo = s_windowsFormsAssembly
                .GetType("System.Windows.Forms.FileDialog+VistaDialogEvents")
                .GetConstructor(c_flags, null, new[] { typeof(FileDialog) }, null);
            private readonly static MethodInfo s_adviseMethodInfo = s_iFileDialogType.GetMethod("Advise");
            private readonly static MethodInfo s_unAdviseMethodInfo = s_iFileDialogType.GetMethod("Unadvise");
            private readonly static MethodInfo s_showMethodInfo = s_iFileDialogType.GetMethod("Show");

            public static ShowDialogResult Show(IntPtr ownerHandle, string initialDirectory, string title) {
                var openFileDialog = new OpenFileDialog {
                    AddExtension = false,
                    CheckFileExists = false,
                    DereferenceLinks = true,
                    Filter = c_foldersFilter,
                    InitialDirectory = initialDirectory,
                    Multiselect = false,
                    Title = title
                };

                var iFileDialog = s_createVistaDialogMethodInfo.Invoke(openFileDialog, new object[] { });
                s_onBeforeVistaDialogMethodInfo.Invoke(openFileDialog, new[] { iFileDialog });
                s_setOptionsMethodInfo.Invoke(iFileDialog, new object[] { (uint) s_getOptionsMethodInfo.Invoke(openFileDialog, new object[] { }) | s_fosPickFoldersBitFlag });
                var adviseParametersWithOutputConnectionToken = new[] { s_vistaDialogEventsConstructorInfo.Invoke(new object[] { openFileDialog }), 0U };
                s_adviseMethodInfo.Invoke(iFileDialog, adviseParametersWithOutputConnectionToken);

                try {
                    int retVal = (int) s_showMethodInfo.Invoke(iFileDialog, new object[] { ownerHandle });
                    return new ShowDialogResult {
                        Result = retVal == 0,
                        FileName = openFileDialog.FileName
                    };
                }
                finally {
                    s_unAdviseMethodInfo.Invoke(iFileDialog, new[] { adviseParametersWithOutputConnectionToken[1] });
                }
            }
        }

        // Wrap an IWin32Window around an IntPtr
        private class WindowWrapper : IWin32Window {
            private readonly IntPtr _handle;
            public WindowWrapper(IntPtr handle) { _handle = handle; }
            public IntPtr Handle { get { return _handle; } }
        }
    }
}

Он используется примерно так в форме Windows:

var dialog = new FolderSelectDialog {
    InitialDirectory = musicFolderTextBox.Text,
    Title = "Select a folder to import music from"
};
if (dialog.Show(Handle)) {
    musicFolderTextBox.Text = dialog.FileName;
}

Конечно, вы можете поиграть с его параметрами и тем, какие свойства он предоставляет. Например, он разрешает множественный выбор в диалоге в стиле Vista.

Второе решение

Саймон Мурье дал ответ, который показывает, как выполнить ту же самую работу, используя взаимодействие с API-интерфейсом Windows напрямую, хотя его версию пришлось бы дополнить, чтобы использовать диалоговое окно более старого стиля, если в более старой версии Windows. К сожалению, я еще не нашел его пост, когда работал над решением. Назови свой яд!

ErikE
источник
Подобный пример использования для вызова этого тонкого диалога как диалогового окна (например, из приложений консольного типа) с пустым дескриптором: компилируется прямо из окна: var dialog = new FolderSelectDialog {InitialDirectory = "C: \\", Title = "Выберите папка для импорта музыки из "}; if (dialog.Show ()) {string myFolder = dialog.FileName; }
Филм
Примечание: мой пример использования в качестве комментария трудно читать, поэтому: наиболее важное изменение в исходном «примере» использования: используйте запятую между InitialDirectory и Title ..
Philm
1

Попробуйте это из Codeproject (кредит Nitron ):

Я думаю, что это тот же диалог, о котором вы говорите - может быть, это поможет, если вы добавите скриншот?

bool GetFolder(std::string& folderpath, const char* szCaption=NULL, HWND hOwner=NULL)
{
    bool retVal = false;

    // The BROWSEINFO struct tells the shell how it should display the dialog.
    BROWSEINFO bi;
    memset(&bi, 0, sizeof(bi));

    bi.ulFlags   = BIF_USENEWUI;
    bi.hwndOwner = hOwner;
    bi.lpszTitle = szCaption;

    // must call this if using BIF_USENEWUI
    ::OleInitialize(NULL);

    // Show the dialog and get the itemIDList for the selected folder.
    LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);

    if(pIDL != NULL)
    {
        // Create a buffer to store the path, then get the path.
        char buffer[_MAX_PATH] = {'\0'};
        if(::SHGetPathFromIDList(pIDL, buffer) != 0)
        {
            // Set the string value.
            folderpath = buffer;
            retVal = true;
        }       

        // free the item id list
        CoTaskMemFree(pIDL);
    }

    ::OleUninitialize();

    return retVal;
}
demoncodemonkey
источник
images.google.com/… Проводите исследования, если не уверены. Я описал то, что хотел, и FolderBrowserDialog уже был дисквалифицирован в качестве ответа.
OwenP
«Я знаю о FolderBrowserDialog, но мне никогда не нравилось это диалоговое окно. Оно начинается слишком маленьким и не позволяет мне воспользоваться возможностью ввода пути». Сделайте некоторые исследования самостоятельно - вы можете ввести путь там. В любом случае, я думаю, что это немного двусмысленный вопрос, так что удачи в этом.
demoncodemonkey
@demoncodemonkey: Вы не можете ввести часть пути, а затем перейти к нужной цели. Далеко не так удобно, как опции, которые предлагает FileOpenDialog.
Треб
1

В Vista вы можете использовать IFileDialog с установленным параметром FOS_PICKFOLDERS. Это приведет к отображению OpenFileDialog-подобного окна, где вы можете выбрать папки:

var frm = (IFileDialog)(new FileOpenDialogRCW());
uint options;
frm.GetOptions(out options);
options |= FOS_PICKFOLDERS;
frm.SetOptions(options);

if (frm.Show(owner.Handle) == S_OK) {
    IShellItem shellItem;
    frm.GetResult(out shellItem);
    IntPtr pszString;
    shellItem.GetDisplayName(SIGDN_FILESYSPATH, out pszString);
    this.Folder = Marshal.PtrToStringAuto(pszString);
}

Для старых Windows вы всегда можете прибегнуть к хитрости с выбором любого файла в папке.

Рабочий пример, который работает на .NET Framework 2.0 и более поздних версиях, можно найти здесь .

Иосип Медведь
источник
1

Вы можете использовать такой код

Фильтр является пустой строкой. Имя файла AnyName, но не пустое

        openFileDialog.FileName = "AnyFile";
        openFileDialog.Filter = string.Empty;
        openFileDialog.CheckFileExists = false;
        openFileDialog.CheckPathExists = false;
lantran
источник
6
Я знаю, что это старый пост, но ради любого, кто хочет попробовать это, он на самом деле не работает, если каталог, который вы хотите открыть, не имеет абсолютно никаких дочерних каталогов. Поэтому, если я хочу позволить своему пользователю перейти к папке и выбрать ее, а также указать путь к папке в каком-либо текстовом поле, пользователь никогда не сможет выбрать C: \ SomeParentDir, если существует каталог C: \ SomeParentDir \ SomeChildDir, так как выберите «Открыть». "просто приводит вас в дочерний каталог.
Джим
Хорошая попытка ... но это приводит к ужасному пользовательскому интерфейсу, так как "AnyFile" в текстовом поле просто ждет, когда пользователь переопределит свой текст ... кроме того, что пользователь также может выбирать файлы - недостаточно хорошо. но хорошая попытка ..
GY
-1

Я знаю, что вопрос был о конфигурации, OpenFileDialogно, увидев, что Google привел меня сюда, я также могу указать, что, если вы ищете ТОЛЬКО папки, вы должны использовать FolderBrowserDialogВместо, как ответ на другой вопрос SO ниже

Как указать путь, используя диалог открытия файла в vb.net?

AltF4_
источник
Вводя в заблуждение. 1) Это не единственный выбор; 2) В большинстве случаев это плохой выбор; Тем не менее, он требует наименьшего количества кода, торгуемого большим количеством времени, затраченного конечным пользователем
Мяу Кошка 2012