57gmc 发表于 2014-8-7 01:33:50

64位VBA 7.1中的“浏览文件夹”系统对话框

此模块将允许您在64位VBA 7.1中使用Windows系统SHBrowseForFolder对话框
'##########################################################################################
'#                                                                                        #
'#                              modFolderBrowse                                       #
'#                               code compiled by                                       #
'#                              Steven Elliott                                          #
'#                        from many sources on the net                                  #
'#                           Released to Public Domain                                    #
'#                                                                                        #
'##########################################################################################
Option Explicit
      
Private Declare PtrSafe Function SHBrowseForFolder Lib "shell32.dll" _
Alias "SHBrowseForFolderA" (lpBrowseInfo As BrowseInfo) As Long

Private Declare PtrSafe Function SHGetPathFromIDList Lib "shell32.dll" _
      (ByVal pidList As Long, ByVal lpBuffer As String) As Long

Public Declare PtrSafe Function SendMessageA Lib "user32" _
      (ByVal hWnd As LongPtr, ByVal wMsg As Long, _
       ByVal wParam As LongPtr, lParam As Any) As LongPtr

Private Declare PtrSafe Sub CoTaskMemFree Lib "ole32.dll" (ByVal hMem As Long)
Private Const BIF_RETURNONLYFSDIRSAs Long = 1
Private Const CSIDL_DRIVES          As Long = &H11
Private Const WM_USER               As Long = &H400
Private Const MAX_PATH            As Long = 260 ' Is it a bad thing that I memorized this value?
'// message from browser
Private Const BFFM_INITIALIZED   As Long = 1
Private Const BFFM_SELCHANGED      As Long = 2
Private Const BFFM_VALIDATEFAILEDA As Long = 3 '// lParam:szPath ret:1(cont),0(EndDialog)
Private Const BFFM_VALIDATEFAILEDW As Long = 4 '// lParam:wzPath ret:1(cont),0(EndDialog)
Private Const BFFM_IUNKNOWN      As Long = 5 '// provides IUnknown to client. lParam: IUnknown*
'// messages to browser
Private Const BFFM_SETSTATUSTEXTA   As Long = WM_USER + 100
Private Const BFFM_ENABLEOK         As Long = WM_USER + 101
Private Const BFFM_SETSELECTIONA    As Long = WM_USER + 102
Private Const BFFM_SETSELECTIONW    As Long = WM_USER + 103
Private Const BFFM_SETSTATUSTEXTW   As Long = WM_USER + 104
Private Const BFFM_SETOKTEXT      As Long = WM_USER + 105 '// Unicode only
Private Const BFFM_SETEXPANDED      As Long = WM_USER + 106 '// Unicode only
      
Public Type BrowseInfo
hWndOwner As LongPtr
pIDLRoot As Long
pszDisplayName As String
lpszTitle As String
ulFlags As Long
lpfnCallback As LongPtr
lParam As LongPtr
iImage As Long
End Type
Private Function PtrToFunction(ByVal lFcnPtr As LongPtr) As LongPtr
PtrToFunction = lFcnPtr
End Function
Private Function CorrectPath(ByVal sPath As String) As String
If Right$(sPath, 1) = "\" Then
    If Len(sPath) > 3 Then sPath = Left$(sPath, Len(sPath) - 1) ' Strip backslash from non-root
Else
    If Len(sPath) = 2 Then sPath = sPath & "\"                  ' Append backslash to root
End If
CorrectPath = sPath
End Function
Public Function FolderBrowse(ByVal sDialogTitle As String, ByVal sPath As String) As String
Dim ReturnPath As String

Dim b(MAX_PATH) As Byte
Dim pItem       As Long
Dim sFullPath   As String
Dim bi          As BrowseInfo
Dim ppidl       As Long

sPath = CorrectPath(sPath)

bi.hWndOwner = 0 'Screen.ActiveForm.hwnd
'SHGetSpecialFolderLocation bi.hWndOwner, CSIDL_DRIVES, ppidl
bi.pIDLRoot = 0 'ppidl
bi.pszDisplayName = VarPtr(b(0))
bi.lpszTitle = sDialogTitle
bi.ulFlags = BIF_RETURNONLYFSDIRS
If FolderExists(sPath) Then bi.lpfnCallback = PtrToFunction(AddressOf BFFCallback)
bi.lParam = StrPtr(sPath)
pItem = SHBrowseForFolder(bi)

If pItem Then ' Succeeded
    sFullPath = Space$(MAX_PATH)
    If SHGetPathFromIDList(pItem, sFullPath) Then
      ReturnPath = Left$(sFullPath, InStr(sFullPath, vbNullChar) - 1) ' Strip nulls
      CoTaskMemFree pItem
    End If
End If

If Right$(ReturnPath, 1)"\" And ReturnPath"" Then'Could be "C:"
    FolderBrowse = ReturnPath & "\"
End If

End Function
Public Function BFFCallback(ByVal hWnd As Long, ByVal uMsg As Long, ByVal lParam As Long, ByVal sData As String) As Long
If uMsg = BFFM_INITIALIZED Then
    SendMessageA hWnd, BFFM_SETSELECTIONA, True, ByVal sData
End If
End Function
Public Function FolderExists(ByVal sFolderName As String) As Boolean
   Dim att As Long
   On Error Resume Next
   att = GetAttr(sFolderName)
   If Err.Number = 0 Then
      FolderExists = True
   Else
      Err.Clear
      FolderExists = False
   End If
   On Error GoTo 0
End Function

将其用于以下简单调用:

Private Sub cmdGetLibraryPath_Click()
   Dim sPath As String
'                        FolderBrowse(DialogBoxTitle, StartingPath)
   sPath = modFolderBrowse.FolderBrowse("Select Folder Containing Block Library", txtLibraryPath.Text)
   If sPath"" Then
      If modFolderBrowse.FolderExists(sPath) Then
         txtLibraryPath.Text = sPath
      End If
   End If
End Sub

Keith™ 发表于 2015-4-29 11:28:21

It#039;太棒了
你能做到吗;opendialog“;和“;savedialog“;在64位VBA7.1中?

57gmc 发表于 2020-9-29 17:36:58

代码在这一行上与AutoCAD崩溃:如果SHGetPathFromIDList(pItem,sFullPath),则

Keith™ 发表于 2020-10-5 09:52:54

更改&nbsp 只要有暗坑&nbsp 长PTR 选项显式服务提供商;当长=&时,n\u的公共常量覆盖了压缩;H2sData
页: [1]
查看完整版本: 64位VBA 7.1中的“浏览文件夹”系统对话框