最近忙於一些相當無聊的事情,還沒忙完,不過,博客還是要寫的,不然我頭頂上會多了幾塊磚頭 。
在上一篇博文中,我們浏覽了文件,今天我們也浏覽一下目錄,如何?
浏覽目錄我們 同樣有兩個規矩,用托管類庫的我就不說了,相信大家兩分鐘就能弄好。重點還是說說第二個規矩,用 API方式。我們用到的是Shell函數,一提到Shell,可能有朋友會感到痛苦,因為它很多函數涉及到COM ,不過,也沒什麼了,反正我的哲學理念是立足於實戰。所以,我給大家總結了思路。
就拿今 天我們要用到的SHBrowseForFolder函數來說吧,先說說這個函數的用途吧,一句話概括:顯示一個對 話框,讓你可以選擇一個目錄。
COM對象需要先初始化,再用,用完了釋放,根據這個思路,大 的步驟如下:
1、CoInitialize(NULL); //初始化。
2、調用函數。
3、 CoUninitialize(); //釋放。
這個動作就好比你去租用商家的自行車去游玩,別人只是把資源 (自行車)借給你用,你給押金(引用計數),等到你耍完了,再去把資源還給人家。
要調用 SHBrowseForFolder函數,先初始化它的參數,也就是BROWSEINFO結構體,這個家伙初始化後,將地址 傳給SHBrowseForFolder的lpbi參數。BROWSEINFO結構你得設置以下成員。
PIDLIST_ABSOLUTE
pIDLIST;//函數返回的值存在這裡
BROWSEINFO brsInfo;
WCHAR fdpath[MAX_PATH]; //接收選擇目錄的字符數組
。。。。。。。。。。。。。。。。。。。
brsInfo.hwndOwner = hWnd; //擁有者窗口
brsInfo.pidlRoot = NULL; //根目錄為桌面
brsInfo.pszDisplayName = fdpath; //返回的被選擇的路徑
brsInfo.lpszTitle = L"請選擇目錄"; //對話框標題
brsInfo.ulFlags= BIF_RETURNONLYFSDIRS | BIF_DONTGOBELOWDOMAIN | BIF_NEWDIALOGSTYLE; //不顯
示網絡路徑
brsInfo.lpfn = NULL; //沒有回調
brsInfo.lParam = NULL; //沒有額外參數
之後就可以調用函數了。
// 初始化COM
組件,用完後記得釋放
CoInitialize(NULL);
pIDLIST = SHBrowseForFolder(&brsInfo);
if(pIDLIST)
{
//取出對話框中用來顯示結果的控件
HWND hStatic = GetDlgItem(hfDlg, IDC_DISPLAY);
SendMessage(hStatic,WM_SETTEXT, NULL, (LPARAM)fdpath);
}
CoUninitialize();
// 釋放IDLIST
CoTaskMemFree((LPVOID)pIDLIST);
由於PIDLIST也是COM對象資源,通過調用CoTaskMemFree 函數將其釋放。
現在,運行一下應用程序。


聰明的你會發現,雖然我們得到了選擇的目錄名字,但不是完整路徑,通常我 們是需要完整的路徑的。這個也不難,我們再請出另一個函數——SHGetPathFromIDList,它可以幫我 們得出完整的路徑。
所以,我們把上面的代碼修改一下。
if(pIDLIST)
{
//得到完整路徑
SHGetPathFromIDList(pIDLIST, fullPath);
//取出對話框中用來顯示結果的控件
HWND hStatic = GetDlgItem(hfDlg, IDC_DISPLAY);
SendMessage(hStatic, WM_SETTEXT, NULL, (LPARAM)fullPath);
//SendMessage(hStatic,WM_SETTEXT, NULL, (LPARAM)fdpath);
}
現在再看看結果,這回你肯定滿意了。

-------------- 【C++ Code】 -------------------------
LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
PIDLIST_ABSOLUTE pIDLIST;//函數返回的值存在這裡
BROWSEINFO brsInfo;
WCHAR fdpath[MAX_PATH]; //接收選擇目錄的字符數組
WCHAR fullPath[MAX_PATH]; //完整路徑
static HWND hfDlg;
switch (message)
{
case WM_CREATE:
hfDlg = CreateDialog(hInst, MAKEINTRESOURCE(IDD_FORMVIEW), hWnd, NULL);
ShowWindow(hfDlg,SW_SHOW);
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜單選擇:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case IDM_BROWSFOLDER:
brsInfo.hwndOwner = hWnd; //擁有者窗口
brsInfo.pidlRoot = NULL; //根目錄為桌面
brsInfo.pszDisplayName = fdpath; //返回的被選擇的路徑
brsInfo.lpszTitle = L"請選擇目錄"; //對話框標題
brsInfo.ulFlags= BIF_RETURNONLYFSDIRS | BIF_DONTGOBELOWDOMAIN |
BIF_NEWDIALOGSTYLE; //不顯示網絡路徑
brsInfo.lpfn = NULL; //沒有回調
brsInfo.lParam = NULL; //沒有額外參數
// 初始化COM組件,用完後記得釋放
CoInitialize(NULL);
pIDLIST = SHBrowseForFolder(&brsInfo);
if(pIDLIST)
{
//得到完整路徑
SHGetPathFromIDList(pIDLIST, fullPath);
//取出對話框中用來顯示結果的控件
HWND hStatic = GetDlgItem(hfDlg, IDC_DISPLAY);
SendMessage(hStatic, WM_SETTEXT, NULL, (LPARAM)fullPath);
//SendMessage(hStatic,WM_SETTEXT, NULL, (LPARAM)fdpath);
}
CoUninitialize();
// 釋放IDLIST
CoTaskMemFree((LPVOID)pIDLIST);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意繪圖代碼...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}