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

VC++ 技術內幕筆記第 7 章:無模式對話框與 Windows 通用對話框

     編輯:VC 教學

核心概念

  • 無模式對話框:顯示後不阻塞主視窗,用戶可在應用程式其他地方繼續操作;
  • 通用對話框:封裝於 COMDLG32.DLL,含檔案、列印、字型、顏色、頁面設定、尋找取代,基類 CCommonDialog;
  • 訊息傳遞:SendMessage (同步、直接呼叫視窗程序) vs PostMessage (非同步、投遞隊列);
  • 對話框屬於**主框架視窗**,不屬於 View;對話框物件生命週期至應用程式結束,DestroyWindow 不會自動 delete C++ 物件,需手動管理。

自定義訊息實戰

// 定義
#define WM_GOODBYE (WM_USER + 5)

// 對話框發送
m_pView->PostMessage(WM_GOODBYE, IDOK); // wParam 附帶 IDOK

// View 類處理
class CMyView : public CView {
    afx_msg LRESULT OnGoodbye(WPARAM wParam, LPARAM lParam);
    DECLARE_MESSAGE_MAP()
};

BEGIN_MESSAGE_MAP(CMyView, CView)
    ON_MESSAGE(WM_GOODBYE, OnGoodbye)  // 必須在 AFX_MSG_MAP 註釋區塊**外側**
END_MESSAGE_MAP()

LRESULT CMyView::OnGoodbye(WPARAM wParam, LPARAM lParam) {
    // wParam = IDOK
    return 0;
}

技巧:建構函數傳遞 View 指標

class CMyDialog : public CDialog {
public:
    CMyDialog(CView* pView, CWnd* pParent = NULL)
        : CDialog(IDD_MYDLG, pParent), m_pView(pView) {}
    CView* m_pView;
};

無模式對話框關鍵重寫

class CMyModelessDlg : public CDialog {
    // 必須重寫,防止 ESC/Enter/按鈕觸發基類 EndDialog
    virtual void OnOK() {
        UpdateData(TRUE);  // 可選:回寫資料
        DestroyWindow();   // 正確銷毀無模式對話框
    }
    virtual void OnCancel() {
        DestroyWindow();
    }
    // 物件銷毀由外部管理,或在 PostNcDestroy 刪除 this
    virtual void PostNcDestroy() { delete this; }
};

通用檔案對話框 CFileDialog 深度應用

嵌套自訂控件 (範例:增加「刪除」按鈕)

  1. 建立子對話框資源,Style: Child / No Border,放入 Group Box,ID 設為 stc32 (固定,系統識別嵌入點);
  2. 衍生 CSpecialFileDialog : public CFileDialog;
  3. 覆寫 OnInitDialog:
    GetParent()->GetDlgItem(IDOK)->SetWindowText(_T("Delete")); 修改既有按鈕文字;
    GetParent()->SetIcon(...) 設定父視窗圖示;
  4. 新增按鈕處理:
    GetParent()->GetDlgItem(0x480)->GetWindowText(m_strFileName); 取檔名編輯框 (ID 0x480);
    GetParent()->SendMessage(WM_COMMAND, IDCANCEL); 關閉對話框。
    CFile::Remove(m_strFileName) 刪除檔案 (不經回收站)。

關鍵結構 m_ofn (OPENFILENAME)

CFileDialog dlg(TRUE); // TRUE=開啟, FALSE=另存新檔
dlg.m_ofn.lpstrFilter = _T("Text\0*.txt\0All\0*.*\0");
dlg.m_ofn.lpstrTitle = _T("選擇檔案");
dlg.m_ofn.Flags |= OFN_EXPLORER | OFN_ENABLEHOOK; // 啟用 Hook
if (dlg.DoModal() == IDOK) {
    CString path = dlg.GetPathName(); // 完整路徑
}

其他通用對話框速查

類別功能
CColorDialog選擇/建立顏色
CFontDialog選擇字型 (填充 LOGFONT,不建立字型物件)
CPrintDialog印表機設定與列印
CPageSetupDialog頁面設定
CFindReplaceDialog尋找/取代 (無模式)

Win32 限制

  • 標準檔案對話框**無法**動態建立控件 (其他通用對話框同);
  • 若需大幅客製,建議自行實作對話框而非 Hook 通用對話框。

對話框標題列加圖示

BOOL CMyDialog::OnInitDialog() {
    CDialog::OnInitDialog();
    HICON hIcon = AfxGetApp()->LoadIcon(IDI_MYICON);
    SetIcon(hIcon, TRUE);  // 大圖示
    SetIcon(hIcon, FALSE); // 小圖示
    return TRUE;
}
// 若為 Child Style 無標題列,需 GetParent()->SetIcon(...) 設定父視窗
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved