最近接到个需求,要求在一个按钮上面同时显示大的文字和小的文字。想到了wtl的控件自绘。百度了下,发现竟然没人给出详细的代码,大部分都只是描述了下怎么弄,只好自己弄。先发个效果图。
.h文件
#pragma once
class CMyButtonEx
: public CWindowImpl
, public COwnerDraw
{
public:
CMyButtonEx();
~CMyButtonEx();
void SetWindowText2(LPCTSTR sText) { m_sText2 = sText; }
BEGIN_MSG_MAP(CMyButtonEx)
CHAIN_MSG_MAP_ALT(COwnerDraw, 1)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
void DrawItem(LPDRAWITEMSTRUCT lpdis);
private:
CString m_sText2;
};
cpp文件
#include "stdafx.h"
#include "MyButtonEx.h"
extern CFont m_defFont; //缺省字体
extern CFont m_fontBig; //大字体
CMyButtonEx::CMyButtonEx()
{
}
CMyButtonEx::~CMyButtonEx()
{
}
void CMyButtonEx::DrawItem(LPDRAWITEMSTRUCT lpdis)
{
CDCHandle dc(lpdis->hDC);
CRect rc(lpdis->rcItem);
CPen pen;
pen.CreatePen(PS_SOLID, 1, (lpdis->itemState & ODS_DISABLED) ? RGB(173, 173, 173) : RGB(191, 191, 191));
HPEN hOldPen = dc.SelectPen(pen.m_hPen);
CBrush brush;
brush.CreateSolidBrush((lpdis->itemState & ODS_DISABLED) ? RGB(204, 204, 204) : RGB(225, 225, 225));
HBRUSH hOldBrush = dc.SelectBrush(brush.m_hBrush);
dc.Rectangle(&rc);
TCHAR szText[MAX_PATH] = { 0 };
::GetWindowText(m_hWnd, szText, MAX_PATH);
if (wcslen(szText) > 0) {
int nOldMode = dc.SetBkMode(TRANSPARENT);
COLORREF crlOld = dc.SetTextColor((lpdis->itemState & ODS_DISABLED) ? RGB(131, 131, 131) : RGB(0, 0, 0));
HFONT hOldFont = dc.SelectFont(m_fontBig.m_hFont);
if (m_sText2.GetLength()) {
SIZE size1, size2;
GetTextExtentPoint32(dc.m_hDC, szText, wcslen(szText), &size1);
dc.SelectFont(m_defFont.m_hFont);
GetTextExtentPoint32(dc.m_hDC, m_sText2, m_sText2.GetLength(), &size2);
CRect rc1;
rc1.left = rc.left + (rc.Width() - size1.cx - size2.cx) / 2;
rc1.top = 0;
rc1.right = rc1.left + size1.cx;
rc1.bottom = rc.bottom;
dc.SelectFont(m_fontBig.m_hFont);
dc.DrawText(szText, -1, rc1, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
CRect rc2;
rc2.left = rc1.right;
rc2.top = 0;
rc2.right = rc2.left + size2.cx;
rc2.bottom = rc.bottom;
dc.SelectFont(m_defFont.m_hFont);
dc.DrawText(m_sText2, -1, rc2, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
else {
dc.DrawText(szText, -1, rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
dc.SelectFont(hOldFont);
dc.SetTextColor(crlOld);
dc.SetBkMode(nOldMode);
}
if (hOldPen)
dc.SelectPen(hOldPen);
if (hOldBrush)
dc.SelectBrush(hOldBrush);
}
创建font
LOGFONT logfont;
memset(&logfont, 0, sizeof(LOGFONT));
lstrcpy(logfont.lfFaceName, _T("宋体")/*_T("Tahoma")*/);
//默认字体
logfont.lfWeight = FW_NORMAL;
logfont.lfHeight = -12;
m_defFont.CreateFontIndirect(&logfont);
//大号字体
logfont.lfWeight = FW_NORMAL;
logfont.lfHeight = -16;
m_fontBig.CreateFontIndirect(&logfont);
如果自绘失败的话,请按如下步骤检查一遍
1.添加自绘控件类,使其派生自COwnerDraw,例如
class MyButtonEx:public CWindowImpl
,public COwnerDraw
2.在自绘控件类中添加消息映射CHAIN_MSG_MAP_ALT,例如:CHAIN_MSG_MAP_ALT(COwnerDraw
3.END_MSG_MAP之前要添加DEFAULT_REFLECTION_HANDLER()
4.重写void DrawItem(LPDRAWITEMSTRUCT lpds)等函数,在此函数中完成自绘工作
5.修改自绘控件类的窗口样式,添加OWNERDRAW属性,例如BS_OWNERDRAW
6.不要使用DDX_CONTROL关联控件变量与控件ID!而是使用SubclassWindow来实现,否则看不出自绘效果!(这一点浪费了我半小时找原因)
引自:https://www.cnblogs.com/mygmh/archive/2012/11/08/2761715.html