duilib-自定义曲线控件

3 篇文章 0 订阅

duilib-自定义曲线控件

duilib现有的控件继承图如下:

在这里插入图片描述
从上图可以看出常见的控件都是由CControlUI继承而来,因此如果需要自定义控件,可以继承CControlUI,重写子类。如何做一个类似windows任务管理器的曲线控件,如下图所示:
在这里插入图片描述

自定义曲线控件展示如下:
在这里插入图片描述

下面详细说明如何在duilib源码中自定义曲线控件,以及如何在xml中设置控件属性。

1、重写控件类CChartCtrlUI,继承于CLabelUI或者CControlUI,控件类CChartCtrlUI中必须重写的函数方法如下:

LPCTSTR GetClass() const;
LPVOID GetInterface(LPCTSTR pstrName);
void DoEvent(TEventUI& event);
void DoPaint(HDC hDC, const RECT& rcPaint);
void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);

GetClass()返回自定义的控件name属性值

LPCTSTR CChartCtrlUI::GetClass() const
{
	return DUI_CTR_CHART_CONTROL;
}

GetInterface()返回控件指针

LPVOID CChartCtrlUI::GetInterface(LPCTSTR pstrName)
{
	if (_tcscmp(pstrName, DUI_CTR_CHART_CONTROL) == 0) return static_cast<CChartCtrlUI*>(this);
	return CControlUI::GetInterface(pstrName);
}

DoEvent()重写控件响应,包括鼠标键盘的动作,触发后发送UI主线程通知消息,如果需要捕获消息请重写DoEvent.

void CChartCtrlUI::DoEvent(TEventUI& event)
{

	CControlUI::DoEvent(event);
}

DoPaint()控件界面重绘,可以在此函数内绘制图像,曲线等等,如何使用gdi+绘制曲线,画图等,可以参考网上资料。

void CChartCtrlUI::DoPaint(HDC hDC, const RECT& rcPaint)
{
	CControlUI::DoPaint(hDC, rcPaint);

	m_rectChart = this->GetPos();

	//重绘制曲线图
	{
		Pen      pen(m_curvPenColor);
		Graphics graphics(hDC);
		graphics.SetSmoothingMode(SmoothingModeAntiAlias);

		Status restatus = graphics.DrawCurve(&pen, (const PointF*)m_stPointXy, m_nCurPointCount);
		m_bDataAdd = false;
	}

}

SetAttribute()解析界面xml文件中控件自定义属性值,如何解析可以参考CLabelUI或CControlUI类中的SetAttribute函数,例如自定义了curvpen,曲线画笔颜色,截取控件宽度值,设置曲线绘制点数总和,方便平移操作。

void CChartCtrlUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
{
	LPTSTR pstr = NULL;
	if (_tcscmp(pstrName, _T("curvpen")) == 0) {
		if (*pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
		LPTSTR pstr = NULL;
		DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
		SetCurvPenColor(clrColor);
	}
	else if (_tcscmp(pstrName, _T("width")) == 0)
	{
		DWORD dwWidth = _tcstoul(pstrValue, &pstr, 10);
		int nWidth;
		nWidth = dwWidth;
		ASSERT(nWidth > 0);
		m_stPointXy = new PointF[nWidth];
		ASSERT(m_stPointXy != NULL);
		CControlUI::SetAttribute(pstrName, pstrValue);
	}
	else
		CControlUI::SetAttribute(pstrName, pstrValue);
}

2、在UIDefine.h中添加控件类名的宏定义。

#define  DUI_CTR_CHART_CONTROL                   (_T("ChartControl"))

3、在UIDlgBuilder.cpp的_paser函数中增加控件的创建代码,根据类名的长度为12,写在case 12下:

			case 12:
				if (_tcscmp(pstrClass, DUI_CTR_CHART_CONTROL) == 0)			  pControl = new CChartCtrlUI;
				break;

4、在UIlib.h中包含头文件

#include "Control/UIChartCtrl.h"

5、使用xml编写

<ChartControl name="cpuChart" text=" " textcolor="#FFFF0000" height="40" width="160" bordersize="1" bordercolor="#FF1E90FF" curvpen="#FF1E90FF" /> 

6、头文件与源文件如下

//UIChartCtrl.h

#ifndef UI_CHART_CTRL_H
#define UI_CHART_CTRL_H
#pragma once

#include <GdiPlus.h>
#pragma comment( lib, "GdiPlus.lib" )
using namespace Gdiplus;
class UILIB_API Gdiplus::RectF;
struct UILIB_API Gdiplus::GdiplusStartupInput;

namespace DuiLib
{
	class UILIB_API CChartCtrlUI : public CLabelUI
	{
	public:
		CChartCtrlUI();
		~CChartCtrlUI();

		LPCTSTR GetClass() const;
		LPVOID GetInterface(LPCTSTR pstrName);

		void		SetEnabledEffect(bool _EnabledEffect);
		bool		GetEnabledEffect();
		void SetText(LPCTSTR pstrText);
		CDuiString	GetText() const;
		void DoEvent(TEventUI& event);
		void DoPaint(HDC hDC, const RECT& rcPaint);
		void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);
		void SetCurvPenColor(DWORD dwColor);


		void InitCtrl(); //初始化数据,分配数据空间
		int GetPointCount();
		void AddPointXy(PointF clsPointF);
		PointF valueToPointF(float value);

	private:
		DWORD					m_curvPenColor; //绘制曲线画笔
		PointF                  * m_stPointXy;//显示100个值,超过就后移
		int					    m_nCurPointCount;
		bool					m_EnableEffect;
		CDuiString				m_TextValue;
		ULONG_PTR				m_gdiplusToken;
		GdiplusStartupInput		m_gdiplusStartupInput;
		bool                    m_bDataAdd; //是否有数据加入,加入则重绘
		bool                    m_bFirstUpdate;  //是否界面更新一次
		RECT					m_rectChart;  //窗口相对于客户区的坐标
	};
}
#endif

//UIChartCtrl.cpp

#include "StdAfx.h"
#include "UIChartCtrl.h"

#include <atlconv.h>
namespace DuiLib
{

	CChartCtrlUI::CChartCtrlUI() : m_gdiplusToken(0),
		m_EnableEffect(false),
		m_stPointXy(NULL),
		m_bDataAdd(false),
		m_bFirstUpdate(false)
	{
		m_nCurPointCount = 0;
		GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);
	}

	CChartCtrlUI::~CChartCtrlUI()
	{
		try
		{
			GdiplusShutdown(m_gdiplusToken);
			if (m_stPointXy != NULL)
			{
				delete m_stPointXy;
				m_stPointXy = NULL;
			}
		}
		catch (...)
		{
			throw "CChartCtrlUI::~CChartCtrlUI";
		}
	}

	LPCTSTR CChartCtrlUI::GetClass() const
	{
		return DUI_CTR_CHART_CONTROL;
	}

	LPVOID CChartCtrlUI::GetInterface(LPCTSTR pstrName)
	{
		if (_tcscmp(pstrName, DUI_CTR_CHART_CONTROL) == 0) return static_cast<CChartCtrlUI*>(this);
		return CControlUI::GetInterface(pstrName);
	}
	CDuiString CChartCtrlUI::GetText() const
	{
		try
		{
			if (!m_EnableEffect)
				return CControlUI::GetText();
			return m_TextValue;
		}
		catch (...)
		{
			throw "CChartCtrlUI::GetText";
		}
	}
	void CChartCtrlUI::SetText(LPCTSTR pstrText)
	{
		try
		{
			if (!GetEnabledEffect())
				return CControlUI::SetText(pstrText);

			m_TextValue = pstrText;
		}
		catch (...)
		{
			throw "CChartCtrlUI::SetText";
		}
	}

	void CChartCtrlUI::SetEnabledEffect(bool _EnabledEffect)
	{
		try
		{
			m_EnableEffect = _EnabledEffect;
		}
		catch (...)
		{
			throw "CLabelUI::SetEnabledEffect";
		}
	}


	bool CChartCtrlUI::GetEnabledEffect()
	{
		try
		{
			return m_EnableEffect;
		}
		catch (...)
		{
			throw "CLabelUI::GetEnabledEffect";
		}
	}
	void CChartCtrlUI::DoEvent(TEventUI& event)
	{

		CControlUI::DoEvent(event);
	}
	void CChartCtrlUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
	{
		LPTSTR pstr = NULL;
		if (_tcscmp(pstrName, _T("curvpen")) == 0) {
			if (*pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
			LPTSTR pstr = NULL;
			DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
			SetCurvPenColor(clrColor);
		}
		else if (_tcscmp(pstrName, _T("width")) == 0)
		{
			DWORD dwWidth = _tcstoul(pstrValue, &pstr, 10);
			int nWidth;
			nWidth = dwWidth;
			ASSERT(nWidth > 0);
			m_stPointXy = new PointF[nWidth];
			ASSERT(m_stPointXy != NULL);
			CControlUI::SetAttribute(pstrName, pstrValue);
		}
		else
			CControlUI::SetAttribute(pstrName, pstrValue);
	}
	void CChartCtrlUI::SetCurvPenColor(DWORD dwColor)
	{
		m_curvPenColor = dwColor;
	}
	int CChartCtrlUI::GetPointCount()
	{
		return m_nCurPointCount;
	}

	void CChartCtrlUI::InitCtrl()
	{
		//int width = this->GetWidth();
		//ASSERT(width > 0);
		//m_stPointXy = new PointF[width];
		//ASSERT(m_stPointXy != NULL);
		int width;
		m_rectChart = this->GetPos();
		width = m_rectChart.right - m_rectChart.left;
		ASSERT(width > 0);
		m_stPointXy = new PointF[width];
		ASSERT(m_stPointXy != NULL);
	}
	void CChartCtrlUI::AddPointXy(PointF clsPointF)
	{
		POINTF tempPf;

		if (m_nCurPointCount > this->GetWidth())
			return;
		if (m_nCurPointCount == this->GetWidth())
		{
			for (int i = 0; i < m_nCurPointCount-1; i++)
			{
				m_stPointXy[i].Y = m_stPointXy[i+1].Y;
				//X值保持不变
			}
			m_stPointXy[m_nCurPointCount-1] = clsPointF;
		}
		else
		{
			m_stPointXy[m_nCurPointCount].X = clsPointF.X;
			m_stPointXy[m_nCurPointCount].Y = clsPointF.Y;
			m_nCurPointCount++;
		}
		m_bDataAdd = true;
	}
	PointF CChartCtrlUI::valueToPointF(float value)
	{
		PointF clsRes;
		int height, width;
		height = this->GetHeight();
		width = this->GetWidth();
		ASSERT(height > 0);
		ASSERT(width > 0);

		clsRes.Y = m_rectChart.top + (height - value / 100.0 * height);
		if (m_nCurPointCount < width)
			clsRes.X = m_nCurPointCount + 1 + m_rectChart.left;
		else
			clsRes.X = m_nCurPointCount + m_rectChart.left;
		return clsRes;
	}
	void CChartCtrlUI::DoPaint(HDC hDC, const RECT& rcPaint)
	{
		CControlUI::DoPaint(hDC, rcPaint);

		m_rectChart = this->GetPos();

		//重绘制曲线图
		//if (m_bDataAdd) //有数据加入
		{
			Pen      pen(m_curvPenColor);
			Graphics graphics(hDC);
			graphics.SetSmoothingMode(SmoothingModeAntiAlias);

			Status restatus = graphics.DrawCurve(&pen, (const PointF*)m_stPointXy, m_nCurPointCount);
			m_bDataAdd = false;
		}

	}
}
  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

feng_blog6688

只需一个赞,谢谢你的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值