简介及相关信息:
我需要有主题的公共控件,但具有不同的文本颜色,和透明的背景。我遇到了一个问题,在这个问题中有很好的记录。
我通过处理NM_CUSTOMDRAW
取得了一些进展,并决定先完成复选框。
问题:
我被困在确定复选框的状态,所以我不能传递DrawThemeBackground()
的正确参数。
代码不仅仅是文字,下面是代码片段:
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) ) // if failed draw without theme
{
SetWindowLongPtr( hDlg, DWLP_MSGRESULT
(LONG_PTR)CDRF_DODEFAULT );
return TRUE;
}
HTHEME hTheme = OpenThemeData(
((LPNMCUSTOMDRAW)lParam)->hdr.hwndFrom,
L"BUTTON" );
if( ! hTheme ) // if failed draw without theme
{
CloseThemeData(hTheme);
SetWindowLongPtr( hDlg, DWLP_MSGRESULT
(LONG_PTR)CDRF_DODEFAULT );
return TRUE;
}
// draw the state-->this is the problem part
// I thought this might be useful
LRESULT state = SendMessage(
((LPNMCUSTOMDRAW)lParam)->hdr.hwndFrom,
BM_GETSTATE, 0, 0 );
int stateID; // parameter for DrawThemeBackground
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;
// get check box dimensions so we can calculate
// rectangle dimensions for text
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 );
// adjust rectangle for text drawing
((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;
文本颜色和文本背景在WM_CTLCOLORSTATIC
处理程序中设置:
case WM_CTLCOLORSTATIC:
{
SetTextColor( (HDC)wParam, RGB( 255, 0, 0 ) );
SetBkMode( (HDC)wParam, TRANSPARENT );
}
return (INT_PTR)( (HBRUSH)GetStockObject(NULL_BRUSH) );
我包含了#pragma comment
和InitCommonControlsEx()
的通用控件6。
问题:
我现在所需要的就是为DrawThemeBackground
传递适当的状态。有人能帮我一下吗?
谢谢。
问好。
NM_CUSTOMDRAW
给出了正在绘制的控件的状态信息。NMCUSTOMDRAW::uItemState
字段是一个位掩码,它可以一次保存多个值,但是您没有考虑到这一点。您需要使用&
位运算符来检查是否存在特定的值。
改变:
// I thought this might be useful
LRESULT state = SendMessage(
((LPNMCUSTOMDRAW)lParam)->hdr.hwndFrom,
BM_GETSTATE, 0, 0 );
int stateID; // parameter for DrawThemeBackground
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;
}
}
变成这样:
int stateID; // parameter for DrawThemeBackground
UINT uiItemState = ((LPNMCUSTOMDRAW)lParam)->uItemState;
bool bChecked = (uiItemState & CDIS_CHECKED);
if (uiItemState & CDIS_HOT)
stateID = bChecked ? CBS_CHECKEDHOT : CBS_UNCHECKEDHOT;
else if (uiItemState & CDIS_SELECTED)
stateID = bChecked ? CBS_CHECKEDPRESSED : CBS_UNCHECKEDPRESSED;
else
stateID = bChecked ? CBS_CHECKEDNORMAL : CBS_UNCHECKEDNORMAL;