VC 大数据量绘图时无闪烁刷屏技术实现
来源:互联网
作者:西部数码
时间:2008-04-09
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();
GetScreenRect();
for(int i=0;i<m_DX;i )
value[i].x=value[i].y=0;
SetTimer(0,10,NULL);
}
void CWaveShowerView::OnOpenData()
{
CString FileName="";
CFile file;
CFileDialog dlg(TRUE,"*","*.*",
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"所有文件(*.*)|*.*||",NULL);
if(dlg.DoModal()==IDOK)
{
KillTimer(1);
FileName=dlg.GetPathName();
file.Open(FileName,CFile::modeReadWrite);
m_BufLen=file.GetLength();
buffer= new unsigned char[m_BufLen m_DX 10];
file.Read(buffer,m_BufLen);
file.Close();
SetTimer(1,10,NULL);
}
}
下面将要添加的定时器响应函数正是本文的重点,为方便对比起见,笔者写了两个OnTimer响应函数,前一个是采用常规的普通方法描点的,运行起来可以很明显地看到画面的闪烁跳动。而后一种则是采用本文所述方法采用的内存画图的方法,运行后几乎画面无闪烁。下面便是两段对比代码的原码部分:
//代码一:有闪烁的代码
void CWaveShowerView::OnTimer(UINT nIDEvent)
{
if(nIDEvent==0)
{
CleanScreen();
for(int i=0;i<m_DX;i )
DrawPoint(value[i],RGB(0,255,0));
}
if(nIDEvent==1)
{
m_dx =2;
for(int i=0;i<m_DX;i )
{
value[i].x=i;
if(m_dx i<0)
buffer[m_dx i]=128;
if(m_dx i<-m_DX)
m_dx-=2;
if(m_dx i>m_BufLen)
buffer[m_dx i]=128;
if(m_dx i>m_BufLen m_DX)
m_dx-=2;
value[i].y=m_DY*(buffer[m_dx i]-128)/256;
}
}
CFormView::OnTimer(nIDEvent);
}
//代码二:无闪烁的代码
void CWaveShowerView::OnTimer(UINT nIDEvent)
{
if(nIDEvent==0)
{
CDC* pDC=GetDC();
CDC dc;
CBitmap bitmap;
CBitmap* pOldBitmap;
CRect client;
pDC->GetClipBox(client); //检取无效区
//创建一个与pDC兼容的内存设备环境
if(dc.CreateCompatibleDC(pDC))
{
//创建一与pDC兼容的位图,大小为整个客户区
if(bitmap.CreateCompatibleBitmap(pDC,rect.Width(), rect.Height()))
{
//使dc与pDC具有同样的映射关系
OnPrepareDC(&dc,NULL);
//将位图选入内存环境
pOldBitmap=dc.SelectObject(&bitmap);
//使dc的整个客户区都成无效区
dc.SelectClipRgn(NULL);
//再“与上”检取的无效区,使内存环境与
//pDC检取的无效区相等
dc.IntersectClipRect(client);
}
}
CleanScreen();
for(int i=0;i<m_DX;i )
DrawPoint(value[i],RGB(0,255,0));
dc.SelectObject(pOldBitmap);
ReleaseDC(pDC);
}
if(nIDEvent==1)
{
m_dx =2;
for(int i=0;i<m_DX;i )
{
value[i].x=i;
if(m_dx i<0)
buffer[m_dx i]=128;
if(m_dx i<-m_DX)
m_dx-=2;
if(m_dx i>m_BufLen)
buffer[m_dx i]=128;
if(m_dx i>m_BufLen m_DX)
m_dx-=2;
value[i].y=m_DY*(buffer[m_dx i]-128)/256;
}
}
CFormView::OnTimer(nIDEvent);
}
虽然通过上述几步可以实现所有的功能,但为了防止内存泄露和养成良好的编程习惯,我们还须做些工作,在视类的构造函数中释放我们曾经申请过的内存以及定时器:
CWaveShowerView::~CWaveShowerView()
{
delete[] value;
KillTimer(0);
KillTimer(1);
}
小结
编译运行此程序,通过菜单选取需要显示的文件(任意文件均可),如在定时器响应代码中采用的是第一种代码,则会看到数据显示的同时伴随着明显的闪烁而采用后一种代码编码则会很平稳的将数据显示出来。本文介绍的这种方法适用于各种牵扯到数组数据图形显示的程序,比如监控软件、数据分析软件、测量软件等等,具有广泛的应用前景。本文所述程度代码在Windows 2000 Professional SP4下由Microsoft Visual C 6.0编译通过。
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!



