1. 程式人生 > 其它 >Duilib 原始碼分析(四)控制元件繪製

Duilib 原始碼分析(四)控制元件繪製

技術標籤: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