最近忙於一些相當無聊的事情,還沒忙完,不過,博客還是要寫的,不然我頭頂上會多了幾塊磚頭 。
在上一篇博文中,我們浏覽了文件,今天我們也浏覽一下目錄,如何?
浏覽目錄我們 同樣有兩個規矩,用托管類庫的我就不說了,相信大家兩分鐘就能弄好。重點還是說說第二個規矩,用 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; }