Duilib实现GroupBox控件
Posted 车臣
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Duilib实现GroupBox控件相关的知识,希望对你有一定的参考价值。
转载:http://blog.csdn.net/asd313346541/article/details/47055113
原作者的源码上说:右边线和下边线显示不出来:
后来经过调试研究测试猜测应该是没有给控件设置borderround属性,后来设置后出来效果:
最后放上源码(稍微做了修改):
.h文件
1 #ifndef _UIGROUPBOX_H_ 2 #define _UIGROUPBOX_H_ 3 4 #define GROUPBOX_TEXT_OFFSET 40 //定义GroupBox中的Text相对于左边的偏移 5 6 class CGroupBoxUI :public CContainerUI 7 { 8 public: 9 CGroupBoxUI(); 10 11 ~CGroupBoxUI(); 12 13 virtual LPCTSTR GetClass() const; 14 15 virtual LPVOID GetInterface(LPCTSTR pstrName); 16 17 virtual void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue); 18 19 void PaintText(HDC hDC); 20 21 void PaintBorder(HDC hDC); 22 23 void SetTextColor(DWORD dwTextColor); 24 25 void SetFont(int iFont); 26 27 void SetShowhtml(bool bShowHtml); 28 29 private: 30 DWORD m_dwTextColor; ///字休颜色 31 int m_iFont; ///字体号,大小 32 bool m_bShowHtml; ///是否显示HTML代码 33 int m_iTextWidth; ///Text文字宽 34 int m_iTextHeigh; ///Text文字高 35 }; 36 37 #endif//_UIGROUPBOX_H_
.cpp文件
1 #include "stdafx.h" 2 #include "UIGroupBox.h" 3 4 CGroupBoxUI::CGroupBoxUI() :m_iFont(-1), m_bShowHtml(false) 5 { 6 7 } 8 9 10 CGroupBoxUI::~CGroupBoxUI() 11 { 12 } 13 14 /// @return LPCTSTR 返回控件类名 15 /// @note 本函数返回控件类,格式为LPCTSTR 16 LPCTSTR CGroupBoxUI::GetClass() const 17 { 18 return TEXT("GroupBoxUI"); 19 } 20 21 22 /// @return LPVOID类型 23 /// @note 获取接口 24 LPVOID CGroupBoxUI::GetInterface(LPCTSTR pstrName) 25 { 26 if (_tcscmp(pstrName, TEXT("GroupBox")) == 0) 27 { 28 return static_cast<CGroupBoxUI*>(this); 29 } 30 31 return CContainerUI::GetInterface(pstrName); 32 } 33 34 35 /// 设置控件属性 36 /// @param pstrname 欲设置的属性名称,LPCTSTR类型 37 /// @param pstrValue 欲设置的属性值,LPCTSTR类型 38 /// @see CControlUI::SetAttribute() 39 /// @note 重载基类,增加部分基类没有的属性 40 void CGroupBoxUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue) 41 { 42 if (_tcscmp(pstrName, _T("font")) == 0) SetFont(_ttoi(pstrValue)); 43 else if (_tcscmp(pstrName, _T("textcolor")) == 0) 44 { 45 if (*pstrValue == _T(\'#\')) pstrValue = ::CharNext(pstrValue); 46 LPTSTR pstr = NULL; 47 DWORD clrColor = _tcstoul(pstrValue, &pstr, 16); 48 SetTextColor(clrColor); 49 } 50 else if (_tcscmp(pstrName, _T("showhtml")) == 0) 51 SetShowHtml(_tcscmp(pstrValue, _T("true")) == 0); 52 53 else CControlUI::SetAttribute(pstrName, pstrValue); 54 } 55 56 /// 设置控件文字颜色 57 /// @param dwTextColor 欲设置的文字颜色 58 /// @note 设置文字颜色,并立即刷新 59 void CGroupBoxUI::SetTextColor(DWORD dwTextColor) 60 { 61 m_dwTextColor = dwTextColor; 62 Invalidate(); 63 } 64 65 66 /// 设置控件字体 67 /// @param iFont 欲设置的字体号 68 /// @note 设置字体,并立即刷新 69 void CGroupBoxUI::SetFont(int iFont) 70 { 71 m_iFont = iFont; 72 Invalidate(); 73 } 74 75 76 void CGroupBoxUI::SetShowHtml(bool bShowHtml) 77 { 78 if (m_bShowHtml == bShowHtml) return; 79 80 m_bShowHtml = bShowHtml; 81 Invalidate(); 82 } 83 84 85 /// 关键部分 86 void CGroupBoxUI::PaintText(HDC hDC) 87 { 88 //如果没有设置字体颜色,则用默认设置 89 if (m_dwTextColor == 0) 90 { 91 m_dwTextColor = m_pManager->GetDefaultFontColor(); 92 } 93 94 95 RECT rc; //文字输出位置 96 rc = GetPos(); 97 98 rc.left = rc.left + m_cxyBorderRound.cx + GROUPBOX_TEXT_OFFSET; //这个地方采用了硬编码的方式,不知道怎么计算文字应该放的位置 99 100 HFONT hOldFont = (HFONT)::SelectObject(hDC, m_pManager->GetFont(m_iFont)); 101 Gdiplus::Graphics graphics(hDC); 102 Gdiplus::Font font(hDC); 103 graphics.SetTextRenderingHint(Gdiplus::TextRenderingHintSystemDefault); 104 graphics.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality); 105 graphics.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic); 106 Gdiplus::RectF rectF((Gdiplus::REAL)rc.left, (Gdiplus::REAL)rc.top, (Gdiplus::REAL)(rc.right - rc.left), (Gdiplus::REAL)(rc.bottom - rc.top)); 107 Gdiplus::SolidBrush brush(Gdiplus::Color(254, GetBValue(m_dwTextColor), GetGValue(m_dwTextColor), GetRValue(m_dwTextColor))); 108 109 Gdiplus::StringFormat stringFormat = Gdiplus::StringFormat::GenericTypographic(); 110 Gdiplus::RectF bounds; 111 graphics.MeasureString(m_sText, -1, &font, rectF, &stringFormat, &bounds); 112 113 // MeasureString存在计算误差,这里加一像素 114 rc.bottom = rc.top + (long)bounds.Height + 1; //这两句是从UIRender.cpp中DrawText()中拷出来的,不知道意义何在 115 rc.right = rc.left + (long)bounds.Width + 1; 116 117 m_iTextWidth = (int)bounds.Width; 118 m_iTextHeigh = (int)bounds.Height; 119 120 graphics.DrawString(m_sText, -1, &font, rectF, &stringFormat, &brush); 121 122 ::SelectObject(hDC, hOldFont); 123 } 124 125 126 void CGroupBoxUI::PaintBorder(HDC hDC) 127 { 128 RECT rc = GetPos(); //画框框时的位置 129 130 rc.top += (m_iTextHeigh * 1) / 2; //最顶部的线移到Text的中下部 131 132 int nSize = m_nBorderSize; 133 //DWORD dwPenColor = m_dwBorderColor; 134 Gdiplus::Graphics graphics(hDC); 135 136 //消除锯齿 137 graphics.SetSmoothingMode(SmoothingModeHighQuality); 138 //const Gdiplus::Pen pen(Gdiplus::Color::Red, 1.0f); 139 140 DWORD dwPenColor = GetAdjustColor(m_dwBorderColor); 141 ASSERT(::GetObjectType(hDC) == OBJ_DC || ::GetObjectType(hDC) == OBJ_MEMDC); 142 HPEN hPen = ::CreatePen(PS_SOLID | PS_INSIDEFRAME, nSize, RGB(GetBValue(dwPenColor), GetGValue(dwPenColor), GetRValue(dwPenColor))); 143 HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen); 144 ::SelectObject(hDC, ::GetStockObject(HOLLOW_BRUSH)); 145 146 //定位四个圆角的位置 147 RECT rcTopLeftCorner = { rc.left, rc.top, rc.left + 2 * m_cxyBorderRound.cx, rc.top + 2 * m_cxyBorderRound.cy }; 148 RECT rcTopRightCorner = { rc.right - 2 * m_cxyBorderRound.cx, rc.top, rc.right, rc.top + 2 * m_cxyBorderRound.cy }; 149 RECT rcBottomLeftCorner = { rc.left, rc.bottom - 2 * m_cxyBorderRound.cy, rc.left + 2 * m_cxyBorderRound.cx, rc.bottom }; 150 RECT rcBottomRightCorner = { rc.right - 2 * m_cxyBorderRound.cx, rc.bottom - 2 * m_cxyBorderRound.cy, rc.right, rc.bottom }; 151 152 //画四个圆角 153 const Gdiplus::Pen pen(Gdiplus::Color(GetBValue(dwPenColor), GetGValue(dwPenColor), GetRValue(dwPenColor)), (float)m_nBorderSize); 154 graphics.DrawArc(&pen, rcTopLeftCorner.left, rcTopLeftCorner.top, rcTopLeftCorner.right - rcTopLeftCorner.left, rcTopLeftCorner.bottom - rcTopLeftCorner.top, 180.0f, 90.0f);//左上角 155 graphics.DrawArc(&pen, rcTopRightCorner.left, rcTopRightCorner.top, rcTopRightCorner.right - rcTopRightCorner.left, rcTopRightCorner.bottom - rcTopRightCorner.top, 270.0f,90.0f);//右上角 156 graphics.DrawArc(&pen, rcBottomLeftCorner.left, rcBottomLeftCorner.top, rcBottomLeftCorner.right - rcBottomLeftCorner.left, rcBottomLeftCorner.bottom - rcBottomLeftCorner.top, 90.0f, 90.0f);//左下角 157 graphics.DrawArc(&pen, rcBottomRightCorner.left, rcBottomRightCorner.top, rcBottomRightCorner.right - rcBottomRightCorner.left-1, rcBottomRightCorner.bottom - rcBottomRightCorner.top-1, 0.0f, 90.0f);//右下角 158 159 160 //画线----GDI 161 MoveToEx(hDC, rc.left, rc.top + m_cxyBorderRound.cy, NULL); //左边线 162 LineTo(hDC, rc.left, rc.bottom - m_cxyBorderRound.cy); 163 164 MoveToEx(hDC, rc.left + m_cxyBorderRound.cx, rc.top, NULL); //上第一条线 165 LineTo(hDC, rc.left + m_cxyBorderRound.cx + GROUPBOX_TEXT_OFFSET - 5, rc.top); //-5 是为了给Text增加左边间距 166 167 MoveToEx(hDC, rc.left + m_cxyBorderRound.cx + GROUPBOX_TEXT_OFFSET + m_iTextWidth + 5, rc.top, NULL); //上第二条线,+5是为了给Text增加右边间距 168 LineTo(hDC, rc.right - m_cxyBorderRound.cx, rc.top); 169 170 MoveToEx(hDC, rc.right, rc.top + m_cxyBorderRound.cy, NULL); //右边线 171 LineTo(hDC, rc.right, rc.bottom - m_cxyBorderRound.cy); 172 173 MoveToEx(hDC, rc.left + m_cxyBorderRound.cx, rc.bottom, NULL); //下边线 174 LineTo(hDC, rc.right - m_cxyBorderRound.cx, rc.bottom); 175 176 177 ::SelectObject(hDC, hOldPen); 178 ::DeleteObject(hPen); 179 }
xml布局:
1 <GroupBox text="测试" textcolor="#FF989898" float="true" pos="125,55,0,0" width="256" height="80" bordercolor="#FF989898" bordersize="1" borderround="4,4" font="1"/>
在窗口中自定义控件:
1 CControlUI* CFrameWnd::CreateControl(LPCTSTR pstrClass) 2 { 3 if (_tcscmp(pstrClass,_T("GroupBox")) == 0) 4 { 5 return new CGroupBoxUI; 6 } 7 return NULL; 8 }
源码demo:GroupBox控件
以上是关于Duilib实现GroupBox控件的主要内容,如果未能解决你的问题,请参考以下文章