@Jie's Blog

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
1. 用什麼函數

  在一些Windows應用程序中,我們會遇到一種對話框,它以樹形列表的形式分層列出所有的磁盤分區和文件夾,並允許我們選擇其中的一個文件夾。這些窗口的外觀都是一致的,所以應該是通過同樣的接口完成的。那麼我們如何在自己的程序中使用文件夾選擇對話框呢。

  這是否是Common Dialog Box呢? 可以明確的說--不是,因為無論是GetOpenFileName還是GetSaveFileName,操作的對像都是文件,它們並未提供一個可設置的Flag值來使彈出的對話框可以選擇文件夾。

  通過對此類應用程序所調用的繫統DLL函數的分析,會發現在shell.dll中有一個名為SHBrowseForFolder的函數。

  在MSDN的Windows Shell Functions的列表裡,我找到這個函數。MSDN對它的解釋是Displays a dialog box that enables the user to select a Shell folder -- 顯示一個對話框以允許用戶選擇一個共享文件夾
。沒錯,就是它。

  知道了用什麼函數,那我們快快把它加到代碼裡吧。

2. 函數的說明

2.1 原型

  函數的原型式是
  LPITEMIDLIST SHBrowseForFolder( LPBROWSEINFO lpbi )

2.2 參數
  其中lpbi指向一個BROWSEINFO結構。通過這個結構,我們可以控制對話框的功能和外觀。

  BROWSEINFO結構如下

typedef struct _browseinfo 
    HWND hwndOwner;        
      
// 父窗口句柄
    LPCITEMIDLIST pidlRoot;              
      // 要顯示的文件夾的根(Root)
    LPTSTR pszDisplayName; 
      // 保存被選取的文件夾路徑的緩衝區
    LPCTSTR lpszTitle;            
       
// 顯示位於對話框左上部的標題
    UINT ulFlags;              
      // 指定對話框外觀和功能的標志
    BFFCALLBACK lpfn;                    
      // 處理事件的回調函數
    LPARAM lParam;               
      // 應用程序傳遞給回調函數的參數
    int iImage;               
      // 保存被選取的文件夾的圖片索引
}
 BROWSEINFO, *PBROWSEINFO, *LPBROWSEINFO; 


  這其中,要注意的參數有這麼幾個。

  pszDisplayName
   -- 這個參數指向一個緩衝區,SHBrowseForFolder默認這個緩衝區的大小為MAX_PATH(繫統定義的宏,表示一個路徑名的最大長度),並用它來保存被選取的文件夾得路徑。

  ulFlags --
  SHBrowseForFolder允許我們指定對話框的功能和外觀,這個參數正是起這樣的用途。它的值可以由十多個宏組合而成。比如BIF_RETURNNONLYFSDIRS是隻返回文件繫統的目錄,BIF_BROWSEFORCOMPUTER是隻返回網絡上的電腦名,BIF_EDITBOX是顯示一個編輯框,允許用戶鍵入文件夾名。一般來說,如果是簡單的用於選擇一個文件夾,設置ulFlags = BIF_RETURNONLYLYFSDIRS即可。

  pidRoot --
  它指向一個ITEMIDLIST結構,作為在列表中顯示的文件夾的根目錄,如果為NULL則默認為Desktop。ITEMIDLIST結構除了用在這裡外,它還用作函數的返回值(參看函數原型)。那麼為什麼不用字符串來表示這個目錄呢,這個結構怎樣表示一個目錄呢?下面作一個簡單的介紹。

2.3 ITEMID和ITEMIDLIST

  Windows Shell的一個功能在於管理並提供方法存取繫統中的眾多對像,這些對像包括了文件,網絡上的計算機,控制面板程序,回收站等等,為了識別每一個對像,Windows Shell使用了Item ID來表示它們,而Iten ID Lists用來表示一個對像的路徑。所以,ITEMID和ITEMIDLIST的關繫類似於文件名和路徑的關繫。如果隻對文件繫統而言的話,ITEMIDLIST可以看成是路徑的另一種表示法,Windows Shell也提供了函數來進行轉換。

  BOOL SHGetPathFromIDList( LPCITEMIDLIST pidl, LPSTR pszPath )
  這個函數將一個ITEMLIST轉換成文件繫統中的路徑。


2.4 返回值

  SHBrowseForFolder的返回值也是一個指向ITEMIDLIST的指針。這個ITEMIDLIST正式表示了用戶所選擇的文件夾。如上所述,通過SHGetPathFromIDList,就可以獲得一個文件夾Path的字符串。

  要注意的是返回的指針必須由應用程序自己來釋放。並且,由於SHBrowseForFolder是通過調用IMalloc Interface來分配Memory,所以,也必須通過這個Interface來釋放。


3. 完整的例子

 BOOL SelectFolder( HWND hWnd, LPSTR lpszFolder )
{
    BROWSEINFO bi; 
    ITEMIDLIST 
*pidl; 
    TCHAR    szPath[MAX_PATH];
    
    memset( 
&bi, 0sizeof(bi) );
    
    bi.hwndOwner 
= hWnd; 
    bi.pidlRoot 
= NULL; 
    bi.pszDisplayName 
= szPath; 
    bi.lpszTitle 
= TEXT("Please select a folder"); 
    bi.ulFlags 
= BIF_RETURNONLYFSDIRS; 
    bi.lpfn 
= NULL; 
    bi.lParam 
= 0
    bi.iImage 
= 0;

    pidl 
= SHBrowseForFolder( &bi );
    
    
if( pidl )
    
{
        SHGetPathFromIDList( pidl, lpszFolder );

        LPMALLOC lpMalloc;

        
if( SUCCEEDED(SHGetMalloc(&lpMalloc)) )
        
{
            lpMalloc
->Free( pidl );
            lpMalloc
->Release();
        }


        
return TRUE;
    }


    
return FALSE;    
}



posted on 2004-11-09 15:55  Zhuang Jie  阅读(889)  评论(0编辑  收藏  举报