• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            franksunny的個人技術空間
            獲得人生中的成功需要的專注與堅持不懈多過天才與機會。 ——C.W. Wendte

             

            使用SHBrowseForFolder函數打開文件目錄對話框

             

            自從第一份工作辭職后,差不多三年多沒有再搞MFC了,對于微軟的Windows桌面開發真的淡忘了,這次接到一個任務,需要開發個小工具,雖然任務很小,但是在一個如何打開文件目錄對話框的小問題上卡了下,雖然通過網絡找到了解決方法,但是網上七拼八湊的文章太多,看的有點費時,所以就抽時間小結一下,雖然也是簡單使用,沒有太多擴展,就當給自己Mark一下吧。

            關于SHBrowseForFolder函數和簡單使用

            打開文件目錄對話框,我找到的方法就是使用SHBrowseForFolder函數,這個函數的原型是LPITEMIDLIST SHBrowseForFolder(LPBROWSEINFO lpbi)。函數很簡單,就一個返回值和一個參數。參數簡單羅列如下

            typedef struct _browseinfo {

                 HWND hwndOwner;            // 父窗口句柄

                 LPCITEMIDLIST pidlRoot;    // 要顯示的文件目錄對話框的根(Root)

                 LPTSTR pszDisplayName;     // 保存被選取的文件夾路徑的緩沖區

                 LPCTSTR lpszTitle;         // 顯示位于對話框左上部的標題

                 UINT ulFlags;              // 指定對話框的外觀和功能的標志

                 BFFCALLBACK lpfn;          // 處理事件的回調函數

                 LPARAM lParam;             // 應用程序傳給回調函數的參數

                 int iImage;                // 文件夾對話框的圖片索引

            } BROWSEINFO, *PBROWSEINFO, *LPBROWSEINFO

            一般而言父窗口句柄(hwndOwner)和根(pidlRoot)設置為Null就可以了,pszDisplayName設定一塊MAX_PATH大小的緩沖區,跟顯示相關的參數就是對話框提示標題(lpszTitle)、對話框樣式(ulFlags)、設定對話框的缺省路徑的操作(lpfnlParam)以及對話框任務欄上顯示的圖標(iImage)。

            由于返回值LPITEMIDLIST是一個指向ITEMIDLIST的指針,這個ITEMIDLIST涉及到Windows Shell中關于管理諸如文件、網絡上的計算機、控制面板程序、回收站等等對象的知識點,Windows Shell為了識別具體的每一個對象,就使用了ITEMID來唯一識別和區分,而ITEMIDLIST就是一個完整的對象路徑。顯然這個函數可以用來瀏覽非文件對象,比如局域網內的電腦等等,在這里這個LPITEMIDLIST返回的對象路徑是一個文件夾的路徑,Windows提供了一個函數BOOL SHGetPathFromIDList(LPCITEMIDLIST pidl, LPSTR pszPath)來實現從對象路徑轉化為文件夾路徑。

            在這里需要注意的是,這個返回值是通過調用IMalloc Interface來分配內存的,函數并不負責釋放內存操作,所以我們在使用完這個返回值之后,必須通過IMalloc Interface來釋放內存。

            下面給出一段最簡單的使用代碼

                   BROWSEINFO bi;

                   char Buffer[MAX_PATH];

                   //初始化入口參數bi開始

                   bi.hwndOwner = NULL;

                   bi.pidlRoot =NULL;//初始化制定的root目錄很不容易

                   bi.pszDisplayName = Buffer;//此參數如為NULL則不能顯示對話框

                   bi.lpszTitle = "選擇Sis目標文件路徑";

                   bi.ulFlags = BIF_EDITBOX;//帶編輯框的風格

                   bi.lpfn = NULL;

                   bi.lParam = 0;

                   bi.iImage=IDR_MAINFRAME;

                   //初始化入口參數bi結束

                   LPITEMIDLIST pIDList = SHBrowseForFolder(&bi);//調用顯示選擇對話框

                   if(pIDList)

                   {

                      SHGetPathFromIDList(pIDList, Buffer);

                      //取得文件夾路徑到Buffer

                      CString m_cSisDes = Buffer;//將路徑保存在一個CString對象里

                   }

                   UpdateData(FALSE);

             

                   // free memory used     

                IMalloc * imalloc = 0;

                   if (SUCCEEDED(SHGetMalloc(&imalloc)))

                   {

                          imalloc->Free (pIDList);

                          imalloc->Release();

                   }

            如上代碼可以顯示一個最簡單的帶編輯框的其實選中對象為我的電腦的瀏覽文件夾對話框。

            創建一個可以新建文件夾且指定選中初始路徑的瀏覽文件夾對話框

            由于我在實際工作中需要的就是一個有新建文件夾功能且指定初始選中路徑的瀏覽文件夾對話框,就把這個需求當做擴展應用吧,由于對話框樣式由ulFlags標記確定,而在系統頭文件SHLOBJ.h頭文件中給出的對話框樣式只有如下幾種

            // Browsing for directory.

            #define BIF_RETURNONLYFSDIRS   0x0001  // For finding a folder to start document searching

            #define BIF_DONTGOBELOWDOMAIN  0x0002  // For starting the Find Computer

            #define BIF_STATUSTEXT         0x0004

            #define BIF_RETURNFSANCESTORS  0x0008

            #define BIF_EDITBOX            0x0010

            #define BIF_VALIDATE           0x0020   // insist on valid result (or CANCEL)

             

            #define BIF_BROWSEFORCOMPUTER  0x1000  // Browsing for Computers.

            #define BIF_BROWSEFORPRINTER   0x2000  // Browsing for Printers

            #define BIF_BROWSEINCLUDEFILES 0x4000  // Browsing for Everything

            沒有滿足我需求的樣式,通過csdn查到其實有一個支持新建文件夾功能的樣式值0x40,通常網絡上給出宏為BIF_NEWDIALOGSTYLEBIF_USENEWUI,由于不知道在具體哪個頭文件中,所以我們可以在代碼中自己定義一下這兩個宏,具體如下

            #define BIF_NEWDIALOGSTYLE   0x40

            #define BIF_USENEWUI (BIF_NEWDIALOGSTYLE|BIF_EDITBOX)

            這樣一來第一個問題解決了,那么如何讓對話框有初始選中的文件夾路徑呢,我起初想著通過pidlRoot,結果撞了一鼻子灰,原來設定初始選中文件夾路徑,是通過那個神奇的回調函數來實現,換句話來說你調用SHBrowseForFolder也就好比你調用了CDialog:: DoModal()函數,具體這個對話框里面的類似初始化,選擇等操作的不同實現就通過lpfn這個回調函數來實現了。

            下面給出這個簡單擴展的代碼

            #define BIF_NEWDIALOGSTYLE   0x40

             

            int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData)  

            {

                   if(uMsg == BFFM_INITIALIZED)

                   {  

                          SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);

                   }

                   return 0;  

            }

             

            void CSisAppendMidDlg::OnButtonSisdes()

            {

                   // TODO: Add your control notification handler code here

                   BROWSEINFO bi;

                   char Buffer[MAX_PATH];

                   //初始化入口參數bi開始

                   bi.hwndOwner = NULL;

                   bi.pidlRoot =NULL;//初始化制定的root目錄很不容易

                   bi.pszDisplayName = Buffer;//此參數如為NULL則不能顯示對話框

                   bi.lpszTitle = "選擇Sis目標文件路徑";

                   bi.ulFlags = BIF_EDITBOX|BIF_NEWDIALOGSTYLE;  

                   CFileFind   finder;

                   if(finder.FindFile(m_cSisDes)==FALSE)

                   {

                          bi.lParam =0;

                          bi.lpfn = NULL;

                   }

                   else

                   {

                          bi.lParam = (long)(m_cSisDes.GetBuffer(m_cSisDes.GetLength()));//初始化路徑,形如(_T("c:\\Symbian"));

                          bi.lpfn = BrowseCallbackProc;

                   }

                   finder.Close();

                   bi.iImage=IDR_MAINFRAME;

                   //初始化入口參數bi結束

                   LPITEMIDLIST pIDList = SHBrowseForFolder(&bi);//調用顯示選擇對話框

                   if(pIDList)

                   {

                      SHGetPathFromIDList(pIDList, Buffer);

                      //取得文件夾路徑到Buffer

                      m_cSisDes = Buffer;//將路徑保存在一個CString對象里

                   }

                   UpdateData(FALSE);

             

                   // free memory used     

                IMalloc * imalloc = 0;

                   if ( SUCCEEDED(SHGetMalloc( &imalloc)))

                   {

                          imalloc->Free (pIDList);

                          imalloc->Release();

                   }

             

            }

            好了,簡單擴展就到這里為止,至于很多大神需要再做更深一步的擴展,那就沿著這個思路走下去就可以了。畢竟我目前也就走到這一步了,呵呵。

             

            posted on 2010-12-30 18:35 frank.sunny 閱讀(18776) 評論(0)  編輯 收藏 引用 所屬分類: MFC相關技術

            常用鏈接

            留言簿(13)

            隨筆分類

            個人其它博客

            基礎知識鏈接

            最新評論

            閱讀排行榜

            評論排行榜

            亚洲精品乱码久久久久久蜜桃| 亚洲国产精品无码久久98| 久久国产亚洲精品| 精品综合久久久久久888蜜芽| 国产AV影片久久久久久| 久久久久国产精品嫩草影院| 久久精品国产久精国产果冻传媒| 2022年国产精品久久久久| 亚洲av成人无码久久精品| 精品国产99久久久久久麻豆| 国产精品久久影院| 综合网日日天干夜夜久久| 久久久久一本毛久久久| 日韩精品久久久肉伦网站| 亚洲国产精品无码久久青草| 伊人久久大香线蕉av一区| 99热都是精品久久久久久| 久久经典免费视频| 久久九九精品99国产精品| 久久妇女高潮几次MBA| 91精品国产色综久久| 久久婷婷五月综合97色直播| 91精品国产91久久久久久蜜臀| 久久午夜无码鲁丝片| 久久国产成人亚洲精品影院| 国产精品免费久久久久影院 | 亚洲AV日韩精品久久久久久| 久久精品国产色蜜蜜麻豆| 久久久午夜精品福利内容| 国产无套内射久久久国产| 久久91精品国产91久久小草| 日日狠狠久久偷偷色综合96蜜桃| 久久久无码精品亚洲日韩蜜臀浪潮| 天堂无码久久综合东京热| 久久夜色精品国产www| 亚洲国产成人精品无码久久久久久综合| 成人a毛片久久免费播放| 欧美亚洲国产精品久久蜜芽| 93精91精品国产综合久久香蕉| 国产69精品久久久久99| 久久青青草原精品国产软件|