在Visual C++ 6.0环境下浏览目录对话框的设计

发表于:2007-07-04来源:作者:点击数: 标签:
石 骁 马 非 在VC++6.0编程中,经常要用到选择目录的功能,就象在 AppWizard中选择放置工作区目录一样。在MFC中提供了类似的标准文件对话框CfileDialog类,支持用户对文件的浏览、查找等操作。用SDK函数构造这么一个对话框至少需要几百行代码,用这个类可以简
石 骁 马 非

  在VC++6.0编程中,经常要用到选择目录的功能,就象在 AppWizard中选择放置工作区目录一样。在MFC中提供了类似的标准文件对话框CfileDialog类,支持用户对文件的浏览、查找等操作。用SDK函数构造这么一个对话框至少需要几百行代码,用这个类可以简单地实现和Windows标准模式一致的文件打开、另存为等功能。但在MFC中并没有提供选择目录对话框的标准类,而这在有关目录路径操作中经常用到。

  针对此问题,笔者设计了一个通用的浏览目录对话框的类CbrowseDirDialog,采用Windows API函数SHBrowseForFolder。用户可以采用这个类浏览任何指定的目录,磁盘,并返回用户最后选择的目录信息。

  下面对这个类的使用作一简单介绍:

  在CbrowseDirDialog.h头文件中,定义了如下成员变量和函数:

   public:

   CDirDialog();

   virtual ~CDirDialog();

   int DoBrowse();

   CString m_Path;

   CString m_InitDir;

   CString m_SelDir;

   CString m_Title;

  int m_ImageIndex;

  用户可以设置对话框中浏览信息的标题在m_Title变量中,如果用户不进行设置,系统默认标题为“打开”;设置起始显示目录在m_InitDir变量中,如用户需要列出C盘下的所有目录,只需在定义的对象中设置m_InitDir=“C:\\”, 如果用户不进行设置,系统默认为整个桌面;设置每次显示的默认目录在m_SelDir变量中,如果用户不进行设置,系统默认为根目录。最后,调用DoBrowse函数,即可显示选择对话框目录。如果该函数返回TRUE,则选中的目录名赋予变量m_Path,与选中的目录相关的图标在系统图标中的索引号赋予变量m_ImageIndex;如果返回FALSE,表明用户按下“取消”按钮放弃了此次操作或者程序中出现其他一些不可知错误。

   附源程序清单(本程序在中文Windows98,Visual C++ 6.0中调试通过):

  ////////////////////////////////////////////////////////////////////////

  // BrowseDirDialog.h

  //////////////////////////////////////////////////////////////////////

  class CBrowseDirDialog

  {

   public:

   CBrowseDirDialog();

   virtual ~CBrowseDirDialog();

   int DoBrowse();

   CString m_Path; //存放返回的路径信息

   CString m_InitDir; //初始显示的路径名,默认为桌面

   CString m_SelDir; //打开对话框后,默认选中的目录名,缺省为根目录

   CString m_Title; //设置对话框中浏览信息的标题,默认为"打开"

   int m_ImageIndex;

  };

  

  ///////////////////////////////////////////////////////////////////////////

  // BrowseDirDialog.cpp

  //////////////////////////////////////////////////////////////////////

  

  #include "stdafx.h"

  #include "BrowseDirDialog.h"

  #include "shlobj.h"

  #ifdef _DEBUG

  #undef THIS_FILE

  static char THIS_FILE[]=__FILE__;

  #define new DEBUG_NEW

  #endif

  

  //SHBrowseForFolder控件在初始化或选择改变后的回调函数

  static int __stdcall BrowseCtrlCallback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)

  {

   CBrowseDirDialog* pBrowseDirDialogObj = (CBrowseDirDialog*)lpData;

   if (uMsg == BFFM_INITIALIZED && !pBrowseDirDialogObj-〉m_SelDir.IsEmpty())

   {

  ::SendMessage(hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)(LPCTSTR)(pBrowseDirDialogObj-〉m_SelDir));

   }

   else // uMsg == BFFM_SELCHANGED

   {

   }

   return 0;

  }

  //构造函数

  CBrowseDirDialog::CBrowseDirDialog()

  {

  }

  //析构函数

  CBrowseDirDialog::~CBrowseDirDialog()

  {

  }

  int CBrowseDirDialog::DoBrowse()

  {

   LPMALLOC pMalloc;

   if (SHGetMalloc (&pMalloc)!= NOERROR)

   {

   return 0;

   }

   BROWSEINFO bInfo;

   LPITEMIDLIST pidl;

   ZeroMemory ( (PVOID) &bInfo,sizeof (BROWSEINFO));

   if (!m_InitDir.IsEmpty ())

   {

   OLECHAR olePath[MAX_PATH];

   ULONG chEaten;

   ULONG dwAttributes;

   HRESULT hr;

   LPSHELLFOLDER pDesktopFolder;

   if (SUCCEEDED(SHGetDesktopFolder(&pDesktopFolder)))

   {

   MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED, m_InitDir.GetBuffer(MAX_PATH), -1,

   olePath, MAX_PATH);

  

   m_InitDir.ReleaseBuffer (-1);

   //转换路径为ITEMLIST

   hr = pDesktopFolder-〉ParseDisplayName(NULL,NULL,olePath,&chEaten,&pidl,

   &dwAttributes);

   if (FAILED(hr))

   {

   pMalloc -〉Free (pidl);

   pMalloc -〉Release ();

   return 0;

   }

   bInfo.pidlRoot = pidl;

   }

   }

   bInfo.hwndOwner = NULL;

   bInfo.pszDisplayName = m_Path.GetBuffer (MAX_PATH);

   bInfo.lpszTitle = (m_Title.IsEmpty()) ? "打开":m_Title;

   bInfo.ulFlags = BIF_RETURNFSANCESTORS|BIF_RETURNONLYFSDIRS;

   bInfo.lpfn = BrowseCtrlCallback; //回调函数地址

   bInfo.lParam = (LPARAM)this;

   if ((pidl = ::SHBrowseForFolder(&bInfo)) == NULL)

   {

   return 0;

   }

   m_Path.ReleaseBuffer();

   m_ImageIndex = bInfo.iImage;

   if (::SHGetPathFromIDList(pidl,m_Path.GetBuffer(MAX_PATH)) == FALSE)

   {

   pMalloc -〉Free(pidl);

   pMalloc -〉Release();

   return 0;

   }

   m_Path.ReleaseBuffer();

   pMalloc -〉Free(pidl);

   pMalloc -〉Release();

   return 1;

  }  

原文转自:http://www.ltesting.net