介绍 YABFFW(另一个BrowseForFolder包装器)是一个CWnd子类,它以一种对mfc友好的方式包装Shell API SHBrowseForFolder()。当然还有其他的方法,但是这里采用的方法(在我看来)可以更干净地集成到MFC应用程序中。我还认为它使定制对话框的外观和行为变得更加容易。 背景 迟早,我们都需要显示一个对话框来允许用户选择目录。在MSDN中搜索会发现函数::SHBrowseForFolder() (<shlobj.h>)。下一步通常是编写或窃取一个c++类,以更友好的方式封装C风格的函数调用。 至少,我是这样的。在我的例子中,我还需要对对话框进行一些定制。具体地说,我想给它添加一个标记为“Recurse”的小复选框,并在用户取消对话框后检索该复选框的值。所以,我开始上网寻找例子。我找到了几个——c++包装器,以及定制“浏览文件夹”对话框的示例——并愉快地开始复制它们。然而,当我实现代码时,我开始看到一种更干净、更可扩展的方式来完成我的任务。CYABFFW就是这个过程的产物。 使用的代码 CYABFFW的不同之处在于,它是一个CWnd,在创建之后就派生了“浏览文件夹”对话框。这样类就可以访问消息映射、CObject诊断、DDX/DDV等等。它也让我们不用调用::SetWindowLong,编写一个WndProc等等。当然,它提交给你MFC。如果你不使用MFC, CYABFFW对你没有多大用处。源代码如下所示,当然您可以将其与示例项目一起下载。 我怎么使用它呢? 在最简单的情况下,CYABFFW的外观和行为与大多数MFC对话框类一样。在堆栈上实例化它,调用DoModal(),然后检查返回值以查看用户做了什么。一旦用户点击“OK”,您就可以通过调用GetPath()或GetItemIdList()来检索他们选择的项,这取决于您希望选择的是路径还是ITEMIDLIST。例如: 隐藏,复制Code
CYABFFW dlg(); if (IDOK == dlg.DoModal()) { CString s = dlg.GetPath(); // Do something with `s' ...
SHBrowseForFolder()允许对对话框的外观和行为进行相当多的定制。您可以通过填写传递给函数的BROWSEINFO结构来实现这一点。我尝试以c++程序员更熟悉的方式公开SHBrowseForFolder()提供的所有功能。第一个扩展点是CYABFFW构造函数。有几个构造函数,每个构造函数都接受控制结果对话框的参数数组。要获得完整的列表,请参阅源代码。不过,这里有一个例子: 隐藏,复制Code
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_INITIALIZED、BFFM_SELCHANGED、BFFM_VALIDATEFAILED的自定义消息。当然,您也可以将消息映射项映射到您的子类,并处理您感兴趣的任何Windows消息。演示项目包括这样做的一个示例,以添加我的“Recurse”复选框。 设置初始选择 在我发布这篇文章的第一个版本后出现的一个问题是如何设置对话框的初始选择。Microsoft KB第179378篇文章建议处理BFFM_INITIALIZED通知并发送BFFM_SETSELECTION消息。我决定构建对此的支持:CYABFFW构造函数现在接受一个可选的默认选择,而CYABFFW::OnInitBFFDialog()将处理适当地设置选择。因此,如果您子类化CYABFFW并覆盖OnInitBFFDialog,请确保您也调用了基类实现。 历史 发布日期:2005年5月7日。日期首次更新:2005年5月10日。日期第二次更新:2007年6月12日 本文转载于:http://www.diyabc.com/frontweb/news427.html