最近忙于一些相當無聊的事情,還沒忙完,不過,博客還是要寫的,不然我頭頂上會多了幾塊磚頭。
在上一篇博文中,我們瀏覽了文件,今天我們也瀏覽一下目錄,如何?
瀏覽目錄我們同樣有兩個規矩,用托管類庫的我就不說了,相信大家兩分鐘就能弄好。重點還是說說第二個規矩,用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;
}
~~~
- 前言
- (1):關于C++的幾個要點
- (2):完整的開發流程
- (3):窗口的重繪
- (4):創建菜單
- (5):具有單選標記的菜單
- (6):創建右鍵菜單
- (7):多邊形窗口
- (8):繪圖(A)
- (9):繪圖(B)
- (10):繪圖(C)
- (11):使用控件——先來耍一下按鈕
- (12):使用控件——單選按鈕
- (13):握手對話框
- (14):用對話框作為主窗口
- (15):ListView控件
- (16):ListView的多個視圖
- (17):啟動和結束進程
- (18):使用對話框的兩個技巧
- (19):瀏覽和打開文件
- (20):瀏覽文件夾
- (21):復制&粘貼&剪貼板操作
- (22):抓取屏幕
- (23):漸變顏色填充
- (24):計時器
- (25):監視剪貼板