duilib学习之一 增加GroupBox

<span style="font-family: 'microsoft yahei'; font-size: 1.7em; line-height: 1.1; white-space: pre-wrap; background-color: rgb(255, 255, 255);">Duilib扩展之增加GropBox控件</span>

才刚开始学习使用duilib,然后发现没有GroupBox,百度了N页也没发现duilib关于这个控件的,难道就没人用这个吗……没办法了,自己动手,丰衣足食。其实GroupBox也不难,它就是一个容器,然后在左上边线显示一个Caption即可。所以只需要继承CContainerUI,然后重新定位Text位置,将上边框线“打断”为两部分就行了,即重写PaintText和PaintBorder。由于这个控件只是自己用,再加上一个新手,不熟悉duilib的具体机制,所以比较粗糙,只实现了自己需要的功能

下面上代码,关键部分都写到注释上去了...

GroupBox.h

#pragma once

#include <UIlib.h>					//如果扩展组件放在DUILIB目录,则包含 stdafx.h

#define  GROUPBOX_TEXT_OFFSET		20		//定义GroupBox中的Text相对于左边的偏移


using namespace DuiLib;
class CGroupBoxUI :
	public CContainerUI
{
public:
	CGroupBoxUI();
	~CGroupBoxUI();
	virtual LPCTSTR GetClass() const;
	virtual LPVOID GetInterface(LPCTSTR pstrName);
	virtual void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);
	void PaintText(HDC hDC);
	void PaintBorder(HDC hDC);
	void SetTextColor(DWORD dwTextColor);
	void SetFont(int iFont);
	void SetShowHtml(bool bShowHtml);

private:
	DWORD	m_dwTextColor;		///字休颜色
	int		m_iFont;			///字体号,大小
	bool	m_bShowHtml;		///是否显示HTML代码
	int		m_iTextWidth;		///Text文字宽
	int		m_iTextHeigh;		///Text文字高
};


GroupBox.cpp

#include "GroupBoxUI.h"
//#include <UIlib.h>

CGroupBoxUI::CGroupBoxUI() :m_iFont(-1), m_bShowHtml(false)
{

}


CGroupBoxUI::~CGroupBoxUI()
{
}

///	@return LPCTSTR 返回控件类名
///	@note	本函数返回控件类,格式为LPCTSTR
LPCTSTR CGroupBoxUI::GetClass() const
{
	return TEXT("GroupBoxUI");
}


/// @return LPVOID类型
///	@note 获取接口
LPVOID CGroupBoxUI::GetInterface(LPCTSTR pstrName)
{
	if (_tcscmp(pstrName, TEXT("GroupBox")) == 0)
	{
		return static_cast<CGroupBoxUI*>(this);
	}
	
	return CContainerUI::GetInterface(pstrName);
}


///	设置控件属性
/// @param pstrname		欲设置的属性名称,LPCTSTR类型
/// @param pstrValue	欲设置的属性值,LPCTSTR类型
/// @see				CControlUI::SetAttribute()
/// @note				重载基类,增加部分基类没有的属性
void CGroupBoxUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
{
	if (_tcscmp(pstrName, _T("font")) == 0) SetFont(_ttoi(pstrValue));
	else if (_tcscmp(pstrName, _T("textcolor")) == 0) 
	{
		if (*pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
		LPTSTR pstr = NULL;
		DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
		SetTextColor(clrColor);
	}
	else if (_tcscmp(pstrName, _T("showhtml")) == 0) 
		SetShowHtml(_tcscmp(pstrValue, _T("true")) == 0);

	else CControlUI::SetAttribute(pstrName, pstrValue);
}

/// 设置控件文字颜色
/// @param	dwTextColor		欲设置的文字颜色
/// @note	设置文字颜色,并立即刷新
void CGroupBoxUI::SetTextColor(DWORD dwTextColor)
{
	m_dwTextColor = dwTextColor;
	Invalidate();
}


/// 设置控件字体
/// @param	iFont		欲设置的字体号
/// @note	设置字体,并立即刷新
void CGroupBoxUI::SetFont(int iFont)
{
	m_iFont = iFont;
	Invalidate();
}


void CGroupBoxUI::SetShowHtml(bool bShowHtml)
{
	if (m_bShowHtml == bShowHtml) return;

	m_bShowHtml = bShowHtml;
	Invalidate();
}


/// 关键部分
void CGroupBoxUI::PaintText(HDC hDC)
{
	//如果没有设置字体颜色,则用默认设置
	if (m_dwTextColor == 0)
	{
		m_dwTextColor = m_pManager->GetDefaultFontColor();
	}


	RECT rc;		//文字输出位置
	rc = GetPos();

	rc.left = rc.left + m_cxyBorderRound.cx + GROUPBOX_TEXT_OFFSET;	//这个地方采用了硬编码的方式,不知道怎么计算文字应该放的位置
		
	HFONT hOldFont = (HFONT)::SelectObject(hDC, m_pManager->GetFont(m_iFont));
	Gdiplus::Graphics graphics(hDC);
	Gdiplus::Font font(hDC);
	graphics.SetTextRenderingHint(Gdiplus::TextRenderingHintSystemDefault);
	graphics.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
	graphics.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic);
	Gdiplus::RectF rectF((Gdiplus::REAL)rc.left, (Gdiplus::REAL)rc.top, (Gdiplus::REAL)(rc.right - rc.left), (Gdiplus::REAL)(rc.bottom - rc.top));
	Gdiplus::SolidBrush brush(Gdiplus::Color(254, GetBValue(m_dwTextColor), GetGValue(m_dwTextColor), GetRValue(m_dwTextColor)));

	Gdiplus::StringFormat stringFormat = Gdiplus::StringFormat::GenericTypographic();
	Gdiplus::RectF bounds;
	graphics.MeasureString(m_sText, -1, &font, rectF, &stringFormat, &bounds);
	
	// MeasureString存在计算误差,这里加一像素
	rc.bottom = rc.top + (long)bounds.Height + 1;		//这两句是从UIRender.cpp中DrawText()中拷出来的,不知道意义何在
	rc.right = rc.left + (long)bounds.Width + 1;
	
	m_iTextWidth = (int)bounds.Width;
	m_iTextHeigh = (int)bounds.Height;
	
	graphics.DrawString(m_sText, -1, &font, rectF, &stringFormat, &brush);

	::SelectObject(hDC, hOldFont);

}


void CGroupBoxUI::PaintBorder(HDC hDC)
{
	RECT rc = GetPos();		//画框框时的位置

	rc.top += (m_iTextHeigh * 1) / 2;		//最顶部的线移到Text的中下部

	int nSize = m_nBorderSize;
	//DWORD dwPenColor = m_dwBorderColor;
	Gdiplus::Graphics graphics(hDC);

	//const Gdiplus::Pen pen(Gdiplus::Color::Red, 1.0f);

	DWORD dwPenColor = GetAdjustColor(m_dwBorderColor);
	ASSERT(::GetObjectType(hDC) == OBJ_DC || ::GetObjectType(hDC) == OBJ_MEMDC);
	HPEN hPen = ::CreatePen(PS_SOLID | PS_INSIDEFRAME, nSize, RGB(GetBValue(dwPenColor), GetGValue(dwPenColor), GetRValue(dwPenColor)));
	HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
	::SelectObject(hDC, ::GetStockObject(HOLLOW_BRUSH));

	//定位四个圆角的位置
	RECT rcTopLeftCorner = { rc.left, rc.top, rc.left + 2 * m_cxyBorderRound.cx, rc.top + 2 * m_cxyBorderRound.cy };
	RECT rcTopRightCorner = { rc.right - 2 * m_cxyBorderRound.cx, rc.top, rc.right, rc.top + 2 * m_cxyBorderRound.cy };
	RECT rcBottomLeftCorner = { rc.left, rc.bottom - 2 * m_cxyBorderRound.cy, rc.left + 2 * m_cxyBorderRound.cx, rc.bottom };
	RECT rcBottomRightCorner = { rc.right - 2 * m_cxyBorderRound.cx, rc.bottom - 2 * m_cxyBorderRound.cy, rc.right, rc.bottom };

	//画四个圆角
	const Gdiplus::Pen pen(Gdiplus::Color(GetBValue(dwPenColor), GetGValue(dwPenColor), GetRValue(dwPenColor)), (float)m_nBorderSize);
	graphics.DrawArc(&pen, rcTopLeftCorner.left, rcTopLeftCorner.top, rcTopLeftCorner.right - rcTopLeftCorner.left, rcTopLeftCorner.bottom - rcTopLeftCorner.top, 180.0f, 90.0f);
	graphics.DrawArc(&pen, rcTopRightCorner.left, rcTopRightCorner.top, rcTopRightCorner.right - rcTopRightCorner.left, rcTopRightCorner.bottom - rcTopRightCorner.top, 270.0f,90.0f);
	graphics.DrawArc(&pen, rcBottomLeftCorner.left, rcBottomLeftCorner.top, rcBottomLeftCorner.right - rcBottomLeftCorner.left, rcBottomLeftCorner.bottom - rcBottomLeftCorner.top, 90, 90);
	graphics.DrawArc(&pen, rcBottomRightCorner.left, rcBottomRightCorner.top, rcBottomRightCorner.right - rcBottomRightCorner.left, rcBottomRightCorner.bottom - rcBottomRightCorner.top, 0, 91);

	
	//画线----GDI
	MoveToEx(hDC, rc.left, rc.top + m_cxyBorderRound.cy, NULL);			//左边线
	LineTo(hDC, rc.left, rc.bottom - m_cxyBorderRound.cy);

	MoveToEx(hDC, rc.left + m_cxyBorderRound.cx, rc.top, NULL);			//上第一条线
	LineTo(hDC, rc.left + m_cxyBorderRound.cx + GROUPBOX_TEXT_OFFSET - 5, rc.top);		//-5 是为了给Text增加左边间距

	MoveToEx(hDC, rc.left + m_cxyBorderRound.cx + GROUPBOX_TEXT_OFFSET + m_iTextWidth + 5, rc.top, NULL);		//上第二条线,+5是为了给Text增加右边间距
	LineTo(hDC, rc.right - m_cxyBorderRound.cx, rc.top);

	MoveToEx(hDC, rc.right, rc.top + m_cxyBorderRound.cy, NULL);		//右边线
	LineTo(hDC, rc.right, rc.bottom - m_cxyBorderRound.cy);

	MoveToEx(hDC, rc.left + m_cxyBorderRound.cx, rc.bottom, NULL);
	LineTo(hDC, rc.right - m_cxyBorderRound.cx, rc.bottom);


	//画线GDI+    GDI+画线 有偏移,得修改width、height
	//graphics.DrawLine(&pen, rc.left, rc.top + m_cxyBorderRound.cy, rc.left, rc.bottom - m_cxyBorderRound.cy);
	//graphics.DrawLine(&pen, rc.left + m_cxyBorderRound.cx, rc.top, rc.left + m_cxyBorderRound.cx + GROUPBOX_TEXT_OFFSET - 5, rc.top);
	//graphics.DrawLine(&pen, rc.left + m_cxyBorderRound.cx + GROUPBOX_TEXT_OFFSET + m_iTextWidth + 5, rc.top, rc.right - m_cxyBorderRound.cx, rc.top);
	//graphics.DrawLine(&pen, rc.right, rc.top + m_cxyBorderRound.cy, rc.right, rc.bottom - m_cxyBorderRound.cy);		//右边线显示不出来
	//graphics.DrawLine(&pen, rc.left + m_cxyBorderRound.cx, rc.bottom, rc.right - m_cxyBorderRound.cx, rc.bottom);	//底边线也显示不出来
	

	
			//开始画圆角矩形边框
			//RECT rcTopLeftCorner = { rc.left, rc.top, rc.left + 20, rc.top + 20 };	//左上角圆角
			//RECT rcTopRightCorner = { rc.right - 2 * m_cxyBorderRound.cx, rc.top, rc.right, rc.top + 2 * m_cxyBorderRound.cy };
			//RECT rcBottomLeftCorner = { rc.left, rc.bottom - 2 * m_cxyBorderRound.cy, rc.left + 2 * m_cxyBorderRound.cx, rc.bottom };
			//RECT rcBottomRightCorner = { rc.right - 2 * m_cxyBorderRound.cx, rc.bottom - 2 * m_cxyBorderRound.cy, rc.right, rc.bottom };
			
			//画左上角圆角
	
			/*MoveToEx(hDC, rc.left, rc.top, NULL);
			LineTo(hDC, rc.left, rc.bottom);

			MoveToEx(hDC, rc.left, rc.top, NULL);
			LineTo(hDC, rc.left, rc.top);

			MoveToEx(hDC, rc.left, rc.top, NULL);
			LineTo(hDC, rc.right, rc.top);

			MoveToEx(hDC, rc.right, rc.top, NULL);
			LineTo(hDC, rc.right, rc.bottom);
			MoveToEx(hDC, rc.left, rc.bottom, NULL);
			LineTo(hDC, rc.right, rc.bottom);*/
			::SelectObject(hDC, hOldPen);
			::DeleteObject(hPen);
			
		
}


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值