1 Duilib的绘制机制

Duilib中一个重要部分就是其绘制窗口以及控件的机制,如果我们需要在Duilib中自定义一个控件,那么弄清楚Duilib的绘制机制就非常重要,Duilib中有太多与绘制相关的函数,比如Paint、DoPaint、PaintBkcolor、PaintStatusImage、PaintText、PaintBorder、DoPostPaint等等,那么这些绘制函数的调用顺序是什么样的呢?

1.1 Duilib中总体绘制流程

基于Duilib的源码,大致梳理一下Duilib的总体绘制流程,

1. 首先在UIManager.cpp文件中的CPaintManagerUI类的MessageHandler函数中对WM_PAINT消息的处理代码,其中

m_pRoot->Paint(m_hDcOffscreen, rcPaint, NULL);

开始对控件进行绘制。

2. 然后在CControlUIPaint函数中调用DoPaint对控件进行绘制,对于每一个控件

PaintBkColor(hDC);
PaintBkImage(hDC);
PaintStatusImage(hDC);
PaintForeColor(hDC);
PaintForeImage(hDC);
PaintText(hDC);
PaintBorder(hDC);

根据上述的源码,每一个控件的绘制顺序为首先绘制背景颜色->绘制背景图片->绘制状态图片->绘制前景颜色->绘制文本->绘制边框。

3. 再回到UIManager.cpp文件中的CPaintManagerUI类的MessageHandler函数中对WM_PAINT消息的处理代码,在

m_pRoot->Paint(m_hDcOffscreen, rcPaint, NULL);

之后我们可以找到以下代码

for( int i = 0; i < m_aPostPaintControls.GetSize(); i++ ) {
    CControlUI* pPostPaintControl = static_cast<CControlUI*>(m_aPostPaintControls[i]);
    pPostPaintControl->DoPostPaint(m_hDcOffscreen, rcPaint);
}

在完成控件绘制之后,并且完成本地窗口的绘制完成之后会调用上述代码。这段代码的意思是遍历所有需要PostPaint的控件,然后按顺序调用各自的DoPostPain函数,这样绘制的东西就会显示所有已绘制控件的上层。

参考链接