匯東網


MFC Windows 文件選擇對話框運行異常,提供替代方案

[編輯] [转简体]
|
作者:huidong | 分類:【編程】Win32
[ 30 瀏覽 0 評論 11 贊 15 踩 ]

概要
VC2005 的 MFC 項目轉移到 VS2022 編譯時,CFileDialog 運行不正常,響應速度極慢,且無法切換當前目錄,網上也沒有看到很好的解決辦法。本文提供一種替代方案。

正文

我用 Win32 原生的 GetOpenFileName 函數也嘗試了,出現同樣的問題。在 Release 模式運行,竟然還出現了 Debug 模式下沒有的運行時異常(可能是其他部分代碼有內存泄漏,但該問題在之前 VC2008 編譯時沒有出現)。

總之 Windows 文件選擇對話框無法正常使用了。因此我寫了一個類來替代 CFileDialog 類(依賴 EasyX):

StdAfx.h

// 我的文件選擇對話框
// 因爲 Windows 自帶的有問題
class CHDFileDialog
{
private:

    CString m_strPathName;
    CString m_strFileName;

    CString m_strSuffix;

    bool InputPath();

    inline void ContractFileName()
    {
        // 找到最后一个'/'或'\'的位置  
        int lastSlash = m_strPathName.ReverseFind('\\');
        if (lastSlash == -1) // 如果没有找到'\',尝试找'/'  
            lastSlash = m_strPathName.ReverseFind('/');

        if (lastSlash != -1) // 如果找到了分隔符  
        {
            // 提取文件名,即分隔符之后的所有内容  
            m_strFileName = m_strPathName.Mid(lastSlash + 1);
        }
        else
        {
            m_strFileName = _T("");
        }
    }

public:

    // 僅用於兼容 CFileDialog 代碼,無實際作用
    // Attributes
    OPENFILENAME m_ofn;
    LPOPENFILENAME m_pOFN;

    CHDFileDialog(CString suffix)
    {
        m_strSuffix = suffix;
    }

    // 兼容 CFileDialog 代碼
    CHDFileDialog(BOOL bOpenFileDialog,
        LPCTSTR lpszDefExt = NULL,
        LPCTSTR lpszFileName = NULL,
        DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
        LPCTSTR lpszFilter = NULL,
        CWnd* pParentWnd = NULL,
        DWORD dwSize = 0,
        BOOL bVistaStyle = TRUE)
    {
        m_strSuffix = lpszFilter;
    }

    inline int DoModal()
    {
        bool ok;
        do
        {
            ok = InputPath();
            ContractFileName();
            if (m_strFileName.GetLength())
            {
                break;
            }
            else
            {
                AfxMessageBox(_T("Incorrect path."), MB_OK);
            }

        } while (ok);

        return ok ? IDOK : -1;
    }

    inline CString GetPathName() const
    {
        return m_strPathName;
    }

    inline CString GetFileName() const
    {
        return m_strFileName;
    }

    // 僅用於兼容 CFileDialog 代碼,無實際作用
    inline void AssertValid() {}
    inline void OnInitDialog() {}
    inline virtual const AFX_MSGMAP* GetMessageMap() const { return NULL; };
};

#define CFileDialog CHDFileDialog


StdAfx.cpp

#include <easyx.h>

bool CHDFileDialog::InputPath()
{
    EnableWindow(AfxGetApp()->GetMainWnd()->GetSafeHwnd(), false);

    TCHAR pszPath[MAX_PATH] = { 0 };

    initgraph(100, 100);
    ShowWindow(GetHWnd(), SW_HIDE);

    TCHAR pszDir[MAX_PATH] = { 0 };
    _tgetcwd(pszDir, MAX_PATH);

    bool ok = InputBox(pszPath, MAX_PATH,
        _T("Your file path (") + m_strSuffix + _T("): "), _T("Select path"), pszDir, 0, 0, false);
    m_strPathName = pszPath;

    closegraph();
    EnableWindow(AfxGetApp()->GetMainWnd()->GetSafeHwnd(), true);
    return ok;
}

如果你還定義了一些 CFileDialog 的子類,那麼你可能還需要將這些之類中的

DECLARE_DYNAMIC(CMyFileDialogExport)
DECLARE_MESSAGE_MAP()

等內容刪除,才能編譯通過。

雖然不甚好用,但姑且算是一種替代方案吧。若你的軟件將發佈給用戶,最好不要採取此方案。

[ 11] [ 15]


 評論區  0 條評論

+ 添加評論