Duilib中已经包含了一些基础的控件,但是很多情况下,duilib自带的基础控件不能满足开发需求,这就需要我们自己在duilib中新增自定义的控件并可以在xml中识别以及自定义控件属性。

比如duilib中没有类似于显示折线图的UI控件,这个时候我们就需要自定义一个显示折线图的UI控件,本文将以这个控件为例简单阐述如何在duilib中新增一个自定义控件。

1 Duilib中新增自定义控件

1.1 新增自定义控件类CLineChartUI

新增自定义控件类CLineChartUI,选择一个duilib中的控件基类进行继承,这里选择CControlUI,然后自定义控件类CLineChartUI必须重写的方法如下:

  • LPCTSTR GetClass() const
  • LPVOID GetInterface(LPCTSTR pstrName)
  • void DoEvent(TEventUI& event)
  • void DoPaint(HDC hDC, const RECT& rcPaint)
  • void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)

其中,

  • LPCTSTR GetClass() const 用于返回自定义控件的name属性值

  • LPVOID GetInterface(LPCTSTR pstrName) 用于返回控件指针

  • void DoEvent(TEventUI& event) :控件的核心函数,用于重写控件消息响应,用来处理Duilib封装过的各个消息,比如鼠标的移入移出、出现的悬停、单击双击、右击、滚轮滑动、获取焦点、设置光标等等。所以如果你的控件需要修改这些行为,必须重写这个函数

  • void DoPaint(HDC hDC, const RECT& rcPaint) :控件的核心函数,控件的绘制处理函数,当Duilib底层要重新绘制这个控件,或者控件自己调用Invalidata函数强制自己刷新时,这个函数就会被触发,在这个函数里完成了各种状态下的背景前景绘制,背景色绘制,文本绘制,边框绘制。而这个函数会调用PaintBkColor、PaintBkImage、PaintStatusImage、PaintText、PaintBorder等函数来完成各个绘制步骤。所以你可以根据需求来决定重写DoPaint或者只重写某几个PaintXXX函数。DoPaint函数经常和DoEvent函数结合使用,DoEvent得到了某个消息后,改变控件的状态,然后调用Invalidate函数让控件重绘。

  • void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue) :用于扩展自定义控件的属性,Duilib的控件本身已经包含name、text、bkimage等属性,如果要增加新属性,就需要重写此函数来扩展属性,如何解析属性可以参考CLabelUI或CControlUI类中的SetAttribute函数

另外一些经常需要重写的函数如下

 virtual void DoEvent(TEventUI& event);
 virtual void DoPaint(HDC hDC, const RECT& rcPaint);
 virtual void PaintBkColor(HDC hDC);
 virtual void PaintBkImage(HDC hDC);
 virtual void PaintStatusImage(HDC hDC);
 virtual void PaintText(HDC hDC);
 virtual void PaintBorder(HDC hDC);
 virtual void DoInit();
 virtual void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);
 virtual bool IsVisible() const;
 virtual void SetVisible(bool bVisible = true);
 virtual void SetInternVisible(bool bVisible = true); // 仅供内部调用,有些UI拥有窗口句柄,需要重写此函数
 virtual void SetPos(RECT rc);

IsVisibleSetVisibleSetInternelVisibleSetPos主要用于控件的显示、隐藏和位置。

根据上面的说明,我们可以按需实现我们自定义控件的一些函数,完成代码的编写。

1.2 在UIDefine.h中增加自定义控件类名宏定义

在Duilib源码的的UIDefine.h增加折线图控件的定义,新增以下行

#define  DUI_CTR_LINE_CHART                     (_T("LineChart"))

1.3 在UIlib.h包含头文件

UIlib.h中包含自定义控件的头文件

#include "Control/UILineChart.h"

1.4 在UIDlgBuilder.cpp_Parse函数增加创建自定义控件功能

UIDlgBuilder.cpp_Parse函数中增加创建CLineChartUI的代码,因为我们在上一步定义的DUI_CTR_LINE_CHART的名称为LineChartLineChart一共9个字符,所以增加以下代码

case 9:
    else if (_tcscmp(pstrClass, DUI_CTR_LINE_CHART) == 0)             pControl = new CLineChartUI;
    break;

1.5 在xml中使用

上述步骤说明了如何在duilib中新增一个自定义控件,之后我们就可以在xml中使用该控件

<LineChart name="my_line_chart" />

参考