MFC--根据串口采集的数据借助GDI绘制曲线

根据采集到的数据绘制曲线

在串口编程中会涉及到这样一个问题,就是将采集到的数据以曲线的形式展示出来,大家自然而然会想到采用方便快捷的控件进行编程。编程周期短,完成任务快,但是真实情况来看,控件会实现很多你用不到的功能,实现机制也不可见,这样在功能上会造成浪费,对性能和实现的效果上会有一些不可控,所以在这一类编程中建议自己通过设备上下文自己编写适合自己软件的曲线图。

我要实现的功能如下图:

这是一个在网上下载的例程运行的效果,我中间采用的编程思想大多来源这里,只是针我要实现的功能进行了修改。因为我的程序现在还没进行设备测试,所以这里借用一下这个效果图。

将画图实现的功能封装在一个类里面,在需要画图的时候,便可以实例化一个对象。

下面是详细的实现过程,为防止屏幕闪烁,采用了双缓冲技术。

实现的过程中主要的两问题是:1、为了绘制速度快,不会因为数据的增加而出现绘制越来越慢,最后卡死的现象,这里采用例程中用的方法,将已经画过的图像保存BitMap 中,来了数据直接在map上绘制,然后再复制在屏幕上。2、我的功能中会根据用户操作改变曲线显示的区域大小,这个时候就需要全部重绘,原来map里的曲线就不能再用了,因为大小已经改变了,这时候在OnPaint函数里面实现的功能就是重新绘制坐标轴框图和根据保存的数据进行曲线的绘制。

该类的头文件函数:

  1 #pragma once
  2
  3
  4
  5 //用于绘制二维曲线
  6 class CDrawView : public CWnd
  7 {
  8     DECLARE_DYNCREATE(CDrawView)
  9
 10 public:
 11     CDrawView();
 12     virtual ~CDrawView();
 13     DECLARE_MESSAGE_MAP()
 14
 15 public:
 16 #ifdef _DEBUG
 17     virtual void AssertValid() const;
 18 #ifndef _WIN32_WCE
 19     virtual void Dump(CDumpContext& dc) const;
 20 #endif
 21 #endif
 22
 23 public:
 24
 25
 26
 27     CPoint m_dCurrentPosition;     //current position
 28     CPoint m_dPreviousPosition;     //previous position
 29     double m_updateRate;//数据更新率
 30     void setUpdateRate(double updateRate);
 31
 32     CList<CPoint,CPoint&> dataList;//用于存储真实数据
 33     CList<CPoint,CPoint&> dataList1;//用于绘图
 34     CList<CPoint,CPoint&> tempDataList;//暂存数据
 35     void InvalidateCtrl();
 36     void SetYRange(double dYLower, double dYUpper, int nYDecimalPlaces);
 37     void SetXRange(int dXLower,int dXUpper,int nXDecimalPlaces);
 38     void SetXUnits(CString string);
 39     void SetYUnits(CString string);
 40     void SetGridColor(COLORREF color);
 41     void SetPlotColor(COLORREF color);
 42     void SetBackgroundColor(COLORREF color);
 43     void SetTitle(CString title);
 44     void AppendPoint(CPoint *newDataList);
 45     void Reset();
 46     void DrawPoint();
 47
 48     //各个部分的颜色
 49     COLORREF m_crBackColor;     //backGround color
 50     COLORREF m_crGridColor;     //Grid color
 51     COLORREF m_crPlotColor;     //data plot color
 52
 53     //设备上下文以及与其相关的位图
 54
 55     CDC m_dcGrid;
 56     CDC m_dcPlot;
 57     CBitmap *m_pBitmapOldGrid;
 58     CBitmap *m_pBitmapOldPlot;
 59     CBitmap m_pBitmapGrid;
 60     CBitmap m_pBitmapPlot;
 61
 62
 63     //画图区域相关
 64     int m_nHalfShiftPixels;
 65     int m_nPlotShiftPixels;
 66     int m_nClientHeight;
 67     int m_nClientWidth;
 68     int m_nPlotHeight;
 69     int m_nPlotWidth;
 70
 71     //坐标轴Y
 72     double m_dYLowerLimit;
 73     double m_dYUpperLimit;
 74     double m_dYRange;
 75     double m_dVerticalFactor;
 76
 77     //坐标轴X
 78     int m_dXLowerLimit;
 79     int m_dXUpperLimit;
 80     double m_dXRange;
 81     double m_dHorizontalFactor;
 82
 83     //title
 84     CString m_sTitile;
 85
 86     CRect m_rectClient;
 87     CRect m_rectPlot;
 88     CPen  m_penPlot;
 89     CBrush m_brushBack;
 90
 91     int m_nShiftPixels;          //amount  to  shift with each new point
 92     int m_nYDecimal;
 93     int m_nXDecimal;
 94
 95     CString m_strXUnitsString;
 96     CString m_strYUnitsString;
 97
 98
 99
100
101     CString str;
102     CList<int,int>listOfFogX;
103
104     afx_msg void OnPaint();
105     BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID=NULL);
106     afx_msg void OnSize(UINT nType, int cx, int cy);
107 };

该类的实现文件内容:

  1 // DrawView.cpp : 实现文件
  2 //
  3
  4 #include "stdafx.h"
  5 #include "IMU4.h"
  6 #include "DrawView.h"
  7 #include "math.h"
  8
  9
 10 // CDrawView
 11
 12 IMPLEMENT_DYNCREATE(CDrawView, CWnd)
 13
 14 CDrawView::CDrawView()
 15 {
 16     m_nYDecimal = 3 ;
 17
 18     m_dPreviousPosition.x = 0;
 19     m_dPreviousPosition.y = 0;
 20
 21     m_dCurrentPosition.x = 0;
 22     m_dCurrentPosition.y = 0;
 23
 24     m_dYLowerLimit = -10.0 ;
 25     m_dYUpperLimit =  10.0 ;
 26     m_dYRange =  m_dYUpperLimit - m_dYLowerLimit ;
 27
 28     m_dXLowerLimit = 0;
 29     m_dXUpperLimit = 1000;
 30     m_dXRange = m_dXUpperLimit - m_dXLowerLimit;
 31
 32     m_dVerticalFactor = (double)m_nPlotHeight / m_dYRange ;
 33     m_dHorizontalFactor = (double)m_nClientWidth / m_dXRange / 100.0;
 34
 35     m_nShiftPixels     = 4 ;
 36     m_nHalfShiftPixels = m_nShiftPixels/2 ;
 37     m_nPlotShiftPixels = m_nShiftPixels + m_nHalfShiftPixels ;
 38
 39     m_crBackColor  = RGB(  0,   0,   0) ;
 40     m_crGridColor  = RGB(  0, 255, 255) ;
 41     m_crPlotColor  = RGB(255, 255, 255) ;
 42
 43     m_penPlot.CreatePen(PS_SOLID, 0, m_crPlotColor) ;
 44     m_brushBack.CreateSolidBrush(m_crBackColor) ;
 45
 46     m_strXUnitsString.Format(_T("")) ;
 47     m_strYUnitsString.Format(_T("")) ;
 48
 49     m_pBitmapOldGrid = NULL ;
 50 }
 51
 52 CDrawView::~CDrawView()
 53 {
 54
 55 }
 56
 57
 58 BEGIN_MESSAGE_MAP(CDrawView, CWnd)
 59     ON_WM_MOUSEACTIVATE()
 60     ON_WM_DESTROY()
 61     ON_WM_PAINT()
 62     ON_WM_SIZE()
 63     ON_WM_TIMER()
 64 END_MESSAGE_MAP()
 65
 66
 67
 68 #ifdef _DEBUG
 69 void CDrawView::AssertValid() const
 70 {
 71     CWnd::AssertValid();
 72 }
 73
 74 #ifndef _WIN32_WCE
 75 void CDrawView::Dump(CDumpContext& dc) const
 76 {
 77     CWnd::Dump(dc);
 78 }
 79 #endif
 80 #endif
 81 void CDrawView::InvalidateCtrl()
 82 {
 83     //用于画坐标轴等信息的函数
 84     int i;
 85     int nCharacters;
 86     int nTopGridPix,nMidGridPix,nBottomGridPix;//分别代表绘图区的三条线(暂定)
 87
 88     CPen *oldPen;
 89     CPen solidPen(PS_SOLID,0,m_crGridColor);//建立一个画实线的画笔对象
 90     CFont axisFont,yUnitFont,*oldFont;//建立三个字体对象
 91     CString strTemp = _T("0");
 92
 93     CClientDC dc(this);
 94     if(m_dcGrid.GetSafeHdc() == NULL)
 95     {
 96         m_dcGrid.CreateCompatibleDC(&dc);
 97         m_pBitmapGrid.CreateCompatibleBitmap(&dc,m_nClientWidth,m_nClientHeight);
 98         m_pBitmapOldGrid = m_dcGrid.SelectObject(&m_pBitmapGrid);
 99     }
100     m_dcGrid.SetBkColor(m_crBackColor);
101     m_dcGrid.FillRect(m_rectClient, &m_brushBack) ;
102     nCharacters = max(abs((int)log10(fabs(m_dYUpperLimit))),abs((int)log10(fabs(m_dYLowerLimit))));
103     nCharacters = nCharacters + 4 + m_nYDecimal;
104
105     m_rectPlot.left = m_rectClient.left + 6 * nCharacters;
106     m_nPlotWidth = m_rectPlot.Width();
107
108     //draw the plot rectangle
109     oldPen = m_dcGrid.SelectObject(&solidPen);
110     m_dcGrid.MoveTo(m_rectPlot.left,m_rectPlot.top);
111     m_dcGrid.LineTo(m_rectPlot.right + 1,m_rectPlot.top);
112     m_dcGrid.LineTo(m_rectPlot.right + 1,m_rectPlot.bottom + 1);
113     m_dcGrid.LineTo(m_rectPlot.left,m_rectPlot.bottom + 1);
114     m_dcGrid.LineTo(m_rectPlot.left,m_rectPlot.top);
115
116     //draw the dotted lines,
117     //use setPixel instead of a dotted pen - this allows for a
118     //finer  dotted line  and a more "" technical "look
119     nMidGridPix = (m_rectPlot.top + m_rectPlot.bottom) / 2;
120     nTopGridPix = nMidGridPix - m_nPlotHeight / 4;
121     nBottomGridPix = nMidGridPix + m_nPlotHeight / 4;
122
123     for(i = m_rectPlot.left; i < m_rectPlot.right; i+= 4)
124     {
125         m_dcGrid.SetPixel(i,nTopGridPix,m_crGridColor);
126         m_dcGrid.SetPixel(i,nMidGridPix,m_crGridColor);
127         m_dcGrid.SetPixel(i,nBottomGridPix,m_crGridColor);
128     }
129
130     //create some fonts (horiaontal  and vertical )
131     //use a height  of 14 pixels and 300 weight
132     //(this may need  to be adjusted depending on the display )
133
134     axisFont.CreateFont (14, 0, 0, 0, 300,
135                        FALSE, FALSE, 0, ANSI_CHARSET,
136                        OUT_DEFAULT_PRECIS,
137                        CLIP_DEFAULT_PRECIS,
138                        DEFAULT_QUALITY,
139                        DEFAULT_PITCH|FF_SWISS, _T("Arial"));
140     yUnitFont.CreateFont (14, 0, 900, 0, 300,
141                        FALSE, FALSE, 0, ANSI_CHARSET,
142                        OUT_DEFAULT_PRECIS,
143                        CLIP_DEFAULT_PRECIS,
144                        DEFAULT_QUALITY,
145                        DEFAULT_PITCH|FF_SWISS, _T("Arial")) ;
146
147     //grab the horizontal font
148     oldFont = m_dcGrid.SelectObject(&axisFont);
149
150     //y max
151     m_dcGrid.SetTextColor(m_crGridColor);
152     m_dcGrid.SetTextAlign(TA_RIGHT|TA_TOP);
153     strTemp.Format (_T("%.*lf"),m_nYDecimal, m_dYUpperLimit) ;//*号会被m_nYDecimals取代,表示保留几位小数
154     m_dcGrid.TextOutW(m_rectPlot.left - 4,m_rectPlot.top,strTemp);
155
156     m_dcGrid.SetTextAlign (TA_LEFT|TA_TOP) ;
157     m_dcGrid.TextOut (m_rectPlot.left - 4, m_rectPlot.bottom - (0 - m_dYLowerLimit) * m_dVerticalFactor, _T("0")) ;
158     //y min
159     m_dcGrid.SetTextAlign(TA_RIGHT|TA_BASELINE);
160     strTemp.Format(_T("%.*lf"),m_nYDecimal,m_dYLowerLimit);
161     m_dcGrid.TextOutW(m_rectPlot.left - 4,m_rectPlot.bottom,strTemp);
162
163     //x min
164     m_dcGrid.SetTextAlign (TA_LEFT|TA_TOP) ;
165     m_dcGrid.TextOut (m_rectPlot.left, m_rectPlot.bottom+4, _T("0")) ;
166     //横坐标
167     for(int i = 1;i <= 5;i++)
168     {
169         m_dcGrid.SetTextAlign(TA_CENTER|TA_TOP);
170         strTemp.Format(_T("%d"),m_dXUpperLimit * i / 6);
171         m_dcGrid.TextOut((m_rectPlot.left + m_nPlotWidth * i / 6),m_rectPlot.bottom + 4, strTemp);
172     }
173     // x max
174      m_dcGrid.SetTextAlign (TA_RIGHT|TA_TOP) ;
175      strTemp.Format (_T("%d"), m_dXUpperLimit) ;
176      m_dcGrid.TextOut (m_rectPlot.right, m_rectPlot.bottom+4, strTemp) ;
177
178      // x units
179     m_dcGrid.SetTextAlign (TA_CENTER|TA_TOP) ;
180     m_dcGrid.TextOut (m_rectPlot.right - 70,
181                     m_rectPlot.bottom+4, m_strXUnitsString) ;
182     //title
183     m_dcGrid.SetTextAlign (TA_CENTER|TA_TOP) ;
184     m_dcGrid.TextOut ((m_rectPlot.left+m_rectPlot.right)/2,
185         m_rectPlot.top-17, m_sTitile) ;
186
187     // restore the font
188     m_dcGrid.SelectObject(oldFont) ;
189     // y units
190     oldFont = m_dcGrid.SelectObject(&yUnitFont) ;
191     m_dcGrid.SetTextAlign (TA_CENTER|TA_BASELINE) ;
192     m_dcGrid.TextOut ((m_rectClient.left+m_rectPlot.left)/2,
193                     (m_rectPlot.bottom+m_rectPlot.top)/2, m_strYUnitsString) ;
194     m_dcGrid.SelectObject(oldFont) ;
195
196     //创建画曲线的内存DC和兼容Bitmap
197     if (m_dcPlot.GetSafeHdc() == NULL)
198     {
199         m_dcPlot.CreateCompatibleDC(&dc) ;
200         m_pBitmapPlot.CreateCompatibleBitmap(&dc, m_nClientWidth, m_nClientHeight) ;
201         m_pBitmapOldPlot = m_dcPlot.SelectObject(&m_pBitmapPlot) ;
202     }
203     // make sure the plot bitmap is cleared
204     m_dcPlot.SetBkColor (m_crBackColor) ;
205     m_dcPlot.FillRect(m_rectClient, &m_brushBack) ;
206 }
207
208 //set title
209 void CDrawView::SetTitle(CString title)
210 {
211     m_sTitile = title;
212     InvalidateCtrl();
213 }
214 void CDrawView::SetYRange(double dYLower, double dYUpper, int nYDecimalPlaces)
215 {
216   ASSERT(dYUpper > dYLower) ;
217
218   m_dYLowerLimit     = dYLower ;
219   m_dYUpperLimit     = dYUpper ;
220   m_nYDecimal      = nYDecimalPlaces ;
221   m_dYRange          = m_dYUpperLimit - m_dYLowerLimit ;
222   m_dVerticalFactor = (double)m_nPlotHeight / m_dYRange ;
223
224   InvalidateCtrl() ;
225 } // SetYRange
226
227 void CDrawView::SetXRange(int dXLower,int dXUpper,int nXDecimalPlaces)
228 {
229     ASSERT(dXUpper > dXLower);
230
231     m_dXLowerLimit = dXLower;
232     m_dXUpperLimit = dXUpper;
233     m_nXDecimal = nXDecimalPlaces;
234     m_dXRange = m_dXUpperLimit - m_dXLowerLimit;
235     m_dHorizontalFactor = (double)m_nPlotWidth / m_dXRange / 400.0 /** (m_updateRate * 400)*/;
236
237     InvalidateCtrl();
238 }
239
240 void CDrawView::SetXUnits(CString string)
241 {
242     m_strXUnitsString = string ;
243     InvalidateCtrl() ;
244
245 }  // SetXUnits
246
247
248 void CDrawView::SetYUnits(CString string)
249 {
250     m_strYUnitsString = string ;
251     InvalidateCtrl() ;
252
253 }  // SetYUnits
254
255 void CDrawView::SetGridColor(COLORREF color)
256 {
257     m_crGridColor = color ;
258     InvalidateCtrl() ;
259
260 }  // SetGridColor
261
262 void CDrawView::SetPlotColor(COLORREF color)
263 {
264     m_crPlotColor = color ;
265
266     m_penPlot.DeleteObject() ;
267     m_penPlot.CreatePen(PS_SOLID, 0, m_crPlotColor) ;
268     InvalidateCtrl() ;
269
270 }  // SetPlotColor
271
272 void CDrawView::SetBackgroundColor(COLORREF color)
273 {
274     m_crBackColor = color ;
275
276     m_brushBack.DeleteObject() ;
277     m_brushBack.CreateSolidBrush(m_crBackColor) ;
278     InvalidateCtrl() ;
279
280 }  // SetBackgroundColor
281
282 void CDrawView::AppendPoint(CPoint *newpPoint)
283 {
284     //在plotBitmap上继续画刚接收到的一个数据点,如果一次画本次接收到的所有数据,耗时严重,实时性不强
285     CPoint dPrevious;
286
287     dPrevious = m_dCurrentPosition;
288     m_dCurrentPosition = *newpPoint;
289     //根据新来的数据点更新纵坐标
290     if(m_dCurrentPosition.y < m_dYLowerLimit)
291     {
292         m_dYLowerLimit = m_dCurrentPosition.y;
293     }
294     if(m_dCurrentPosition.y > m_dYUpperLimit)
295     {
296         m_dYUpperLimit = m_dCurrentPosition.y;
297     }
298     //将数据保存在链表里用于重绘以及后面的参数计算
299     dataList.AddTail(m_dCurrentPosition);
300     //在plotBitmap上接着画当前数据点
301     DrawPoint();
302     //在界面上显示出来
303     //在这里要注意CClientDC和CPaintDC的区别,一定要避免在OnPaint函数里直接或间接的用CClientDC,这样会使界面一直重绘,造成假死现象
304     if(IsWindow(this->m_hWnd))
305     {
306         CClientDC dc(this) ;  // device context for painting
307         CDC memDC ;            //定义一个内存设备描述表对象(即后备缓冲区)
308         CBitmap memBitmap ;    //定义一个位图对象
309         CBitmap* oldBitmap ; // bitmap originally found in CMemDC
310
311         if(dc.GetSafeHdc() != NULL)
312         {
313             memDC.CreateCompatibleDC(&dc) ;//建立与屏幕设备描述表(前端缓冲区)兼容的内存设备描述表句柄(后备缓冲区)
314             memBitmap.CreateCompatibleBitmap(&dc, m_nClientWidth, m_nClientHeight) ;//建立一个与屏幕设备描述表(或者内存设备描述表)兼容的位图
315             oldBitmap = (CBitmap *)memDC.SelectObject(&memBitmap) ;//只有选入了位图的设备描述表才有地方绘图,画到指定的位图上
316
317             if (memDC.GetSafeHdc() != NULL)
318             {
319                 // first drop the grid on the memory dc
320                 memDC.BitBlt(0, 0, m_nClientWidth, m_nClientHeight,
321                          &m_dcGrid, 0, 0, SRCCOPY) ;
322              // now add the plot on top as a "pattern" via SRCPAINT.
323              // works well with dark background and a light plot
324                 memDC.BitBlt(0, 0, m_nClientWidth, m_nClientHeight,
325                            &m_dcPlot, 0, 0, SRCPAINT) ;  //SRCPAINT
326              // finally send the result to the display
327                 dc.BitBlt(0, 0, m_nClientWidth, m_nClientHeight,
328                           &memDC, 0, 0, SRCCOPY) ;
329             }
330
331             memDC.SelectObject(oldBitmap) ;
332         }
333     }
334 }
335 //将当前数据点绘制到plotBitmap上
336 void CDrawView::DrawPoint()
337 {
338     double currX, prevX, currY, prevY ;
339
340     CPen *oldPen ;
341     CRect rectCleanUp ;
342
343     if (m_dcPlot.GetSafeHdc() != NULL)
344     {
345
346         oldPen = m_dcPlot.SelectObject(&m_penPlot) ;
347      // 移到由prevX和prevY指定的前一个位置
348         prevX = m_rectPlot.left +  m_dPreviousPosition.x * m_dHorizontalFactor;
349         prevY = m_rectPlot.bottom -
350               (long)((m_dPreviousPosition.y - m_dYLowerLimit) * m_dVerticalFactor);
351         m_dcPlot.MoveTo (prevX, prevY);
352
353      // 画到当前点的位置
354         currX = m_rectPlot.left + m_dCurrentPosition.x * m_dHorizontalFactor;
355         currY = m_rectPlot.bottom -
356             (long)((m_dCurrentPosition.y - m_dYLowerLimit) * m_dVerticalFactor);
357         m_dcPlot.LineTo (currX, currY);
358
359     // restore the pen
360         m_dcPlot.SelectObject(oldPen) ;
361     // store the current point for connection to the next point
362         m_dPreviousPosition.x = m_dCurrentPosition.x ;
363         m_dPreviousPosition.y = m_dCurrentPosition.y;
364   }
365
366 } // end DrawPoint
367 void CDrawView::OnPaint()
368 {
369         if(m_dcGrid.GetSafeHdc() != NULL)
370         {
371             m_dcGrid.DeleteDC();
372             m_pBitmapGrid.DeleteObject();
373         }
374         if(m_dcPlot.GetSafeHdc() != NULL)
375         {
376             m_dcPlot.DeleteDC();
377             m_pBitmapPlot.DeleteObject();
378         }
379
380     InvalidateCtrl();
381
382     double pointX,pointY;
383     CPoint tempPoint;
384     CPen *oldPen1 ;
385     //dataList1.RemoveAll();
386     if(dataList.GetCount() > 1)
387     {
388         //绘图区域大小已经改变,需要重绘
389         if(m_dcPlot.GetSafeHdc() != NULL )
390         {
391             oldPen1 = m_dcPlot.SelectObject(&m_penPlot) ;
392             POSITION pos1 = dataList.GetHeadPosition();
393
394             tempPoint = dataList.GetNext(pos1);
395             pointX = m_rectPlot.left + tempPoint.x * m_dHorizontalFactor;
396             pointY = m_rectPlot.bottom -
397                 (long)((tempPoint.y - m_dYLowerLimit) * m_dVerticalFactor);
398             m_dcPlot.MoveTo(pointX,pointY);
399             CString str;
400             str.Format(_T("long is %d"),dataList.GetCount());
401             //TRACE(str);
402             for(int i = 1; i < dataList.GetCount();i++ )
403             {
404                 tempPoint = dataList.GetNext(pos1);
405                 pointX = m_rectPlot.left + tempPoint.x * m_dHorizontalFactor;
406                 pointY = m_rectPlot.bottom -
407                 (long)((tempPoint.y - m_dYLowerLimit) * m_dVerticalFactor);
408                 m_dcPlot.LineTo(pointX,pointY);
409                 m_dcPlot.MoveTo(pointX,pointY);
410             }
411             m_dcPlot.SelectObject(oldPen1);
412         }
413     }
414
415
416     if(m_nClientHeight != 0)
417     {
418         CPaintDC dc(this) ;  // device context for painting
419
420         CDC memDC ;            //定义一个内存设备描述表对象(即后备缓冲区)
421         CBitmap memBitmap ;    //定义一个位图对象
422         CBitmap* oldBitmap ; // bitmap originally found in CMemDC
423
424         memDC.CreateCompatibleDC(&dc) ;//建立与屏幕设备描述表(前端缓冲区)兼容的内存设备描述表句柄(后备缓冲区)
425         memBitmap.CreateCompatibleBitmap(&dc, m_nClientWidth, m_nClientHeight) ;//建立一个与屏幕设备描述表(或者内存设备描述表)兼容的位图
426         oldBitmap = (CBitmap *)memDC.SelectObject(&memBitmap) ;//只有选入了位图的设备描述表才有地方绘图,画到指定的位图上
427
428         if (memDC.GetSafeHdc() != NULL)
429         {
430
431              //first drop the grid on the memory dc
432             memDC.BitBlt(0, 0, m_nClientWidth, m_nClientHeight,
433                  &m_dcGrid, 0, 0, SRCCOPY) ;
434              // now add the plot on top as a "pattern" via SRCPAINT.
435          // works well with dark background and a light plot
436
437             memDC.BitBlt(0, 0, m_nPlotWidth, m_nPlotHeight,
438                    &m_dcPlot, 0, 0, SRCPAINT) ;  //SRCPAINT
439           //finally send the result to the display
440             dc.BitBlt(0, 0, m_nClientWidth, m_nClientHeight,
441                   &memDC, 0, 0, SRCCOPY) ;
442
443         }
444
445         memDC.SelectObject(oldBitmap) ;
446         memDC.DeleteDC();
447         memBitmap.DeleteObject();
448     }
449 }
450
451
452 void CDrawView::Reset()
453 {
454   InvalidateCtrl() ;
455 }
456
457
458 BOOL CDrawView::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
459 {
460     // TODO: 在此添加专用代码和/或调用基类
461     BOOL result;
462     static CString className = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW);//注册窗口类,返回值包含创建的窗口类的信息
463     result = CWnd::CreateEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE,
464                           className, NULL, dwStyle,
465                           rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
466                           pParentWnd->GetSafeHwnd(), (HMENU)nID) ;
467     m_dPreviousPosition.x = 0;
468     m_dPreviousPosition.y = 0;
469
470     m_dCurrentPosition.x = 0;
471     m_dCurrentPosition.y = 0;
472     if (result != 0)
473         // InvalidateCtrl() ;
474
475     return result ;
476 }
477
478
479 void CDrawView::OnSize(UINT nType, int cx, int cy)
480 {
481     CWnd::OnSize(nType, cx, cy);
482
483     GetClientRect(&m_rectClient) ;
484     // set some member variables to avoid multiple function calls
485     m_nClientHeight = m_rectClient.Height() ;
486     m_nClientWidth  = m_rectClient.Width() ;
487     // the "left" coordinate and "width" will be modified in
488     // InvalidateCtrl to be based on the width of the y axis scaling
489     m_rectPlot.left   = 20 ;
490     m_rectPlot.top    = 25;
491     m_rectPlot.right  = m_rectClient.right-10 ;
492     m_rectPlot.bottom = m_rectClient.bottom-25 ;
493
494     // set some member variables to avoid multiple function calls
495     m_nPlotHeight = m_rectPlot.Height() ;
496     m_nPlotWidth  = m_rectPlot.Width() ;
497
498     // set the scaling factor for now, this can be adjusted
499     // in the SetRange functions
500     m_dVerticalFactor = (double)m_nPlotHeight / m_dYRange ;
501     m_dHorizontalFactor = (double)m_nClientWidth / m_dXRange /400.0 /** (m_updateRate * 400)*/;
502
503 }
504 void CDrawView::setUpdateRate(double updateRate)
505 {
506     m_updateRate = updateRate;
507 }

时间: 2024-10-05 23:27:51

MFC--根据串口采集的数据借助GDI绘制曲线的相关文章

51采集PCF8591数据通过ESP8266上传C#上位机

效果    如果想用手机做可以参考这篇文章,自己的协议规定在文章中 android 之TCP客户端编程 ---恢复内容开始--- 请问一下博客为什么又不能直接复制粘贴图片了呢............ 先看8266的配置,8266我是用的Lua语言写的,,因为方便快捷....这次写的当然比以前完善...... 关于WIFI模块可以看这几篇 ESP8266使用详解 NodeMCU初探 ESP8266刷AT固件与nodemcu固件 (一)Lua脚本语言入门 (二)Lua脚本语言入门 (三)Lua脚本语

基于opencv和mfc的摄像头采集代码(GOMFCTemplate2)

基于opencv和mfc的摄像头采集框架(GOMFCTemplate2) 编写带界面的图像处理程序,选择opencv+mfc是一种很好的选择:在读取摄像头数据方面,网上的方法很多,其中shiqiyu的camerads的方法是较好的. 基于现有资料,通过在实际项目中的积累,我总结出来一套结合opencv和mfc的摄像头采集框架.具有以下特点: 1.基于directshow,兼容性好,速度快.到目前为止,无论是工业相机还是普通相机,没发现不兼容的: 2.摄像头部分通过线程读取,保证界面的运行流畅:

[转]MFC子线程更改图像数据后更新主窗口图像显示方法

程序思路是由外部的输入输出控制卡发出采集图像信号,之后相机采集图像得到图像数据指针,接收图像数据指针创建成图像最后显示到MFC对话框应用程序的Picture Control控件上,同时,为了标定相机位置,在主对话框类CMyDlg的OnPaint函数中有对Picture Control的绘图操作(不改变图像数据,进行画线,画矩形等操作). 设计时考虑到I/O卡何时发出采集信号或者相机何时得到图像数据指针是不确定的(不使用OnTime),同时考虑到I/O卡和相机的回调函数与主程序之间的数据交换会更加

C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子)

转自原文C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子) 阅读目录 1.HtmlAgilityPack简介 2.XPath技术介绍与使用 3.采集天气网站案例 4.资源 第一次接触HtmlAgilityPack是在5年前,一些意外,让我从技术部门临时调到销售部门,负责建立一些流程和寻找潜在客户,最后在阿里巴巴找到了很多客户信息,非常全面,刚开始是手动复制到Excel,是真尼玛的累,虽然那个时候C#还很菜,也想能不能通过程序来批量获取(所以平时想法要多才好).几

用IO模拟串口协议发送数据

<pre name="code" class="cpp">//文件usend.h #ifndef _USEND_H_ #define _USEND_H_ //====红外接收相关定义============================= #define PuTx_High (P_uTx = 1) //数据高 #define PuTx_Low (P_uTx = 0) //数据低 #define V_SendDatNum 6//6 //发送数据字节数 /

抓取网页中的内容、如何解决乱码问题、如何解决登录问题以及对所采集的数据进行处理显示的过程

本文主要介绍如何抓取网页中的内容.如何解决乱码问题.如何解决登录问题以及对所采集的数据进行处理显示的过程.效果如下所示: 1.下载网页并加载至HtmlAgilityPack 这里主要用WebClient类的DownloadString方法和HtmlAgilityPack中HtmlDocument类LoadHtml方法来实现.主要代码如下. var url = page == 1 ? "http://www.cnblogs.com/" : "http://www.cnblogs

android4.2串口jni收发数据(基于自定义协议)

代码已经验证过,没问题 ! 代码层次结构: |-----serial_communication_class--- |                     |-------src--------- |                                  |------com------ |                                             |----object----- |                                

将HTML表格的每行每列转为数组,采集表格数据

将HTML表格的每行每列转为数组,采集表格数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 //将HTML表格的每行每列转为数组,采集表格数据 <? function get_td_array($table) { $table = preg_replace("'<table[^>]*?>'si","",$table); //OSPHP.COm.CN

第七章 KinectV2结合MFC显示和处理图像数据(下)

第七章  KinectV2结合MFC显示和处理图像数据(下) 首先声明一下,本系统所使用的开发环境版本是计算机系统Windows 10.Visual Studio 2013.Opencv3.0和Kinect SDK v2.0.这些都可以在百度上找到,download下来安装一下即可. 一.在MFC中如何显示OpenCV的图像Mat 前段时间一直在学习opencv,但学习过程中写的例子都是基于控制台的.今天打算把之前写的一些例子都移植到MFC中,基本上就是复制以前的代码,唯一的区别在于在控制台中,