如何用c++的mfc绘制柱状图
2016-06-13 · 百度知道合伙人官方认证企业
用c++的mfc绘制柱状图的方法如下:
1:取GroupBox的区域,并保存四个值 左,上,右,下
//获取屏幕坐标
((CWnd*)GetDlgItem(IDC_STATIC_CHART))->GetWindowRect(rect);
//计算x轴y轴基本单位
int dx = (rect.right-rect.left)/50;
int dy = (rect.bottom-rect.top)/80;
//转换成对话框坐标
ScreenToClient(rect);
//保存4个值
int L = rect.left,R = rect.right,T = rect.top,B = rect.bottom;
GroupBox的区域我忘记标出来了,就在上面图中柱状图那一块
2:获取DC,这一步没什么好说的
CPaintDC dc(this);
3:画X轴,Y轴
//X
dc.MoveTo(L+dx*2,B-dy*3);
dc.LineTo(L+dx*49,B-dy*3);
//最后的那个箭头
dc.MoveTo(L+dx*49,B-dy*3);
dc.LineTo(L+dx*48,B-dy*2);
dc.MoveTo(L+dx*49,B-dy*3);
dc.LineTo(L+dx*48,B-dy*4);
Y轴同理,但是考虑到dx,dy的值不一样,当画Y轴的箭头时,需要交换dx和dy的位置
//纵坐标线 dc.MoveTo(L+dx*2,B-dy*3);
dc.LineTo(L+dx*2,B-dy*77);
dc.MoveTo(L+dx*2,B-dy*77);
//交换了dx,dy的位置
dc.LineTo(L+dx*2-dy,B-dy*77+dx);
dc.MoveTo(L+dx*2,B-dy*77);
//交换了dx,dy的位置
dc.LineTo(L+dx*2+dy,B-dy*77+dx);
绘制完结果如图:
4:画柱状图,这里主要根据前面计算dx,dy时,划分的数量来计算每个柱的宽度,以及柱间的间隔
//第一个柱状体的左下坐标
int x = L+dx*3;
int y = B-dy*3;
for(int i=0;i
CRect rc;
rc.left=x+i*dx*9;
rc.right=rc.left+dx*7;
rc.bottom=y;
rc.top=rc.bottom-dy*answer[index][i+1];
//这里把柱状图的信息输出,这里输出的是一个数字,因为要转换成字符串,比较麻烦
//处理了一下,肯定有简洁的处理方式,但是我也懒得去想了,我很懒的
dc.SetBkMode(TRANSPARENT);//设置透明背景,要不然输出文字之后会有一块白,难看
char num[10];
sprintf(num,"%d",answer[index][i+1]);
CString strnum(num);
dc.TextOutW((rc.left+rc.right)/2-dx,rc.bottom-dy*(answer[index][i+1]+3),strnum);
//画刷是我之前就定义好的,直接拿来用
dc.FillRect(&rc,brushs+i);
}
5:添加控件消息响应函数
维护一个全局变量index来保存当前题号,创建重绘函数updateInfo
void CEnglishReportDlg::updateInfo(){
int count = choose_c[index];
int i;
//选项存在,赋值,L是宏命令与TEXT()相同功能
for(i=0;i
m_strLable[i] = choose[index][i];
}
//无此选项,置空
for(;i<5;i++)
m_strLable[i] = L"";
m_strTopic = topics[index];
//获取GroupBox区域,并转换成对话框坐标
CRect rect;
((CWnd*)GetDlgItem(IDC_STATIC_CHART))->GetWindowRect(rect);
ScreenToClient(rect);
//重绘此区域
InvalidateRect(rect);
//将控件变量更新到前台
UpdateData(FALSE);
}
函数1:响应ListBox的SelChange事件
void CEnglishReportDlg::OnLbnSelchangeListTopic()
{
// TODO: 在此添加控件通知处理程序代码
index = m_listtopic.GetCurSel();
updateInfo();
}
函数2:上一页按钮的Click事件
void CEnglishReportDlg::OnBnClickedButtonPre()
{
// TODO: 在此添加控件通知处理程序代码
if(index>0)
index--;
updateInfo();
m_listtopic.SetCurSel(index);
}
函数3:下一页按钮的Clicl事件
void CEnglishReportDlg::OnBnClickedButtonNext()
{
// TODO: 在此添加控件通知处理程序代码
if(index<19)
index++;
updateInfo();
m_listtopic.SetCurSel(index);
}
至此基本的功能都已经实现了,还差最后一步:
6:初始化对话框
for(int i=0;i<20;i++){
m_listtopic.AddString(topics[i]);
}
//index初始化为0,直接刷新
updateInfo();
m_listtopic.SetCurSel(index);
运行结果如下: