powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Диалог вида OpenFileDialog но для выбора папки, а не файла
11 сообщений из 11, страница 1 из 1
Диалог вида OpenFileDialog но для выбора папки, а не файла
    #39650570
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Очень редко встречается,
но в частности есть в студии при выборе расположения проекта при его создании, кнопка Обзор.
Картинку прикладываю.
Чуть ли не в единственном месте такое видел.

Т.е. очевидно, что это OpenFileDialog
Оно же - ф-ция GetOpenFileName , структура OPENFILENAME

Но:
надпись Папка,
кнопка Выбор папки,
при выделение вот именно папки имя ее бухается в поле "Папка",
ну и в проводнике только папки и отображаются.

Как сие сделать?

Обычно я для этих целей использую маленький диалог SHBrowseForFolder function (в .Net классах он тоже вроде есть, не помню как называется, из-за какого-то глюка не использую)

Но столкнулся с ситуацией, когда в качестве стартовой папки надо выбрать подпапку "скрытой",
да и как бы "проводник" не лишний, диалог Open/SaveAs поприличней выглядит.

И я вот думаю, или я туплю и это что-то штатное, м.б. готовый класс в .Net есть или в OpenFileDialog что-то не знаю,
или это кастомизация типа как когда-то делал (но правда делал только с диалогами XP вида а не этими новыми кот. на висте появились).
Внешний вид/стиль Common Dialog Save/Open
8409073
(жаль картинок не сохранилось)
...
Рейтинг: 0 / 0
Диалог вида OpenFileDialog но для выбора папки, а не файла
    #39650576
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
http://www.lyquidity.com/devblog/?p=136
Первая ссылка в тексте на архив с исходниками.
...
Рейтинг: 0 / 0
Диалог вида OpenFileDialog но для выбора папки, а не файла
    #39650588
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны http://www.lyquidity.com/devblog/?p=136
Первая ссылка в тексте на архив с исходниками.
Фиговая какая-то ссылка, скрипт какой-то запускается вместо скачки зипа.

Ну, то что это не тривиально, это я уже понял.

Вот чего нашел.
http://www.ookii.org/software/dialogs/
Но, блин, пишут люди dll-ы на все случаи жизни и тащатся от этого, нет чтоб простенький класс, замучаешься из этого вороха код вытаскивать.

Сон Веры Павловны, а Вы мне вот что скажите.
Классическими API
ф-ция GetOpenFileName , структура OPENFILENAME
эту штуку не достать (в них довольно хорошо ориентируюсь, но Callback, без которого те же кастомизации например не сделаешь, сразу сбрасывает к XP виду)?
Только интерфейсами?
...
Рейтинг: 0 / 0
Диалог вида OpenFileDialog но для выбора папки, а не файла
    #39650592
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Есть же Класс FolderBrowserDialog ?
...
Рейтинг: 0 / 0
Диалог вида OpenFileDialog но для выбора папки, а не файла
    #39650593
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот здесь FILEOPENDIALOGOPTIONS enumeration есть
FOS_PICKFOLDERSPresent an Open dialog that offers a choice of folders rather than files.Очевидно это оно.

А в OPENFILENAME structure
в Flags аналога не вижу,

а с "интерфейсами" не на столько на ты, в отличии от обычных API.
...
Рейтинг: 0 / 0
Диалог вида OpenFileDialog но для выбора папки, а не файла
    #39650595
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cat2Есть же Класс FolderBrowserDialog ?Да я про него упомянул уже, это маленькое окно "Обзор папок", соответствует SHBrowseForFolder
Обычно я для этих целей использую маленький диалог SHBrowseForFolder function (в .Net классах он тоже вроде есть, не помню как называется, из-за какого-то глюка не использую)
Это не то. Или он как на картинке тоже умеет выводить?
...
Рейтинг: 0 / 0
Диалог вида OpenFileDialog но для выбора папки, а не файла
    #39650598
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Сон Веры Павловны http://www.lyquidity.com/devblog/?p=136
Первая ссылка в тексте на архив с исходниками.
Фиговая какая-то ссылка, скрипт какой-то запускается вместо скачки зипа.
У меня качается нормально.
Вот исходники:
...
Рейтинг: 0 / 0
Диалог вида OpenFileDialog но для выбора папки, а не файла
    #39650600
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
P.S. В силу особенностей реализации это работает только на ОС от висты и выше. На ХР будет всё тот же FolderBrowserDialog.
...
Рейтинг: 0 / 0
Диалог вида OpenFileDialog но для выбора папки, а не файла
    #39650610
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры ПавловныУ меня качается нормально.
Вот исходники:
Не знаю, у меня ссылка какую-то "надстройку офис" пыталась ("неудачно") установить, мне это не понравилось.
Скачал работает, спасибо.

Вот еще аналог нарыл:
https://www.medo64.com/2011/12/openfolderdialog/
Тоже рабочий (C# проект).
Код VB.Net приведенный там по правда нерабочий, с ходу точно не фурычит.


Сон Веры ПавловныP.S. В силу особенностей реализации это работает только на ОС от висты и выше. На ХР будет всё тот же FolderBrowserDialog.
Это понятно, диалогов такого вида в XP в принципе нет. Мне надо от Win7, XP не нужен.
Жалко конечно что в OpenFileDialog флаг не добавили, из-за чего все эти интерфейсы делать надо.
Более того, придется на VB.Net это перекраивать.
Готового проекта на VB. кстати нету?
Ну, во всяком случае стратегически решение есть.

Сон Веры Павловны,
спасибо еще раз за быстрый корректный ответ.
...
Рейтинг: 0 / 0
Диалог вида OpenFileDialog но для выбора папки, а не файла
    #39650619
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Диалог вида OpenFileDialog но для выбора папки, а не файла
    #39650832
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Нашел для VB.Net готовый код:
https://stackoverflow.com/questions/16036853/folderbrowser-with-textbox-in-vb-net

Исправил кой-какие глюки (SHCreateItemFromParsingName в VB была неправильно задекларирована, пара мелочей), добавил свойство Title. Сделал свой модуль с классом, убрав громкое "NativeMethods." (не люблю этих .Net-понтов в каждой строчке кода).
В общем вполне таки аккуратно получилось, на всяк. случай выложу под спойлер, мож кому пригодится:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
Imports System.Runtime.InteropServices
Imports System.Runtime.CompilerServices

'https://stackoverflow.com/questions/16036853/folderbrowser-with-textbox-in-vb-net


Module m_IFileDialog

#Region "Constants"

  'Shell Reference > Shell Constants, Enumerations, and Flags
  ' FILEOPENDIALOGOPTIONS enumeration
  Public Const FOS_NOCHANGEDIR As UInteger = &H8
  Public Const FOS_PICKFOLDERS As UInteger = &H20
  Public Const FOS_FORCEFILESYSTEM As UInteger = &H40
  Public Const FOS_NOVALIDATE As UInteger = &H100
  Public Const FOS_PATHMUSTEXIST As UInteger = &H800 'The item returned must be in an existing folder. This is a default value.
  Public Const FOS_NOTESTFILECREATE As UInteger = &H10000
  Public Const FOS_DONTADDTORECENT As UInteger = &H2000000

  ' SIGDN enumeration
  Public Const SIGDN_FILESYSPATH As UInteger = &H80058000UI

#End Region

#Region "COM"

  <ComImport(), ClassInterface(ClassInterfaceType.None), TypeLibType(TypeLibTypeFlags.FCanCreate), Guid("DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7")> _
  Friend Class FileOpenDialogRCW
  End Class

  'Shell Interfaces -> IFileDialog
  <ComImport(), Guid("42F85136-DB7E-439C-85F1-E4075D135FC8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
  Friend Interface IFileDialog
    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    <PreserveSig()> _
    Function Show(<[In](), [Optional]()> ByVal hwndOwner As IntPtr) As UInteger
    'IModalWindow 

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function SetFileTypes(<[In]()> ByVal cFileTypes As UInteger, <[In](), MarshalAs(UnmanagedType.LPArray)> ByVal rgFilterSpec As IntPtr) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function SetFileTypeIndex(<[In]()> ByVal iFileType As UInteger) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function GetFileTypeIndex(ByRef piFileType As UInteger) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function Advise(<[In](), MarshalAs(UnmanagedType.[Interface])> ByVal pfde As IntPtr, ByRef pdwCookie As UInteger) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function Unadvise(<[In]()> ByVal dwCookie As UInteger) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function SetOptions(<[In]()> ByVal fos As UInteger) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function GetOptions(ByRef fos As UInteger) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Sub SetDefaultFolder(<[In](), MarshalAs(UnmanagedType.[Interface])> ByVal psi As IShellItem)

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function SetFolder(<[In](), MarshalAs(UnmanagedType.[Interface])> ByVal psi As IShellItem) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function GetFolder(<MarshalAs(UnmanagedType.[Interface])> ByRef ppsi As IShellItem) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function GetCurrentSelection(<MarshalAs(UnmanagedType.[Interface])> ByRef ppsi As IShellItem) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function SetFileName(<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal pszName As String) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function GetFileName(<MarshalAs(UnmanagedType.LPWStr)> ByRef pszName As String) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function SetTitle(<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal pszTitle As String) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function SetOkButtonLabel(<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal pszText As String) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function SetFileNameLabel(<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal pszLabel As String) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function GetResult(<MarshalAs(UnmanagedType.[Interface])> ByRef ppsi As IShellItem) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function AddPlace(<[In](), MarshalAs(UnmanagedType.[Interface])> ByVal psi As IShellItem, ByVal fdap As UInteger) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function SetDefaultExtension(<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal pszDefaultExtension As String) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function Close(<MarshalAs(UnmanagedType.[Error])> ByVal hr As UInteger) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function SetClientGuid(<[In]()> ByRef guid As Guid) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function ClearClientData() As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function SetFilter(<MarshalAs(UnmanagedType.[Interface])> ByVal pFilter As IntPtr) As UInteger
  End Interface


  'Shell Interfaces -> IShellItem
  <ComImport(), Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
  Friend Interface IShellItem
    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function BindToHandler(<[In]()> ByVal pbc As IntPtr, <[In]()> ByRef rbhid As Guid, <[In]()> ByRef riid As Guid, <Out(), MarshalAs(UnmanagedType.[Interface])> ByRef ppvOut As IntPtr) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function GetParent(<MarshalAs(UnmanagedType.[Interface])> ByRef ppsi As IShellItem) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function GetDisplayName(<[In]()> ByVal sigdnName As UInteger, ByRef ppszName As IntPtr) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function GetAttributes(<[In]()> ByVal sfgaoMask As UInteger, ByRef psfgaoAttribs As UInteger) As UInteger

    <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
    Function Compare(<[In](), MarshalAs(UnmanagedType.[Interface])> ByVal psi As IShellItem, <[In]()> ByVal hint As UInteger, ByRef piOrder As Integer) As UInteger
  End Interface

#End Region

End Module

Public Class ISelectFolderDialog
  Implements IDisposable

  Private Const S_OK As UInteger = &H0

  'Shell Reference > Shell Functions
  Private Declare Unicode Function SHCreateItemFromParsingName Lib "shell32.dll" _
   (ByVal pszPath As String, ByVal pbc As IntPtr, ByRef riid As Guid, ByRef ppv As IShellItem) As Integer

  'local variable(s) to hold property value(s)
  Private m_InitialFolder As String
  Private m_DefaultFolder As String
  Private m_Folder As String
  Private m_Title As String

  ''' <summary>
  ''' Gets/sets folder in which dialog will be open.
  ''' </summary>
  Public Property InitialFolder() As String
    Get
      Return m_InitialFolder
    End Get
    Set(ByVal value As String)
      m_InitialFolder = value
    End Set
  End Property

  ''' <summary>
  ''' Gets/sets directory in which dialog will be open if there is no recent directory available.
  ''' </summary>
  Public Property DefaultFolder() As String
    Get
      Return m_DefaultFolder
    End Get
    Set(ByVal value As String)
      m_DefaultFolder = value
    End Set
  End Property

  ''' <summary>
  ''' Gets selected folder.
  ''' </summary>
  Public Property Folder() As String
    Get
      Return m_Folder
    End Get
    Private Set(ByVal value As String)
      m_Folder = value
    End Set
  End Property

  ''' <summary>
  ''' Gets/sets the title of the dialog.
  ''' </summary>
  Public Property Title() As String
    Get
      Return m_Title
    End Get
    Set(ByVal value As String)
      m_Title = value
    End Set
  End Property


  Public Function ShowDialog(ByVal owner As IWin32Window) As DialogResult
    If Environment.OSVersion.Version.Major >= 6 Then
      Dim frm = DirectCast(New FileOpenDialogRCW(), IFileDialog)

      Dim options As UInteger
      frm.GetOptions(options)
      'options = options Or NativeMethods.FOS_PICKFOLDERS Or NativeMethods.FOS_FORCEFILESYSTEM Or NativeMethods.FOS_NOVALIDATE Or NativeMethods.FOS_NOTESTFILECREATE Or NativeMethods.FOS_DONTADDTORECENT
      options = options Or FOS_PICKFOLDERS Or FOS_FORCEFILESYSTEM Or _
       FOS_NOVALIDATE Or FOS_NOTESTFILECREATE Or FOS_DONTADDTORECENT Or FOS_NOCHANGEDIR Or FOS_PATHMUSTEXIST
      frm.SetOptions(options)

      If Me.InitialFolder IsNot Nothing Then
        Dim directoryShellItem As IShellItem = Nothing
        Dim riid = New Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE")
        'IShellItem
        If SHCreateItemFromParsingName(Me.InitialFolder, IntPtr.Zero, riid, directoryShellItem) = S_OK Then
          frm.SetFolder(directoryShellItem)
        End If
      End If

      If Me.DefaultFolder IsNot Nothing Then
        Dim directoryShellItem As IShellItem = Nothing
        Dim riid = New Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE")
        'IShellItem
        If SHCreateItemFromParsingName(Me.DefaultFolder, IntPtr.Zero, riid, directoryShellItem) = S_OK Then
          frm.SetDefaultFolder(directoryShellItem)
        End If
      End If

      If Me.Title IsNot Nothing Then
        frm.SetTitle(Me.Title)
      End If

      If frm.Show(owner.Handle) = S_OK Then
        Dim shellItem As IShellItem = Nothing
        If frm.GetResult(shellItem) = S_OK Then
          Dim pszString As IntPtr
          If shellItem.GetDisplayName(SIGDN_FILESYSPATH, pszString) = S_OK Then
            If pszString <> IntPtr.Zero Then
              Try
                Me.Folder = Marshal.PtrToStringAuto(pszString)
                Return DialogResult.OK
              Finally
                Marshal.FreeCoTaskMem(pszString)
              End Try
            End If
          End If
        End If
      End If
      Return DialogResult.Cancel
    Else
      '!!!не надо это использовать на XP/2003 -ясно что работать не будет
      Return DialogResult.Cancel
    End If
  End Function

  Public Sub Dispose() Implements IDisposable.Dispose
    'just to have possibility of Using statement.
  End Sub

End Class



Вообще конечно кухня нужная, хорошая стартовая точка для кастомизации "вистовских" Open/Save диалогов.
У меня есть пара-тройка кастомизированных, но они все XP-стиля (не переделывал).
Вот нашел с картинкой:
17456717
А вот тут подсказали куда двигаться чтоб кастомизировать "Вистовские":
Using the new IFileDialog interface for customizable Open/Save (TLB, Vista+)

Ну т.е. откуда плясать, теперь понятно. Дойдут ли руки когда-нибудь...
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Диалог вида OpenFileDialog но для выбора папки, а не файла
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]