首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

C++Builder 目錄選擇對話框兩種實作:SHBrowseForFolder 與 SelectDirectory

     編輯:VC 教學

前言

應用程式常需讓使用者選擇目錄(如匯出路徑、掃描根目錄)。C++Builder 提供兩種主要方式:Windows Shell SHBrowseForFolder(樹狀瀏覽、支援網路芳鄰)與 VCL 封裝 SelectDirectory(類似檔案對話框、可新建資料夾)。本文完整實作兩種封裝函式,並對比優缺點與適用場景。

方法一:SHBrowseForFolder — 標準 Shell 目錄瀏覽器

完整封裝函式


#include   // 需連結 shell32.lib

AnsiString SelectFolder(AnsiString Caption)
{
    BROWSEINFO bi = {0};
    LPITEMIDLIST pidl = NULL;
    char displayName[MAX_PATH] = {0};
    char path[MAX_PATH] = {0};

    bi.hwndOwner = Application->Handle;
    bi.pszDisplayName = displayName;
    bi.lpszTitle = Caption.c_str();
    bi.ulFlags = BIF_RETURNONLYFSDIRS |   // 僅回傳檔案系統目錄
                 BIF_NEWDIALOGSTYLE |     // Vista+ 新樣式 (可調整大小、搜尋框)
                 BIF_BROWSEINCLUDEFILES;  // 選項:允許顯示檔案 (通常目錄選擇不需)

    pidl = SHBrowseForFolder(&bi);
    if (!pidl) return ""; // 使用者取消

    if (SHGetPathFromIDList(pidl, path))
    {
        CoTaskMemFree(pidl); // 必須釋放 PIDL 記憶體
        AnsiString result = path;
        if (!result.IsEmpty() && result[result.Length()] != '\\')
            result += '\\';
        return result;
    }

    CoTaskMemFree(pidl);
    return "";
}

關鍵旗標 (ulFlags) 速查

旗標效果
BIF_RETURNONLYFSDIRS僅回傳檔案系統目錄(過濾虛擬資料夾如控制台、印表機)
BIF_DONTGOBELOWDOMAIN不顯示網路芳鄰下層
BIF_STATUSTEXT在對話框顯示狀態文字 (需回呼函式)
BIF_RETURNFSANCESTORS允許選擇非檔案系統目錄的父目錄
BIF_EDITBOX舊版:包含編輯框輸入路徑
BIF_NEWDIALOGSTYLEVista+ 新樣式:可調整大小、搜尋、輕鬆存取
BIF_BROWSEINCLUDEFILES樹中顯示檔案 (通常目錄選擇不勾選)
BIF_UAHINT顯示使用者存取控制提示
BIF_NONEWFOLDERBUTTON隱藏「新建資料夾」按鈕 (新樣式預設顯示)

進階:自訂回呼函式 (BFFCALLBACK)


int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
    switch (uMsg)
    {
        case BFFM_INITIALIZED:
            // 設定初始目錄
            SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)lpData);
            break;
        case BFFM_SELCHANGED:
            // 選擇變更:啟用/禁用 OK 按鈕、更新狀態文字
            // SHGetPathFromIDList((LPITEMIDLIST)lParam, buffer);
            // SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)buffer);
            break;
        case BFFM_VALIDATEFAILED:
            // 驗證失敗 (輸入無效路徑)
            return 1; // 1=保持對話框, 0=關閉
    }
    return 0;
}

// 使用回呼
bi.lpfn = BrowseCallbackProc;
bi.lParam = (LPARAM)"C:\\Initial\\Path"; // 初始目錄

方法二:SelectDirectory — VCL 封裝對話框

完整封裝函式


#include 

AnsiString SelectDir(AnsiString Dir)
{
    // TSelectDirOpts 選項組合
    TSelectDirOpts opts;
    opts << sdAllowCreate   // 允許使用者輸入新資料夾名稱
         << sdPerformCreate // 實際建立新資料夾
         << sdPrompt;       // 顯示提示訊息

    if (SelectDirectory(Dir, opts, 0))
        return Dir;
    return "";
}

選項 (TSelectDirOpts) 速查

選項效果
sdAllowCreate允許在編輯框輸入新資料夾名稱
sdPerformCreate按下 OK 時實際建立資料夾 (需搭配 sdAllowCreate)
sdPrompt對話框標題列顯示提示文字
sdShowEdit顯示編輯框 (舊樣式)

兩者詳細對比

特性SHBrowseForFolderSelectDirectory
介面風格樹狀瀏覽 (類似總管左側)類似開啟/儲存檔案對話框
網路芳鄰支援完整支援不支援
新建資料夾新樣式預設支援 (BIF_NONEWFOLDERBUTTON 控制)需 sdAllowCreate + sdPerformCreate
鍵盤輸入路徑新樣式支援搜尋/輸入支援 (sdShowEdit)
本地化系統自動本地化 (中文 Windows 顯示中文)介面固定英文 (VCL 內建資源)
自訂程度高 (回呼函式可控制啟用/禁用、狀態文字、初始目錄)低 (僅選項旗標)
相依性shell32.lib, shlobj.hFileCtrl.hpp (VCL 內建)
回傳值AnsiString 路徑bool 成功, 路徑由參考參數回傳

使用範例


// 1. Shell 方式 (推薦:支援網路、本地化、新樣式)
AnsiString dest = SelectFolder("請選擇匯出資料的目標目錄");
if (!dest.IsEmpty())
{
    ExportData(dest);
}

// 2. VCL 方式 (簡單、不需網路、可新建)
AnsiString dest2 = "";
if (SelectDirectory(dest2, TSelectDirOpts() << sdAllowCreate << sdPerformCreate, 0))
{
    ExportData(dest2);
}

現代替代方案:IFileDialog (Vista+)

Windows Vista 引入 IFileDialog (配合 FOS_PICKFOLDERS),提供更現代的資料夾選擇體驗:

  • 支援搜尋、標籤、庫、已知資料夾虛擬化
  • 完整 COM 介面,可自訂事件、置換控制項
  • C++Builder 可透過 ComObj.hpp + ShlObj.hpp 使用

// 簡易範例
IFileDialog* pfd = NULL;
CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
    IID_IFileDialog, (void**)&pfd);
DWORD options;
pfd->GetOptions(&options);
pfd->SetOptions(options | FOS_PICKFOLDERS);
pfd->Show(Application->Handle);
IShellItem* psi;
pfd->GetResult(&psi);
LPWSTR pszPath;
psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
AnsiString path = pszPath;
CoTaskMemFree(pszPath);
psi->Release();
pfd->Release();

選擇建議

  • 需支援網路芳鄰、系統本地化、現代 UI → SHBrowseForFolder (加 BIF_NEWDIALOGSTYLE)
  • 簡單本地目錄選擇、需新建資料夾、程式碼極簡 → SelectDirectory
  • Vista/Win7/10/11 專屬、追求最佳 UX、願意寫 COM 代碼 → IFileDialog + FOS_PICKFOLDERS

掌握這三種方式,即可應對從舊版相容到現代體驗的所有目錄選擇需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved