以前一直以为要改变按钮文字颜色就必须自绘按钮,但后来用Spy++查看WinXP自带的那个计算器发现它的按钮并没有BS_OWNERDRAW样式也没被子类化,那它怎么自绘呢? 然后我想起了NM_CUSTOMDRAW, 但因为看到Win2K的计算器也是同样的按钮文字颜色,就惘然了:难道不是NM_CUSTOMDRAW? 之后因为忙别的事就没再研究这个问题......
直到最近我又再想起了这个问题,这次我才想到Win2K的计算器和WinXP的计算器的按钮文字颜色的实现方法可能不一样,毕竟Win2K下不必考虑主题的问题,自绘按钮会简单得多......果然不出所料,Win2K的计算器的按钮都有BS_OWNERDRAW样式,很明显是处理WM_DRAWITEM实现的;而WinXP的计算器在Win2K下运行或者删掉24资源(manifest)就没有那样的按钮文字颜色了,可以肯定是处理NM_CUSTOMDRAW实现的了。
处理NM_CUSTOMDRAW的方法实现按钮文本颜色可以更简单,按钮也不用自己画,只需DrawText就行了,但缺点就如上所说:XP以下系统是不支持的。
代码参考:
#define BTN_MAX_STRLEN 64
#define GetButtonStyle(hBtn) (WORD)(GetWindowLongPtr((hBtn), GWL_STYLE) & 0x000F)
BOOL DrawButtonText(LPNMCUSTOMDRAW lpNMCD)
{
switch (GetButtonStyle(((LPNMHDR)lpNMCD)->hwndFrom))
{
case BS_PUSHBUTTON:
case BS_DEFPUSHBUTTON:
{
TCHAR szText[BTN_MAX_STRLEN];
switch (((LPNMHDR)lpNMCD)->idFrom) //根据控件ID设置按钮文字颜色,也可以在WM_CTLCOLORBTN中设置
{
case IDOK:
SetTextColor(lpNMCD->hdc, 0xFF00FF);
break;
case IDCANCEL:
SetTextColor(lpNMCD->hdc, 0xFF0000);
break;
//case ...:
}
SetBkMode(lpNMCD->hdc, TRANSPARENT);
GetWindowText(((LPNMHDR)lpNMCD)->hwndFrom, szText, BTN_MAX_STRLEN);
DrawText(lpNMCD->hdc, szText, -1, &lpNMCD->rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
return TRUE;
}
}
return FALSE;
}
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
//............
//............
//............
case WM_NOTIFY:
{
if (((LPNMHDR)lParam)->code == NM_CUSTOMDRAW)
{
if (((LPNMCUSTOMDRAW)lParam)->dwDrawStage == CDDS_PREPAINT)
{
TCHAR szClassName[16];
GetClassName(((LPNMHDR)lParam)->hwndFrom, szClassName, 16);
if (!lstrcmp(szClassName, _T("Button")))
{
if (DrawButtonText((LPNMCUSTOMDRAW)lParam))
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_SKIPDEFAULT);
return TRUE;
}
}
}
}
}
}
return FALSE;
}