MFC CFileDialog实现源码

// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"
#include <dlgs.h>       // for standard control IDs for commdlg


#define new DEBUG_NEW

// Workaround for symbols missing from Windows Server R2 IA64 SDK.
// This enables IA64 applications built with that SDK to link with static MFC libraries.
#include <initguid.h>
extern "C"
{
static CLSID CLSID_FileOpenDialog_MFC       = {0xDC1C5A9C,0xE88A,0x4DDE,{0xA5,0xA1,0x60,0xF8,0x2A,0x20,0xAE,0xF7}};
static CLSID CLSID_FileSaveDialog_MFC       = {0xC0B4E2F3,0xBA21,0x4773,{0x8D,0xBA,0x33,0x5E,0xC9,0x46,0xEB,0x8B}};

static IID IID_IFileDialogEvents_MFC        = {0x973510DB,0x7D7F,0x452B,{0x89,0x75,0x74,0xA8,0x58,0x28,0xD3,0x54}};
static IID IID_IFileDialogControlEvents_MFC = {0x36116642,0xD713,0x4B97,{0x9B,0x83,0x74,0x84,0xA9,0xD0,0x04,0x33}};
}


// FileOpen/FileSaveAs common dialog helper

CFileDialog::CFileDialog(BOOL bOpenFileDialog,
	LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags,
	LPCTSTR lpszFilter, CWnd* pParentWnd, DWORD dwSize, BOOL bVistaStyle)
	: CCommonDialog(pParentWnd)
{
	OSVERSIONINFO vi;
	ZeroMemory(&vi, sizeof(OSVERSIONINFO));
	vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	::GetVersionEx(&vi);

	// if running under Vista
	if (vi.dwMajorVersion >= 6)
	{
		m_bVistaStyle = bVistaStyle;
	}
	else
	{
		m_bVistaStyle = FALSE;
	}

	// determine size of OPENFILENAME struct if dwSize is zero
	if (dwSize == 0)
	{
		dwSize = sizeof(OPENFILENAME);
	}

	// size of OPENFILENAME must be at least version 5
	ASSERT(dwSize >= sizeof(OPENFILENAME));
	// allocate memory for OPENFILENAME struct based on size passed in
	m_pOFN = static_cast<LPOPENFILENAME>(malloc(dwSize));
	ASSERT(m_pOFN != NULL);
	if (m_pOFN == NULL)
		AfxThrowMemoryException();

	memset(&m_ofn, 0, dwSize); // initialize structure to 0/NULL
	m_szFileName[0] = '\0';
	m_szFileTitle[0] = '\0';
	m_pofnTemp = NULL;

	m_bOpenFileDialog = bOpenFileDialog;
	m_nIDHelp = bOpenFileDialog ? AFX_IDD_FILEOPEN : AFX_IDD_FILESAVE;

	m_ofn.lStructSize = dwSize;
	m_ofn.lpstrFile = m_szFileName;
	m_ofn.nMaxFile = _countof(m_szFileName);
	m_ofn.lpstrDefExt = lpszDefExt;
	m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle;
	m_ofn.nMaxFileTitle = _countof(m_szFileTitle);
	m_ofn.Flags |= dwFlags | OFN_ENABLEHOOK | OFN_EXPLORER;
	if(dwFlags & OFN_ENABLETEMPLATE)
		m_ofn.Flags &= ~OFN_ENABLESIZING;
	m_ofn.hInstance = AfxGetResourceHandle();
	m_ofn.lpfnHook = (COMMDLGPROC)_AfxCommDlgProc;

	// setup initial file name
	if (lpszFileName != NULL)
		Checked::tcsncpy_s(m_szFileName, _countof(m_szFileName), lpszFileName, _TRUNCATE);

	// Translate filter into commdlg format (lots of \0)
	if (lpszFilter != NULL)
	{
		m_strFilter = lpszFilter;
		LPTSTR pch = m_strFilter.GetBuffer(0); // modify the buffer in place
		// MFC delimits with '|' not '\0'
		while ((pch = _tcschr(pch, '|')) != NULL)
			*pch++ = '\0';
		m_ofn.lpstrFilter = m_strFilter;
		// do not call ReleaseBuffer() since the string contains '\0' characters
	}

	if (m_bVistaStyle == TRUE)
	{
		if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))
		{ // multi-threaded is not supported
			IFileDialog* pIFileDialog;
			IFileDialogCustomize* pIFileDialogCustomize;

			HRESULT hr;

			USE_INTERFACE_PART_STD(FileDialogEvents);
			USE_INTERFACE_PART_STD(FileDialogControlEvents);

			if (m_bOpenFileDialog)
			{
				hr = CoCreateInstance(CLSID_FileOpenDialog_MFC, NULL, CLSCTX_INPROC_SERVER, 
									  IID_PPV_ARGS(&pIFileDialog));
			}
			else
			{
				hr = CoCreateInstance(CLSID_FileSaveDialog_MFC, NULL, CLSCTX_INPROC_SERVER, 
									  IID_PPV_ARGS(&pIFileDialog));
			}
			if (FAILED(hr))
			{
				m_bVistaStyle = FALSE;
				return;
			}

			hr = pIFileDialog->QueryInterface(IID_PPV_ARGS(&pIFileDialogCustomize));
			ENSURE(SUCCEEDED(hr));

			hr = pIFileDialog->Advise(reinterpret_cast<IFileDialogEvents*>(&m_xFileDialogEvents), &m_dwCookie);
			ENSURE(SUCCEEDED(hr));

			m_pIFileDialog = static_cast<void*>(pIFileDialog);
			m_pIFileDialogCustomize = static_cast<void*>(pIFileDialogCustomize);
		}
		else
		{
			m_bVistaStyle = FALSE;
		}
	}
}

CFileDialog::~CFileDialog()
{
	free(m_pOFN);

	if (m_bVistaStyle == TRUE)
	{
		HRESULT hr;
		hr = (static_cast<IFileDialog*>(m_pIFileDialog))->Unadvise(m_dwCookie);
		ENSURE(SUCCEEDED(hr));

		(static_cast<IFileDialogCustomize*>(m_pIFileDialogCustomize))->Release();

		UINT ref = (static_cast<IFileDialog*>(m_pIFileDialog))->Release();
		ENSURE(ref == 0);
		CoUninitialize();
	}
}

const OPENFILENAME& CFileDialog::GetOFN() const
{
	return *m_pOFN;
}

OPENFILENAME& CFileDialog::GetOFN()
{
	return *m_pOFN;
}

void CFileDialog::UpdateOFNFromShellDialog()
{
	ASSERT(m_bVistaStyle == TRUE);
	if (m_bVistaStyle == TRUE)
	{
		IShellItem *psiResult;
		HRESULT hr = (static_cast<IFileDialog*>(m_pIFileDialog))->GetResult(&psiResult);
		if (SUCCEEDED(hr))
		{
			LPWSTR wcPathName = NULL;
			hr = psiResult->GetDisplayName(SIGDN_FILESYSPATH, &wcPathName);
			if (SUCCEEDED(hr))
			{
				CStringW strTmp(wcPathName);
				::PathRemoveFileSpecW(strTmp.GetBuffer());
				strTmp.ReleaseBuffer();
				size_t offset = strTmp.GetLength();
				if (wcPathName[offset] == L'\\')
				{
					offset++;
				}
#ifdef UNICODE
				wcsncpy_s(m_ofn.lpstrFile, m_ofn.nMaxFile - 1, wcPathName, _TRUNCATE);
				wcsncpy_s(m_ofn.lpstrFileTitle, m_ofn.nMaxFileTitle, wcPathName + offset, _TRUNCATE);
#else
				::WideCharToMultiByte(CP_ACP, 0, wcPathName + offset,
										-1, m_ofn.lpstrFileTitle, m_ofn.nMaxFileTitle, NULL, NULL);
				m_ofn.lpstrFileTitle[m_ofn.nMaxFileTitle - 1] = _T('\0');
				::WideCharToMultiByte(CP_ACP, 0, wcPathName, -1, m_ofn.lpstrFile,
										m_ofn.nMaxFile - 1, NULL, NULL);
				m_ofn.lpstrFile[m_ofn.nMaxFile - 2] = _T('\0');
#endif
				m_ofn.lpstrFile[_tcslen(m_ofn.lpstrFile) + 1] = _T('\0');
				CoTaskMemFree(wcPathName);
			}
			psiResult->Release();
		}
		else if (m_ofn.Flags & OFN_ALLOWMULTISELECT)
		{
			IFileOpenDialog *pfod = NULL;
			HRESULT hr = (static_cast<IFileDialog*>(m_pIFileDialog))->QueryInterface(IID_PPV_ARGS(&pfod));
			if (SUCCEEDED(hr))
			{
				IShellItemArray *ppenum = NULL;
				HRESULT hr = pfod->GetResults(&ppenum);
				if (SUCCEEDED(hr))
				{
					IEnumShellItems *ppenumShellItems;
					hr = ppenum->EnumItems(&ppenumShellItems);
					if (SUCCEEDED(hr))
					{
						IShellItem *rgelt[1];
						ULONG celtFetched = 0;
						if (ppenumShellItems
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值