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);
- 根据传入的样式和颜色创建 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 /* ...._ */
- 创建填充画刷为透明色,这样的话就只绘制边框本身,中间没有填充色
- 然后调用 RoundRect 绘制的圆角矩形
- 根据传入的样式和颜色创建 Pen, 可以通过
- 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
的色值进行绘制