2011-11-14 90 views
0

要更改MFC複選框和單選按鈕的外觀(背景顏色和文本前景色),我使用了以下在Windows2000中正常工作的實現,在Windows XP中一半正常,但不行在Windows 7中:由Windows 7忽略的MFC CButton背景

BEGIN_MESSAGE_MAP(mycheckbox, CButton) 
    ... 
    ON_WM_CTLCOLOR_REFLECT() 
    ... 
END_MESSAGE_MAP() 

HBRUSH mycheckbox::CtlColor(CDC* pDC, UINT nCtlColor) 
{ 
    pDC->SetBkColor(RGB(255, 0, 0)); 
    pDC->SetTextColor(RGB(0, 255, 0)); 
    return m_brush; 
} 

只要使用Windows經典主題,此工作正常。 但是,使用不同的主題時:

  • 症狀在Windows XP:SetBkColor的作品,但SetTextColor在Windows 7忽略
  • 症狀:既SetBkColorSetTextColor被忽略

我試圖OnEraseBkgnd到用自定義顏色填充背景(pDC->FillSolidRect),但即使這樣也沒有效果。

我想避免使用ownerdrawn OnPaint,以便檢查和無線電標記可以跟蹤在Windows中處於活動狀態的主題。如前所述,此代碼用於W2000,Windows XP,Vista和Windows 7 ...我只想更改背景顏色和文本顏色。

回答

1

我寫了一個CButton,當主題在Windows中使用時,它將使用ownerdraw(當使用Windows Classic時,情況並非如此),並且會動態地實現。此示例代碼不完整,但它演示了獲取結果所需的一切。

難點在於您需要表示突出顯示和按下的狀態,請參閱DrawCheckBox的參數。我無視他們,因爲他們在我的申請中不會完全錯過。

IMPLEMENT_DYNAMIC(mycheckbox, CButton) 

mycheckbox::mycheckbox() 
    : mv_bIsChecked(false) 
{ 
    m_brush.CreateSolidBrush(RGB(0,0,255)); 
} 

mycheckbox::~mycheckbox() 
{ 
} 

BEGIN_MESSAGE_MAP(mycheckbox, CButton) 
    ON_WM_CTLCOLOR_REFLECT() 
    ON_WM_PAINT() 
    ON_CONTROL_REFLECT(BN_CLICKED, &mycheckbox::OnBnClicked) 
END_MESSAGE_MAP() 

HBRUSH mycheckbox::CtlColor(CDC* pDC, UINT nCtlColor) 
{ 
    pDC->SetBkColor(RGB(255, 0, 0)); // text background color 
    pDC->SetTextColor(RGB(0, 255, 0)); // text foreground color 
    return m_brush;      // control background 
} 

void mycheckbox::DrawItem(LPDRAWITEMSTRUCT) 
{ 
} 

void mycheckbox::OnPaint() 
{ 
    if((GetStyle() & BS_OWNERDRAW) == BS_OWNERDRAW) 
    { 
    CPaintDC dc(this); 

    RECT rect; 
    GetClientRect(& rect); 
    rect.right = rect.left + 20; 
    CMFCVisualManager::GetInstance()->DrawCheckBox(
       & dc 
       , rect 
       , false        // highlighted 
       , mv_bIsChecked ? 1 : 0 // state 
       , true        // enabled 
       , false        // pressed 
      ); 

    // draw text next to the checkbox if you like 
    } 
    else 
    __super::OnPaint(); 
} 

    // when BS_OWNERDAW is active, 
    // GetCheck() is reporting a wrong value 
    // so we have to do a little bookkeeping ourselves 
void mycheckbox::OnBnClicked() 
{ 
    mv_bIsChecked = ! mv_bIsChecked; 
} 

BOOL mycheckbox::PreCreateWindow(CREATESTRUCT & cs) 
{ 
    CString lv_szValue; 
    CSettingsStore lv_Registry(FALSE, TRUE); 
    lv_Registry.Open(_T("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager")); 
    lv_Registry.Read(_T("ThemeActive"), lv_szValue); 
    lv_Registry.Close(); 
    if(lv_szValue == _T("1")) 
    cs.style |= BS_OWNERDRAW; 

    return CButton::PreCreateWindow(cs); 
} 

我甚至嘗試運行時主題切換,然而,從Windows 7主題切換到Windows Classic時給出不良影響(複選框,然後看起來像一個普通的按鈕)。所以,我沒有使用這一點,但也許這是有趣的分享:

void mycheckbox::OnNMThemeChanged(NMHDR * pNMHDR, LRESULT * pResult) 
{ 
    CString lv_szValue; 
    CSettingsStore lv_Registry(FALSE, TRUE); 
    lv_Registry.Open(_T("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager")); 
    lv_Registry.Read(_T("ThemeActive"), lv_szValue); 
    lv_Registry.Close(); 

    ModifyStyle(BS_OWNERDRAW, 0); // turn off 
    if(lv_szValue == _T("1")) 
    ModifyStyle(0, BS_OWNERDRAW); // turn on 

    // This feature requires Windows XP or greater. 
    // The symbol _WIN32_WINNT must be >= 0x0501. 
    // TODO: Add your control notification handler code here 
    *pResult = 0; 
} 
1

CButton除了調用Windows默認的窗口過程來繪製按鈕之外不會做任何其他的事情。你可以重寫OnPaint代碼來完成你自己的事情,但是我可以理解爲什麼你想避免這種情況 - 在每種情況下獲得適當的外觀都是很多工作。

MFC提供了另一個類CMFCButton,它有一個可覆蓋的方法OnFillBackground,看看是否適合你。

+0

'CMFCButton'不能顯示覆選框或單選按鈕,即使方法'器isChecked()'返回TRUE時的風格'BS_CHECKBOX'用來。有趣。 –

+1

當閱讀關於'CMFCButton'的文章時,我遇到了函數'CMFCVisualManager :: GetInstance() - > DrawCheckBox'和'CMFCVisualManager :: GetInstance() - > DrawRadioButton' –

0

根據this Microsoft article

要改變一個按鈕控件的背景色在Windows 3.0和 後來,有必要創建一個所有者繪製按鈕。

如果您希望特定的控件以不同的方式出現,我認爲最好將其子類化。

This article將有助於理解子類。

這裏改變一個按鈕,您將需要派生新類從CButtonMyButton並覆蓋其DrawItem功能添加代碼繪製在你的方式,特別是控制背景文本顏色

注意:您需要將所有者繪製屬性(BS_OWNERDRAW)設置爲這些控件。

0

相信我,這裏最好的解決方案是讓CStatic帶有文本一個只包含複選框的CButton。從Vista開始,改變複選框的背景是一個問題,至少可以說。