首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

MFC對話框程式架構深度解析:從AppWizard生成代碼到檔案複製小工具實戰

     編輯:關於VC++

Visual Studio .NET(2002/2003)帶來了全中文化MSDN、強化的類別檢視與智慧提示,大幅降低MFC學習門檻。本文將以VS.NET建立的對話框專案為例,逐行剖析AppWizard生成的樣板代碼結構,並以「檔案複製工具」為實戰案例,示範控制項變數綁定、常用對話框(檔案選取、訊息框)、WinAPI封裝類別(CFileDialog、CString)的實戰用法。

對話框專案建立差異:VC6 vs VS.NET

步驟VC++ 6.0VS.NET (2002/2003)
新建專案File→New→Projects→MFC AppWizard(exe)File→New→Project→Visual C++ Projects→MFC Application
專案類型Step 1 選 Dialog basedApplication Type 選 Dialog based
完成FinishFinish

核心類別架構剖析

三大核心類別

類別檢視中可見三個類別:

  • CApp(如 CDialogApp)——應用程式類別,繼承 CWinApp
  • CDlg(如 CDialogDlg)——主對話框類別,繼承 CDialog
  • CAboutDlg——關於對話框,繼承 CDialog

CWinApp 派生類:應用程式單例

class CDialogApp : public CWinApp {
public:
    virtual BOOL InitInstance(); // 唯一需覆寫的初始化函數
};
  • MFC框架提供 WinMain,內部建立唯一 CWinApp 派生物件 theApp
  • theApp 為全域物件,最早構造,可透過 AfxGetApp() 取得指標存取資源
  • 啟動流程:WinMain → InitApplication() → InitInstance() → Run()(訊息迴圈) → ExitInstance()

InitInstance 逐行解析

BOOL CDialogApp::InitInstance()
{
    InitCommonControls();           // XP視覺樣式支援(ComCtl32 v6+)
    CWinApp::InitInstance();        // 父類別預設初始化
    AfxEnableControlContainer();    // ActiveX控制項容器支援
    
    CDialogDlg dlg;                 // 建立模態對話框物件(棧上)
    m_pMainWnd = &dlg;              // 設為主視窗
    INT_PTR nResponse = dlg.DoModal(); // 模態顯示,阻塞直到關閉
    
    if (nResponse == IDOK) { /* 確定鍵關閉處理 */ }
    else if (nResponse == IDCANCEL) { /* 取消鍵關閉處理 */ }
    
    return FALSE; // 對話框關閉後直接退出應用程式(不進入Run迴圈)
}

關鍵點:DoModal() 內部跑自己的訊息迴圈,返回 IDOK/IDCANCEL;InitInstance 回傳 FALSE 讓框架知曉無需進入主訊息泵。

CDialogDlg 類別結構

class CDialogDlg : public CDialog {
public:
    CDialogDlg(CWnd* pParent = NULL);   // 建構函數
    enum { IDD = IDD_DIALOG_DIALOG };   // 對話框模板資源ID
    
protected:
    virtual BOOL OnInitDialog();        // 對話框初始化
    afx_msg void OnSysCommand(UINT, LPARAM); // 系統選單
    afx_msg void OnPaint();             // 重繪
    afx_msg HCURSOR OnQueryDragIcon();  // 最小化圖示
    
    DECLARE_MESSAGE_MAP()
};

繼承鏈:CDialogDlg → CDialog → CWnd → CCmdTarget → CObject

訊息對應表


BEGIN_MESSAGE_MAP(CDialogDlg, CDialog)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()

這是分析程式功能的最佳切入點——直接看支援哪些訊息、對應哪些處理函數。

OnInitDialog 詳細流程


BOOL CDialogDlg::OnInitDialog()
{
    CDialog::OnInitDialog(); // 父類別初始化
    
    // 將「關於...」加入系統選單
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);
    
    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; // 未手動設定焦點時回傳TRUE
}

實戰案例:檔案複製小工具

介面佈局

刪除預設控制項,新增:

  • 2個編輯框:IDC_SOURCE(來源)、IDC_TARGET(目標)
  • 4個按鈕:IDC_BROWSE_SRC、IDC_BROWSE_DST、IDC_COPY、IDC_CANCEL
  • 對應靜態文字標籤

檔案複製工具介面

粗體字為控制項ID

新增控制項變數與事件

使用類別精靈(Ctrl+W)為4按鈕加入 BN_CLICKED 處理函數:

  • OnBnClickedBrowseSrc()
  • OnBnClickedBrowseDst()
  • OnBnClickedCopy()
  • OnBnClickedCancel()

核心功能實作

1. 取消按鈕——關閉對話框


void CFileCopyDlg::OnBnClickedCancel()
{
    EndDialog(IDCANCEL); // 以IDCANCEL結束模態對話框
}

2. 瀏覽按鈕——CFileDialog 檔案選取


// 來源瀏覽:開啟舊檔
void CFileCopyDlg::OnBnClickedBrowseSrc()
{
    CFileDialog dlg(TRUE, _T(""), _T(""), 
        OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
        _T("所有檔案 (*.*)|*.*||"), this);
    
    if (dlg.DoModal() == IDOK) {
        CString path = dlg.GetPathName();
        SetDlgItemText(IDC_SOURCE, path);
    }
}

// 目標瀏覽:另存新檔
void CFileCopyDlg::OnBnClickedBrowseDst()
{
    CFileDialog dlg(FALSE, _T(""), _T(""), 
        OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
        _T("所有檔案 (*.*)|*.*||"), this);
    
    if (dlg.DoModal() == IDOK) {
        CString path = dlg.GetPathName();
        SetDlgItemText(IDC_TARGET, path);
    }
}

關鍵點:

  • 建構函數第一參數 TRUE=開啟舊檔 / FALSE=另存新檔
  • 篩選字串格式:「描述|*.ext|描述2|*.ext2||」 雙管號結尾
  • GetPathName() 取得完整路徑,SetDlgItemText 設定控制項文字

3. 複製按鈕——WinAPI CopyFile 封裝


void CFileCopyDlg::OnBnClickedCopy()
{
    CString src, dst;
    GetDlgItemText(IDC_SOURCE, src);
    GetDlgItemText(IDC_TARGET, dst);
    
    if (src.IsEmpty() || dst.IsEmpty()) {
        MessageBox(_T("請先選擇來源與目標檔案!"), _T("提示"), MB_ICONWARNING);
        return;
    }
    
    // CopyFile: 來源、目標、TRUE=目標存在時失敗 / FALSE=覆蓋
    if (CopyFile(src, dst, FALSE)) {
        MessageBox(_T("檔案複製成功!"), _T("完成"), MB_OK | MB_ICONINFORMATION);
    } else {
        DWORD err = GetLastError();
        CString msg;
        msg.Format(_T("複製失敗(錯誤碼:%lu)"), err);
        MessageBox(msg, _T("錯誤"), MB_OK | MB_ICONERROR);
    }
}

CString 可直接當字串用、支援 Format、運算子 + 串接,極大簡化字串操作。

MFC核心類別速查表

MFC類別封裝對象常用方法
CWnd視窗 (HWND)CreateWindow, ShowWindow, SetWindowText, GetDlgItemText, MessageBox
CDialog對話框DoModal, OnInitDialog, EndDialog, Get/SetDlgItemText
CFileDialog檔案開啟/儲存對話框DoModal, GetPathName, GetFileName, GetFileExt
CString字串Format, LoadString, IsEmpty, GetLength, 運算子+
CMenu選單 (HMENU)GetSystemMenu, AppendMenu, LoadMenu

學習建議與下篇預告

  1. 善用MSDN:VS.NET附帶完整中文MSDN,搜尋技巧(關鍵字、篩選「MFC」、看範例代碼)能事半功倍
  2. 閱讀生成代碼:別只會用精靈,要能看懂InitInstance、DoModal、訊息對應表的運作邏輯
  3. 動手改:嘗試加入進度條、多執行緒複製、拖放檔案支援

下一篇將進入 動態連結庫(DLL)開發:__declspec(dllexport)、.def 檔、隱式/顯式連結、MFC擴展DLL與一般DLL差異、DLL記憶體管理陷阱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved