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

MFC StaticText 字體顯示異常解決:背景刷子、WM_CTLCOLOR 與透明模式完整指南

     編輯:Java 程式設計入門

問題現象

MFC 對話方塊/視圖中修改 CStatic (StaticText) 字體顏色/字型時,文字背景出現灰白條紋/邊框殘留,與對話方塊背景不融合。

字體背景異常

根因分析

  • OnCtlColor 返回的 HBRUSH 決定控件背景繪製方式
  • 預設返回 NULL 或父類筆刷,導致文字區域使用系統預設背景色 (通常灰白)
  • 修改字體/顏色後,若筆刷不匹配對話方塊背景,會出現「文字框」效果

完整解決方案:自定義筆刷匹配背景色

步驟 1:成員變數宣告 (在類定義中)


class CMyDialog : public CDialogEx {
    // ...
protected:
    CFont m_customFont;      // 自定義字體
    CBrush m_bgBrush;        // 背景筆刷 (關鍵)
    COLORREF m_textColor;    // 文字顏色
    COLORREF m_bgColor;      // 背景顏色
};

步驟 2:初始化 (OnInitDialog / 建構函數)


BOOL CMyDialog::OnInitDialog() {
    CDialogEx::OnInitDialog();

    // 1. 設定目標顏色 (與對話方塊背景一致)
    m_textColor = RGB(0, 0, 255);       // 藍色文字
    m_bgColor = GetSysColor(COLOR_BTNFACE); // 系統按鈕面板色 (典型灰白)
    // 或指定確切色值:m_bgColor = RGB(240, 240, 240);

    // 2. 建立字體
    m_customFont.CreatePointFont(100, _T("微軟正黑體")); // 10 點大小
    // 或 LOGFONT 精細控制

    // 3. 建立背景筆刷 (核心步驟!)
    m_bgBrush.CreateSolidBrush(m_bgColor);

    // 4. 關聯控件變數 (若使用 DDX_Control)
    // m_staticCtrl.SubclassDlgItem(IDC_STATIC_INFO, this);

    return TRUE;
}

步驟 3:處理 WM_CTLCOLOR (關鍵)


HBRUSH CMyDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) {
    HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor); // 必須調用基類

    // 針對特定 Static 控件
    if (pWnd->GetDlgCtrlID() == IDC_STATIC_INFO) {
        // 1. 設定文字顏色
        pDC->SetTextColor(m_textColor);
        
        // 2. 設定文字背景模式:透明 (關鍵!)
        pDC->SetBkMode(TRANSPARENT); 
        
        // 3. 選入自定義字體
        pDC->SelectObject(&m_font);
        
        // 4. 返回自定義背景筆刷
        return m_bgBrush;
    }

    return hbr;
}

關鍵點解析

設置作用錯誤後果
SetBkMode(TRANSPARENT)文字背景透明,由筆刷填充文字周圍出現不透明矩形框
CreateSolidBrush(bgColor)實體筆刷填充控件背景背景色與對話框不一致
SelectObject(&font)應用自定義字體字體不生效
返回 m_bgBrush告訴系統用此筆刷繪製背景使用預設筆刷

進階:動態顏色切換


void CMyDialog::SetStaticColor(COLORREF textColor, COLORREF bgColor) {
    m_textColor = textColor;
    m_bgColor = bgColor;
    
    // 重建筆刷
    if (m_bgBrush.GetSafeHandle()) m_bgBrush.DeleteObject();
    m_bgBrush.CreateSolidBrush(m_bgColor);
    
    // 觸發重繪
    CWnd* pStatic = GetDlgItem(IDC_STATIC_INFO);
    if (pStatic) pStatic->Invalidate(TRUE); // TRUE = 擦除背景
}

替代方案:Owner Draw (完全控制)


// 1. 控件屬性設定 Owner Draw (固定)
// 2. 重寫 DrawItem
void CMyDialog::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
    if (lpDrawItemStruct->CtlID == IDC_STATIC_INFO) {
        CDC dc;
        dc.Attach(lpDrawItemStruct->hDC);
        
        CRect rect = lpDrawItemStruct->rcItem;
        // 填充背景
        dc.FillSolidRect(rect, m_bgColor);
        // 設定文字屬性
        dc.SetTextColor(m_textColor);
        dc.SetBkMode(TRANSPARENT);
        CFont* pOldFont = dc.SelectObject(&m_customFont);
        // 繪製文字
        CString text;
        GetDlgItemText(IDC_STATIC_INFO, text);
        dc.DrawText(text, rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
        dc.SelectObject(pOldFont);
        
        dc.Detach();
        return;
    }
    CDialogEx::DrawItem(lpDrawItemStruct);
}

常見誤區避坑

  • 忘記 DeleteObject:筆刷/字體為 GDI 物件,類銷毀時必須釋放 (或用智能指針 CBrush/CFont 自動管理)
  • 筆刷顏色硬編碼:應用 GetSysColor(COLOR_BTNFACE) 或 GetSysColor(COLOR_WINDOW) 適應主題切換
  • 未設 SetBkMode(TRANSPARENT):90% 背景異常源於此
  • 基類 OnCltColor 未調用:導致其他控件繫結異常
  • 字體創建失敗未檢查:CreatePointFont 返回 BOOL,失敗時 GetSafeHandle() 為 NULL

效果對比

修正前:

異常背景

修正後:

正常背景

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