Duilib 源码分析之字体篇

在 Duilib 中,我们可以定义多种字体,不同的控件使用不同的字体来丰富我们的界面,今天我们来介绍一下 Duilib 是如何使用字体的。

首先,Duilib 中定义字体的方法如下:

<Font id="0" name="Microsoft YaHei" size="12" bold="false" italic="false" default="true"/>
<Font id="1" name="Microsoft YaHei" size="14" bold="false" italic="false"/>
<Font id="2" name="Microsoft YaHei" size="16" bold="false" italic="false"/>
<Font id="3" name="Microsoft YaHei" size="18" bold="false" italic="false"/>

在之前的 xml 解析篇中,我们已经知道, xml 解析是按节点进行解析的。 <Font> 类型的节点也有对应的 CMarkupNode 对象被保存起来,解析完成后,根据 CMarkupNode 创建控件等内容时,当遇到 <Font> 节点,则解析出对应的属性,将创建的字体保存在 CPaintManagerUI 中。

接下来看一下字体保存的数据结构是什么样的,字体信息被保存在一个 Map 中,类型为 : CDuiStringPtrMap。 Key 是字体的 id, Value 是 TFontInfo* 类型的字体信息,当需要取得某控件的字体属性时,则调用 TFontInfo* CPaintManagerUI::GetFontInfo(int id) 获取到对应的字体信息来绘制文字。 那么 TFontInfo* 类型对象又是如何创建的呢?接下来我们来看一下 CPaintManagerUI::AddFont 中的关键代码:

LOGFONT lf = { 0 };
::GetObject(::GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf);
_tcsncpy(lf.lfFaceName, pStrFontName, LF_FACESIZE);
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfHeight = -nSize;
if( bBold ) lf.lfWeight += FW_BOLD;
if( bUnderline ) lf.lfUnderline = TRUE;
if( bItalic ) lf.lfItalic = TRUE;
HFONT hFont = ::CreateFontIndirect(&lf);
if( hFont == NULL ) return NULL;

TFontInfo* pFontInfo = new TFontInfo;
if( !pFontInfo ) return false;
::ZeroMemory(pFontInfo, sizeof(TFontInfo));
pFontInfo->hFont = hFont;
pFontInfo->sFontName = pStrFontName;
pFontInfo->iSize = nSize;
pFontInfo->bBold = bBold;
pFontInfo->bUnderline = bUnderline;
pFontInfo->bItalic = bItalic;
if( m_hDcPaint ) {
    HFONT hOldFont = (HFONT) ::SelectObject(m_hDcPaint, hFont);
    ::GetTextMetrics(m_hDcPaint, &pFontInfo->tm);
    ::SelectObject(m_hDcPaint, hOldFont);
}

在Windows内部,字体是以一个名为 LOGFONT 的结构来表示(参见:LOGFONT)。第二行中的代码获取了界面默认的 LOGFONT 信息,然后根据函数的传入参数改变对应的属性值,得到新的 LOGFONT 信息后,调用 CreateFontIndirect 获取到 HFONT,这个就是我们绘制文字时需要用到的字体句柄。 下一段代码就是创建 TFontInfo 类型对象,代码很简单,这里只说一下 ::GetTextMetrics(m_hDcPaint, &pFontInfo->tm) 这行代码,根据指定的 HFONT,获取对应的 TEXTMETRIC 信息。

这个 TEXTMETRIC 其实是非常有意思的(参见:TEXTMETRIC),如图所示(图片来自百度百科)
TextMetric

这里着重说明几点,具体请参考上面的 LOGFONT 链接:

  • tmHeight : 代表字符的高度,不包括行间距 (Duilib 代码中多次用到了这个属性)
  • tmInternalLeading :一般用来表示重音符号等
  • tmExternalLeading : 图片中没有描绘出来,位于 tmInternalLeading 之上,代表外间距,就是行间距
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
duilib是一个开的C++图形界面库,它提供了丰富的控件和布局管理功能,以及良好的跨平台支持。下面我将对duilib码进行简要分析。 1. 基础架构:duilib码采用了模块化的设计,主要分为“Core”和“UI”两个部分。其中,“Core”模块是duilib的核心部分,提供了基础的窗口、消息循环等功能;而“UI”模块则提供了各种控件和布局管理等高级功能。 2. 控件类别:duilib提供了丰富的控件类别,包括基础的窗口类(如窗口、对话框)、容器类(如水平布局、垂直布局)、常用控件类(如按钮、文本框)、自定义控件类等。每个控件类都有相应的成员函数和消息处理函数,以便实现对控件的创建、设置属性和处理事件等操作。 3. 消息处理机制:duilib使用了消息映射的机制来处理控件的事件。每个控件类都有自己的消息映射表,用于将消息和相应的处理函数关联起来。当控件接收到特定的消息时,duilib会根据映射表找到对应的处理函数进行处理。 4. 布局管理:duilib提供了灵活且强大的布局管理功能,可以通过设置布局属性实现控件的自动适应和自动排列。布局管理器可以根据指定的规则对子控件进行自动布局,以适应不同的窗口尺寸。 5. 绘制引擎:duilib使用了自定义的绘制引擎来实现界面绘制。该绘制引擎可以根据控件的属性和状态来决定绘制的方式,以实现不同的视觉效果。 总结来说,duilib分析涉及到基础架构、控件类别、消息处理机制、布局管理和绘制引擎等方面。通过深入研究这些内容,我们可以更好地理解duilib的设计理念和工作原理,以便能够更好地使用和定制duilib提供的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值