本帖基于的 Duilib 版本为 “Duilib 开源项目圈2群” 中下载的版本,和大家使用的可能有些出入。我曾使用过的一个版本的 Duilib 中的 CLabelUI
实现的内容较少,本帖中的 CLabelUI
功能都相当于我曾经使用的 CTextUI
了,但这个区别没有关系,大家只需要了解各个功能是如何实现的就可以了,具体使用的时候参考自己使用的 Duilib 版本,稍看下源码,就知道自己使用的控件具体支持哪些属性了
我的习惯是,接触一个新的控件时,首先去查看 SetAttribute
方法,因为在这个方法中明确写出的属性往往都是相对于父类多出来的属性,然后搜索一下各个属性使用的地方,就大概明白各个功能如何使用了。
闲话到此结束,现在开始介绍 CLabelUI
,直接看成员变量:
- DWORD m_dwTextColor 文字的颜色,最终会传入到 GDI+ 中的
Gdiplus::SolidBrush
对象中,或者 GDI 中的SetTextColor(_In_ HDC hdc, _In_ COLORREF color)
函数中。 可以通过textcolor
属性控制 - DWORD m_dwDisabledTextColor 当控件
enable=false
时的文字颜色 - int m_iFont 字体,关于字体的内容可以参考:Duilib 源码分析之字体篇
- UINT m_uTextStyle 绘制文字时的样式,请考考 Duilib 源码分析之 文字样式(m_uTextStyle) 篇
- RECT m_rcTextPadding 实际绘制文字的矩形和传入的矩形的外间距
- bool m_bShowHtml true 的情况下会根据传入的 html 文本来进行解析后绘制。但是这里的 html 文本格式和平时使用的并不一致,详细可参考
DrawHtmlText
方法中的注释部分 - bool m_bAutoCalcWidth 是否自动计算宽度,true 的情况下计算控件宽度时会根据当前文字的宽度进行设置
CLableUI
的用法比较简单,这里大家先关注一下以下内容就可以了:
m_uTextStyle
默认属性为 DT_VCENTER | DT_SINGLELINE, 垂直居中和单行显示的。若有多行显示的需求或者需改变对齐方式,可以通过对应的属性来修改void DoEvent(TEventUI& event)
这个控件只负责显示文字,所以在DoEvent
中只对焦点进行了处理。不过焦点问题在基类CControlUI
中也有处理,所以我认为直接使用基类的方法即可void PaintText(HDC hDC)
核心成员方法。稍作解释:
- 未设置文字颜色时使用默认的文字颜色
- 设置了
m_rcTextPadding
的情况下,需要把当前控件的矩形区域减掉四周的边距后,剩下的矩形区域作为文字绘制区域 - Enable 的情况下使用正常的文字颜色,否则使用禁用状态下的文字颜色
m_bShowHtml
为 true 的情况下进行 html 的解析后绘制文字
void SetText(LPCTSTR pstrText)
CControlUI::SetText(pstrText); if(GetAutoCalcWidth()) { NeedParentUpdate(); }
注意这个方法内的
NeedParentUpdate()
, 有些版本的 Duilib 中这段代码没有这行代码,这样的话只有在第一次计算控件位置时才会动态的根据当前文字计算宽度,之后若再修改文字,m_rcItem
不会更改。 调用了NeedParentUpdate
后,会更新父控件,重新计算父控件的所有子控件的位置。
以上内容仅是我使用的 Duilib 版本中 CLabelUI
的所有内容。另外有些版本,像 https://github.com/duilib/duilib 中的 CLabelUI
支持更多的功能,这些更多的功能是使用 GDI+ 来实现的。支持颜色渐变、阴影、重影、发光效果 (我自己起的效果名字,权当代号~~)。 不过发光效果我通过代码测试未发现效果,而且发光效果的代码也没有理解,因为我也没有使用过 GDI+ 绘制过复杂的效果。
阴影效果
其实相当于绘制两次文字,但对于底层的所谓”阴影”文字可以设置m_ShadowOffset
实现一些阴影文字的错位,这样的话就可以实现阴影效果。上图1中,我设置了阴影颜色为红色,且设置了m_GradientAngle=50
改变了颜色渐变方向为右上到坐下,默认情况是垂直的,垂直的情况下若前景文字颜色不透明则不会看到阴影。颜色渐变
上图 2 我设置了绿色到蓝色渐变,且渐变方向仍用m_GradientAngle
控制重影效果
如上图 3 ,除了阴影效果,前景文字效果,多了重影效果。LinearGradientBrush nLineGrBrushStroke(Point(GetGradientAngle(),0),Point(0,rc.bottom-rc.top+2),ARGB2Color(GetStrokeColor()),ARGB2Color(GetStrokeColor())); nRc.Offset(-1,0); nGraphics.DrawString(m_sText,m_sText.GetLength(),&nFont,nRc,&format,&nLineGrBrushStroke); nRc.Offset(2,0); nGraphics.DrawString(m_sText,m_sText.GetLength(),&nFont,nRc,&format,&nLineGrBrushStroke); nRc.Offset(-1,-1); nGraphics.DrawString(m_sText,m_sText.GetLength(),&nFont,nRc,&format,&nLineGrBrushStroke); nRc.Offset(0,2); nGraphics.DrawString(m_sText,m_sText.GetLength(),&nFont,nRc,&format,&nLineGrBrushStroke); nRc.Offset(0,-1);
这段代码比较好理解,实际上就是在原始绘制文字的矩形的上下左右各差1像素的地方共绘制 4 次后,再绘制阴影和前景文字。这样背景就显得非常”厚重”
发光效果
源码中发光效果的代码因为本人还未理解,无法给出解释了,若以后有新的认识会更新此贴。 若有哪位大侠知道原理的,希望留言予以解答,不胜感激。
源码中贴出了做法的参考原贴:http://bbs.csdn.net/topics/390346428。