INTRODUCTION AND RELEVANT INFORMATION:
I need to have
themed common controls but with different text color, and transparent background. I have ran into a problem that is well documented in
this question[
^].
I have made some progress by handling
NM_CUSTOMDRAW
and have decided to finish the
checkbox first.
PROBLEM:
I got stuck with determining the state of the
checkbox, so I can not pass the correct parameter for
DrawThemeBackground()
.
Code speaks more than words, so here is the snippet:
case WM_NOTIFY:
{
if( ((LPNMHDR)lParam)->code == NM_CUSTOMDRAW )
{
switch( ((LPNMHDR)lParam)->idFrom )
{
case IDC_CHECK1:
{
switch( ((LPNMCUSTOMDRAW)lParam)->dwDrawStage )
{
case CDDS_PREERASE:
{
HRESULT hr =
DrawThemeParentBackground( (
(LPNMCUSTOMDRAW)lParam)->hdr.hwndFrom,
((LPNMCUSTOMDRAW)lParam)->hdc,
&((LPNMCUSTOMDRAW)lParam)->rc );
if( FAILED(hr) )
{
SetWindowLongPtr( hDlg, DWLP_MSGRESULT,
(LONG_PTR)CDRF_DODEFAULT );
return TRUE;
}
HTHEME hTheme =
OpenThemeData(
((LPNMCUSTOMDRAW)lParam)->hdr.hwndFrom,
L"BUTTON" );
if(!hTheme)
{
CloseThemeData(hTheme);
SetWindowLongPtr( hDlg,
DWLP_MSGRESULT,
(LONG_PTR)CDRF_DODEFAULT );
return TRUE;
}
LRESULT state = SendMessage(
((LPNMCUSTOMDRAW)lParam)->hdr.hwndFrom,
BM_GETSTATE, 0, 0 );
int stateID;
switch( ((LPNMCUSTOMDRAW)lParam)->uItemState )
{
case CDIS_HOT:
{
if( IsDlgButtonChecked( hDlg,
((LPNMCUSTOMDRAW)lParam)->hdr.idFrom ) )
stateID = CBS_CHECKEDHOT;
else
stateID = CBS_UNCHECKEDHOT;
break;
}
case CDIS_DEFAULT:
{
if( IsDlgButtonChecked( hDlg,
((LPNMCUSTOMDRAW)lParam)->hdr.idFrom ) )
stateID = CBS_CHECKEDNORMAL;
else
stateID = CBS_UNCHECKEDNORMAL;
break;
}
case CDIS_FOCUS:
{
if( IsDlgButtonChecked( hDlg,
((LPNMCUSTOMDRAW)lParam)->hdr.idFrom ) )
stateID = CBS_CHECKEDNORMAL;
else
stateID = CBS_UNCHECKEDNORMAL;
break;
}
case CDIS_SELECTED:
{
if( IsDlgButtonChecked( hDlg,
((LPNMCUSTOMDRAW)lParam)->hdr.idFrom ) )
stateID = CBS_CHECKEDPRESSED;
else
stateID = CBS_UNCHECKEDPRESSED;
break;
}
}
RECT r;
SIZE s;
GetThemePartSize( hTheme,
((LPNMCUSTOMDRAW)lParam)->hdc,
BP_CHECKBOX,
stateID,
NULL,
TS_TRUE ,&s );
r.left = ((LPNMCUSTOMDRAW)lParam)->rc.left;
r.top = ((LPNMCUSTOMDRAW)lParam)->rc.top;
r.right = ((LPNMCUSTOMDRAW)lParam)->rc.left + s.cx;
r.bottom = ((LPNMCUSTOMDRAW)lParam)->rc.top + s.cy;
DrawThemeBackground( hTheme,
((LPNMCUSTOMDRAW)lParam)->hdc,
BP_CHECKBOX, stateID,
&r,
NULL );
((LPNMCUSTOMDRAW)lParam)->rc.left += 2 + s.cx;
DrawText( ((LPNMCUSTOMDRAW)lParam)->hdc,
L"Example text",
-1, &((LPNMCUSTOMDRAW)lParam)->rc,
DT_SINGLELINE | DT_VCENTER );
CloseThemeData(hTheme);
SetWindowLongPtr( hDlg, DWLP_MSGRESULT,
(LONG_PTR)CDRF_SKIPDEFAULT );
return TRUE;
}
}
}
break;
}
}
}
break;
The text color and text background are set in the
WM_CTLCOLORSTATIC
handler:
case WM_CTLCOLORSTATIC:
{
SetTextColor( (HDC)wParam, RGB( 255, 0, 0 ) );
SetBkMode( (HDC)wParam, TRANSPARENT );
}
return (INT_PTR)( (HBRUSH)GetStockObject(NULL_BRUSH) );
I have included common controls 6 with the
#pragma comment
and
InitCommonControlsEx()
.
QUESTION:
All I need for now is to pass proper state for the
DrawThemeBackground
. Can someone help me with this?
EDIT:
The solution that satisfied my needs can be found
here[
^].
The only problem was in the line
bool bChecked = (uiItemState & CDIS_CHECKED);
.
It threw
C4800 warning[
^].
After numerous tries I had to rewrite the offensive line to
bool bChecked = ( BST_CHECKED == IsDlgButtonChecked( hDlg, ((LPNMCUSTOMDRAW)lParam)->hdr.idFrom ) );
.
In order for everything to work properly I also had to rearrange the order of
if
statements :
if (uiItemState & CDIS_SELECTED)
stateID = (bChecked) ? CBS_CHECKEDPRESSED : CBS_UNCHECKEDPRESSED;
else
if (uiItemState & CDIS_HOT)
stateID = (bChecked) ? CBS_CHECKEDHOT : CBS_UNCHECKEDHOT;
else
stateID = (bChecked) ? CBS_CHECKEDNORMAL : CBS_UNCHECKEDNORMAL;
The only thing left is to handle keyboard focus by drawing focus rectangle, but I have trouble in using the correct color.
END OF EDIT
Thank you.
Best regards.