Duilib 源码分析(四)控件绘制

渲染引擎CRenderEngine:封装GDI

//duilib-masterDuiLibCoreUIRender.h
class DUILIB_API CRenderEngine
{
    DrawLine      //绘制直线
    DrawRect      //绘制直角边框
    DrawRoundRect //绘制圆角边框
    DrawImage     //绘制图片
    DrawColor     //绘制纯色
    DrawGradient  //绘制渐变色
    DrawText      //绘制普通文本
    DrawHtmlText  //绘制HTML文本
}

//duilib-masterDuiLibCoreUIRender.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-masterDuiLibCoreUIControl.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-masterDuiLibControlUILabel.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-masterDuiLibControlUIButton.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

原文地址:https://www.cnblogs.com/wwgk/p/14344698.html