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

MFC 按鈕控件 CButton 完整開發指南:九種風格、自動狀態、三態邏輯、自繪與位圖按鈕

     編輯:關於C語言

按鈕是最基礎的交互控件。MFC CButton 統一封裝普通按鈕、複選框、單選按鈕三大類九種風格,支持自動狀態切換、三態邏輯、自繪、位圖按鈕及完整消息處理。本文系統講解風格對比、創建參數、狀態控制、自繪實現及 CBitmapButton 使用。

一、 九大按鈕風格完整對比

BOOL Create(LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
風格類型視覺特徵自動狀態典型用途
BS_PUSHBUTTON普通按鈕矩形,點擊凹陷否確定、取消、執行動作
BS_DEFPUSHBUTTON默認按鈕粗黑邊框,Enter 觸發否對話框默認確認鍵
BS_CHECKBOX複選框小方框+右側文本否獨立開關選項
BS_AUTOCHECKBOX自動複選框方框+勾選標記是 (點擊切換)標準複選框
BS_RADIOBUTTON單選按鈕小圓圈+右側文本否互斥組項目
BS_AUTORADIOBUTTON自動單選按鈕圓圈+實心點是 (自動互斥)標準單選組
BS_3STATE三態複選框方框+勾選/灰色/空否部分選中狀態
BS_AUTO3STATE自動三態複選框方框+三態循環是 (循環切換)父子節點關聯
BS_OWNERDRAW自繪按鈕完全自定義繪製否非標準外觀、動畫按鈕
BS_LEFTTEXT文本左側 (輔助)文本在圖標/框左側-右對齊佈局
BS_BITMAP位圖按鈕 (配合 CBitmapButton)顯示位圖-圖標按鈕、工具欄風格

二、 創建參數詳解

  • lpszCaption:按鈕顯示文本 (自繪/位圖按鈕可為空)
  • dwStyle:WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_XXX
  • rect:位置大小 (對話框單位為對話框單位,非像素)
  • pParentWnd:父窗口指針
  • nID:控件 ID (命令消息識別用)

三、 狀態控制核心函數

操作函數適用風格
獲取/設置勾選狀態GetCheck() / SetCheck(int)CHECKBOX, RADIO, 3STATE
獲取/設置按鈕文本GetWindowText() / SetWindowText()所有
啟用/禁用EnableWindow(BOOL)所有
設置/獲取按鈕狀態SetButtonStyle(UINT) / GetButtonStyle()所有
設置/獲取圖標SetIcon(HICON) / GetIcon()BS_ICON (需風格)
設置/獲取位圖SetBitmap(HBITMAP) / GetBitmap()BS_BITMAP
設置/獲取游標SetCursor(HCURSOR) / GetCursor()所有

三態狀態值

  • 0:未選中 (BST_UNCHECKED)
  • 1:選中 (BST_CHECKED)
  • 2:不確定/灰色 (BST_INDETERMINATE) — 僅三態風格

四、 自動單選按鈕分組機制

核心規則:同一父窗口中,連續的 BS_AUTORADIOBUTTON 自動形成互斥組。組別由 WS_GROUP 風格分隔。

正確佈局代碼

// 第1組:性別
btnMale.Create(_T("男"), WS_CHILD|WS_VISIBLE|WS_GROUP|BS_AUTORADIOBUTTON, rect1, this, IDC_MALE);
btnFemale.Create(_T("女"), WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON, rect2, this, IDC_FEMALE);

// 第2組:會員等級 (WS_GROUP 斷開上一組)
btnVip1.Create(_T("銀卡"), WS_CHILD|WS_VISIBLE|WS_GROUP|BS_AUTORADIOBUTTON, rect3, this, IDC_VIP1);
btnVip2.Create(_T("金卡"), WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON, rect4, this, IDC_VIP2);
btnVip3.Create(_T("鉆石"), WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON, rect5, this, IDC_VIP3);

五、 自繪按鈕 (BS_OWNERDRAW) 實現

1. 繼承 CButton 重載 DrawItem

class COwnerDrawBtn : public CButton {
    DECLARE_DYNAMIC(COwnerDrawBtn)
public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
};

void COwnerDrawBtn::DrawItem(LPDRAWITEMSTRUCT lpDIS) {
    CDC* pDC = CDC::FromHandle(lpDIS->hDC);
    CRect rect(lpDIS->rcItem);
    UINT state = lpDIS->itemState;
    
    // 1. 繪製背景
    COLORREF bg = (state & ODS_SELECTED) ? RGB(0,120,215) : RGB(240,240,240);
    pDC->FillSolidRect(rect, bg);
    
    // 2. 繪製邊框
    if (state & ODS_FOCUS) {
        pDC->DrawFocusRect(rect);
    }
    CPen pen(PS_SOLID, 1, (state & ODS_SELECTED) ? RGB(0,80,160) : RGB(180,180,180));
    CPen* pOld = pDC->SelectObject(&pen);
    pDC->Rectangle(rect);
    pDC->SelectObject(pOld);
    
    // 3. 繪製文本
    CString text;
    GetWindowText(text);
    pDC->SetBkMode(TRANSPARENT);
    pDC->SetTextColor((state & ODS_SELECTED) ? RGB(255,255,255) : RGB(0,0,0));
    pDC->DrawText(text, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}

2. 對話框中使用

// 頭文件
COwnerDrawBtn m_btnCustom;

// OnInitDialog
m_btnCustom.SubclassDlgItem(IDC_CUSTOM_BTN, this);
// 確保資源編輯器中按鈕風格設置為 Owner Draw

六、 CBitmapButton 位圖按鈕 (最簡單圖片按鈕)

資源準備

  • 一張位圖包含 4 個狀態:正常、按下、聚焦、禁用 (水平排列)
  • 或 4 張獨立位圖資源

代碼實現

class CMyDialog : public CDialog {
    CBitmapButton m_btnBitmap;
public:
    BOOL OnInitDialog() {
        CDialog::OnInitDialog();
        
        // 關鍵:AutoLoad 自動關聯 4 狀態位圖
        // 位圖資源 ID: IDB_BTN_NORMAL, IDB_BTN_PUSHED, IDB_BTN_FOCUS, IDB_BTN_DISABLED
        // 或單一位圖 IDB_BTN_ALL (包含4狀態)
        m_btnBitmap.AutoLoad(IDC_BITMAP_BTN, this);
        
        // 手動指定位圖 (可選)
        // m_btnBitmap.LoadBitmaps(IDB_NORMAL, IDB_PUSHED, IDB_FOCUS, IDB_DISABLED);
        
        // 設置大小 (可選,默認按位圖尺寸)
        m_btnBitmap.SizeToContent();
        
        return TRUE;
    }
};

七、 常用消息映射

ON_BN_CLICKED(IDC_BTN, OnBtnClicked)       // 點擊 (所有按鈕)
ON_BN_DOUBLECLICKED(IDC_BTN, OnBtnDblClk)   // 雙擊
ON_BN_SETFOCUS(IDC_BTN, OnBtnSetFocus)      // 獲得焦點
ON_BN_KILLFOCUS(IDC_BTN, OnBtnKillFocus)    // 失去焦點
ON_BN_DISABLE(IDC_BTN, OnBtnDisable)        // 禁用狀態 (罕用)

八、 避坑指南

  1. 自動單選按鈕分組失效:缺少 WS_GROUP 分隔,導致所有單選按鈕成一組
  2. BS_CHECKBOX 不自動切換:必須用 BS_AUTOCHECKBOX 才有點擊切換效果
  3. 三態邏輯混淆:BS_AUTO3STATE 循環順序 0→1→2→0,業務邏輯需明確 2 的含義
  4. 自繪按鈕不響應點擊:資源編輯器中必須勾選 Owner Draw,且類重載 DrawItem
  5. CBitmapButton 位圖不顯示:位圖尺寸需一致,4 狀態水平排列無間隙,調用 AutoLoad 或 LoadBitmaps
  6. 按鈕文本與圖標衝突:BS_BITMAP/BS_ICON 風格下文本不顯示,需自繪實現圖文混排

本文整理自 MFC 經典技術文檔,適用於 VC6~VS2022 所有版本。

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