wtl自绘,按钮Button

最近接到个需求,要求在一个按钮上面同时显示大的文字和小的文字。想到了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, 1)

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

你可能感兴趣的:(wtl)