MFC 静态文本的自绘 空心字的实现

   想在对话框里,显示几个字是很简单的,只要用静态文本的输出就可以了。然而有时候我们需要显示特效的字,我们希望显示的文字就像Word里的艺术字一样,看起来美观。这时我们可以重写CStatic类。用DrawItem方法重绘。
     首先,我们想要激活CStatic控件的自绘属性,这样DrawItem才能有效。我们发现用激活CButton自绘属性的方法那样来激活 CStatic控件的自绘属性是不行的。他们的激活方式是不一样的。
    不用说先新建一个MFC类叫CCustomStatic类并继承于CStatic父类。覆写PreSubclassWindow方法,在PreSubclassWindow激活CStatic的自绘属性。

代码如下:

void CCustomStatic::PreSubclassWindow()
{
    DWORD dwstyle = GetStyle();
    SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwstyle | SS_OWNERDRAW );
    CStatic::PreSubclassWindow();
} 

 现在我们可以覆写DrawItem方法了。
  代码如下:

void CCustomStatic::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    CString strText;
    GetWindowText(strText);
    CDC dc;
    dc.Attach(lpDrawItemStruct->hDC);
    UINT state = lpDrawItemStruct->itemState;
    CRect rect;
    GetClientRect(rect);
    
    CFont font;
    CFont *pOldFont;
    font.CreateFont(
        0.9*rect.Height(),                        // nHeight
        20,                         // nWidth
        40,                         // nEscapement
        0,                         // nOrientation
        FW_BOLD,                 // nWeight
        TRUE,                     // bItalic
        FALSE,                     // bUnderline
        0,                         // cStrikeOut
        ANSI_CHARSET,              // nCharSet
        OUT_DEFAULT_PRECIS,        // nOutPrecision
        CLIP_DEFAULT_PRECIS,       // nClipPrecision
        DEFAULT_QUALITY,           // nQuality
        DEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily
        _T("宋体"));                 // lpszFacename

    pOldFont = dc.SelectObject(&font);
    dc.SetBkMode(TRANSPARENT);

    CPen pen(PS_SOLID, 1, RGB(0, 128, 255));
    CPen *pOldPen;
    pOldPen = dc.SelectObject(&pen);
    dc.BeginPath();
    dc.TextOut(rect.top-10, rect.left +12, strText);
    dc.EndPath();
    int num = dc.GetPath(NULL, NULL, 0);
    CPoint *pt = new CPoint[num];
    BYTE *type = new BYTE[num];
    num = dc.GetPath(pt, type, num);
    CPoint pstart;
    for (int j = 0; j < num; j++)
    {
        switch (type[j])
        {
        case PT_MOVETO:
            dc.MoveTo(pt[j]);
            pstart = pt[j];
            break;
        case PT_LINETO:
            dc.LineTo(pt[j]);
            break;
        case PT_BEZIERTO:
            dc.PolyBezierTo(pt + j, 3);
            j += 2;
            break;
        case PT_BEZIERTO|PT_CLOSEFIGURE:
            pt[j+2] = pstart;
            dc.PolyBezierTo(pt + j, 3);
            j += 2;
            break;
        case PT_LINETO| PT_CLOSEFIGURE :
            dc.LineTo(pstart);
            break;
        }
        dc.CloseFigure();
    }
    font.DeleteObject();
    pen.DeleteObject();
    delete pt;
    delete type;

    dc.Detach();
}

头文件里不要忘记了声明

virtual void PreSubclassWindow();

void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); 

运行效果如下:空心字 效果

 

posted @ 2016-11-20 13:17  高山百川  阅读(2281)  评论(1编辑  收藏  举报