I have written a CButton that will use ownerdraw when theming is active in Windows (that is not the case when Windows Classic is used), and will do so dynamically. This sample code is not complete but it demonstrates everything needed to get the results.
The difficult part is that you need to represent highlighted and pressed states, see the parameters for DrawCheckBox
. I am ignoring them as they will not be entirely missed in my application.
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);
}
I even tried runtime theme switching, however that gives undesired effect when switching from Windows 7
theme to Windows Classic
(checkbox then looks like a regular button). So I am not using this but maybe it is interesting to share:
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;
}