通过WTL自定义CShellFileDialog对话框,即实现IFileDialogControlEvents接口和处理IFileDialogCustomize接口

一、简单介绍一下WTL的CShellFileDialog对话框

1、在WTL中用于实现CShellFileDialog模板有

class CShellFileDialogImpl<T>;        //基于IFileDialogEvents接口的基础模板,主要封装相关事件,是CShellFileOpenDialogImpl和CShellFileSaveDialogImpl的基础
class CShellFileOpenDialogImpl<T>;    //基于IFileOpenDialog接口的基础模板,IFileOpenDialog是IFileDialog的派送类,MFC中是使用IFileDialog作为成员变量的,而后通过传入的参数,实际实例化IFileOpenDialog或者IFileSaveDialog
class CShellFileOpenDialog;           //基于IFileOpenDialog接口的基础模板的实现类
class CShellFileSaveDialogImpl<T>;    //基于IFileSaveDialog接口的基础模板,IFileSaveDialog是IFileDialog的派送类,MFC中是使用IFileDialog作为成员变量的,而后通过传入的参数,实际实例化IFileOpenDialog或者IFileSaveDialog
class CShellFileSaveDialog;           //基于IFileSaveDialog接口的基础模板的实现类

CShellFileDialogImpl<T>已经实现了所有IFileDialogEvents接口,并通过_Advise和_Unadvise来实现对事件的绑定和实际调用
CShellFileOpenDialogImpl<T>是CShellFileDialogImpl<T>派送类,并对集成了IFileOpenDialog接口应用的简单封装,主要完成了构造函数的初始化,其实际功能需要通过GetPtr函数返回的IFileOpenDialog指针来完成
CShellFileOpenDialog则是CShellFileOpenDialogImpl<T>模板的实例,其中_Advise和_Unadvise函数被刻意置空,也就是默认没有实现对自定义事件的实现功能

2、自定义事件处理
要对自定义事件进行处理,就需要自己对CShellFileOpenDialogImpl<T>模板派送一个实例,添加对应的处理函数,但不能添加_Advise和_Unadvise函数,而是让其继承CShellFileDialogImpl< T >中的相关函数用于绑定事件处理

class MyShellFileOpenDialog : public CShellFileOpenDialogImpl<CShellFileOpenDialog>
{
public:
	MyShellFileOpenDialog(LPCWSTR lpszFileName = NULL, 
	                     DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST, 
	                     LPCWSTR lpszDefExt = NULL, 
	                     const COMDLG_FILTERSPEC* arrFilterSpec = NULL, 
	                     UINT uFilterSpecCount = 0U) : CShellFileOpenDialogImpl<MyShellFileOpenDialog>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
	{ }

	virtual ~MyShellFileOpenDialog()
	{ }
    //删除原CShellFileOpenDialog中的_Advise和_Unadvise即可以绑定事件
	//void _Advise(DWORD& /*dwCookie*/){ }

	//void _Unadvise(DWORD /*dwCookie*/){ }
    HRESULT OnFileOk()//添加处理函数
	{
        MessageBox(....);
		return S_OK;
	}
};

二、实现界面的自定义(IFileDialogCustomize)以及实现自定义事件处理(IFileDialogControlEvents)

1、IFileDialogControlEvents接口是系统自动从实现了IFileDialogEvents接口的对象中调取,不需要用户另外配置或绑定的

class CShellFileOpenDialogCustomizeImpl : public IFileDialogEvents, public IFileDialogControlEvents;
//或者利用WTL已经实现CShellFileDialogImpl,则我们只需要再实现IFileDialogControlEvents
template <class T>
class CShellFileDialogCustomizeImpl : public IFileDialogControlEvents< T >;
template <class T>
class CShellFileOpenDialogCustomizeImpl : public WTL::CShellFileDialogImpl< T >, public CShellFileDialogCustomizeImpl< T >

2、IFileDialogCustomize接口,此接口是用于添加控件,实现界面及控件自定义的关键,这个接口可直接从IFileOpenDialog接口中获取

ATL::CComPtr<IFileOpenDialog> m_spFileDlg;
ATL::CComPtr<IFileDialogCustomize> m_spFileDlgCust;

HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileOpenDialog);
hRet = m_spFileDlg->QueryInterface(IID_PPV_ARGS(&m_spFileDlgCust));

完成后,只需要调用m_spFileDlgCust(IFileDialogCustomize)中的相关函数的调用,即可完成对对话框的添加控件的任务

保存对话框也是类似,只是接口由IFileOpenDialog变成了IFileSaveDialog

三、全部实现代码如下:

#ifndef _FILEDIALOGCUSTOMIZE_H_
#define _FILEDIALOGCUSTOMIZE_H_

#include <atlwin.h>
#include <atldlgs.h>

namespace WTL {
	template <class T>
	class ATL_NO_VTABLE CShellFileDialogCustomizeImpl : public IFileDialogControlEvents {
	public:
	// Implementation - IUnknown interface
		STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
		{
			if(ppvObject == NULL)
				return E_POINTER;

			T* pT = static_cast<T*>(this);
			if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IFileDialogControlEvents))
			{
				*ppvObject = (IFileDialogControlEvents*)pT;
				// AddRef() not needed
				return S_OK;
			}

			return E_NOINTERFACE;
		}

		virtual ULONG STDMETHODCALLTYPE AddRef()
		{
			return 1;
		}

		virtual ULONG STDMETHODCALLTYPE Release()
		{
			return 1;
		}

		virtual HRESULT STDMETHODCALLTYPE OnButtonClicked(IFileDialogCustomize *pfdc, DWORD dwIDCtl)
		{
			T* pT = static_cast<T*>(this);
			ATLASSERT(pT->m_spFileDlgCust.IsEqualObject(pfdc));
			(void)pfdc;   // avoid level 4 warning
			return pT->OnButtonClicked(dwIDCtl);
		}

		virtual HRESULT STDMETHODCALLTYPE OnCheckButtonToggled(IFileDialogCustomize *pfdc, DWORD dwIDCtl, BOOL bChecked)
		{
			T* pT = static_cast<T*>(this);
			ATLASSERT(pT->m_spFileDlgCust.IsEqualObject(pfdc));
			(void)pfdc;   // avoid level 4 warning
			return pT->OnCheckButtonToggled(dwIDCtl, bChecked);
		}

		virtual HRESULT STDMETHODCALLTYPE OnControlActivating(IFileDialogCustomize *pfdc, DWORD dwIDCtl)
		{
			T* pT = static_cast<T*>(this);
			ATLASSERT(pT->m_spFileDlgCust.IsEqualObject(pfdc));
			(void)pfdc;   // avoid level 4 warning
			return pT->OnControlActivating(dwIDCtl);
		}

		virtual HRESULT STDMETHODCALLTYPE OnItemSelected(IFileDialogCustomize *pfdc, DWORD dwIDCtl, DWORD dwIDItem)
		{
			T* pT = static_cast<T*>(this);
			ATLASSERT(pT->m_spFileDlgCust.IsEqualObject(pfdc));
			(void)pfdc;   // avoid level 4 warning
			return pT->OnItemSelected(dwIDCtl, dwIDItem);
		}

	// Overrideables - Event handlers
		HRESULT OnButtonClicked(DWORD /*dwIDCtl*/)
		{
			return E_NOTIMPL;
		}

		HRESULT OnCheckButtonToggled(DWORD /*dwIDCtl*/, BOOL /*bChecked*/)
		{
			return E_NOTIMPL;
		}

		HRESULT OnControlActivating(DWORD /*dwIDCtl*/)
		{
			return E_NOTIMPL;
		}

		HRESULT OnItemSelected(DWORD /*dwIDCtl*/, DWORD /*dwIDItem*/)
		{
			return E_NOTIMPL;
		}
	};

	template <class T>
	class ATL_NO_VTABLE CShellFileOpenDialogCustomizeImpl : public CShellFileDialogImpl< T >, public CShellFileDialogCustomizeImpl< T > {
	public:
		ATL::CComPtr<IFileOpenDialog> m_spFileDlg;
		ATL::CComPtr<IFileDialogCustomize> m_spFileDlgCust;

		CShellFileOpenDialogCustomizeImpl(LPCWSTR lpszFileName = NULL,
								 DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST,
								 LPCWSTR lpszDefExt = NULL,
								 const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
								 UINT uFilterSpecCount = 0U)
		{
			HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileOpenDialog);

			if(SUCCEEDED(hRet))
				this->_Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount);
			hRet = m_spFileDlg->QueryInterface(IID_PPV_ARGS(&m_spFileDlgCust));
		}

		virtual ~CShellFileOpenDialogCustomizeImpl()
		{ }

		STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
		{
//			static const QITAB qit[] =
//			{
//				QITABENT(CShellFileOpenDialogCustomizeImpl, IID_IFileDialogEvents),
//				QITABENT(CShellFileOpenDialogCustomizeImpl, IID_IFileDialogControlEvents),
//				{ 0 },
//			};
//			return QISearch(this, qit, riid, ppv);

			if(ppvObject == NULL)
				return E_POINTER;

			T* pT = static_cast<T*>(this);
			if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IFileDialogEvents))
			{
				*ppvObject = (IFileDialogEvents*)pT;
				// AddRef() not needed
				return S_OK;
			}
			else if (IsEqualGUID(riid, IID_IFileDialogControlEvents))
			{
				*ppvObject = (IFileDialogControlEvents*)pT;
				// AddRef() not needed
				return S_OK;
			}

			return E_NOINTERFACE;
		}

		IFileOpenDialog* GetPtr()
		{
			return m_spFileDlg;
		}
		IFileDialogCustomize* GetCustomizePtr()
		{
			return m_spFileDlgCust;
		}
	};
	//自定时直接派生CShellFileOpenDialogCustomizeImpl<CShellFileOpenDialogCustomize>,如class CFileDialogCustomize : public  CShellFileOpenDialogCustomizeImpl<CFileDialogCustomize>
	//如果派生函数不需要响应消息事件是如CShellFileOpenDialogCustomize中直接添加void _Advise(DWORD& /*dwCookie*/){}和void _Unadvise(DWORD /*dwCookie*/){}
	//如果需要响应的话,则在新函数中不能添加_Advise和_Unadvise函数
	class CShellFileOpenDialogCustomize : public CShellFileOpenDialogCustomizeImpl<CShellFileOpenDialogCustomize> {
	public:
		CShellFileOpenDialogCustomize(LPCWSTR lpszFileName = NULL,
							 DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST,
							 LPCWSTR lpszDefExt = NULL,
							 const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
							 UINT uFilterSpecCount = 0U) : CShellFileOpenDialogCustomizeImpl<CShellFileOpenDialogCustomize>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
		{ }

		virtual ~CShellFileOpenDialogCustomize()
		{ }

		// Implementation (remove _Advise/_Unadvise code using template magic)
		void _Advise(DWORD& /*dwCookie*/)
		{ }

		void _Unadvise(DWORD /*dwCookie*/)
		{ }
	};

	template <class T>
	class ATL_NO_VTABLE CShellFileSaveDialogCustomizeImpl : public CShellFileDialogImpl< T >, public CShellFileDialogCustomizeImpl< T > {
	public:
		ATL::CComPtr<IFileSaveDialog> m_spFileDlg;
		ATL::CComPtr<IFileDialogCustomize> m_spFileDlgCust;

		CShellFileSaveDialogCustomizeImpl(LPCWSTR lpszFileName = NULL,
								DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT,
								LPCWSTR lpszDefExt = NULL,
								const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
								UINT uFilterSpecCount = 0U)
		{
			HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileSaveDialog);

			if(SUCCEEDED(hRet))
				this->_Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount);
			hRet = m_spFileDlg->QueryInterface(IID_PPV_ARGS(&m_spFileDlgCust));
		}

		virtual ~CShellFileSaveDialogCustomizeImpl()
		{ }

		STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
		{
			if(ppvObject == NULL)
				return E_POINTER;

			T* pT = static_cast<T*>(this);
			if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IFileDialogEvents))
			{
				*ppvObject = (IFileDialogEvents*)pT;
				// AddRef() not needed
				return S_OK;
			}
			else if (IsEqualGUID(riid, IID_IFileDialogControlEvents))
			{
				*ppvObject = (IFileDialogControlEvents*)pT;
				// AddRef() not needed
				return S_OK;
			}

			return E_NOINTERFACE;
		}

		IFileSaveDialog* GetPtr()
		{
			return m_spFileDlg;
		}
		IFileDialogCustomize* GetCustomizePtr()
		{
			return m_spFileDlgCust;
		}
	};

	class CShellFileSaveDialogCustomize : public CShellFileSaveDialogCustomizeImpl<CShellFileSaveDialogCustomize> {
	public:
		CShellFileSaveDialogCustomize(LPCWSTR lpszFileName = NULL,
							DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT,
							LPCWSTR lpszDefExt = NULL,
							const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
							UINT uFilterSpecCount = 0U) : CShellFileSaveDialogCustomizeImpl<CShellFileSaveDialogCustomize>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
		{ }

		virtual ~CShellFileSaveDialogCustomize()
		{ }

		// Implementation (remove _Advise/_Unadvise code using template magic)
		void _Advise(DWORD& /*dwCookie*/)
		{ }

		void _Unadvise(DWORD /*dwCookie*/)
		{ }
	};
}
#endif //_FILEDIALOGCUSTOMIZE_H_

四、调用实例,模仿记事本中选取编码的对话框

#define ID_SHELLFILEDIALOG_VISUALGROUP  32807
#define ID_SHELLFILEDIALOG_COMBOBOX     32808
enum{EN_AUTO, EN_UTF_16_LE, EN_UTF_16_BE, EN_UTF_8_BOM, EN_ANSI_UTF_8};
//
COMDLG_FILTERSPEC fileFilter[] =	{{_T("文本文件"), _T("*.txt")},
									{_T("所有文件"), _T("*.*")}};
CShellFileOpenDialogCustomize shellFileDlg(NULL, FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST, _T("txt"), fileFilter, 2);

//使用我的文档作为默认打开目录
CComPtr<IShellItem> iShellItem;
HRESULT hr = ::SHCreateItemInKnownFolder(FOLDERID_Documents, KF_FLAG_DEFAULT, NULL, IID_PPV_ARGS(&iShellItem));//使用IID_PPV_ARGS宏
if (SUCCEEDED(hr)) {
	hr = shellFileDlg.GetPtr()->SetFolder(iShellItem);//设置SetFolder而不是SetDefaultFolder
}

shellFileDlg.GetCustomizePtr()->StartVisualGroup(ID_SHELLFILEDIALOG_VISUALGROUP, _T("编码:"));
shellFileDlg.GetCustomizePtr()->AddComboBox(ID_SHELLFILEDIALOG_COMBOBOX);
shellFileDlg.GetCustomizePtr()->EndVisualGroup();
shellFileDlg.GetCustomizePtr()->AddControlItem(ID_SHELLFILEDIALOG_COMBOBOX, EN_AUTO, _T("自动监测"));
shellFileDlg.GetCustomizePtr()->AddControlItem(ID_SHELLFILEDIALOG_COMBOBOX, EN_UTF_16_LE, _T("UTF-16"));
shellFileDlg.GetCustomizePtr()->AddControlItem(ID_SHELLFILEDIALOG_COMBOBOX, EN_UTF_16_BE, _T("UTF-16 BE"));
shellFileDlg.GetCustomizePtr()->AddControlItem(ID_SHELLFILEDIALOG_COMBOBOX, EN_UTF_8_BOM, _T("UTF-8带BOM"));
shellFileDlg.GetCustomizePtr()->AddControlItem(ID_SHELLFILEDIALOG_COMBOBOX, EN_ANSI_UTF_8, _T("ANSI或者UTF-8"));
shellFileDlg.GetCustomizePtr()->SetSelectedControlItem(ID_SHELLFILEDIALOG_COMBOBOX, 0);
if (IDOK == shellFileDlg.DoModal()) {
	CString strFile;
	HRESULT hr = shellFileDlg.GetFilePath(strFile);
	if (SUCCEEDED(hr)) {
		UINT nFileTypeIndex = 0;
		hr = shellFileDlg.GetPtr()->GetFileTypeIndex(&nFileTypeIndex);
		DWORD nEncoded = 0;
		shellFileDlg.GetCustomizePtr()->GetSelectedControlItem(ID_SHELLFILEDIALOG_COMBOBOX, &nEncoded);
		if (SUCCEEDED(hr)) {
			if (0 == nFileTypeIndex) {
				LoadTextFile(strFile, nEncoded);
			}
			else {
				LoadUnknownFile(strFile, nEncoded);
			}
		}
	}
}

效果如下:

 五、如需要添加事件

#define ID_SHELLFILEDIALOG_VISUALGROUP  32807
#define ID_SHELLFILEDIALOG_COMBOBOX     32808
enum{EN_AUTO, EN_UTF_16_LE, EN_UTF_16_BE, EN_UTF_8_BOM, EN_ANSI_UTF_8};
//
class CFileDialogCustomize : public CShellFileOpenDialogCustomizeImpl<CFileDialogCustomize> {
public:
	CFileDialogCustomize(LPCWSTR lpszFileName = NULL, 
		DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST, 
		LPCWSTR lpszDefExt = NULL, 
		const COMDLG_FILTERSPEC* arrFilterSpec = NULL, 
		UINT uFilterSpecCount = 0U) : CShellFileOpenDialogCustomizeImpl<CFileDialogCustomize>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
	{
		m_Encoded = 0;
		m_spFileDlgCust->StartVisualGroup(ID_SHELLFILEDIALOG_VISUALGROUP, _T("编码:"));
		m_spFileDlgCust->AddComboBox(ID_SHELLFILEDIALOG_COMBOBOX);
		m_spFileDlgCust->EndVisualGroup();
		m_spFileDlgCust->AddControlItem(ID_SHELLFILEDIALOG_COMBOBOX, EN_AUTO, _T("自动监测"));
		m_spFileDlgCust->AddControlItem(ID_SHELLFILEDIALOG_COMBOBOX, EN_UTF_16_LE, _T("UTF-16"));
		m_spFileDlgCust->AddControlItem(ID_SHELLFILEDIALOG_COMBOBOX, EN_UTF_16_BE, _T("UTF-16 BE"));
		m_spFileDlgCust->AddControlItem(ID_SHELLFILEDIALOG_COMBOBOX, EN_UTF_8_BOM, _T("UTF-8带BOM"));
		m_spFileDlgCust->AddControlItem(ID_SHELLFILEDIALOG_COMBOBOX, EN_ANSI_UTF_8, _T("ANSI或者UTF-8"));
		m_spFileDlgCust->SetSelectedControlItem(ID_SHELLFILEDIALOG_COMBOBOX, 0);
	}
	virtual ~CFileDialogCustomize()
	{ }

	DWORD get_encoded()const{return m_Encoded;}
	HRESULT OnItemSelected(DWORD dwIDCtl, DWORD dwIDItem)//自定义选取事件
	{
		if(ID_SHELLFILEDIALOG_COMBOBOX == dwIDCtl) {
			m_Encoded = dwIDItem;
		}
		return S_OK;
	}

private:
	DWORD m_Encoded;
};

COMDLG_FILTERSPEC fileFilter[] =	{{_T("文本文件"), _T("*.txt")},
									{_T("所有文件"), _T("*.*")}};
CFileDialogCustomize shellFileDlg(NULL, FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST, _T("txt"), fileFilter, 2);

//使用我的文档作为默认打开目录
CComPtr<IShellItem> iShellItem;
HRESULT hr = ::SHCreateItemInKnownFolder(FOLDERID_Documents, KF_FLAG_DEFAULT, NULL, IID_PPV_ARGS(&iShellItem));//使用IID_PPV_ARGS宏
if (SUCCEEDED(hr)) {
	hr = shellFileDlg.GetPtr()->SetFolder(iShellItem);//设置SetFolder而不是SetDefaultFolder
}

if (IDOK == shellFileDlg.DoModal()) {
	CString strFile;
	HRESULT hr = shellFileDlg.GetFilePath(strFile);
	if (SUCCEEDED(hr)) {
		UINT nFileTypeIndex = 0;
		hr = shellFileDlg.GetPtr()->GetFileTypeIndex(&nFileTypeIndex);
		DWORD nEncoded = shellFileDlg.get_encoded();//调用自定义函数获取选取项
		if (SUCCEEDED(hr)) {
			if (0 == nFileTypeIndex) {
				LoadTextFile(strFile, nEncoded);
			}
			else {
				LoadUnknownFile(strFile, nEncoded);
			}
		}
	}
}

六、不太喜欢WTL中关于CShellFileOpenDialog和CShellFileSaveDialog命名

namespace WTL
{
    template <bool IsOpenDialog>
	class CShellFileDialogCustomize;

	template <>
	class CShellFileDialogCustomize<true> : public CShellFileOpenDialogCustomizeImpl<CShellFileDialogCustomize<true> > {
	public:
		CShellFileDialogCustomize(LPCWSTR lpszFileName = NULL,
							 DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST,
							 LPCWSTR lpszDefExt = NULL,
							 const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
							 UINT uFilterSpecCount = 0U) : CShellFileOpenDialogCustomizeImpl<CShellFileDialogCustomize>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
		{ }

		virtual ~CShellFileDialogCustomize()
		{ }

		// Implementation (remove _Advise/_Unadvise code using template magic)
		void _Advise(DWORD& /*dwCookie*/)
		{ }

		void _Unadvise(DWORD /*dwCookie*/)
		{ }
	};

	template <>
	class CShellFileDialogCustomize<false> : public CShellFileSaveDialogCustomizeImpl<CShellFileDialogCustomize<false> > {
	public:
		CShellFileDialogCustomize(LPCWSTR lpszFileName = NULL,
							DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT,
							LPCWSTR lpszDefExt = NULL,
							const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
							UINT uFilterSpecCount = 0U) : CShellFileSaveDialogCustomizeImpl<CShellFileDialogCustomize>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
		{ }

		virtual ~CShellFileDialogCustomize()
		{ }

		// Implementation (remove _Advise/_Unadvise code using template magic)
		void _Advise(DWORD& /*dwCookie*/)
		{ }

		void _Unadvise(DWORD /*dwCookie*/)
		{ }
	};
}

七、备注

关于获取特定目录作为默认目录,可以使用SHCreateItemFromParsingName函数将路径转换为IShellItem,也可以使用SHGetKnownFolderPath获取特定目录的IShellItem

//使用自定义路径作为默认打开路径
CComPtr<IShellItem> iShellItem;
HRESULT hr = ::SHCreateItemFromParsingName(L"C:\\", NULL, NULL, IID_PPV_ARGS(&iShellItem));//使用IID_PPV_ARGS宏
if (SUCCEEDED(hr)) {
	hr = shellFileDlg.GetPtr()->SetFolder(iShellItem);//设置SetFolder而不是SetDefaultFolder
}

或者

//获取特定目录(我的文档)作为默认打开路径
CComPtr<IShellItem> iShellItem;
HRESULT hr = ::SHCreateItemInKnownFolder(FOLDERID_Documents, KF_FLAG_DEFAULT, NULL, IID_PPV_ARGS(&iShellItem));//使用IID_PPV_ARGS宏
if (SUCCEEDED(hr)) {
	hr = shellFileDlg.GetPtr()->SetFolder(iShellItem);//设置SetFolder而不是SetDefaultFolder
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值