Окно выбора директории (папки) - VB

Узнай цену своей работы

Формулировка задачи:

Всем привет! Давно ищу в интернете нормальное диалоговое окно выбора директории (по типа того что предоставляет CommonDialog для выбора файлов). Кстати на VBA такая вещь присутствует! Вот пример на VBA :
Листинг программы
  1. Public Enum SpecialFolderIDs
  2. sfidDESKTOP = &H0 'рабочий стол
  3. sfidPROGRAMS = &H2
  4. sfidPERSONAL = &H5
  5. sfidFAVORITES = &H6
  6. sfidSTARTUP = &H7
  7. sfidRECENT = &H8
  8. sfidSENDTO = &H9
  9. sfidSTARTMENU = &HB
  10. sfidDESKTOPDIRECTORY = &H10
  11. sfidNETHOOD = &H13
  12. sfidFONTS = &H14
  13. sfidTEMPLATES = &H15
  14. sfidCOMMON_STARTMENU = &H16
  15. sfidCOMMON_PROGRAMS = &H17
  16. sfidCOMMON_STARTUP = &H18
  17. sfidCOMMON_DESKTOPDIRECTORY = &H19
  18. sfidAPPDATA = &H1A
  19. sfidPRINTHOOD = &H1B
  20. sfidProgramFiles = &H10000
  21. sfidCommonFiles = &H10001
  22. End Enum
  23. Private Declare Function SHGetSpecialFolderLocation Lib "shell32" (ByVal hwndOwner As Long, ByVal nFolder As SpecialFolderIDs, ByRef pIdl As Long) As Long
  24. Private Declare Function SHGetPathFromIDListA Lib "shell32" (ByVal pIdl As Long, ByVal pszPath As String) As Long
  25. Const NOERROR = 0
  26. Dim sPath As String
  27. Dim IDL As Long
  28. Dim strPath As String
  29. Dim lngPos As Long
  30.  
  31. Public Function GetFolderPath(Optional ByVal Title As String = "Выберите папку", Optional ByVal InitialPath As String = "c:\") As String
  32. ' функция выводит диалоговое окно выбора папки с заголовком Title,
  33. ' начиная обзор диска с папки InitialPath
  34. ' возвращает полный путь к выбранной папке, или пустую строку в случае отказа от выбора
  35. Dim PS As String: PS = Application.PathSeparator
  36. With Application.FileDialog(msoFileDialogFolderPicker)
  37. If Not Right$(InitialPath, 1) = PS Then InitialPath = InitialPath & PS
  38. .ButtonName = "Выбрать": .Title = Title: .InitialFileName = InitialPath
  39. If .Show <> -1 Then Exit Function
  40. GetFolderPath = .SelectedItems(1)
  41. If Not Right$(GetFolderPath, 1) = PS Then GetFolderPath = GetFolderPath & PS
  42. End With
  43. End Function

Решение задачи: «Окно выбора директории (папки)»

textual
Листинг программы
  1. Option Explicit
  2.  
  3. Private Type OPENFILENAME
  4.     lStructSize As Long
  5.     hwndOwner As Long
  6.     hInstance As Long
  7.     lpstrFilter As String
  8.     lpstrCustomFilter As String
  9.     nMaxCustFilter As Long
  10.     nFilterIndex As Long
  11.     lpstrFile As String
  12.     nMaxFile As Long
  13.     lpstrFileTitle As String
  14.     nMaxFileTitle As Long
  15.     lpstrInitialDir As String
  16.     lpstrTitle As String
  17.     Flags As Long
  18.     nFileOffset As Integer
  19.     nFileExtension As Integer
  20.     lpstrDefExt As String
  21.     lCustData As Long
  22.     lpfnHook As Long
  23.     lpTemplateName As String
  24.     pvReserved As Long
  25.     dwReserved As Long
  26.     FlagsEx As Long
  27. End Type
  28. Public Enum CdlgExt_Flags
  29.     OFNAllowMultiselect = &H200
  30.     OFNCreatePrompt = &H2000
  31.     OFNexplorer = &H80000
  32.     OFNEnableHook = &H20
  33.     OFNExtensionDifferent = &H400
  34.     OFNFileMustExist = &H1000
  35.     OFNHelpButton = &H10
  36.     OFNHideReadOnly = &H4
  37.     OFNLongNames = &H200000
  38.     OFNNoChangeDir = &H8
  39.     OFNNoDereferenceLinks = &H100000
  40.     OFNNoLongNames = &H40000
  41.     OFNNoReadOnlyReturn = &H8000
  42.     OFNNoValidate = &H100
  43.     OFNOverwritePrompt = &H2
  44.     OFNPathMustExist = &H800
  45.     OFNReadOnly = &H1
  46.     OFNShareAware = &H4000
  47. End Enum
  48. Private Type NMHDR
  49.     hwndFrom As Long
  50.     idfrom As Long
  51.     code As Long
  52. End Type
  53. Private Type LVITEM
  54.     mask As Long
  55.     iItem As Long
  56.     iSubItem As Long
  57.     state As Long
  58.     stateMask As Long
  59.     pszText As String
  60.     cchTextMax As Long
  61.     iImage As Long
  62.     lParam As Long
  63.     iIndent As Long
  64. End Type
  65.  
  66. Private Const GWL_WNDPROC = (-4)
  67.  
  68. Private Const WM_INITDIALOG = &H110
  69. Private Const WM_DESTROY = &H2
  70. Private Const WM_NOTIFY = &H4E
  71. Private Const WM_USER = &H400
  72. Private Const WM_COMMAND = &H111
  73.  
  74. Private Const CDN_FIRST = -601&
  75. Private Const CDN_INITDONE = (CDN_FIRST - 0&)
  76. Private Const CDN_FILEOK = (CDN_FIRST - 5&)
  77.  
  78. Private Const CDM_FIRST = (WM_USER + 100)
  79. Private Const CDM_HIDECONTROL = (CDM_FIRST + &H5)
  80. Private Const CDM_SETCONTROLTEXT = (CDM_FIRST + &H4)
  81. Private Const CDM_GETFOLDERPATH = (CDM_FIRST + &H2)
  82.  
  83. Private Const BN_CLICKED As Long = &H0
  84.  
  85. Private Const MAX_PATH = 260
  86.  
  87. Private Const IDOK = 1
  88. Private Const IDFILETYPECOMBO = &H470
  89. Private Const IDFILETYPESTATIC = &H441      ' Files of Type
  90. Private Const IDFILENAMESTATIC = &H442      ' File Name
  91. Private Const IDFILELIST = &H460            ' Listbox
  92.  
  93. Private Const LVM_FIRST = &H1000&
  94. Private Const LVM_GETSELECTEDCOUNT = LVM_FIRST + 50
  95. Private Const LVM_GETNEXTITEM = (LVM_FIRST + 12)
  96. Private Const LVM_GETITEMTEXT = LVM_FIRST + 45
  97.  
  98. Private Const LVIS_SELECTED = &H2&
  99.  
  100. Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
  101. Private Declare Function GetDlgItem Lib "user32" (ByVal hDlg As Long, ByVal nIDDlgItem As Long) As Long
  102. Private Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (pOpenFilename As OPENFILENAME) As Long
  103. Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
  104. Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
  105. Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  106. Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
  107. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, lpvSource As Any, ByVal Count As Long)
  108. Private Declare Function DestroyWindow Lib "user32" (ByVal hwnd As Long) As Long
  109.  
  110. Dim OFN As OPENFILENAME
  111. Dim OldWndProc As Long
  112. Dim hwndDlg As Long
  113. Dim mFolders As Collection
  114. Dim mPath As String
  115.  
  116. Public Property Get Folders() As Collection
  117.     Set Folders = mFolders
  118. End Property
  119. Public Property Get Path() As String
  120.     Path = mPath
  121. End Property
  122.  
  123. Public Function PickFolder() As String
  124.  
  125.     If mFolders Is Nothing Then Set mFolders = New Collection
  126.    
  127.     Do While mFolders.Count: mFolders.Remove (1): Loop
  128.    
  129.     With OFN
  130.         .lStructSize = Len(OFN)
  131.         .hInstance = App.hInstance
  132.         .lpfnHook = lHookAddress(AddressOf DialogHookFunction)
  133.         .Flags = OFNexplorer Or OFNNoChangeDir Or OFNEnableHook Or OFNHideReadOnly Or OFNAllowMultiselect
  134.         .lpstrFile = String$(MAX_PATH, 0)
  135.         .nMaxFile = MAX_PATH
  136.         .lpstrFileTitle = String$(MAX_PATH, 0)
  137.         .nMaxFileTitle = MAX_PATH
  138.         .lpstrFilter = "Folders" & Chr$(0) & "*.ЛЮБОЕ НЕСУЩЕСТВУЮЩЕЕ РАСШИРЕНИЕ" & String$(2, Chr$(0))
  139.         .lpstrTitle = "Pick folders"
  140.         .nFilterIndex = 0
  141.     End With
  142.     GetOpenFileName OFN
  143. End Function
  144.  
  145. Private Function lHookAddress(lPtr As Long) As Long
  146.     lHookAddress = lPtr
  147. End Function
  148. Private Function DialogHookFunction(ByVal hDlg As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  149.     Select Case wMsg
  150.         Case WM_INITDIALOG
  151.             hwndDlg = GetParent(hDlg)
  152.             OldWndProc = SetWindowLong(hwndDlg, GWL_WNDPROC, AddressOf DlgWndProc)
  153.         Case WM_NOTIFY
  154.             Dim tNMH As NMHDR
  155.             CopyMemory tNMH, ByVal lParam, Len(tNMH)
  156.             Select Case tNMH.code
  157.             Case CDN_INITDONE
  158.                 SendMessage hwndDlg, CDM_SETCONTROLTEXT, IDOK, ByVal "Pick folder"
  159.                 SendMessage hwndDlg, CDM_SETCONTROLTEXT, IDFILENAMESTATIC, ByVal "Folder name"
  160.                 SendMessage hwndDlg, CDM_HIDECONTROL, IDFILETYPECOMBO, ByVal 0&
  161.                 SendMessage hwndDlg, CDM_HIDECONTROL, IDFILETYPESTATIC, ByVal 0&
  162.             End Select
  163.         Case WM_DESTROY
  164.         Case Else
  165.     End Select
  166. End Function
  167. Private Function DlgWndProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  168.     Select Case Msg
  169.     Case WM_COMMAND
  170.         If HiWord(wParam) = BN_CLICKED Then
  171.             Dim hwndPick As Long
  172.                        
  173.             hwndPick = GetDlgItem(hwndDlg, IDOK)
  174.                        
  175.             If lParam = hwndPick Then
  176.                 Dim hwndLVParent As Long, hwndLV As Long
  177.                 Dim Pos As Long, Itm As LVITEM, txtLen As Long
  178.                
  179.                 hwndLVParent = FindWindowEx(hwndDlg, ByVal 0&, "SHELLDLL_DefView", vbNullString)
  180.                 hwndLV = FindWindowEx(hwndLVParent, ByVal 0&, "SysListView32", vbNullString)
  181.  
  182.                 Pos = SendMessage(hwndLV, LVM_GETNEXTITEM, -1, ByVal LVIS_SELECTED)
  183.                
  184.                 If Pos >= 0 Then
  185.                    
  186.                     Itm.cchTextMax = MAX_PATH
  187.                     Itm.pszText = String(MAX_PATH, 0)
  188.                    
  189.                     txtLen = SendMessage(hwndLV, LVM_GETITEMTEXT, Pos, Itm)
  190.                    
  191.                     mFolders.Add Left(Itm.pszText, txtLen)
  192.                    
  193.                     Do Until Pos = -1
  194.                         Pos = SendMessage(hwndLV, LVM_GETNEXTITEM, Pos, ByVal LVIS_SELECTED)
  195.                         txtLen = SendMessage(hwndLV, LVM_GETITEMTEXT, Pos, Itm)
  196.                         If Pos >= 0 Then mFolders.Add Left(Itm.pszText, txtLen)
  197.                     Loop
  198.                    
  199.                     mPath = String(MAX_PATH, 0)
  200.                     txtLen = SendMessage(hwndDlg, CDM_GETFOLDERPATH, MAX_PATH, ByVal mPath)
  201.                     mPath = Left(mPath, txtLen - 1)
  202.                     DestroyWindow hwndDlg
  203.                 End If
  204.             Else
  205.                 DlgWndProc = CallWindowProc(OldWndProc, hwnd, Msg, wParam, lParam)
  206.             End If
  207.         End If
  208.     Case Else
  209.         DlgWndProc = CallWindowProc(OldWndProc, hwnd, Msg, wParam, lParam)
  210.     End Select
  211. End Function
  212.  
  213. Private Function LoWord(ByVal LongIn As Long) As Integer
  214.     Call CopyMemory(LoWord, LongIn, 2)
  215. End Function
  216. Private Function HiWord(ByVal LongIn As Long) As Integer
  217.     Call CopyMemory(HiWord, ByVal (VarPtr(LongIn) + 2), 2)
  218. End Function

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

9   голосов , оценка 3.889 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы