引言:沒想到2022年還有很多工業軟體公司依然使用MFC,微軟也一直在更新MFC的庫,這次使用MFC封裝的CFileDialog類,寫一個獲得選定檔案路徑,名稱,擴充套件名的程式。
個人技術部落格(文章整理+原始碼): https://zobolblog.github.io/LearnWinAPI/
最終效果:
1.CFileDialog的使用
CFileDialog是MFC對windows api的FileDialog的簡單封裝,增加了一些介面,他的建構函式只有一個:
explicit CFileDialog( 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);
第1個引數bOpenFileDialog為TRUE則表示開啟檔案對話方塊,為FALSE則表示儲存檔案對話方塊。它也是我們必須填寫的,其他的都有預設值。
第2個引數lpszFileName指定預設的副檔名。就是txt,exe這類。
第3個引數lpszFileName指定預設的檔名。一般是儲存檔案框用的。
第4個引數dwFlags 指明一些特定風格,比如多選對話方塊,可讀檔案,隱藏檔案不顯示。
第5個引數lpszFilter是過濾器意思,寫法國內的部落格很亂,但其實微軟官方給了一種很易讀的寫法。
static TCHAR BASED_CODE szFilter[] = _T("Chart Files (*.xlc)|*.xlc|")
_T("Worksheet Files (*.xls)|*.xls|Data Files (*.xlc;*.xls)|")
_T("*.xlc; *.xls|All Files (*.*)|*.*||");
第6個引數pParentWnd指定父視窗的指標。
第7個引數dwSize是指OPENFILENAME結構的大小,這此值取決於作業系統版本。MFC使用此引數確定要建立的適當型別的對話方塊。預設大小0表示MFC程式碼將根據執行程式的作業系統版本確定要使用的正確對話方塊大小。
第8個引數bVistaStyle,預設都是true。它實際上是因為微軟在vs2008後,設計了新的對話方塊風格。所以就用一個bool型別,表示新舊風格。(微軟就不考慮用宏或者列舉,萬一以後又出一個第3風格版本呢。。)
2.DoModal()函數
就像QT裡面的show函數一樣,雖然CFileDialog dlg在記憶體中創造了一個對話方塊物件,但是顯示出來給人看,還需要專門的函數DoModal()。
「Call this function to display the Windows common file dialog box and allow the user to browse files and directories and enter a filename.」呼叫此函數可顯示Windows公用檔案對話方塊,允許使用者瀏覽檔案和目錄並輸入檔名。
3.DoModal()函數的返回值IDOK和IDCANCEL
在視窗的生命週期結束後,domodal還會返回一個值,告訴我們一些情況。但是MFC的設計在這裡非常的煩人,單純的IDCANCEL只能告訴我們出現了問題。至於是什麼問題還需要呼叫一個CommDlgExtendedError函數才可以知道。(至於這裡為什麼不設計成返回一個結構體,直接包含錯誤資訊,估計是90年代開發MFC的時候,計算機效能不夠?)
原始碼:
CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,_T("All FILE|*.*|"),NULL,NULL,1); if (dlg.DoModal() != IDOK) { CommDlgExtendedError(); } else { CString filePathName = dlg.GetPathName(); CString fileName = dlg.GetFileName(); // return only filename CString fileExt = dlg.GetFileExt(); // return only ext CString fileTitle = dlg.GetFileTitle(); // return file title }
效果: