CBarChart源码下载: https://www.codeproject.com/Articles/17105/CBarChart?msg=3210667#xx3210667xx
修改过的CBarChart源码: https://download.csdn.net/download/u010096608/10879033
问题: 再调用下面的函数来调用显示图表时,调用次数多了后,会出现图表区域无法显示的问题
void ShowBarChart(int *hours,int n,bool bClass)
{
CRect rcClient;
CString strTemp;
GetClientRect(&rcClient);
int crl = 1;
if (!m_chart.Create(CRect(crl, crl, rcClient.Width()-crl, rcClient.Height() - crl), this, 1000 ))
{
if (!m_chart.GetSafeHwnd())
{
AfxMessageBox(_T("不能创建图表控件!"));
return;
}
m_chart.Reset();
m_chart.SetAutoScale(FALSE);
}
m_chart.SetAutoScale(TRUE);
m_chart.SetTitle(_T("生 产 数 据 分 时 段 显 示"));
m_chart.SetBKColor(RGB(255, 255, 240));
m_chart.ShowTooltip(TRUE);
for (int i=0;i<DATA_ITEM_COUNT-1;i++)
{
if (!bClass)
strTemp.Format(_T("%d时"),8+i);
else
strTemp.Format(_T("%d时"),(20+i)%24);
m_chart.AddBar(hours[i],strTemp,RGB(130,235,250));
}
if (!bClass)
strTemp.Format(_T("%d时"),8+DATA_ITEM_COUNT);
else
strTemp.Format(_T("%d时"),(20+DATA_ITEM_COUNT)%24);
m_chart.AddBar(hours[DATA_ITEM_COUNT-1],strTemp,RGB(130,235,250),TRUE);
}
正常情况下的显示:
点击多次查询,不停调用ShowBarChart()后,出现异常:
解决: 经过跟踪调试,发现问题是出现在了BarChart的ReSet()函数上。Reset()函数如下:
// Removes all bars, and forces the chart to be redrawn.
void CBarChart::Reset()
{
m_bars.RemoveAll();
m_rctMemPic = CRect(0, 0, 0, 0);
CClientDC dc(this);
RedrawChart(&dc);
}
Reset主要删除数据和重设位图,而我在reset后进行AddBar操作,添加数据并显示柱状图,AddBar函数如下:
// Adds a bar to the chart
// Parameters:
// udValue : Value of the bar
// szLabel : Label of the bar, will be shown under the bar
// color : Color of the bar. This color will be used to create a gradient.
// bRepaint: If set to TRUE, forces the chart to show changes on the screen
// Default is set to false. It is recommended to set it to true just
// For last Add bar of the chart, so the chart won't be forced to
// Show changes every time a single bar is added.
void CBarChart::AddBar(double udValue, CString szLabel, COLORREF color, BOOL bRepaint)
{
m_bars.AddBar(udValue, szLabel, color);
if (bRepaint)
{
CClientDC dc(this);
RedrawChart(&dc);
Invalidate();
}
}
AddBar主要添加数据和重设位图以及显示。问题就出在RedrawChart()中,RedrawChart()函数如下:
void CBarChart::RedrawChart(CDC* pDC)
{
if (!m_dcMem.GetSafeHdc())
{
m_dcMem.CreateCompatibleDC(pDC);
}
// Deselect and destroy old bitmap, and create a new one
ResetBitmap(pDC);
Refresh();
}
可以看到,RedrawChart中进行了删除位图和创建新位图,并刷新,刷新是调用Invalidate()函数, 但是对于Invalidate()函数,只有在函数运行完后才会发送WM_PAINT消息,然后窗口才会重绘。
因此,Reset函数中在删除位图和创建新位图后,并没有能够实现刷新窗口 并显示位图,而是在AddBar中又一次删除 位图和创建新位图,然后才能够重绘窗口显示位图。 这样容易出现 保存位图的DC资源异常的问题,导致后面显示都是一片黑色。
解决方法是不要在Addbar前面调用Reset函数,只需删除旧的数据旧可以了。更新后的代码 如下:
void ShowBarChart(int *hours,int n,bool bClass)
{
CRect rcClient;
CString strTemp;
GetClientRect(&rcClient);
int crl = 1;
if (!m_chart.Create(CRect(crl, crl, rcClient.Width()-crl, rcClient.Height() - crl), this, 1000 ))
{
if (!m_chart.GetSafeHwnd())
{
AfxMessageBox(_T("不能创建图表控件!"));
return;
}
//m_chart.Reset();//用reset后再addbar,只会执行一次重绘
m_chart.SetAutoScale(FALSE);
}
m_chart.RemoveAll();
m_chart.SetAutoScale(TRUE);
m_chart.SetTitle(_T("生 产 数 据 分 时 段 显 示"));
m_chart.SetBKColor(RGB(255, 255, 240));
m_chart.ShowTooltip(TRUE);
for (int i=0;i<DATA_ITEM_COUNT-1;i++)
{
if (!bClass)
strTemp.Format(_T("%d时"),8+i);
else
strTemp.Format(_T("%d时"),(20+i)%24);
m_chart.AddBar(hours[i],strTemp,RGB(130,235,250));
}
if (!bClass)
strTemp.Format(_T("%d时"),8+DATA_ITEM_COUNT);
else
strTemp.Format(_T("%d时"),(20+DATA_ITEM_COUNT)%24);
m_chart.AddBar(hours[DATA_ITEM_COUNT-1],strTemp,RGB(130,235,250),TRUE);
}