1. 程式人生 > >MFC如何畫餅圖詳解

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就需要改動多一點才能正常執行。