Duilib 源码分析(四)控件绘制
渲染引擎CRenderEngine:封装GDI
//duilib-master\DuiLib\Core\UIRender.h
class DUILIB_API CRenderEngine
{
DrawLine //绘制直线
DrawRect //绘制直角边框
DrawRoundRect //绘制圆角边框
DrawImage //绘制图片
DrawColor //绘制纯色
DrawGradient //绘制渐变色
DrawText //绘制普通文本
DrawHtmlText //绘制HTML文本
}
//duilib-master\DuiLib\Core\UIRender.cpp
void CRenderEngine::DrawLine( HDC hDC, const RECT& rc, int nSize, DWORD dwPenColor, int nStyle)
{
ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
// 使用操作系统提供的GDI接口进行绘制
LOGPEN lg;
lg.lopnColor = RGB(GetBValue(dwPenColor), GetGValue(dwPenColor), GetRValue(dwPenColor));
lg.lopnStyle = nStyle;
lg.lopnWidth.x = nSize;
HPEN hPen = CreatePenIndirect(&lg);
HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
POINT ptTemp = { 0 };
::MoveToEx(hDC, rc.left, rc.top, &ptTemp);
::LineTo(hDC, rc.right, rc.bottom);
::SelectObject(hDC, hOldPen);
::DeleteObject(hPen);
}
绘制刷新流程
// 设置控件无效
void CControlUI::Invalidate()
{
m_pManager->Invalidate(invalidateRc);
}
//设置一个无效区域,并且发送WM_PAINT消息
void CPaintManagerUI::Invalidate(RECT& rcItem)
{
::InvalidateRect(m_hWndPaint, &rcItem, FALSE);
}
//处理WM_PAINT消息
bool CPaintManagerUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes)
{
case WM_PAINT:
int iSaveDC = ::SaveDC(m_hDcPaint);
m_pRoot->Paint(m_hDcPaint, rcPaint, NULL);
::RestoreDC(m_hDcPaint, iSaveDC);
}
//进行绘制
bool CControlUI::Paint(HDC hDC, const RECT& rcPaint, CControlUI* pStopControl)
{
OnPaint(this)
DoPaint(hDC, rcPaint, pStopControl)
}
//真正进行绘制
bool CControlUI::DoPaint(HDC hDC, const RECT& rcPaint, CControlUI* pStopControl)
{
// 绘制循序:背景颜色->背景图->状态图->文本->边框
PaintBkColor(hDC);
PaintBkImage(hDC);
PaintStatusImage(hDC);
PaintText(hDC);
PaintBorder(hDC);
}
//背景颜色
void CControlUI::PaintBkColor(HDC hDC)
{
// 渐变色
CRenderEngine::DrawGradient
// 纯色
CRenderEngine::DrawColor
}
//背景图
void CControlUI::PaintBkImage(HDC hDC)
{
CRenderEngine::DrawImage
}
//状态图
void CControlUI::PaintStatusImage(HDC hDC)
{
CRenderEngine::DrawImage
}
//文本
void CControlUI::PaintText(HDC hDC)
{
CRenderEngine::DrawText
}
//边框
void CControlUI::PaintBorder(HDC hDC)
{
//画圆角边框(边框圆角属性大于0)
if( m_cxyBorderRound.cx > 0 || m_cxyBorderRound.cy > 0 )
CRenderEngine::DrawRoundRect
//画直角边框(四条边框的宽度一样)
if (m_rcBorderSize.right == m_rcBorderSize.left && m_rcBorderSize.top == m_rcBorderSize.left && m_rcBorderSize.bottom == m_rcBorderSize.left)
CRenderEngine::DrawRect
//画四条直线(四条边框的宽度不同)
if(m_rcBorderSize.left > 0) CRenderEngine::DrawLine
if(m_rcBorderSize.top > 0) CRenderEngine::DrawLine
if(m_rcBorderSize.right > 0) CRenderEngine::DrawLine
if(m_rcBorderSize.bottom > 0)CRenderEngine::DrawLine
}
控件基类UIControl
//duilib-master\DuiLib\Core\UIControl.h
class DUILIB_API CControlUI
{
//初始化
virtual void Init();
virtual void DoInit();
//事件
virtual void Event(TEventUI& event);
virtual void DoEvent(TEventUI& event);
//绘制
virtual bool Paint(HDC hDC, const RECT& rcPaint, CControlUI* pStopControl=NULL);
virtual bool DoPaint(HDC hDC, const RECT& rcPaint, CControlUI* pStopControl);
//名字
virtual CDuiString GetName() const;
virtual void SetName(LPCTSTR pstrName);
//文本
virtual CDuiString GetText() const;
virtual void SetText(LPCTSTR pstrText);
//图像
DWORD GetBkColor() const;
void SetBkColor(DWORD dwBackColor);
LPCTSTR GetBkImage();
void SetBkImage(LPCTSTR pStrImage);
bool IsColorHSL() const;
void SetColorHSL(bool bColorHSL);
SIZE GetBorderRound() const;
void SetBorderRound(SIZE cxyRound);
//边框
DWORD GetBorderColor() const;
void SetBorderColor(DWORD dwBorderColor);
RECT GetBorderSize() const;
void SetBorderSize(RECT rc);
int GetBorderStyle() const;
void SetBorderStyle(int nStyle);
//位置
virtual const RECT& GetPos() const;
virtual void SetPos(RECT rc, bool bNeedInvalidate = true);
//提示
virtual CDuiString GetToolTip() const;
virtual void SetToolTip(LPCTSTR pstrText);
//快捷键
virtual TCHAR GetShortcut() const;
virtual void SetShortcut(TCHAR ch);
//菜单
virtual bool IsContextMenuUsed() const;
virtual void SetContextMenuUsed(bool bMenuUsed);
}
标签控件CLabelUI
// 继承CControlUI
// duilib-master\DuiLib\Control\UILabel.h
class DUILIB_API CLabelUI : public CControlUI
{
//设置属性
void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);
//文本属性
void SetTextStyle(UINT uStyle);
UINT GetTextStyle() const;
bool IsMultiLine();
void SetMultiLine(bool bMultiLine = true);
void SetTextColor(DWORD dwTextColor);
DWORD GetTextColor() const;
void SetFont(int index);
int GetFont() const;
//文本绘制
void PaintText(HDC hDC);
}
按钮控件CButtonUI
// 继承CLabelUI
// duilib-master\DuiLib\Control\UIButton.h
class DUILIB_API CButtonUI : public CLabelUI
{
//按钮激活
bool Activate();
//事件处理
void DoEvent(TEventUI& event);
//状态图片
LPCTSTR GetXXXImage();
void SetXXXImage(LPCTSTR pStrImage);
//绘制文本
void PaintText(HDC hDC);
//绘制状态图片
void PaintStatusImage(HDC hDC);
}
小结
控件绘制,最底层还是操作系统提供的GDI接口。渲染引擎CRenderEngine对GDI进一步的封装,方便调用。而控件则根据自身的类型使用CRenderEngine进行绘制。
Duilib技术交流群:799142530
源码地址:https://github.com/KongKong20/DuilibTutor