Duilib 源码分析之 PaintBorder 篇

Duilib 中的控件在调用 DoPaint 进行绘制当前控件的最后一步是绘制边框,其中边框的绘制又分为圆角矩形边框和直角矩形边框,边框的样式也可以自定义。
首先, 绘制边框的三个方法:

  • void CRenderEngine::DrawRoundRect(HDC hDC, const RECT& rc, int width, int height, int nSize, DWORD dwPenColor, int nStyle = PS_SOLID)
    如果给控件的属性设置了 borderround 且部不为0, 则会调用 DrawRoundRect, 源码如下:

    ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
        HPEN hPen = ::CreatePen(nStyle, nSize, RGB(GetBValue(dwPenColor), GetGValue(dwPenColor), GetRValue(dwPenColor)));
        HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
        ::SelectObject(hDC, ::GetStockObject(HOLLOW_BRUSH));
        ::RoundRect(hDC, rc.left, rc.top, rc.right, rc.bottom, width, height);
        ::SelectObject(hDC, hOldPen);
        ::DeleteObject(hPen);
    1. 根据传入的样式和颜色创建 Pen, 可以通过 bordercolor bordersize borderstyle 设置边框的颜色、宽度和样式,常用的样式如下, borderstyle 的值直接设置为以下几个值即可,默认为 0。 有一点需要注意,若画笔的样式中有 PS_INSIDEFRAME,则相当于绘制内边框,否则是外边框
      • #define PS_SOLID 0
      • #define PS_DASH 1 /* ——- */
      • #define PS_DOT 2 /* ……. */
      • #define PS_DASHDOT 3 /* ... */
      • #define PS_DASHDOTDOT 4 /* ...._ */
    2. 创建填充画刷为透明色,这样的话就只绘制边框本身,中间没有填充色
    3. 然后调用 RoundRect 绘制的圆角矩形
  • void DrawRect(HDC hDC, const RECT& rc, int nSize, DWORD dwPenColor, int nStyle = PS_SOLID)
    具体实现和 DrawRoundRect 类似,只是调用了 Rectangle 而不是 RoundRect
  • void DrawLine(HDC hDC, const RECT& rc, int nSize, DWORD dwPenColor, int nStyle = PS_SOLID)
    当设置的 bordersize 上下左右宽度不一致时,则会分别绘制 4 条边,看以下两端代码

    if(m_rcBorderSize.left > 0){
                    rcBorder        = m_rcItem;
                    rcBorder.right  = m_rcItem.left;
                    CRenderEngine::DrawLine(hDC,rcBorder,m_rcBorderSize.left,GetAdjustColor(m_dwBorderColor),m_nBorderStyle);
                }

    rcBorder 代表绘制的位置,目前取的是控件的 (left,top) 到 (left,bottom) 的一条线段,这样的话就是以此线段为中心绘制,也有的代码可能会绘制内边框,这样的话这条线段就得向控件的 right 方向移动 rcBorder.left / 2 个像素位置,以此位置进行绘制

    void CRenderEngine::DrawLine( HDC hDC, const RECT& rc, int nSize, DWORD dwPenColor,int nStyle /*= PS_SOLID*/ )
    {
    ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
    
    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);
    }

    上述代码即是根据传入的位置 rc 进行绘制以 nSize 为宽度、以 nStyle 为样式的边框

另外,若设置了边框选中时的颜色属性 focusbordercolor , 在控件被选中的情况下,也就是 IsFocused() == true 的情况下,则会以 focusbordercolor 的色值进行绘制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值