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

VC++ 實用技巧大全(二):對話框、進程啟動、控件操作、位圖按鈕與動態創建

     編輯:VC++

程序化結束應用程序


// 優雅關閉:發送 WM_CLOSE,觸發 OnClose 可提示保存
AfxGetMainWnd()->SendMessage(WM_CLOSE);

// 強制終止指定標題窗口 (不推薦,標題可變)
void TerminateWindow(LPCTSTR caption) {
    CWnd* pWnd = CWnd::FindWindow(NULL, caption);
    if (pWnd) pWnd->SendMessage(WM_CLOSE);
}
// 更穩健:枚舉進程/窗口匹配類名/進程ID

無模式對話框完整實現

關鍵差異:模式 `DoModal()` + `EndDialog()`;無模式 `Create()` + `DestroyWindow()` + `PostNcDestroy` 刪除對象。


class CMyModelessDlg : public CDialog {
public:
    CMyModelessDlg() : CDialog(IDD_MY_DIALOG) {}
    // 重寫關閉處理
    virtual void OnOK() {
        if (!UpdateData(TRUE)) return;
        DestroyWindow(); // 不調用 EndDialog
    }
    virtual void OnCancel() { DestroyWindow(); }
    // 關鍵:窗口銷毀後刪除 C++ 對象
    virtual void PostNcDestroy() { delete this; }
};

// 主框架調用
void CMainFrame::OnShowModeless() {
    CMyModelessDlg* pDlg = new CMyModelessDlg(); // 堆分配
    if (pDlg->Create(IDD_MY_DIALOG)) {
        pDlg->ShowWindow(SW_SHOW);
    } else {
        delete pDlg; // 創建失敗清理
    }
}

啟動外部程序:三大 API 對比

API複雜度功能典型用途
`WinExec`極簡 (2 參數)路徑 + 顯示方式簡單啟動,無返回值,已棄用
`ShellExecute`簡單文件/URL/動詞 (open/print/編輯)、工作目錄**首選**:打開文檔、瀏覽器、關聯程序
`CreateProcess`複雜 (10 參數)完整進程控制:安全屬性、繼承、優先級、環境、啟動信息需精細控制子進程、重定向 I/O、調試器

ShellExecute 範例


// 打開文本文件 (自動關聯 Notepad)
ShellExecute(NULL, _T("open"), _T("c:\\readme.txt"), NULL, _T("c:\\"), SW_SHOWNORMAL);
// 打開網址
ShellExecute(NULL, _T("open"), _T("https://example.com"), NULL, NULL, SW_SHOWNORMAL);
// 打印文檔
ShellExecute(NULL, _T("print"), _T("doc.pdf"), NULL, NULL, SW_HIDE);

CreateProcess 精簡範例


STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
if (CreateProcess(
    _T("C:\\Windows\\Notepad.exe"), // 應用程序名
    NULL,                           // 命令行 (NULL 用應用程序名)
    NULL, NULL,                     // 進程/線程安全屬性
    FALSE,                          // 不繼承句柄
    NORMAL_PRIORITY_CLASS,          // 優先級
    NULL,                           // 環境塊 (繼承父進程)
    NULL,                           // 當前目錄 (繼承父進程)
    &si, &pi)) {
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess); // 或等待/監控
}

對話框背景顏色

全局設置 (影響所有對話框)


BOOL CMyApp::InitInstance() {
    SetDialogBkColor(RGB(0,0,255), RGB(255,255,0)); // 藍底黃字
    return TRUE;
}

單個視圖/對話框自定義背景


class CMyFormView : public CFormView {
    CBrush m_brush; // 成員變量保持刷子生命週期
public:
    CMyFormView() : CFormView(IDD_MY_FORM) {
        m_brush.CreateSolidBrush(RGB(0,0,255)); // 藍色刷子
    }
    // 處理 WM_CTLCOLOR
    HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) {
        if (nCtlColor == CTLCOLOR_DLG) // 僅對話框背景
            return (HBRUSH)m_brush.GetSafeHandle();
        return CFormView::OnCtlColor(pDC, pWnd, nCtlColor); // 控件交給默認
    }
};

控件指針獲取與操作

方法適用場景代碼
`GetDlgItem`臨時獲取、無 DDX 變量`CSpinButtonCtrl* p = (CSpinButtonCtrl*)GetDlgItem(IDC_SPIN);`
類向導 DDX 變量持久成員、類型安全、自動數據交換`CSpinButtonCtrl m_spin;` → `DDX_Control(pDX, IDC_SPIN, m_spin);`

啟用/禁用控件


m_btnOK.EnableWindow(FALSE);   // 禁用
m_btnApply.EnableWindow(TRUE);  // 啟用

修改控件字體


// 成員變量保持字體對象
CFont m_font;

BOOL CMyDialog::OnInitDialog() {
    CDialog::OnInitDialog();
    // 創建 8pt Arial
    m_font.CreatePointFont(80, _T("Arial")); // 80 = 8pt * 10
    m_btnOK.SetFont(&m_font);
    return TRUE;
}
// 注意:字體對象必須比控件存活久 (成員變量滿足)

OLE 控件顏色轉換


// OLE_COLOR (長整數) → COLORREF
COLORREF cr = TranslateColor(GetBackColor());
CBrush brush(cr);
pDC->FillRect(&rc, &brush);

無通用對話框顯示文件列表


BOOL CMyDialog::OnInitDialog() {
    CDialog::OnInitDialog();
    TCHAR path[MAX_PATH] = _T("C:\\Windows");
    // 填充組合框
    DlgDirListComboBox(path, IDC_COMBO, IDC_CURDIR, 
        DDL_READWRITE | DDL_READONLY | DDL_HIDDEN | DDL_SYSTEM | DDL_ARCHIVE);
    return TRUE;
}

旋鈕控件 (Spin Control) 常見問題

現象原因解決
按 ↑ 數值減小默認範圍 0~100,上限 0 下限 100`m_spin.SetRange(0, 100);` 設置正確上下限
不自動更新關聯編輯框Tab Order 中編輯框不在旋鈕之前Ctrl+D 調整 Tab Order,確保 Buddy 編輯框優先

位圖/圖標按鈕


BOOL CMyDialog::OnInitDialog() {
    CDialog::OnInitDialog();
    // 按鈕屬性設置 BS_BITMAP 或 BS_ICON
    m_btn1.SetIcon(AfxGetApp()->LoadIcon(IDI_ICON1));
    m_btn2.SetBitmap(LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BMP1)));
    return TRUE;
}
// 注意:位圖按鈕背景色需與對話框一致,否則有邊框

三態按鈕 (Push-like Checkbox)


// 資源編輯器:Checkbox + "Push-like" 樣式
// 程序無需額外代碼,自動呈現:未選中/選中/不確定 三態

動態創建控件


// 類成員
CButton* m_pDynamicBtn;

void CMyDialog::CreateDynamicButton() {
    m_pDynamicBtn = new CButton(); // 必須堆分配
    m_pDynamicBtn->Create(
        _T("動態按鈕"), 
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        CRect(10, 10, 110, 34), // 位置大小
        this, IDC_DYNAMIC_BTN);
}
// 銷毀對話框時 delete m_pDynamicBtn (或 PostNcDestroy)

限制編輯框輸入字符

簡單:數字輸入 (ES_NUMBER)


// 資源編輯器設置 Edit Control 樣式:Number (ES_NUMBER)
// 僅允許 0-9,自動過濾

進階:自定義字符過濾 (派生 CEdit + WM_CHAR)


class CAlphaEdit : public CEdit {
    DECLARE_MESSAGE_MAP()
    afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
};

BEGIN_MESSAGE_MAP(CAlphaEdit, CEdit)
    ON_WM_CHAR()
END_MESSAGE_MAP()

void CAlphaEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) {
    if (isalpha(nChar) || nChar == VK_BACK) // 允許字母和退格
        CEdit::OnChar(nChar, nRepCnt, nFlags); // 調用基類處理
    // 其他字符直接忽略 (不調用基類)
}

// 大寫轉換版本
void CUpperEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) {
    if (isalpha(nChar)) nChar = toupper(nChar);
    // 必須繞過 CEdit::OnChar 直接調用 DefWindowProc
    DefWindowProc(WM_CHAR, nChar, MAKELPARAM(nRepCnt, nFlags));
}

// 對話框中子類化
CAlphaEdit m_edit;
BOOL CMyDialog::OnInitDialog() {
    CDialog::OnInitDialog();
    m_edit.SubclassDlgItem(IDC_EDIT, this); // 關鍵:運行時替換控件類
    return TRUE;
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved