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()
等內容刪除,才能編譯通過。
雖然不甚好用,但姑且算是一種替代方案吧。若你的軟件將發佈給用戶,最好不要採取此方案。