基于单文档的VC++动态曲线绘制

CEvent EndPaintLine;//用来控制绘制线程结束的事件
POINT polyline[61];//存放动态数据曲线数据值的数组
DWORD pLinePoints;//当前需绘制曲线的点数
int TimeSpan_GetData;//绘制动态曲线的时间间隔,具体系统中可在界面上加一微调按钮调整
UINT DataLineThread(LPVOID lp)
{
 //首先创建画实时曲线的画笔和画刷
 CPen* pPenRed=new CPen;
 CPen* pPenGreen=new CPen;
 CPen* pPenBlue=new CPen;
 CPen* pPenBlack=new CPen;
 CPen* pPenBKcolor=new CPen;
 CBrush* pBrushBlack=new CBrush;
 pPenRed->CreatePen(PS_DOT,1,RGB(150,0,0));
 pPenBlue->CreatePen(PS_DOT,1,RGB(10,150,255));
 pPenBlack->CreatePen(PS_SOLID,1,RGB(0,0,0));
 pPenGreen->CreatePen(PS_SOLID,1,RGB(0,255,0));
 pPenBKcolor->CreatePen(PS_SOLID,1,RGB(190,190,190));
 pBrushBlack->CreateSolidBrush(RGB(0,0,0));
 //以下为在全局函数中获得从cFormView类继承来的应用程序
 //窗口中获得静态文本框控件绘图环境的代码
 //首先获得应用程序主窗口指针(用它进行绘制时绘制区域包括菜单条、工具条等)
 CWnd* pMainWnd=AfxGetMainWnd();
 //然后获得系统视图工作区窗口指针
 CWnd* pClient=pMainWnd->GetWindow(GW_CHILD);
 //再获得视图区中的相应控件子窗口的指针
 CWnd* pData=pClient->GetDlgItem(IDC_DATA_ON_TIME_thread);
 //最后获得相应控件子窗口的绘图环境
 CDC* pDC=pData->GetDC();
 //完成此操作后,就可以利用pDC指针进行绘图操作了
 BOOL runThread=TRUE;
 //绘制线程循环结束标志,其值为FALSE时退出线程
 while(runThread) //循环执行,直到结束事件到来
  {
  //此处加入绘制曲线的函数体,可以直接采用定时器实现方法时的绘制代码
//  CWnd* pWnd=pClient->GetDlgItem(IDC_DATA_ON_TIME_thread);//undeclared identifier???添加pClient->及_thread是否正确
  //获取绘制坐标的文本框
//  CDC* pDC=pWnd->GetDC();
  //选中蓝色画笔,并保存以前的画笔
  CGdiObject* pOldPen=pDC->SelectObject(pPenBlue);
  static int count_T=0;//记录格线的移动次数
  pDC->SetBkColor(RGB(0,0,0));//以下代码为绘制纵向格线
  for(int i=0;i<=60;i+=5)
  //画横向格线,每隔50个像素点的距离画一条
  {
   pOldPen=pDC->SelectObject(pPenBlue);
   pDC->SetBkColor(RGB(0,0,0));
   pDC->MoveTo(i*10,0);
   pDC->LineTo(i*10,400);
   pDC->SelectObject(pOldPen);
  }

  for(i=0;i<=40;i+=2)
  //画横向格线,每隔50个像素点的距离画一条
  {
   pOldPen=pDC->SelectObject(pPenRed);
   pDC->SetBkColor(RGB(0,0,0));
   pDC->MoveTo(0,i*10);
   pDC->LineTo(600,i*10);
   pDC->SelectObject(pOldPen);
  }
 
  if(pLinePoints>=2)//用背景色重绘原曲线,使之产生动画效果
  {
   pOldPen=pDC->SelectObject(pPenBlack);
   pDC->Polyline(polyline,pLinePoints);
   pDC->SelectObject(pOldPen);
  }
  //以上为重绘即擦掉原曲线
  static int col=0; //用来计算当前数据曲线各点的值
  int m_OnData;
  char mC[40];

  //用来存放当前需要显示的实时数据值
  if(col<61)
  {
   for(int j=0;j<=col;j++)
   polyline[j].x=600-(col-j)*10;
   //给数据曲线各点横坐标赋值
   m_OnData=abs(rand()) 0;
   //利用随机数模拟实际需要显示的实时数据
   polyline[col].y=m_OnData;
   col++;
   pLinePoints++;
  }
  else //if(col>=31)即当数组装满时顺次前移,将数组第一个元素丢掉
  {
   pLinePoints=61;
   for(int t=0;t<60;t++)
    polyline[t].y=polyline[t+1].y;
   //横坐标已经在第一次循环中放好故不需再改变
   //m_Ondata存放需要显示的实时数据。
   
   m_OnData=abs(rand()) 0;
   polyline[60].y=m_OnData;
   //数组最后一个元素始终存放当前最新实时数据
  }
  itoa(m_OnData,mC,10);
  pDC->SetBkColor(RGB(230,230,230));
  //设置显示文本的背景颜色
  pDC->TextOut(610,35,"实时数据");
  if(pLinePoints>=2)
  //当有两个或以上有效数据点时开始画动态数据曲线
  {
   pOldPen=pDC->SelectObject(pPenGreen);
   //选择新画笔并保存系统原先的画笔
   pDC->Polyline(polyline,pLinePoints); //绘制动态实时数据曲线
   pDC->SetTextColor(RGB(0,250,0));
   //用数字显示实时数据值,颜色与实时曲线相同
   pDC->TextOut(610,60,mC);
   pDC->SetTextColor(RGB(0,0,0));
   //恢复原来系统显示文字的字体颜色
   pDC->SelectObject(pOldPen);//恢复系统原先画笔
  }
  //检查是否有结束事件发来
  int retCode=::WaitForSingleObject(EndPaintLine.m_hObject,0);
  if(retCode==WAIT_OBJECT_0)
  runThread=FALSE;
  //如有结束事件发来,则修改runThread退出循环
//  ::Sleep(TimeSpan_GetData);
  ::Sleep(100);  //时间间隔可由TimeSpan_GetData来确定
  //采集绘制实时数据曲线的时间间隔
  } //endwhile
 //删除已经创建的画笔
 delete pPenRed;
 delete pPenBlue;
 delete pPenGreen;
 delete pPenBlack;
 delete pPenBKcolor;
 delete pBrushBlack;
 return 0;//线程必须有一返回值
}

 

void CProjectView::OnDataLine()
{
 //启动工作线程并画出绘制动态曲线的子窗口的背景矩形框
 CBrush* pBrushBlack=new CBrush;  //添加是否正确
 pBrushBlack->CreateSolidBrush(RGB(0,0,0));  //添加是否正确
 CWnd *pWnd=GetDlgItem(IDC_DATA_ON_TIME_thread);
 //获取绘制曲线文本框窗口指针
 CDC *pDC=pWnd->GetDC();
 CGdiObject *pOldBrush=pDC->SelectObject(pBrushBlack);
 pDC->Rectangle(0,0,600,400);
 //用黑色绘制显示动态数据曲线的子窗口
 pDC->SelectObject(pOldBrush);
 CWinThread *pThreadDataOnTime=AfxBeginThread(DataLineThread,GetSafeHwnd(),THREAD_PRIORITY_NORMAL);//启动绘图线程
  
}

void CProjectView::OnEndDataLine()
//通过全局事件变量通知绘图线程结束绘制
{
 EndPaintLine.SetEvent(); 
}

void CProjectView::OnPaint()
{
 CBrush* pBrushBlack=new CBrush;  //添加是否正确
 CPen* pPenRed=new CPen;
 CPen* pPenBlue=new CPen;
 pBrushBlack->CreateSolidBrush(RGB(0,0,0));  //添加是否正确
 pPenRed->CreatePen(PS_DOT,1,RGB(150,0,0));
 pPenBlue->CreatePen(PS_DOT,1,RGB(10,150,255));
 CPaintDC dc(this); // device context for painting
 //以下代码为绘出画实时曲线的背景子窗口
 CWnd *pWnd=GetDlgItem(IDC_DATA_ON_TIME_thread);
 //获取绘制曲线的文本框指针
 pWnd->Invalidate();
 pWnd->UpdateWindow();
 CDC *pDC=pWnd->GetDC();
 CGdiObject *pOldBrush=pDC->SelectObject(pBrushBlack);
 CGdiObject *pOldPen=pDC->SelectObject(pPenRed);
 pDC->Rectangle(0,0,600,400);//绘制画曲线的矩形区域
 
  for(int i=0;i<=60;i+=5)
  //画横向格线,每隔50个像素点的距离画一条
  {
   pOldPen=pDC->SelectObject(pPenBlue);
   pDC->SetBkColor(RGB(0,0,0));
   pDC->MoveTo(i*10,0);
   pDC->LineTo(i*10,400);
   pDC->SelectObject(pOldPen);
  }
  //绘制横纵坐标刻度值
  for(i=0;i<=60;i+=5)
  {
   CString strX;
   strX.Format(_T("%d"),i/5);//int值转为字符
   pDC->SetBkColor(RGB(230,230,230));
   pDC->TextOut(i*10-5,405,strX);
  }

  for(i=0;i<=40;i+=2)
  //画横向格线,每隔50个像素点的距离画一条
  {
   pOldPen=pDC->SelectObject(pPenRed);
   pDC->SetBkColor(RGB(0,0,0));
   pDC->MoveTo(0,i*10);
   pDC->LineTo(600,i*10);
   pDC->SelectObject(pOldPen);
  }
  //绘制纵坐标刻度值
  for(i=20;i<=40;i++)
  {
   CString strY;
   strY.Format(_T("%d"),i);//int值转为字符
   pDC->SetBkColor(RGB(230,230,230));
   pDC->TextOut(-20,390-(i-20)*20,strY);
  }
 pDC->SelectObject(pOldBrush); 
 // Do not call CFormView::OnPaint() for painting messages
}

http://blog.sina.com.cn/s/blog_8269650b01013rly.html

你可能感兴趣的:(基于单文档的VC++动态曲线绘制)