关键字:“添加到收藏夹”对话框, 模态窗口,ishelluihelper,doaddtofavdlg, doorganizefavdlg
1、概述
调用“添加到收藏夹”对话框(如下)与调用“整理收藏夹”对话框有不同之处,前者所做的工作比后者要来得复杂。将链接添加到收藏夹除了将链接保存之外,还可能会有脱机访问的设置,从ie 4.0到ie 5.0,处理的方式也发生了一些变化。

2、ishelluihelper接口
微软专门提供了一个接口ishelluihelper来实现对windows shell api一些功能的访问,将链接添加到收藏夹也是其中之一,就是下面的addfavorite函数。
hresult ishelluihelper::addfavorite(bstr url, variant *title);
实例代码如下:
void cmyhtmlview::onaddtofavorites()
{
ishelluihelper* pshelluihelper;
hresult hr = cocreateinstance(clsid_shelluihelper, null,
clsctx_inproc_server, iid_ishelluihelper,(lpvoid*)&pshelluihelper);
if (succeeded(hr))
{
_variant_t vttitle(gettitle().allocsysstring());
cstring strurl = m_webbrowser.getlocationurl();
pshelluihelper->addfavorite(strurl.allocsysstring(), &vttitle);
pshelluihelper->release();
}
}
我们注意到这里的“addfavorite”函数并没有像“doorganizefavdlg”那样需要一个父窗口句柄。这也导致与在ie中打开不同,通过ishelluihelper接口显示出来的“添加到收藏夹”对话框是“非模态”的,有一个独立于我们应用程序的任务栏按钮,这使我们的浏览器显得非常不专业(我是个追求完美的人,这也是我的浏览器迟迟不能发布的原因之一)。
于是我们很自然地想到“shdocvw.dll”中除了“doorganizefavdlg”外,应该还有一个类似的函数,可以传入一个父窗口句柄用以显示模态窗口,也许就像这样:
typedef uint (callback* lpfnaddfav)(hwnd, lptstr, lptstr);
事实上,这样的函数确实存在于“shdocvw.dll”中,那就是“doaddtofavdlg”。
3、doaddtofavdlg函数
“doaddtofavdlg”函数也是“shdocvw.dll”暴露出来的函数之一,其原型如下:
typedef bool (callback* lpfnaddfav)(hwnd, tchar*, uint, tchar*, uint,lpitemidlist);
第一个参数正是我们想要的父窗口句柄,第二和第四个参数分别是初始目录(一般来说就是收藏夹目录)和要添加的链接的名字(比如网页的title),第三和第五个参数分别是第二和第四两个缓冲区的长度,而最后一个参数则是指向与第二个参数目录相关的item identifier list的指针(pidl)。但最奇怪的是这里并没有像“addfavorite”函数一样的链接url,那链接是怎样添加的呢?答案是“手动创建”。
第二个参数在函数调用返回后会包含用户在“添加到收藏夹”对话框中选择或创建的完整链接路径名(如“x:\xxx\mylink.url”),我们就根据这个路径和网页的url来创建链接,代码如下(为简化,此处省去检查"shdocvw.dll"是否已在内存中的代码,参见《internet explorer 编程简述(三)“整理收藏夹”对话框》):
void cmyhtmlview::onfavaddtofav()
{
typedef bool (callback* lpfnaddfav)(hwnd, tchar*, uint, tchar*, uint,lpitemidlist);
hmodule hmod = (hmodule)loadlibrary("shdocvw.dll");
if (hmod)
{
lpfnaddfav lpfndoaddtofavdlg = (lpfnaddfav)getprocaddress( hmod, "doaddtofavdlg");
if (lpfndoaddtofavdlg)
{
tchar szpath[max_path];
lpitemidlist pidlfavorites;
if (shgetspecialfolderpath(null, szpath, csidl_favorites, true) &&
(succeeded(shgetspecialfolderlocation(null, csidl_favorites, &pidlfavorites))))
{
tchar sztitle[max_path];
strcpy(sztitle, getlocationname());
tchar szurl[max_path];
strcpy(szurl, getlocationurl());
bool bok = lpfndoaddtofavdlg(m_hwnd, szpath,