vb中5种打开文件夹浏览框的方法总结

众所周知,在vb中如果是打开某一个文件的话,非常简单,使用CommonDialog组件即可轻松完成,但是他只能选择文件,之后或许选取的文件路径,而如果想要浏览文件夹,就没这么方便了。

这里介绍3个办法来实现文件夹浏览。

第一个非常简单,利用Shell对象
程序代码 程序代码
'引用Microsoft Shell Controls And Automation
Dim ShellA As New Shell
Private Sub Command1_Click()    '建立一个按钮对象                                                    
Dim Shellb As Folder
Set Shellb = ShellA.BrowseForFolder(0, "选择文件夹", 0)
ShellA.Open b
End Sub


记得一定要引用Microsoft Shell Controls And Automation

第二种方法,我们同样利用shell对象,但是加几个函数
程序代码 程序代码
'引用Microsoft Shell Controls And Automation
Private shlShell As Shell32.Shell
Private shlFolder As Shell32.Folder
Private Const BIF_RETURNONLYFSDIRS = &H1
Private Sub Command1_Click() '
    If shlShell Is Nothing Then
       Set shlShell = New Shell32.Shell
    End If
    Set shlFolder = shlShell.BrowseForFolder(Me.hWnd, "请选择文件夹", BIF_RETURNONLYFSDIRS)
    If Not shlFolder Is Nothing Then
       MsgBox shlFolder.Items.Item.Path  '测试
    End If
End Sub


上面2个方法的结果如图:
点击放大图片

第三个方法,是利用API来操作。
程序代码 程序代码
Private Const BIF_RETURNONLYFSDIRS = 1
Private Const BIF_DONTGOBELOWDOMAIN = 2
Private Const MAX_PATH = 260

Private Declare Function SHBrowseForFolder Lib "Shell32" (lpbi As BrowseInfo) As Long
Private Declare Function SHGetPathFromIDList Lib "Shell32" (ByVal pidList As Long, ByVal lpBuffer As String) As Long
Private Declare Function lstrcat Lib "kernel32" Alias "lstrcatA" (ByVal lpString1 As String, ByVal lpString2 As String) As Long
Private Type BrowseInfo
     hWndOwner As Long
     pIDLRoot As Long
     pszDisplayName As Long
     lpszTitle As Long
     ulFlags    As Long
     lpfnCallback     As Long
     lParam     As Long
     iImage     As Long
End Type
Private Sub Command1_Click()
     Dim lpIDList As Long
     Dim sBuffer As String
     Dim szTitle As String
     Dim tBrowseInfo As BrowseInfo
     szTitle = App.Path
     With tBrowseInfo
          .hWndOwner = Me.hWnd
          .lpszTitle = lstrcat(szTitle, "")
          .ulFlags = BIF_RETURNONLYFSDIRS + BIF_DONTGOBELOWDOMAIN
     End With

     lpIDList = SHBrowseForFolder(tBrowseInfo)
     If (lpIDList) Then
          sBuffer = Space(MAX_PATH)
          SHGetPathFromIDList lpIDList, sBuffer
          sBuffer = Left(sBuffer, InStr(sBuffer, vbNullChar) - 1)
          MsgBox sBuffer
     End If
End Sub


如果希望对话框中有“新建文件夹”,那么就给.ulFlags 加上BIF_USENEWUI属性,BIF_RETURNONLYFSDIRS 的意思是仅仅返回文件夹。
效果如图:
点击放大图片

同时我也打包2个完整的利用此API的代码,有意者请自己学习了。


第4个方法。
其实是第三个方法的改进,就是打开对话框后,自动定位到当前文件夹位置 。

程序代码 程序代码
'Objects:   Form1、Command1、Module1  
  'Form1:  
  Option   Explicit  
  Private   Const   BIF_RETURNONLYFSDIRS   =   1  
  Private   Const   BIF_DONTGOBELOWDOMAIN   =   2  
  Private   Const   MAX_PATH   =   260  
  Private   Declare   Function   SHBrowseForFolder   Lib   "shell32"   (lpbi   As   BrowseInfo)   As   Long  
  Private   Declare   Function   SHGetPathFromIDList   Lib   "shell32"   (ByVal   pidList   As   Long,   ByVal   lpBuffer   As   String)   As   Long  
  Private   Declare   Function   lstrcat   Lib   "kernel32"   Alias   "lstrcatA"   (ByVal   lpString1   As   String,   ByVal   lpString2   As   String)   As   Long  
  Private   Declare   Function   LocalAlloc   Lib   "kernel32"   (ByVal   uFlags   As   Long,   ByVal   uBytes   As   Long)   As   Long  
  Private   Declare   Sub   CopyMemory   Lib   "kernel32"   Alias   "RtlMoveMemory"   (pDest   As   Any,   pSource   As   Any,   ByVal   dwLength   As   Long)  
  Private   Const   LPTR   =   (&H0   or   &H40)  
  Private   Type   BrowseInfo  
                  hWndOwner             As   Long  
                  pIDLRoot             As   Long  
                  pszDisplayName   As   Long  
                  lpszTitle             As   Long  
                  ulFlags                 As   Long  
                  lpfnCallback     As   Long  
                  lParam                 As   Long  
                  iImage                 As   Long  
  End   Type  
  Private   Function   MyAddressOf(AddressOfX   As   Long)   As   Long  
  MyAddressOf   =   AddressOfX  
  End   Function  
    
  Private   Sub   Command1_Click()  
  Dim   lpIDList   As   Long  
  Dim   sBuffer   As   String  
  Dim   szTitle   As   String  
  Dim   tBrowseInfo   As   BrowseInfo  
  Dim   Ret   As   Long  
  szTitle   =   "This   is   the   title"  
  Dim   sPath   As   String  
  sPath   =   VBA.InputBox("初始路径:",   ,   "C:\program   files")  
  With   tBrowseInfo  
          .hWndOwner   =   Me.hWnd  
          .lpszTitle   =   lstrcat(szTitle,   "")  
          .ulFlags   =   BIF_RETURNONLYFSDIRS   +   BIF_DONTGOBELOWDOMAIN  
          .lpfnCallback   =   MyAddressOf(AddressOf   BrowseForFolders_CallbackProc)  
          Ret   =   LocalAlloc(LPTR,   VBA.Len(sPath)   +   1)  
          CopyMemory   ByVal   Ret,   ByVal   sPath,   VBA.Len(sPath)   +   1  
          .lParam   =   Ret  
  End   With  
  lpIDList   =   SHBrowseForFolder(tBrowseInfo)  
  If   (lpIDList)   Then  
      sBuffer   =   VBA.Space(MAX_PATH)  
      SHGetPathFromIDList   lpIDList,   sBuffer  
      sBuffer   =   VBA.Left(sBuffer,   VBA.InStr(sBuffer,   vbNullChar)   -   1)  
      MsgBox   sBuffer  
      End   If  
  End   Sub  
    
  'Module1:  
  Option   Explicit  
  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  
  Private   Const   WM_USER   =   &H400  
  Private   Const   BFFM_SETSelectIONA   As   Long   =   (WM_USER   +   102)  
  Private   Const   BFFM_SETSelectIONW   As   Long   =   (WM_USER   +   103)  
  Private   Const   BFFM_INITIALIZED   As   Long   =   1  
  Public   Function   BrowseForFolders_CallbackProc(ByVal   hWnd   As   Long,   ByVal   uMsg   As   Long,   ByVal   lParam   As   Long,   ByVal   lpData   As   Long)   As   Long  
  If   uMsg   =   BFFM_INITIALIZED   Then  
      SendMessage   hWnd,   BFFM_SETSelectIONA,   True,   ByVal   lpData  
  End   If  
  End   Function


效果如图:

点击放大图片

看了这个代码后,你会发现它确实定位到了当前文件夹,但是他有一个问题就是,没有选定当前文件夹。咱们继续看方法5.

第5个方法。
他同样是第3个方法的加强版,不过这个方法应当是最为完美的方法,不仅定位到当前文件夹,而且选定它。
建立一个模块文件

程序代码 程序代码
'form1
''Module1:  
Option Explicit
Private Const BIF_STATUSTEXT = &H4&
Private Const BIF_RETURNONLYFSDIRS = 1
Private Const BIF_DONTGOBELOWDOMAIN = 2
Private Const MAX_PATH = 260

Private Const WM_USER = &H400
Private Const BFFM_INITIALIZED = 1
Private Const BFFM_SELCHANGED = 2
Private Const BFFM_SETSTATUSTEXT = (WM_USER + 100)
Private Const BFFM_SETSelectION = (WM_USER + 102)

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
Private Declare Function SHBrowseForFolder Lib "shell32" (lpbi As BrowseInfo) As Long
Private Declare Function SHGetPathFromIDList Lib "shell32" (ByVal pidList As Long, ByVal lpBuffer As String) As Long
Private Declare Function lstrcat Lib "kernel32" Alias "lstrcatA" (ByVal lpString1 As String, ByVal lpString2 As String) As Long

Private Type BrowseInfo
  hWndOwner      As Long
  pIDLRoot       As Long
  pszDisplayName As Long
  lpszTitle      As Long
  ulFlags        As Long
  lpfnCallback   As Long
  lParam         As Long
  iImage         As Long
End Type

Private m_CurrentDirectory As String   'The current directory
Public Function BrowseForFolder(owner As Form, Title As String, StartDir As String) As String
  Dim lpIDList As Long
  Dim szTitle As String
  Dim sBuffer As String
  Dim tBrowseInfo As BrowseInfo
  m_CurrentDirectory = StartDir & vbNullChar

  szTitle = Title
  With tBrowseInfo
    .hWndOwner = owner.hWnd
    .lpszTitle = lstrcat(szTitle, "")
    .ulFlags = BIF_RETURNONLYFSDIRS + BIF_DONTGOBELOWDOMAIN + BIF_STATUSTEXT
    .lpfnCallback = GetAddressofFunction(AddressOf BrowseCallbackProc)  'get address of function.
  End With

  lpIDList = SHBrowseForFolder(tBrowseInfo)
  If (lpIDList) Then
    sBuffer = Space(MAX_PATH)
    SHGetPathFromIDList lpIDList, sBuffer
    sBuffer = Left(sBuffer, InStr(sBuffer, vbNullChar) - 1)
    BrowseForFolder = sBuffer
  Else
    BrowseForFolder = ""
  End If
  
End Function

Private Function BrowseCallbackProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal lp As Long, ByVal pData As Long) As Long
    Dim lpIDList As Long
  Dim ret As Long
  Dim sBuffer As String  
  On Error Resume Next      
  Select Case uMsg  
    Case BFFM_INITIALIZED
      Call SendMessage(hWnd, BFFM_SETSelectION, 1, m_CurrentDirectory)      
    Case BFFM_SELCHANGED
      sBuffer = Space(MAX_PATH)
      
      ret = SHGetPathFromIDList(lp, sBuffer)
      If ret = 1 Then
        Call SendMessage(hWnd, BFFM_SETSTATUSTEXT, 0, sBuffer)
      End If      
  End Select  
  BrowseCallbackProc = 0  
End Function
Private Function GetAddressofFunction(add As Long) As Long
  GetAddressofFunction = add
End Function


建立一个窗口和一个按钮
程序代码 程序代码
Option Explicit
Private getdir As String
Private Sub Command1_Click()    
    getdir = BrowseForFolder(Me, "Select A Directory", Text1.Text)
    If Len(getdir) = 0 Then Exit Sub     Text1.Text = getdir    
End Sub
Private Sub Form_Load()
  Text1.Text = CurDir
End Sub



最终结果如图:
点击放大图片

上面是对vb中调用文件夹对话框的一个总结,个人认为第5个方法是最为完美的,这也是从国外坛子淘到的

不得不说,国外对源码共享还是走在我们前面的。

全文完

by  daokers
2010.3.12  于广州






欢迎在此留言,也欢迎加入刀城交流,此文刀城地址http://forum.daokers.com/read.php?tid=1220



严正声明:转载我的文章可以!但是别修改我的标题!!!



以下说明属本文之一部分:
转载请保持完整并注明:转自 金刀客[www.daokers.com]


[本日志由 admin 于 2010-03-17 11:43 AM 编辑]
相关日志:
在线RSS阅读器订阅:
feedsky
抓虾 pageflakes Rojo google reader
my yahoo newsgator bloglines 有道
鲜果 飞豆 哪吒 Netvibes
Netvibes Netvibes

手机订阅:


本站订阅地址:
RSS2:点击复制
Atom:点击复制
        本站所有原创文章均遵循 [创作共用协议]
        本站原创文章可以转载,但须保持完整性并注明出处。
        COPYRIGHT 2008-2010  §  HTTP://WWW.DAOKERS.COM  §    ALL RIGHTS
评论: 1 | 引用: 0 | 查看次数: -
回复回复VBhere[2010-03-16 05:51 PM | del]
问下作者,用第一、二种方法,我想实现仅仅返回文件夹的效果,可行吗?
回复来自 admin 的评论 admin 于 2010-03-16 10:42 PM 回复
这所有的方法都是返回文件夹的路径啊,comobox组件?你是什么意思我还没怎么领会明白。
发表评论
昵 称:
密 码: 游客发言不需要密码.
验证码: 验证码提示:单击自动获取验证码
内 容:
最多可输入,当前共,还可输入
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.