How about modernizing our code that uses the common CFileDialog
dialog?
Sample code:
void CExportSettingsDlg::OnBnClickedMfcbuttonImportXsl()
{
CString strFilter; // This will be used to display the right type of template files
CString strTargetFolder = theApp.GetWorkingPath(); // Default
TCHAR* pszFile = new TCHAR[32767]; // Buffer for the files selected by the user
TCHAR szTabText[_MAX_PATH] = { 0 }; // Buffer for the selected tab text (we use it for the filter description)
// Initialise the filter string
strFilter = _T("Styles|SRRSchedule*.xsl;SRRSchedule*.css||");
// Initialise the file dialog
CFileDialog dlgImport(TRUE,
_T(".XSL"), _T(""), OFN_ALLOWMULTISELECT | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, strFilter, this);
ZeroMemory(pszFile, 32767 * sizeof(TCHAR));
dlgImport.m_ofn.lpstrFile = pszFile;
dlgImport.m_ofn.nMaxFile = 32767;
dlgImport.m_ofn.nFileOffset = 0;
if (dlgImport.DoModal() != IDOK)
{
// User did not select any files so tidy up the memory
delete[] pszFile;
return;
}
// Iterate the selected files
POSITION pos = dlgImport.GetStartPosition();
CString strSourceFilePath, strTargetFilePath, strSourceFileName, strSourceFileTitle, strSourceExtension, strFileName;
while (pos)
{
strSourceFilePath = dlgImport.GetNextPathName(pos);
// ...
}
// Tidy memory
delete[] pszFile;
}
How can we turn this into using a smart pointer? The lpstrFile
variable is of type LPWSTR
.
Whenever you need an automatically managed, heap-allocated array, std::vector
is the go-to solution. All new[]
's and delete[]
's will miraculously disappear, and the parameters set in the OPENFILENAME
structure will match, as a bonus.
Something like this:
void CExportSettingsDlg::OnBnClickedMfcbuttonImportXsl()
{
// ...
// The controlled sequence is default-initialized (i.e. zeroed out)
auto pszFile = std::vector<TCHAR>(32767);
// ...
// Initialise the file dialog
CFileDialog dlgImport(TRUE,
_T(".XSL"), _T(""), OFN_ALLOWMULTISELECT | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, strFilter, this);
dlgImport.m_ofn.lpstrFile = pszFile.data();
// Without the cast this would raise a signed/unsigned mismatch warning
// depending on the target architecture
dlgImport.m_ofn.nMaxFile = static_cast<uint32_t>(pszFile.size());
dlgImport.m_ofn.nFileOffset = 0;
if (dlgImport.DoModal() != IDOK)
{
// User did not select any files so simply return
// Memory is cleaned up by vector's d'tor
return;
}
// ...
// No need to clean up
}