文章来源:http://www.cnblogs.com/koangel/p/5192603.html
由于SOUI是一种双渲染引擎的DUI库,默认在SKIA渲染引擎下是支持特效字体的,具体请参考DEMO中的源码。
但是使用GDI+渲染时是没有这些特效的,着实比较苦恼,此代抛砖引玉,细节实现 请自己再去封装,此处只封装了STATIC控件。
部分效果使用了库:TextDesigner
CodePRoject: http://www.codeproject.com/Articles/42529/Outline-Text
此代码有一个小BUG,在使用SOUI布局时,POS必须4个参数都指定,类似如此:pos="15,20,-15,@25"
有兴趣的朋友可以自己实现一下。
先看下预览效果:
我只实现了部分效果,由于效果组合太多,所以这里暂时把我常用的先贴出来。
参数说明:
drawMode: 1为描边 2阴影 3外发光 4双描边,具体特效请自己设置颜色和渲染效果
EffectColor: 特效的颜色数值
EffectColor2: 使用双效果时的第二个数值颜色
底层使用GDI+所以默认支持多行,但是请根据多行来设置对应的高宽,否则显示肯定错误。
头文件:
1 /*! 2 * /file SEffectStatic.h 3 * /date 2016/02/15 19:51 4 * 5 * /author koangel 6 * Contact: jackliu100@Gmail.com 7 * blog: http://www.cnblogs.com/koangel/ 8 * 9 * /brief GDI渲染模式下专用静态特效渲染库 10 *11 * /note GDI+渲染模式下专用,如果在SKIA模式下,直接切换为标准SSTAIC模式渲染12 * 效果使用GDI编写,暂不支持SKIA13 * 部分效果使用TextDesigner库编写。14 * CodeProject: http://www.codeproject.com/Articles/42529/Outline-Text15 * TextDesigner版权归原作者所有。16 */17 #pragma once18 #include <gdiplus.h>19 20 #pragma comment(lib,"gdiplus.lib")21 22 class SEffectStatic : public SStatic23 {24 SOUI_CLASS_NAME(SStatic, L"eff_text")25 public:26 SEffectStatic();27 virtual ~SEffectStatic();28 /**29 * SStatic::SDrawText30 * @brief 绘制文本31 * @param IRenderTarget *pRT -- 绘制设备句柄32 * @param LPCTSTR pszBuf -- 文本内容字符串33 * @param int cchText -- 字符串长度34 * @param LPRECT pRect -- 指向矩形结构RECT的指针35 * @param UINT uFormat -- 正文的绘制选项36 *37 * Describe 对DrawText封装38 */39 virtual void DrawText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);40 41 protected:42 43 void DrawMultiLine(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);44 void DrawShadowMultiLine(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);45 46 // 渲染带阴影的字体47 void DrawShadowText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);48 void DrawStrokeText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);49 void DrawDoubleStrokeText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);50 void DrawGowText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);51 52 void initGDIFont(IRenderTarget *pRT,Gdiplus::Font& gf);53 54 LOGFONT* GetGDIFont(IRenderTarget *pRT);55 Gdiplus::StringFormat* toFormat(UINT uFormat);56 57 int m_nEffectDrawMode; /**< 渲染模式 */58 COLORREF m_nEffectColor; /**< 效果颜色 */59 COLORREF m_nEffectColor2; /**< 效果颜色 */60 Word m_StrokeSize; /**< 描边大小 */61 62 SOUI_ATTRS_BEGIN()63 ATTR_INT(L"drawMode", m_nEffectDrawMode, FALSE)64 ATTR_COLOR(L"effectColor", m_nEffectColor, FALSE)65 ATTR_COLOR(L"effectColor2", m_nEffectColor2, FALSE)66 ATTR_INT(L"strokeSize", m_StrokeSize, FALSE)67 SOUI_ATTRS_END()68 };实现文件:
1 /*! 2 * /file SEffectStatic.cpp 3 * /date 2016/02/16 13:00 4 * 5 * /author koangel 6 * Contact: jackliu100@gmail.com 7 * 8 * /brief 渲染对应的静态文本,多行文本渲染可能存在问题 9 * 10 * TODO: blog http://www.cnblogs.com/koangel/ 11 * 12 * /note 13 */ 14 #include "stdafx.h" 15 #include "SEffectStatic.h" 16 enum DRAW_EFFECT_MODE 17 { 18 DRAW_TEXT_NORMAL = 0, // 默认渲染 19 DRAW_TEXT_STROKE, // 渲染 描边 20 DRAW_TEXT_SHADOW, // 渲染 阴影 21 DRAW_TEXT_GROW, // 渲染 外发光效果 22 DRAW_TEXT_DBSTROKE, // 渲染 双描边 23 }; 24 25 #define GR(rgb) ((BYTE)(rgb)) 26 #define GG(rgb) ((BYTE)(((WORD)(rgb)) >> 8)) 27 #define GB(rgb) ((BYTE)((rgb)>>16)) 28 29 // 默认调用之前的构造函数 30 SEffectStatic::SEffectStatic() : SStatic(), 31 m_nEffectColor(0xFFFFFF), 32 m_nEffectColor2(0xFF0080), 33 m_nEffectDrawMode(0), 34 m_StrokeSize(1) 35 { 36 } 37 38 39 SEffectStatic::~SEffectStatic() 40 { 41 42 } 43 44 void SEffectStatic::DrawText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat) 45 { 46 if (!m_bMultiLines) 47 { 48 switch (m_nEffectDrawMode) 49 { 50 case DRAW_TEXT_NORMAL: 51 __super::DrawText(pRT, pszBuf, cchText, pRect, uFormat); 52 break; 53 case DRAW_TEXT_STROKE: 54 DrawStrokeText(pRT, pszBuf, cchText, pRect, uFormat); 55 break; 56 case DRAW_TEXT_SHADOW: 57 DrawShadowText(pRT, pszBuf, cchText, pRect, uFormat); 58 break; 59 case DRAW_TEXT_GROW: 60 DrawGowText(pRT, pszBuf, cchText, pRect, uFormat); 61 break; 62 case DRAW_TEXT_DBSTROKE: 63 DrawDoubleStrokeText(pRT, pszBuf, cchText, pRect, uFormat); 64 break; 65 } 66 } 67 else 68 { 69 switch (m_nEffectDrawMode) 70 { 71 case DRAW_TEXT_NORMAL: 72 { 73 if (uFormat&(DT_VCENTER | DT_BOTTOM) && !(uFormat & DT_CALCRECT)) 74 { 75 //static 多行控件支持垂直居中及底对齐 76 CRect rcText = *pRect; 77 DrawMultiLine(pRT, pszBuf, cchText, &rcText, uFormat | DT_CALCRECT); 78 CSize szTxt = rcText.Size(); 79 rcText = *pRect; 80 switch (GetStyle().GetTextAlign()&(DT_VCENTER | DT_BOTTOM)) 81 { 82 case DT_VCENTER: 83 rcText.DeflateRect(0, (rcText.Height() - szTxt.cy) / 2); 84 break; 85 case DT_BOTTOM: 86 rcText.DeflateRect(0, (rcText.Height() - szTxt.cy)); 87 break; 88 } 89 DrawMultiLine(pRT, pszBuf, cchText, &rcText, uFormat); 90 } 91 else 92 { 93 DrawMultiLine(pRT, pszBuf, cchText, pRect, uFormat); 94 } 95 break; 96 } 97 case DRAW_TEXT_STROKE: 98 DrawStrokeText(pRT, pszBuf, cchText, pRect, uFormat); 99 break;100 case DRAW_TEXT_SHADOW:101 DrawShadowMultiLine(pRT, pszBuf, cchText, pRect, uFormat);102 break;103 case DRAW_TEXT_GROW:104 DrawGowText(pRT, pszBuf, cchText, pRect, uFormat);105 break;106 case DRAW_TEXT_DBSTROKE:107 DrawDoubleStrokeText(pRT, pszBuf, cchText, pRect, uFormat);108 break;109 } 110 }111 }112 113 void SEffectStatic::DrawMultiLine(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)114 {115 SIZE szChar;116 int i = 0, nLine = 1;117 if (cchText == -1) cchText = _tcslen(pszBuf);118 LPCTSTR p1 = pszBuf;119 POINT pt = { pRect->left,pRect->top };120 pRT->MeasureText(_T("A"), 1, &szChar);121 int nLineHei = szChar.cy;122 int nRight = pRect->right;123 pRect->right = pRect->left;124 while (i<cchText)125 {126 LPTSTR p2 = CharNext(p1);127 if (*p1 == _T('//') && p2 && *p2 == _T('n'))128 {129 pt.y += nLineHei + m_nLineInter;130 pt.x = pRect->left;131 nLine++;132 i += p2 - p1;133 p1 = CharNext(p2);134 i += p1 - p2;135 continue;136 }137 pRT->MeasureText(p1, p2 - p1, &szChar);138 if (pt.x + szChar.cx > nRight)139 {140 pt.y += nLineHei + m_nLineInter;141 pt.x = pRect->left;142 nLine++;143 continue;144 }145 if (!(uFormat & DT_CALCRECT))146 {147 pRT->TextOut(pt.x, pt.y, p1, p2 - p1);148 }149 pt.x += szChar.cx;150 if (pt.x > pRect->right && uFormat & DT_CALCRECT) pRect->right = pt.x;151 i += p2 - p1;152 p1 = p2;153 }154 if (uFormat & DT_CALCRECT)155 {156 pRect->bottom = pt.y + nLineHei;157 }158 }159 160 void SEffectStatic::DrawShadowMultiLine(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)161 {162 COLORREF textColor = this->m_style.GetTextColor(0);163 164 Gdiplus::StringFormat *strFmt = toFormat(uFormat);165 166 Gdiplus::Graphics gs(pRT->GetDC());167 Gdiplus::Font gf(pRT->GetDC(), GetGDIFont(pRT));168 169 gs.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);170 gs.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAliasGridFit);171 gs.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);172 173 Gdiplus::Rect rectF(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);174 175 Gdiplus::FontFamily ffamliy;176 gf.GetFamily(&ffamliy);177 178 Gdiplus::SolidBrush br1(Gdiplus::Color(255, GR(textColor), GG(textColor), GB(textColor)));179 180 TextDesigner::OutlineText outtext;181 outtext.EnableShadow(true);182 outtext.TextNoOutline(br1);183 outtext.Shadow(Gdiplus::Color(128, GR(m_nEffectColor), GG(m_nEffectColor), GB(m_nEffectColor)), 2, Gdiplus::Point(1,2));184 outtext.DrawString(&gs, &ffamliy, (Gdiplus::FontStyle) gf.GetStyle(), gf.GetSize(), pszBuf, rectF, strFmt);185 }186 187 void SEffectStatic::DrawShadowText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)188 {189 COLORREF textColor = this->m_style.GetTextColor(0);190 191 Gdiplus::StringFormat *strFmt = toFormat(uFormat);192 Gdiplus::Graphics gs(pRT->GetDC());193 Gdiplus::Font gf(pRT->GetDC(), GetGDIFont(pRT));194 195 gs.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);196 gs.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAliasGridFit);197 gs.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);198 199 Gdiplus::Rect rectF(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);200 201 Gdiplus::FontFamily ffamliy;202 gf.GetFamily(&ffamliy);203 204 Gdiplus::SolidBrush br1(Gdiplus::Color(255, GR(textColor), GG(textColor), GB(textColor)));205 206 TextDesigner::OutlineText outtext;207 outtext.EnableShadow(true);208 outtext.TextNoOutline(br1);209 outtext.Shadow(Gdiplus::Color(128, GR(m_nEffectColor), GG(m_nEffectColor), GB(m_nEffectColor)), 2, Gdiplus::Point(1,2));210 outtext.DrawString(&gs, &ffamliy,(Gdiplus::FontStyle) gf.GetStyle(), gf.GetSize() , pszBuf, rectF, strFmt);211 }212 213 void SEffectStatic::DrawStrokeText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)214 {215 COLORREF textColor = this->m_style.GetTextColor(0);216 Gdiplus::Graphics gs(pRT->GetDC());217 Gdiplus::Font gf(pRT->GetDC(), GetGDIFont(pRT));218 Gdiplus::StringFormat *strFmt = toFormat(uFormat);219 220 gs.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);221 gs.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAliasGridFit);222 gs.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);223 224 Gdiplus::RectF rectF(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);225 226 Gdiplus::SolidBrush br1(Gdiplus::Color(255,GR(textColor), GG(textColor), GB(textColor)));227 Gdiplus::SolidBrush br2(Gdiplus::Color(250,GR(m_nEffectColor), GG(m_nEffectColor), GB(m_nEffectColor)));228 229 int nOffsetX[8] = { 1,1,1,0,-1,-1,-1,0 };230 int nOffsetY[8] = { -1,0,1,1,1,0,-1,-1 };231 232 for (int i = 0; i < 8;i++)233 {234 Gdiplus::RectF lRecf(rectF);235 lRecf.Offset(nOffsetX[i], nOffsetY[i]);236 gs.DrawString(pszBuf, cchText, &gf, lRecf, strFmt, &br2);237 }238 239 gs.DrawString(pszBuf, cchText, &gf, rectF, toFormat(uFormat), &br1);240 }241 242 void SEffectStatic::DrawDoubleStrokeText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)243 {244 COLORREF textColor = this->m_style.GetTextColor(0);245 Gdiplus::StringFormat *strFmt = toFormat(uFormat);246 Gdiplus::Graphics gs(pRT->GetDC());247 Gdiplus::Font gf(pRT->GetDC(), GetGDIFont(pRT));248 249 gs.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);250 gs.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAliasGridFit);251 gs.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);252 253 Gdiplus::Rect rectF(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);254 255 Gdiplus::FontFamily ffamliy;256 gf.GetFamily(&ffamliy);257 258 Gdiplus::SolidBrush br1(Gdiplus::Color(255, GR(textColor), GG(textColor), GB(textColor)));259 260 TextDesigner::OutlineText outtext;261 outtext.EnableShadow(false);262 outtext.TextDblOutline(br1, Gdiplus::Color(255, GR(m_nEffectColor), GG(m_nEffectColor), GB(m_nEffectColor)),263 Gdiplus::Color(255, GR(m_nEffectColor2), GG(m_nEffectColor2), GB(m_nEffectColor2)), 3,3);264 outtext.DrawString(&gs, &ffamliy, (Gdiplus::FontStyle) gf.GetStyle(), gf.GetSize(), pszBuf, rectF, strFmt);265 }266 267 void SEffectStatic::DrawGowText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)268 {269 COLORREF textColor = this->m_style.GetTextColor(0);270 Gdiplus::StringFormat *strFmt = toFormat(uFormat);271 Gdiplus::Graphics gs(pRT->GetDC());272 Gdiplus::Font gf(pRT->GetDC(), GetGDIFont(pRT));273 274 gs.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);275 gs.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAliasGridFit);276 gs.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);277 278 Gdiplus::Rect rectF(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);279 280 Gdiplus::FontFamily ffamliy;281 gf.GetFamily(&ffamliy);282 283 Gdiplus::SolidBrush br1(Gdiplus::Color(255, GR(textColor), GG(textColor), GB(textColor)));284 285 TextDesigner::OutlineText outtext;286 outtext.EnableShadow(false);287 outtext.TextGlow(br1,Gdiplus::Color(64, GR(m_nEffectColor), GG(m_nEffectColor), GB(m_nEffectColor)),6);288 outtext.DrawString(&gs, &ffamliy, (Gdiplus::FontStyle) gf.GetStyle(), gf.GetSize(), pszBuf, rectF, strFmt);289 }290 291 LOGFONT* SEffectStatic::GetGDIFont(IRenderTarget *pRT)292 {293 SOUI::IFontPtr pFont = m_style.GetTextFont(0);294 SOUI::IFontPtr pDFont = (SOUI::IFontPtr)pRT->GetCurrentObject(OT_FONT);295 LOGFONT * logFont = NULL;296 if (pFont == NULL)297 logFont = (LOGFONT*)pDFont->LogFont();298 else299 logFont = (LOGFONT*)pFont->LogFont();300 301 return logFont;302 }303 304 Gdiplus::StringFormat* SEffectStatic::toFormat(UINT uFormat)305 {306 Gdiplus::StringFormat *strFmt = Gdiplus::StringFormat::GenericTypographic()->Clone();307 308 if (uFormat&(DT_VCENTER | DT_BOTTOM))309 {310 strFmt->SetAlignment(Gdiplus::StringAlignmentCenter);311 strFmt->SetLineAlignment(Gdiplus::StringAlignmentCenter);312 }313 else314 {315 strFmt->SetAlignment(Gdiplus::StringAlignmentNear);316 strFmt->SetLineAlignment(Gdiplus::StringAlignmentNear);317 }318 319 return strFmt;320 }以上代码抛砖引玉,希望各位发扬光大,多写一些组件库噢。
新闻热点
疑难解答