// 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
MFC CFileDialog实现源码
最新推荐文章于 2024-04-09 23:43:46 发布
本文档详细介绍了MFC库中的CFileDialog类,用于实现文件打开和保存对话框。CFileDialog类通过判断运行环境来决定是否使用Vista风格的对话框,并通过COM接口与Windows API交互。类中包含了构造函数、成员变量、成员函数等,用于设置对话框的参数、处理回调事件等。
摘要由CSDN通过智能技术生成