浏览文件窗口中指定默认目录

本文介绍了一个文件选择器对话框的实现方法,通过使用Windows API函数SHBrowseForFolder展示一个允许用户从所有可用本地驱动器和网络资源中选择文件夹的对话框。

 int CALLBACK BrowseCallbackProc(HWND hwnd,
                                             UINT uMsg,
                                             LPARAM lParam,
                                             LPARAM lpData
                                             )
{
 char szPath[MAX_PATH];

 switch(uMsg)
 {
  case BFFM_INITIALIZED:
   SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
   break;

  case BFFM_SELCHANGED:
   if (SHGetPathFromIDList((LPITEMIDLIST) lParam ,szPath))
   {
    SendMessage(hwnd, BFFM_SETSTATUSTEXT,0,(LPARAM)szPath); 

   }
   break;
 }

 // if((uMsg   &   BFFM_INITIALIZED)   ==   BFFM_INITIALIZED)
 // {
 //SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
 // }
  return   0;  

}

void CSystemParam::OnBnClickedBtnPathBrowse()
{
 //ITEMIDLIST *ppidl;
 //SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP ,&ppidl);
 //if ( ppidl == NULL)
 //{
 // AfxMessageBox(_T("启动路径浏览失败") ) ;
 // return;
 //}

 BROWSEINFO bi;
 memset(&bi,0,sizeof(BROWSEINFO));
    bi.lpszTitle = _T("请选择一个数据文件保存文件");
 bi.lpfn = BrowseCallbackProc;
 bi.lParam = (LPARAM)(LPCTSTR)m_sFileSavePath;
 bi.ulFlags = BIF_RETURNONLYFSDIRS /*| BIF_EDITBOX*/ | BIF_STATUSTEXT /*| BIF_NEWDIALOGSTYLE*/;
    LPITEMIDLIST pidl = SHBrowseForFolder ( &bi );
    if ( pidl != 0 )
    {
        // get the name of the folder
        TCHAR path[MAX_PATH];
        if ( SHGetPathFromIDList ( pidl, path ) )
        {
   m_sFileSavePath.Format(_T("%s"),path);
   if(m_sFileSavePath.GetAt(m_sFileSavePath.GetLength()-1)!=_T('//'))
    m_sFileSavePath.AppendChar(_T('//'));
   UpdateData(FALSE);
        }

        // free memory used
        IMalloc * imalloc = 0;
        if ( SUCCEEDED( SHGetMalloc ( &imalloc )) )
        {
            imalloc->Free ( pidl );
            imalloc->Release ( );
        }
    }
}

参考资料:

The ''Browse For Folder'' dialog allows the user to select a folder from all available local drives and network resources.
The following code snippet demonstrate how to display this dialog-box. The BrowseFolders function accept 3 parameters:
hwnd - The handle of the parent window
lpszFolder - Address of a buffer to receive the selected folder. Before calling this function, you should fill this buffer with the folder that you want to be selected when the dialog-box is loaded at first.
lpszTitle - The text that should be displayed as a title of the ''Browse Folders'' dialog-box


Return back to C/C++ code index

#include <windows.h>
#include <shlobj.h>

int CALLBACK BrowseForFolderCallback(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData)
{
 char szPath[MAX_PATH];

 switch(uMsg)
 {
  case BFFM_INITIALIZED:
   SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData);
   break;

  case BFFM_SELCHANGED:
   if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szPath))
   {
    SendMessage(hwnd, BFFM_SETSTATUSTEXT,0,(LPARAM)szPath); 

   }
   break;
 }

 return 0;
}

BOOL BrowseFolders(HWND hwnd, LPSTR lpszFolder, LPSTR lpszTitle)
{
 BROWSEINFO bi;
 char szPath[MAX_PATH + 1];
 LPITEMIDLIST pidl;
 BOOL bResult = FALSE;

 LPMALLOC pMalloc;

    if (SUCCEEDED(SHGetMalloc(&pMalloc)))
 {
  bi.hwndOwner = hwnd;
  bi.pidlRoot = NULL;
  bi.pszDisplayName = NULL;
  bi.lpszTitle = lpszTitle;
  bi.ulFlags = BIF_STATUSTEXT; //BIF_EDITBOX
  bi.lpfn = BrowseForFolderCallback;
  bi.lParam = (LPARAM)lpszFolder;
  
  pidl = SHBrowseForFolder(&bi);
  if (pidl)
  {
   if (SHGetPathFromIDList(pidl,szPath))
   {
    bResult = TRUE;
    strcpy(lpszFolder, szPath);
   }

     pMalloc->Free(pidl);
     pMalloc->Release();
               
  }
 }

 return bResult;
 
}

 


文章出处:http://www.diybl.com/course/3_program/c++/cppsl/2008520/117219.html

<think> 我们正在讨论Word VBA中Do While循环条件倒置导致无限弹窗的问题,并提供了解决方案。现在用户提出了一个新的问题:如何在VBA中调出浏览文件路径窗口。用户引用了三段内容,其中引用[3]提到了使用.ini文件存储路径,但我们的新问题与文件对话框有关。 根据用户的新问题,我们需要提供在VBA中调出浏览文件路径窗口的方法。在VBA中,通常使用Application.FileDialog属性来调出文件对话框。 解决方案: 1. 使用Application.FileDialog方法,并指定对话框类型(如打开对话框、保存对话框等)。 2. 设置对话框的属性,如初始路径、标题、文件过滤等。 3. 显示对话框并获取用户选择的路径。 具体步骤: - 创建文件对话框对象:使用Application.FileDialog方法,传入对话框类型(msoFileDialogOpen用于打开,msoFileDialogSaveAs用于保存等)。 - 配置对话框:设置InitialFileName(初始路径)、Title(标题)、Filters(文件类型过滤器)等。 - 使用Show方法显示对话框,并检查用户是否点击了“确定”。 - 获取用户选择的文件路径(FileDialog.SelectedItems集合)。 示例代码: 以下是一个示例,展示如何调出“浏览文件夹”对话框(注意:这里不是打开文件对话框,而是选择文件夹的对话框)以及如何调出打开文件对话框。 注意:在Word VBA中,我们可以使用相同的FileDialog对象,因为它是Office应用程序共用的。 但是,用户可能想要的是选择文件夹(而不是文件)的对话框。在VBA中,选择文件夹的对话框有两种方法: 方法1:使用FileDialog,并设置其类型为msoFileDialogFolderPicker(选择文件夹)。 方法2:使用Windows API(较复杂,但更灵活)。 我们这里主要使用FileDialog方法,因为它是内置的,无需声明API。 示例1:调出选择文件夹的对话框。 示例2:调出打开文件的对话框。 我们将分别给出这两个示例。 另外,引用[3]中提到了使用.ini文件来存储上一次的路径,我们可以在示例中加入如何保存上一次选择的路径,并在下次打开对话框时使用该路径作为初始路径。 由于用户引用[2]提到了录制宏的方法,但录制宏只能得到打开文件对话框的代码(不能得到选择文件夹的对话框),所以我们也会提到如何通过录制宏得到打开文件对话框的代码。 具体代码示例: 示例1:选择文件夹浏览文件夹窗口) 示例2:选择文件(打开文件窗口) 同时,我们可以提供一个保存路径到.ini文件的示例,以便下次使用。 下面开始编写回答: </think> ### VBA调出浏览文件路径窗口的完整解决方案 在VBA中实现文件路径浏览功能主要依靠`Application.FileDialog`对象,结合路径存储技术可实现更智能化的操作。以下是详细实现方法: #### 一、基础文件对话框实现 ##### 1. 文件夹选择对话框(浏览目录) ```vba Sub BrowseFolderPath() Dim fDialog As FileDialog Set fDialog = Application.FileDialog(msoFileDialogFolderPicker) ' 设置对话框属性 fDialog.Title = "请选择目标文件夹" fDialog.AllowMultiSelect = False If fDialog.Show = -1 Then ' 用户点击确定 Dim selectedPath As String selectedPath = fDialog.SelectedItems(1) MsgBox "已选择路径:" & selectedPath Else MsgBox "操作已取消" End If End Sub ``` - `msoFileDialogFolderPicker`:专用文件夹选择模式[^1] - `SelectedItems(1)`:获取首个选定项目路径 ##### 2. 文件选择对话框(浏览文件) ```vba Sub BrowseFilePath() Dim fDialog As FileDialog Set fDialog = Application.FileDialog(msoFileDialogOpen) ' 设置文件过滤器 With fDialog .Title = "请选择文本文件" .Filters.Clear .Filters.Add "文本文件", "*.txt" .Filters.Add "所有文件", "*.*" .FilterIndex = 1 End With If fDialog.Show = -1 Then MsgBox "已选择文件:" & fDialog.SelectedItems(1) End If End Sub ``` - `Filters.Add`:添加文件类型过滤器[^2] - `FilterIndex = 1`:默认选中的过滤器 #### 二、增强功能:记忆上次路径 通过INI文件存储历史路径(引用[3]技术)[^3]: ```vba ' 在模块顶部声明API函数 #If VBA7 Then Private Declare PtrSafe Function WritePrivateProfileString _ Lib "kernel32" Alias "WritePrivateProfileStringA" _ (ByVal lpApplicationName As String, _ ByVal lpKeyName As Any, _ ByVal lpString As Any, _ ByVal lpFileName As String) As Long #Else Private Declare Function WritePrivateProfileString _ Lib "kernel32" Alias "WritePrivateProfileStringA" _ (ByVal lpApplicationName As String, _ ByVal lpKeyName As Any, _ ByVal lpString As Any, _ ByVal lpFileName As String) As Long #End If Sub SmartPathBrowser() Dim iniPath As String iniPath = ThisDocument.Path & "\settings.ini" ' 读取上次路径 Dim lastPath As String lastPath = ReadINI("Settings", "LastPath", iniPath) ' 设置初始路径 Dim fDialog As FileDialog Set fDialog = Application.FileDialog(msoFileDialogFolderPicker) If Len(lastPath) > 0 Then fDialog.InitialFileName = lastPath If fDialog.Show = -1 Then Dim newPath As String newPath = fDialog.SelectedItems(1) ' 保存新路径 WritePrivateProfileString "Settings", "LastPath", newPath, iniPath MsgBox "路径已保存:" & newPath End If End Sub ' INI文件读取函数 Function ReadINI(Section As String, Key As String, FilePath As String) As String Dim RetVal As String * 255 GetPrivateProfileString Section, Key, "", RetVal, Len(RetVal), FilePath ReadINI = Left(RetVal, InStr(RetVal, Chr(0)) - 1) End Function ``` 关键技术点: 1. `WritePrivateProfileString`:Windows API写入INI文件 2. `GetPrivateProfileString`:读取INI配置项 3. `InitialFileName`:初始化对话框路径 #### 三、特殊场景处理 ##### 1. 多文件选择 ```vba If fDialog.Show = -1 Then Dim i As Integer For i = 1 To fDialog.SelectedItems.Count Debug.Print "文件" & i & ": " & fDialog.SelectedItems(i) Next i End If ``` ##### 2. 自定义按钮文本 ```vba ' 需Windows API实现 Private Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr Private Declare PtrSafe Function SetWindowText Lib "user32" Alias "SetWindowTextA" _ (ByVal hwnd As LongPtr, ByVal lpString As String) As Long ' 在.Show方法前调用 SetWindowText GetActiveWindow(), "自定义窗口标题" ``` ##### 3. 路径验证 ```vba If fDialog.Show = -1 Then If Dir(fDialog.SelectedItems(1), vbDirectory) = "" Then MsgBox "路径无效!" Exit Sub End If End If ``` #### 四、替代方案对比 | **方法** | **优点** | **缺点** | 适用场景 | |------------------------|-----------------------------|-----------------------------|----------------------| | Application.FileDialog | 官方支持,无需引用 | 无法修改界面细节 | 大多数标准场景 | | Win API 自定义对话框 | 完全自定义界面 | 代码复杂,兼容性问题 | 专业级应用开发 | | 用户窗体+TreeView控件 | 完全控制流程 | 开发周期长 | 高度定制化需求 | | 录制宏生成代码 | 快速获取基础代码[^2] | 生成的代码冗余 | 简单文件操作 | #### 五、最佳实践建议 1. **路径标准化处理** ```vba ' 确保路径结尾有反斜杠 If Right(selectedPath, 1) <> "\" Then selectedPath = selectedPath & "\" ``` 2. **错误处理增强** ```vba On Error Resume Next Set fDialog = Application.FileDialog(msoFileDialogFolderPicker) If Err.Number <> 0 Then MsgBox "创建对话框失败:" & Err.Description Exit Sub End If On Error GoTo 0 ``` 3. **跨平台兼容** ```vba #If Mac Then ' MacOS特殊处理 Dim macPath As String macPath = MacScript("choose folder as string") #Else ' Windows标准处理 #End If ``` > 关键技巧:结合`CurrentDocument.Path`获取当前文档路径作为初始位置,提升用户体验[^1]。 --- ### 总结 在VBA中调出浏览路径窗口的核心方法是: 1. 使用`Application.FileDialog`对象 2. 选择适当的对话框类型: - `msoFileDialogFolderPicker`:浏览文件夹 - `msoFileDialogOpen`:打开文件 - `msoFileDialogSaveAs`:保存文件 3. 通过`InitialFileName`属性设置初始路径 4. 使用`SelectedItems`集合获取用户选择 对于高级需求: - 通过INI文件实现路径记忆[^3] - 使用Windows API自定义对话框 - 添加路径验证确保有效性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值