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就需要改动多一点才能正常运行。

猜你喜欢

转载自blog.csdn.net/qq_18297675/article/details/73520197