#pragma once // TimeGraphics_Ctrl.h : header file // #include <math.h> / // CTimeGraphics_Ctrl window #define GRID_X_NUMBER 10 //X轴坐标栅格数 #define GRID_Y_NUMBER 10 //Y轴坐标栅格数 #define FULL_SHOW_CELL_NUMBER 50 //最多显示数目 class CTimeGraphics_Ctrl : public CStatic { private: CPtrArray m_Data_Array; double m_Coordiante_Y_MaxData; double m_Coordiante_Y_MinData; CFont mFont; // Construction public: CTimeGraphics_Ctrl() { m_BackColor = RGB(0,0,0); m_GridLineColor = RGB(160, 160, 160); m_TextColor = RGB(255, 255, 255); m_DataLineColor = RGB(0, 255, 0); m_Coordiante_Y_MaxData = 100; m_Coordiante_Y_MinData = 0; m_Data_Array.RemoveAll(); } virtual ~CTimeGraphics_Ctrl() { mFont.DeleteObject(); Reset_Data(); // } // Attributes public: COLORREF m_TextColor; COLORREF m_BackColor; COLORREF m_GridLineColor; COLORREF m_DataLineColor; // Operations public: int Insert_Data(double dbData) //插入新数据 { while(m_Data_Array.GetSize() >= FULL_SHOW_CELL_NUMBER) //删除超出规定长度的数据 { double *pCell = (double *)m_Data_Array.GetAt(0); delete pCell; m_Data_Array.RemoveAt(0); } double *pNewCell = (double *)new double; *pNewCell = dbData; m_Data_Array.Add(pNewCell); //加入新数据 //处理范围 double min=dbData, max=dbData; for(int nPos=0; nPos<m_Data_Array.GetSize(); nPos++) { double *pCell = (double *)m_Data_Array.GetAt(nPos); if(*pCell < min) min = *pCell; if(*pCell > max) max = *pCell; } Auto_Zoom_Range(min, max); //自动缩放 m_Coordiante_Y_MinData = min; m_Coordiante_Y_MaxData = max; //刷新 if(GetSafeHwnd()) Invalidate(); return( m_Data_Array.GetSize() ); } void Reset_Data(double min=0, double max=0) //复位数据序列 { while(m_Data_Array.GetSize() > 0) { double *pCell = (double *)m_Data_Array.GetAt(0); delete pCell; m_Data_Array.RemoveAt(0); } m_Coordiante_Y_MaxData = max; m_Coordiante_Y_MinData = min; if(GetSafeHwnd()) Invalidate(); } // protected: void OnPaint(CDC *pDC) { CRect rcBounds; GetClientRect(&rcBounds); CDC memDC; memDC.CreateCompatibleDC(pDC); int saveDC = memDC.SaveDC(); CBitmap bitmap; bitmap.CreateCompatibleBitmap(pDC,rcBounds.Width(),rcBounds.Height()); CBitmap *pold_Bitmap = memDC.SelectObject(&bitmap); memDC.FillSolidRect(rcBounds, m_BackColor); //填充背景色 if(mFont.m_hObject == NULL) mFont.CreatePointFont(96, _T("宋体")); //创建默认字体 CFont *pFont = memDC.SelectObject(&mFont); //选择字体 TEXTMETRIC mTextMetrics; memDC.GetTextMetrics(&mTextMetrics); //获取字体属性 CRect TextRect = rcBounds; TextRect.right = TextRect.left + 6 * mTextMetrics.tmAveCharWidth; //保留坐标显示字体区域 CRect rect = rcBounds; rect.left = TextRect.right + 1; rect.right -= 1; int wx = rect.Width() / GRID_X_NUMBER; int ex = rect.Width() - GRID_X_NUMBER * wx; rect.left += ex/2; rect.right -= ex/2; rect.top = rect.top + mTextMetrics.tmHeight /2 + 1; rect.bottom = rect.bottom - mTextMetrics.tmHeight /2 - 1; int hy = rect.Height() / GRID_Y_NUMBER; int ey = rect.Height() - GRID_Y_NUMBER * hy; rect.top += ey/2; rect.bottom -= ey/2; memDC.SetBkMode(TRANSPARENT); //背景不接触模式 memDC.SetTextColor(m_TextColor); //设置字体颜色 if(1) //绘制网格 { CBrush brush(m_GridLineColor); //CBrush *pBrush = memDC.SelectObject(&brush); memDC.FrameRect(rect, &brush); //memDC.SelectObject(pBrush); int i; //竖直的坐标线 double dx = rect.Width() / GRID_X_NUMBER; CPen pen(PS_DOT,1, m_GridLineColor); CPen *oldpen = memDC.SelectObject(&pen); double xx = rect.left; CPoint s_p(rect.left,rect.top),e_p(rect.left,rect.bottom); for(i=0; i<=GRID_X_NUMBER; i++) { if(i!=0 && i!=GRID_X_NUMBER) { memDC.MoveTo((int)xx, rect.top); memDC.LineTo((int)xx, rect.bottom); } xx += dx; } //水平的坐标线 double dy = rect.Height() / GRID_Y_NUMBER; double yy = rect.bottom; for(i=0; i<=GRID_Y_NUMBER; i++) { if(i%2==0) { CRect txtRect = TextRect; txtRect.top = (int)(yy - mTextMetrics.tmHeight/2.0)-1; txtRect.bottom = (int)(yy + mTextMetrics.tmHeight/2.0)+1; double tmpDb = m_Coordiante_Y_MinData + (m_Coordiante_Y_MaxData - m_Coordiante_Y_MinData) * i/GRID_Y_NUMBER; CString str = Printf_Format_Data(tmpDb); memDC.DrawText(str, txtRect, DT_SINGLELINE | DT_RIGHT | DT_VCENTER); } if(i!=0 && i != GRID_Y_NUMBER) { memDC.MoveTo(rect.left, (int)yy); memDC.LineTo(rect.right, (int)yy); } yy -= dy; } memDC.SelectObject(oldpen); //恢复画笔 } //绘制数据 if(m_Data_Array.GetSize() > 0) { CPen LinePen(PS_SOLID, 1, m_DataLineColor); CPen *pOldPen = memDC.SelectObject( & LinePen); double dx = (double) rect.Width() / (double)FULL_SHOW_CELL_NUMBER; double sx = rect.left + (FULL_SHOW_CELL_NUMBER - m_Data_Array.GetSize()) * dx; double dy = (double)rect.Height() / (m_Coordiante_Y_MaxData - m_Coordiante_Y_MinData) ; for(int nPos=0; nPos<m_Data_Array.GetSize(); nPos++) { double *pCell = (double *)m_Data_Array.GetAt(nPos); double guiX = sx; double guiY = rect.bottom - (*pCell - m_Coordiante_Y_MinData) * dy; CRect fillRect((int)sx-2, (int)guiY-2, (int)sx+2, (int)guiY+2); memDC.FillSolidRect(&fillRect, m_DataLineColor); if(nPos == 0) { memDC.MoveTo((int)guiX, (int)guiY); } memDC.LineTo((int)guiX, (int)guiY); sx += dx; } memDC.SelectObject(pOldPen); } pDC->BitBlt(0,0,rcBounds.Width(),rcBounds.Height(),&memDC,0,0,SRCCOPY); memDC.SelectObject(pFont);//恢复字体 memDC.SelectObject(pold_Bitmap); //恢复位图 memDC.RestoreDC(saveDC); //恢复设备 bitmap.DeleteObject(); //删除位图 memDC.DeleteDC(); //删除设备 // Do not call CStatic::OnPaint() for painting messages } void Auto_Zoom_Range(double &min, double &max) { bool b_h_05 = 0; //0.5标记 double h_sig, h_rate, h_data; h_sig = max < 0 ? -1:1; h_data = fabs(max); if(h_data<5) { h_rate = 1; } else if(h_data<10.0) { h_rate = 0.1; b_h_05 = 1; } else if(h_data<100.0) { h_rate = 0.10; b_h_05 = 1; } else if(h_data < 1000.0) { h_rate = 0.01; b_h_05 = 1; } else if(h_data < 10000.0) { h_rate = 0.001; b_h_05 = 1; } else { h_rate = 0.0001; b_h_05 = 1; } h_data = h_data * h_rate; bool b_l_05 = 0; double l_sig, l_rate, l_data; l_sig = min < 0 ? -1:1; l_data = fabs(min); if(l_data<1) { l_rate = 1; } else if(l_data<10.0) { l_rate = 0.1; b_l_05 = 1; } else if(l_data<100.0) { l_rate = 0.010; b_l_05 = 1; } else if(l_data < 1000.0) { l_rate = 0.01; b_l_05 = 1; } else if(l_data < 10000.0) { l_rate = 0.001; b_l_05 = 1; } else { l_rate = 0.0001; b_l_05 = 1; } l_data = l_data * l_rate; if(l_data == h_data) { h_data += 0.1; l_data -= 0.1; } max = ceil(h_data); min = floor(l_data); if( b_h_05 && (max - h_data > 0.5)) { max -= 0.5; } if( b_l_05 && (l_data - min > 0.5) ) { min += 0.5; } max /= h_rate; max *= h_sig; min /= l_rate; min *= l_sig; } // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CTimeGraphics_Ctrl) //}}AFX_VIRTUAL virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { if(message == WM_ERASEBKGND) { return true; } if(message == WM_PAINT) { PAINTSTRUCT ps; CDC* pDC = BeginPaint(&ps); OnPaint(pDC); EndPaint(&ps); return true; } return CStatic::WindowProc(message, wParam, lParam); } }; / //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line.