首页 > 代码库 > Duilib实现GroupBox控件

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 =http://www.mamicode.com/= _T(#)) pstrValue =http://www.mamicode.com/ ::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控件