我们如何在 CFileDialog 和多文件选择中使用智能指针?

How do we use smart pointers with CFileDialog and multi-file selection?

如何使我们使用通用 CFileDialog 对话框的代码现代化?

示例代码:

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;
}

我们怎样才能把它变成使用智能指针呢? lpstrFile 变量的类型为 LPWSTR.

只要您需要一个自动管理的堆分配数组,std::vector 就是首选解决方案。所有 new[]delete[] 都会奇迹般地消失,OPENFILENAME 结构中设置的参数将匹配,作为奖励。

像这样:

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
}