65.9K
CodeProject 正在变化。 阅读更多。
Home

CYABFFW:另一个BrowseForFolder包装器

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.97/5 (10投票s)

2005 年 5 月 10 日

3分钟阅读

viewsIcon

74657

downloadIcon

1239

另一个用于::BrowseForFolder函数的包装器。

CYABFFW in action

引言

YABFFW(另一个 BrowseForFolder 包装器)是一个 CWnd 子类,它以 MFC 友好的方式包装了 Shell API SHBrowseForFolder()。市面上肯定有其他的包装器,但(在我看来)这里采用的方法能更干净地集成到 MFC 应用程序中。我也相信它能让对话框的外观和行为更容易定制。

背景

迟早,我们都需要显示一个允许用户选择目录的对话框。在 MSDN 中搜索会找到函数 ::SHBrowseForFolder() (<shlobj.h>)。接下来的步骤通常是编写或“窃取”一个 C++ 类,将 C 风格的函数调用包装成更 MFC 友好的方式。

至少,我就是这样做的。在我的例子中,我还想稍微定制一下对话框。具体来说,我想在里面添加一个带有“递归”标签的小复选框,并在用户关闭对话框后检索该复选框的值。于是,我开始在网上搜索示例。我找到了几个——C++ 包装器,以及定制“浏览文件夹”对话框的示例——并很高兴地开始复制代码。然而,在实现代码的过程中,我开始看到一种更清晰、更可扩展的方式来完成我的任务。CYABFFW 就是这个过程的产物。

使用代码

CYABFFW 的不同之处在于它是一个 CWnd,它在创建后立即对“浏览文件夹”对话框进行子类化。这使得该类可以访问消息映射、CObject 诊断、DDX/DDV 等功能。我们也不再需要调用 ::SetWindowLong、编写 WndProc 等等。当然,这也意味着你必须使用 MFC。如果你不使用 MFC,CYABFFW 对你来说就没有多大用处了。下面是源代码,当然你也可以下载它以及一个示例项目。

我该如何使用它?

最简单的情况下,CYABFFW 的外观和行为与大多数 MFC 对话框类一样。你在堆栈上实例化它,调用 DoModal(),然后检查返回值来查看用户做了什么。一旦用户点击“确定”,你就可以通过调用 GetPath()GetItemIdList() 来检索他们选择的项,这取决于你是想要路径还是 ITEMIDLIST。例如:

CYABFFW dlg();
if (IDOK == dlg.DoModal())
{
    CString s = dlg.GetPath();
    // Do something with `s' ...

SHBrowseForFolder() 允许对对话框的外观和行为进行相当程度的自定义。你可以通过填充一个传递给函数的 BROWSEINFO struct 来实现。我试图以 C++ 程序员更熟悉的方式暴露 SHBrowseForFolder() 提供的所有功能。第一个扩展点是 CYABFFW 构造函数。有几个构造函数,每个都接受一个参数数组来控制生成的对话框。有关完整列表,请参阅源代码。不过,这里有一个示例:

CYABFFW dlg(_T("Please select a directory"), // Hint to user
            BIF_USE_NEWUI,                   // Flags for the dlg
            this,                            // Parent window
            CSIDL_DRIVES);                   // Root of search
if (IDOK == dlg.DoModal())
{
    CString s = dlg.GetPath();
    // Do something with `s' ...

如果你想通过构造函数参数以外的方式来定制对话框,你需要对 CYABFFW 进行子类化。CYABFFW 定义了三个可以重写的虚函数:OnInitBFFDialog()OnBFFSelChanged()OnBFFValidateFailed()。这些分别对应 SHBrowseForFolder() 发送给可选回调函数的自定义消息 BFFM_INITIALIZEDBFFM_SELCHANGEDBFFM_VALIDATEFAILED。当然,你也可以将消息映射条目添加到你的子类中,并处理任何你感兴趣的 Windows 消息。演示项目包括一个这样做的示例,用于添加我的“递归”复选框。

设置初始选择

在我发布本文第一个版本后出现的一个问题是如何为对话框设置初始选择。Microsoft KB 文章 179378 建议处理 BFFM_INITIALIZED 通知并向自己发送 BFFM_SETSELECTION 消息。我决定为此添加支持:CYABFFW 构造函数现在接受一个可选的默认选择,并且 CYABFFW::OnInitBFFDialog() 将负责相应地设置选择。因此,如果你对 CYABFFW 进行子类化并重写 OnInitBFFDialog,请确保也调用基类实现。

历史

  • 发布日期:2005 年 5 月 7 日。
  • 首次更新日期:2005 年 5 月 10 日。
  • 第二次更新日期:2007 年 6 月 12 日。
© . All rights reserved.