为了更改MFC复选框和无线电按钮的外观(背景颜色和文本前景色),我使用了以下实现,该实现在Windows2000中运行良好,在Windows中工作正常,但在Windows7中不工作:
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经典主题,它就能正常工作。然而,当使用不同的主题时:
SetBkColor工作,但SetTextColor被忽略SetBkColor和SetTextColor都被忽略我试着用自定义颜色( OnEraseBkgnd )填充背景,但即使这样也没有效果。
我希望避免使用所有者绘制的OnPaint,因此检查和广播标记会一直遵循在Windows中活动的主题。如前所述,此代码用于W2000、Windows、Vista和Windows7.我只想改变背景颜色和文字颜色。
发布于 2011-11-16 16:24:46
我已经编写了一个CButton,它将在主题在Windows中活动时使用所有者绘图(在使用Windows时不是这样),并且将动态地这样做。此示例代码尚未完成,但它演示了获得结果所需的一切。
困难之处在于,您需要表示高亮显示和按下的状态,请参见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;
}发布于 2011-11-14 16:15:46
CButton只会调用来绘制按钮。您可以重写OnPaint代码来完成您自己的事情,但是我可以理解您为什么要避免这种情况--在每种不同的情况下获得正确的外观都是一项艰巨的工作。
MFC提供了另一个类CMFCButton,它具有可重写的方法OnFillBackground,看看它是否适用于您。
发布于 2011-11-15 12:08:05
根据这篇微软文章的说法:
若要更改Windows 3.0及更高版本中按钮控件的背景色,必须创建所有者绘制按钮。
如果您希望特定控件以不同的形式出现,我认为最好将其子类化。
这篇文章将有助于理解子类。
在这里,要更改按钮的背景、和文本颜色,您将需要从CButton派生一个新类,例如MyButton,并重写其DrawItem函数,以添加以您的方式绘制该特定控件的代码。
注意:您需要将所有者绘制属性(BS_OWNERDRAW)设置为这些控件。
https://stackoverflow.com/questions/8123526
复制相似问题