本文以 Visual Studio .NET (VC7+) 為環境,逐行解析 MFC 對話框專案自動產生的核心代碼結構,並在此基礎上實作一個「檔案複製小工具」,涵蓋控制項配置、事件處理、檔案對話框、複製 API 與訊息盒。
DialogDemo。CDialogDemoApp : CWinApp — 應用程式物件,唯一全域實例 theApp。CDialogDemoDlg : CDialog — 主對話框視窗。CAboutDlg : CDialog — 關於對話框。
class CDialogDemoApp : public CWinApp {
public:
virtual BOOL InitInstance(); // 重寫:初始化、建立主對話框
};
// 全域唯一實例
CDialogDemoApp theApp;
BOOL CDialogDemoApp::InitInstance()
{
InitCommonControls(); // XP 視覺樣式必要
CWinApp::InitInstance(); // 父類別初始化
AfxEnableControlContainer(); // ActiveX 容器支援
CDialogDemoDlg dlg; // 建立主對話框物件 (棧上)
m_pMainWnd = &dlg; // 設為主視窗
INT_PTR nResponse = dlg.DoModal(); // 模態顯示,阻塞直到關閉
if (nResponse == IDOK) { /* 使用者按確定 */ }
else if (nResponse == IDCANCEL) { /* 使用者按取消 */ }
return FALSE; // 對話框關閉後結束應用程式 (不進入訊息迴圈)
}
class CDialogDemoDlg : public CDialog {
public:
CDialogDemoDlg(CWnd* pParent = NULL); // 標準建構函式
enum { IDD = IDD_DIALOGDEMO_DIALOG }; // 對話框模板資源 ID
protected:
virtual BOOL OnInitDialog(); // 對話框初始化
afx_msg void OnSysCommand(UINT, LPARAM); // 系統選單
afx_msg void OnPaint(); // 重繪
afx_msg HCURSOR OnQueryDragIcon(); // 拖曳圖示
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CDialogDemoDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()
BOOL CDialogDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 系統選單加入「關於...」
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu) {
CString strAbout; strAbout.LoadString(IDS_ABOUTBOX);
if (!strAbout.IsEmpty()) {
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAbout);
}
}
SetIcon(m_hIcon, TRUE); // 大圖示
SetIcon(m_hIcon, FALSE); // 小圖示
return TRUE;
}
IDC_EDIT_SRC (來源)、IDC_EDIT_DST (目標)。IDC_BTN_BROWSE_SRC、IDC_BTN_BROWSE_DST、IDC_BTN_COPY、IDC_BTN_CANCEL。
class CDialogDemoDlg : public CDialog {
// ...
CString m_strSrc, m_strDst;
afx_msg void OnBnClickedBrowseSrc();
afx_msg void OnBnClickedBrowseDst();
afx_msg void OnBnClickedCopy();
afx_msg void OnBnClickedCancel();
// ...
};
void CDialogDemoDlg::OnBnClickedBrowseSrc()
{
CFileDialog dlg(TRUE, _T(""), _T(""), OFN_FILEMUSTEXIST | OFN_HIDEREADONLY,
_T("所有檔案 (*.*)|*.*||"), this);
if (dlg.DoModal() == IDOK) {
m_strSrc = dlg.GetPathName();
SetDlgItemText(IDC_EDIT_SRC, m_strSrc);
}
}
void CDialogDemoDlg::OnBnClickedBrowseDst()
{
CFileDialog dlg(FALSE, _T(""), _T(""), OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY,
_T("所有檔案 (*.*)|*.*||"), this);
if (dlg.DoModal() == IDOK) {
m_strDst = dlg.GetPathName();
SetDlgItemText(IDC_EDIT_DST, m_strDst);
}
}
void CDialogDemoDlg::OnBnClickedCopy()
{
UpdateData(TRUE); // 從控制項取得資料
if (m_strSrc.IsEmpty() || m_strDst.IsEmpty()) {
AfxMessageBox(_T("請先選擇來源與目標檔案"));
return;
}
if (CopyFile(m_strSrc, m_strDst, FALSE)) { // FALSE=覆蓋現有
AfxMessageBox(_T("複製成功!"), MB_ICONINFORMATION);
} else {
CString err; err.Format(_T("複製失敗,錯誤碼: %d"), GetLastError());
AfxMessageBox(err, MB_ICONERROR);
}
}
void CDialogDemoDlg::OnBnClickedCancel()
{
EndDialog(IDCANCEL); // 關閉模態對話框
}
void CDialogDemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_SRC, m_strSrc);
DDX_Text(pDX, IDC_EDIT_DST, m_strDst);
}
按 F5 執行,介面將顯示兩個輸入框與三個按鈕,點選「瀏覽」選擇檔案,點選「複製」執行複製並彈出結果訊息。
CWinApp 派生類別唯一全域實例 theApp,InitInstance 相當於主函式。DoModal 模態對話框會啟動內部訊息迴圈,關閉後返回 IDOK/IDCANCEL。CFileDialog 封裝 GetOpenFileName/GetSaveFileName,TRUE=開啟舊檔,FALSE=另存新檔。CopyFile 為 Win32 API,第三個參數 FALSE 允許覆蓋。DDX_Text 實現控制項文字與 CString 成員雙向綁定。CListCtrl、CTreeCtrl 等常用控制項。