用户登录  |  用户注册
首 页商业源码原创产品编程论坛
当前位置:PB创新网文章中心编程技巧Visual C++

VC++大数据量绘图时无闪烁刷屏技术实现

减小字体 增大字体 作者:佚名  来源:本站整理  发布时间:2009-03-16 20:37:30


void CWaveShowerView::GetScreenRect()
{
 CWnd* pStatic = GetDlgItem(IDC_SCREEN);
 pStatic->GetWindowRect(&rect);
 ScreenToClient(&rect);
 rect.top+=4;
 rect.left+=4;
 rect.bottom-=4;
 rect.right-=4;
 m_Y0=(rect.bottom-rect.top)/2+rect.top;
 m_DX=rect.Width();
 m_DY=rect.Height()/2;
 value=new CPoint[m_DX];
}
void CWaveShowerView::CleanScreen()
{
 CDC* pDC=GetDC();
 CPen pen1(PS_SOLID,1,RGB(0,0,0));
 CPen* oldPen1=pDC->SelectObject(&pen1);
 for(int i=rect.top;i<rect.bottom;i++)
 {
  pDC->MoveTo(rect.left,i);
  pDC->LineTo(rect.right,i);
 }
 pDC->SelectObject(&oldPen1);
 CPen pen2(PS_SOLID,1,RGB(0,0,255));
 CPen* oldPen2=pDC->SelectObject(&pen2);
 pDC->MoveTo(rect.left,m_Y0);
 pDC->LineTo(rect.right,m_Y0);
 pDC->SelectObject(&oldPen2);
 ReleaseDC(pDC);
}
void CWaveShowerView::DrawPoint(CPoint pt, COLORREF color)
{
 CDC* pDC=GetDC();
 pDC->SetPixel(rect.left+pt.x,m_Y0-pt.y,color);
 ReleaseDC(pDC);
}

  接下来,在视类的OnInitialUpdate()初始化函数中添加代码以进行数据显示的各项前期准备工作,并在“打开数据文件”菜单的响应函数中添加代码以读取文件的内码。

void CWaveShowerView::OnInitialUpdate()
{
 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_HIDEREADONLYOFN_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);
}

  虽然通过上述几步可以实现所有的功能,但为了防止内存泄露和养成良好的编程习惯,我们还须做些工作,在视类的构造函数中释放我们曾经申请过的内存以及定时器:
天极yesky

上一页  [1] [2] [3]  下一页

Tags:

作者:佚名

文章评论评论内容只代表网友观点,与本站立场无关!

   评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
PB创新网ourmis.com】Copyright © 2000-2009 . All Rights Reserved .
页面执行时间:19,718.75000 毫秒
Email:ourmis@126.com QQ:2322888 蜀ICP备05006790号