MFC如何画饼图详解

==> 学习汇总(持续更新)
==> 从零搭建后端基础设施系列(一)-- 背景介绍


有个画扇形的API,但是现在先不解释,因为不懂画饼图的原理,你也不懂怎么用。接下来就一步步带大家去计算饼图的扇形两点坐标。

直接看下图,文字解释总是太抽象。

接下来就是用Pie这个函数来画出扇形了。
其原型如下:

BOOL Pie( 
   LPCRECT lpRect,
   POINT ptStart,
   POINT ptEnd  
);

lpRect: 这个就是上图中的外接矩形
ptStart: 扇形的起点
ptEnd: 扇形的终点

这里的起点终点指的是,从圆心引出的直线,相交于圆的两点,一般假设角度大的为终点。

还有一个比较重要的问题,那就是坐标原点的设置,要知道在MFC中,坐标原点是左上角开始(0,0)处,如果我们接着用这个坐标原点的话,会导致坐标的计算很复杂。所以要用SetViewportOrgEx函数设置坐标的原点。设置后,其增长方式仍然没变,往右是x增大的方向,往下是y增大的方向,相反即为负。

核心代码如下:

	CPaintDC dc(this);
	CRect rect;
	GetClientRect(&rect);
	CBrush brush(RGB(255, 255, 255));
	dc.FillRect(&rect, &brush);

	//设置坐标原点
	SetViewportOrgEx(dc, m_COpt.x, m_COpt.y, NULL);

	//设置圆的外接矩形大小
	CRect pieRect(-m_Radius, -m_Radius, m_Radius, m_Radius);
	dc.Ellipse(&pieRect);

	POINT pt_start;
	POINT pt_end;

	//画饼图
	double R = m_Radius;
	const double PI = 3.1415926;
	double sum = 0;
	for (int i = 0; i < m_itemNums; i++)
		sum += m_percentage[i];
	//验证占比加起来等不等于1
	if (sum == 1)
	{
		//第一个扇形的坐标
		int angle = m_percentage[0] * 360;  //计算占的角度
		POINT pt_s_e;
		pt_start = { (int)R,0 };
		pt_s_e = pt_start;
		pt_end = { int(R*cos(angle * PI / 180)),int(-R*sin(angle * PI / 180)) };
		dc.SelectObject(CreateSolidBrush(m_color[0])); //上颜色
		dc.Pie(&pieRect, pt_start, pt_end);
		for (int i = 1; i < m_itemNums; i++)
		{	
			pt_start = pt_end;
			angle += m_percentage[i] * 360;
			pt_end = { int(R*cos(angle * PI / 180)),int(-R*sin(angle * PI / 180)) };
			dc.SelectObject(CreateSolidBrush(m_color[i])); //上颜色
			if(i == m_itemNums - 1)
			    dc.Pie(&pieRect, pt_start, pt_s_e);
			else
			    dc.Pie(&pieRect, pt_start, pt_end);
		}

		

		//画小矩形
		CRect expRect;
		int l = 0, t = 0;
		for (int i = 0; i < m_itemNums; i++)
		{
			l = m_Radius + 50;
			t = -2*m_Radius + m_expH*i;
			expRect = {l,t + 10,l + m_expW,t + m_expH };
			dc.SelectObject(CreateSolidBrush(m_color[i])); //上颜色
			dc.Rectangle(&expRect);
			dc.TextOut(l + m_expW + 10, t + m_expH / 3, m_itemName[i]);
		}

		//显示百分比
		CString s;
		int strLen = m_itemName[0].GetLength();
		for (int i = 0; i < m_itemNums; i++)
		{
			l = -2*m_Radius - strLen*10;
			t = -2 * m_Radius + m_expH*i;
			s.Format(TEXT("%s -- %0.2f%s"), m_itemName[i],m_percentage[i] * 100,TEXT("%"));
			dc.TextOut(l, t + m_expH / 3, s);
		}
	}

我把画饼图的方法,封装成一个通用的类,以添加item的方式,添加扇形。
使用示例如下:

	PieChart piechart;
	piechart.SetCoordinateOrigin({ 300,200 }); //设置坐标原点
	piechart.SetRadius(100); //设置半径
	piechart.SetExplainRect(50,30); //设置小矩形大小
	piechart.AddItem("苹果", RGB(255, 0, 0), 0.4);
	piechart.AddItem("雪梨", RGB(0, 255, 0), 0.1);
	piechart.AddItem("香蕉", RGB(0, 0, 255), 0.2);
	piechart.AddItem("木瓜", RGB(0, 255, 255), 0.3);
	piechart.DoModal();

结果如图:

饼图类下载(github下载)

饼图类下载(这是CSDN下载,需要1积分)

注:因为我是在VS2015编译的,只能保证向下兼容到2013,其它版本可能有不确定错误。或者直接把有用代码复制粘贴,这样就能保证能兼容所有VS,VC就需要改动多一点才能正常运行。

  • 6
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值