MFC如何畫餅圖詳解
阿新 • • 發佈:2018-11-01
有個畫扇形的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就需要改動多一點才能正常執行。