www.gusucode.com > VC++环境下从串口读取数据并实时绘制曲线图 > VC++环境下从串口读取数据并实时绘制曲线图/读取串口数据并画实时曲线的VC++程序源码/Graphics.cpp
#include "stdafx.h" //#include <windows.h> //#include <stdio.h> #include "graphics.h" /////////////////////////////////////////////////////////////////////////////// // class CGroupLines CGraphics::CGraphics() { m_Ratio.xmin = 0; m_Ratio.ymin = 0; m_Ratio.xmax = 1; m_Ratio.ymax = 1; m_nBackColor = RGB(255, 255, 255); m_nGridColor = RGB(192, 192, 192); m_nBorderColor = RGB(0, 0, 0); m_nTickColor = RGB(0, 0, 255); m_nTitleColor = RGB(255, 0, 0); m_nXDecimal = 0; m_nYDecimal = 0; XGridTicks = 10; YGridTicks = 10; XTicks = 50; YTicks = 50; m_bEnableLegend = true; m_bPrinting = false; m_bLegendShadow = true; m_bMemoryDraw = true; m_nPrintScale = 8; m_nAxesType = XY; m_nXStep = 0; m_nYStep = 0; m_LogFont.lfWidth = 0; m_LogFont.lfItalic = false; m_LogFont.lfUnderline = false; m_LogFont.lfStrikeOut = false; m_LogFont.lfCharSet = ANSI_CHARSET; m_LogFont.lfOutPrecision = OUT_DEFAULT_PRECIS; m_LogFont.lfClipPrecision = CLIP_DEFAULT_PRECIS; m_LogFont.lfQuality = PROOF_QUALITY; m_LogFont.lfPitchAndFamily = DEFAULT_PITCH; strcpy(m_LogFont.lfFaceName,"Ariel"); crTable[0] = RGB(255, 255, 255); // White crTable[1] = RGB( 0, 0, 0); // Black crTable[2] = RGB(255, 0, 0); // Red crTable[3] = RGB( 0, 255, 0); // Green crTable[4] = RGB( 0, 0, 255); // Blue crTable[5] = RGB(255, 0, 255); // Magenta crTable[6] = RGB( 0, 255, 255); // Cyan crTable[7] = RGB(128, 128, 128); // Grey crTable[8] = RGB(128, 128, 0); // Brown crTable[9] = RGB(128, 0, 128); // Purple crTable[10] = RGB( 0, 128, 128); // Aqua crTable[11] = RGB(128, 0, 0); // crTable[12] = RGB( 0, 128, 0); // crTable[13] = RGB( 0, 0, 128); // crTable[14] = RGB(192, 192, 192); // crTable[15] = RGB(255, 255, 0); // Yellow m_Bitmap = 0; } void CGraphics::SetPrintScale(HDC& hDC, RECT& rect) { int Width = ::GetDeviceCaps(hDC, HORZRES); int Height = ::GetDeviceCaps(hDC, VERTRES); int wd = abs(rect.right - rect.left); int ht = abs(rect.bottom - rect.top); m_nPrintScale = (wd + ht) / (Width + Height); m_bPrinting = true; RecalcRects(rect); } void CGraphics::RecalcRects(RECT& rt) { //m_Rect = rt; m_ClientRect = rt; SetPixelRect(rt); m_bM = (m_Rect.bottom - m_Rect.top) / 6; m_tM = (m_Rect.bottom - m_Rect.top) / 10; m_lM = m_rM = (m_Rect.right - m_Rect.left) / 8; m_PlotRect.left = m_Rect.left + m_lM; if (m_bEnableLegend) m_PlotRect.right= m_Rect.right - 3 * m_rM / 2; else m_PlotRect.right= m_Rect.right - m_rM; m_PlotRect.top = m_Rect.top + m_tM; m_PlotRect.bottom = m_Rect.bottom - m_bM; GL = m_PlotRect.left; GR = m_PlotRect.right; GT = m_PlotRect.top; GB = m_PlotRect.bottom; PX = GR - GL; PY = GB - GT; m_Scale.dx = (m_Scale.xmax- m_Scale.xmin) / PX; m_Scale.dy = (m_Scale.ymax- m_Scale.ymin) / PY; m_Size.cx = (PY < PX) ? PY : PX; } void CGraphics::BeginDraw(HDC hDC) { if (m_bPrinting || !m_bMemoryDraw) m_hDC = hDC; else { ::GetClipBox(hDC, &m_ClipBox); m_hDC = ::CreateCompatibleDC(hDC); m_Bitmap = ::CreateCompatibleBitmap(hDC, m_ClipBox.right - m_ClipBox.left, m_ClipBox.bottom - m_ClipBox.top); m_OldBitmap = (HBITMAP)::SelectObject(m_hDC, m_Bitmap); ::SetWindowOrgEx(m_hDC, m_ClipBox.left, m_ClipBox.top, NULL); } DrawBkGround(); } void CGraphics::EndDraw(HDC hDC) { if (m_bPrinting || !m_bMemoryDraw) { m_bPrinting = false; return; } ::BitBlt(hDC, m_ClipBox.left, m_ClipBox.top, m_ClipBox.right - m_ClipBox.left, m_ClipBox.bottom - m_ClipBox.top, m_hDC, m_ClipBox.left, m_ClipBox.top, SRCCOPY); ::SelectObject(m_hDC, m_OldBitmap); ::DeleteObject(m_Bitmap); ::DeleteDC(m_hDC); } void CGraphics::DrawBkGround() { HBRUSH hBrush = ::CreateSolidBrush(m_nBackColor); HBRUSH hBrold = (HBRUSH)::SelectObject(m_hDC, hBrush); ::Rectangle(m_hDC, m_ClientRect.left, m_ClientRect.top, m_ClientRect.right, m_ClientRect.bottom); ::SelectObject(m_hDC, hBrold); ::DeleteObject(hBrush); } void CGraphics::SetRatio(double xmin, double ymin, double xmax, double ymax) { m_Ratio.xmin = xmin; m_Ratio.ymin = ymin; m_Ratio.xmax = xmax; m_Ratio.ymax = ymax; } void CGraphics::GetPixelRect(RECT& rt) { rt.left = m_Rect.left; rt.top = m_Rect.top; rt.right = m_Rect.right; rt.bottom = m_Rect.bottom; } void CGraphics::SetPixelRect(RECT rt) { LONG Width = rt.right - rt.left; LONG Height = rt.bottom - rt.top; m_Rect.left = (LONG)(rt.left + m_Ratio.xmin * Width); m_Rect.top = (LONG)(rt.top + m_Ratio.ymin * Height); m_Rect.right = (LONG)(rt.right - (1 - m_Ratio.xmax) * Width); m_Rect.bottom = (LONG)(rt.bottom - (1 - m_Ratio.ymax) * Height); } void CGraphics::Title(const char* Title, int Pos) { m_LogFont.lfHeight = (int)(m_Size.cx / -15.0); if (m_LogFont.lfHeight > -10) m_LogFont.lfHeight = -10; m_LogFont.lfWeight = 700; m_LogFont.lfOrientation= 0; m_LogFont.lfEscapement = 0; m_Font = ::CreateFontIndirect(&m_LogFont); if (m_Font) { int bm = ::SetBkMode(m_hDC, TRANSPARENT); HFONT hOldFont = (HFONT)::SelectObject(m_hDC, m_Font); ::SetTextColor(m_hDC, RGB(0, 0, 0)); SetStringAlign(CENTER, CENTER); if (Pos == TOP) { PrintString((GL + GR) / 2, (m_Rect.top + GT ) / 2 + 1, 0, Title); ::SetTextColor(m_hDC, m_nTitleColor); PrintString((GL + GR) / 2, (m_Rect.top + GT ) / 2, 0, Title); } else { int n = m_Rect.bottom - (m_Rect.bottom - GB) / 3; PrintString((GL + GR) / 2, n + 1, 0, Title); ::SetTextColor(m_hDC, m_nTitleColor); PrintString((GL + GR) / 2, n, 0, Title); } ::SelectObject(m_hDC, hOldFont); ::DeleteObject(m_Font); ::SetBkMode(m_hDC, bm); } } void CGraphics::XAxisTitle(const char* Title, int Pos) { m_LogFont.lfHeight = (int)(m_Size.cx / -20.0); if (m_LogFont.lfHeight > -10) m_LogFont.lfHeight = -10; m_LogFont.lfWeight = 700; m_LogFont.lfOrientation= 0; m_LogFont.lfEscapement = 0; m_Font = ::CreateFontIndirect(&m_LogFont); if (m_Font) { int bm = ::SetBkMode(m_hDC, TRANSPARENT); HFONT hOldFont = (HFONT)::SelectObject(m_hDC, m_Font); ::SetTextColor(m_hDC, m_nTitleColor); SetStringAlign(CENTER, CENTER); if (Pos == TOP) PrintString((GL + GR) / 2, (m_Rect.top + GT ) / 2, 0, Title); else PrintString((GL + GR) / 2, m_Rect.bottom - (m_Rect.bottom - GB) / 3, 0, Title); ::SelectObject(m_hDC, hOldFont); ::DeleteObject(m_Font); ::SetBkMode(m_hDC, bm); } } void CGraphics::YAxisTitle(const char* Title, int Pos) { m_LogFont.lfHeight = (int)(m_Size.cx / -20.0); if (m_LogFont.lfHeight > -10) m_LogFont.lfHeight = -10; m_LogFont.lfWeight = 700; if (Pos == LEFT) { m_LogFont.lfOrientation= 900; m_LogFont.lfEscapement = 900; } else { m_LogFont.lfOrientation= -900; m_LogFont.lfEscapement = -900; } m_Font = ::CreateFontIndirect(&m_LogFont); if (m_Font) { int bm = ::SetBkMode(m_hDC, TRANSPARENT); HFONT hOldFont = (HFONT)::SelectObject(m_hDC, m_Font); ::SetTextColor(m_hDC, m_nTitleColor); SetStringAlign(CENTER, CENTER); if (Pos == LEFT) PrintString(m_Rect.left + (GL - m_Rect.left) / 3, (GT + GB) / 2, 90, Title); else PrintString(m_Rect.right - (m_Rect.right - GR) / 3, (GT + GB) / 2, -90, Title); ::SelectObject(m_hDC, hOldFont); ::DeleteObject(m_Font); ::SetBkMode(m_hDC, bm); } } void CGraphics::DrawBoundary(COLORREF cr, int size) { HPEN hPen = ::CreatePen(PS_SOLID, size, cr); HPEN hOldPen = (HPEN)::SelectObject(m_hDC, hPen); int n = 5; if (m_bPrinting) n *= m_nPrintScale; DrawRectangle(m_Rect.left + n, m_Rect.top + n, m_Rect.right - n, m_Rect.bottom - n); ::SelectObject(m_hDC, hOldPen); ::DeleteObject(hPen); } void CGraphics::Legend(COLORREF cr, int Index, const char* Name) { m_LogFont.lfHeight = (int)(m_Size.cx / -25.0); if (m_LogFont.lfHeight > -10) m_LogFont.lfHeight = -10; m_LogFont.lfWeight = 500; m_LogFont.lfOrientation= 0; m_LogFont.lfEscapement = 0; m_Font = ::CreateFontIndirect(&m_LogFont); if (m_Font) { int n = (m_Rect.right - GR) / 20 + 1; int xb = GR + 2 * n; int xe = xb + 4 * n; int y = GT - 3 * Index * m_LogFont.lfHeight / 2; DrawLine(xb, y, xe, y); int bm = ::SetBkMode(m_hDC, TRANSPARENT); HFONT hOldFont = (HFONT)::SelectObject(m_hDC, m_Font); ::SetTextColor(m_hDC, cr); SetStringAlign(LEFT, CENTER); PrintString(xe + n, y, 0, Name); ::SelectObject(m_hDC, hOldFont); ::DeleteObject(m_Font); ::SetBkMode(m_hDC, bm); } } void CGraphics::DrawCircle(int x, int y, int radius) { int x1 = x - radius; int y1 = y - radius; int x2 = x + radius; int y2 = y + radius; ::Arc(m_hDC, x1, y1, x2, y2, x, y2, x, y2); } void CGraphics::DrawFilledCircle(int x, int y, int radius) { int x1 = x - radius; int y1 = y - radius; int x2 = x + radius; int y2 = y + radius; ::Ellipse(m_hDC, x1, y1, x2, y2); } void CGraphics::DrawRectangle(int x1, int y1, int x2, int y2) { ::MoveToEx(m_hDC, x1, y1, NULL); ::LineTo(m_hDC, x1, y2); ::LineTo(m_hDC, x2, y2); ::LineTo(m_hDC, x2, y1); ::LineTo(m_hDC, x1, y1); } void CGraphics::PrintString(int x, int y, int theta, const char* fmt) { WORD Height, Width; UINT PreSet; double thta; PreSet = ::SetTextAlign(m_hDC, TA_LEFT|TA_TOP); SIZE size; ::GetTextExtentPoint32(m_hDC, fmt, lstrlen(fmt), &size); Height = (WORD)size.cy; Width = (WORD)size.cx; thta = PiV*theta/ConstV; if(m_StrAlign.HAlign == LEFT && m_StrAlign.VAlign == TOP) { } else if(m_StrAlign.HAlign == LEFT && m_StrAlign.VAlign == CENTER) { x = (int)(x - Height/2.*sin(thta)); y = (int)(y - Height/2.*cos(thta)); } else if(m_StrAlign.HAlign == CENTER && m_StrAlign.VAlign == TOP) { x = (int)(x - Width/2. * cos(thta)); y = (int)(y + Width/2. * sin(thta)); } else if(m_StrAlign.HAlign == CENTER && m_StrAlign.VAlign == CENTER) { x = (int)(x - Width/2. * cos(thta) - Height/2.*sin(thta)); y = (int)(y + Width/2. * sin(thta) - Height/2.*cos(thta)); } else if(m_StrAlign.HAlign == CENTER && m_StrAlign.VAlign == BOTTOM) { x = (int)(x - Width/2. * cos(thta) - Height*sin(thta)); y = (int)(y + Width/2. * sin(thta) - Height*cos(thta)); } else if(m_StrAlign.HAlign == RIGHT && m_StrAlign.VAlign == TOP) { x = (int)(x - Width * cos(thta)); y = (int)(y + Width * sin(thta)); } else if(m_StrAlign.HAlign == RIGHT && m_StrAlign.VAlign == CENTER) { x = (int)(x - Width * cos(thta) - Height/2.*sin(thta)); y = (int)(y + Width * sin(thta) - Height/2.*cos(thta)); } else if(m_StrAlign.HAlign == RIGHT && m_StrAlign.VAlign == BOTTOM) { x = (int)(x - Width * cos(thta) - Height*sin(thta)); y = (int)(y + Width * sin(thta) - Height*cos(thta)); } else //if(m_StrAlign.HAlign == LEFT && m_StrAlign.VAlign == BOTTOM) { x = (int)(x - Height*sin(thta)); y = (int)(y - Height*cos(thta)); } ::TextOut(m_hDC, x, y, fmt, lstrlen(fmt)); ::SetTextAlign(m_hDC, PreSet); } void CGraphics::Format(int decimal, char* str, float value) { char tstr[24]; switch(decimal) { case 0: sprintf(str, "%.f", value); return; case 1: sprintf(tstr, "%.1f", value); break; case 2: sprintf(tstr, "%.2f", value); break; case 3: sprintf(tstr, "%.3f", value); break; case 4: sprintf(tstr, "%.4f", value); break; default: sprintf(tstr, "%.5f", value); break; } if (fabs(value) > 0.99999) { _gcvt(atof(tstr), 12, str); if (str[lstrlen(str)-1] == '.') str[lstrlen(str)-1] = '\0'; } else { if (fabs(value) <1.0e-10) lstrcpy(str, "0"); else { lstrcpy(str, tstr); int n = lstrlen(str) - 1; while(str[n] == '0' && n >= 0) str[n--] = '\0'; } } } void CGraphics::Grid() { int i, j; HPEN hPen = ::CreatePen(PS_DOT, 0, m_nGridColor); HPEN hOldPen = (HPEN)::SelectObject(m_hDC, hPen); for(i = 1; i < XGridTicks; i ++) { j = GL + (int)(1.0 * i * (GR-GL) / XGridTicks); DrawLine(j, GT + 1, j, GB - 1); } for(i = 1; i < YGridTicks; i ++) { j = GT + (int)(1.0 * i * (GB-GT) / YGridTicks); DrawLine(GL + 1, j, GR - 1, j); } ::SelectObject(m_hDC, hOldPen); ::DeleteObject(hPen); } void CGraphics::XAxis() { int xb, yb, xe, ye; int i, j; char str[32]; float value; yb=GB; j = XTicks / 10; for(i = 0; i <= XTicks; i ++) { xb = xe = (int)(GL + 1.0 * PX * i / XTicks ); if((i % j) == 0) { ye = GB + m_bM / 7; value = (float)(m_Scale.xmin + i * (m_Scale.xmax - m_Scale.xmin) / XTicks); Format(m_nXDecimal, str, value); PrintString(xb, GB + m_bM / 5, 0, str); } else ye = GB + m_bM / 14; if (i > 0 && i < XTicks) DrawLine(xb, yb, xe, ye); } } void CGraphics::YAxis() { int xb, yb, xe, ye; int i, j; char str[32]; float value; xe = GL; j = YTicks / 10; for(i = 0; i <= YTicks; i ++) { yb = ye = (int)(GT + 1.0 * PY * i / YTicks ); if((i % j) == 0) { xb = GL - m_lM / 10; value = (float)(m_Scale.ymax - i * (m_Scale.ymax - m_Scale.ymin) / YTicks); Format(m_nYDecimal, str, value); PrintString(GL - m_lM / 6, yb, 0, str); } else xb = GL - m_lM / 20; if (i > 0 && i < YTicks) DrawLine(xb, yb, xe, ye); } } void CGraphics::Ticks() { SetStringAlign(CENTER, TOP); XAxis(); SetStringAlign(RIGHT, CENTER); YAxis(); } void CGraphics::RightYTick() { if (m_bEnableLegend) return; int xb, yb, xe, ye; int i, j, k; char str[32]; float value; xb = GR; SetStringAlign(LEFT, CENTER); if (m_nAxesType == XY || m_nAxesType == XLOG) { j = YTicks / 10; for(i = 0; i <= YTicks; i ++) { yb = ye = (int)(GT + 1.0 * PY * i / YTicks ); if((i % j) == 0) { xe = GR + m_rM / 10; value = (float)(m_Scale.ymax - i * (m_Scale.ymax - m_Scale.ymin) / YTicks); Format(m_nYDecimal, str, value); PrintString(GR + m_rM / 6, yb, 0, str); } else xe = GR + m_rM / 20; if (i > 0 && i < YTicks) DrawLine(xb, yb, xe, ye); } } else { for(i = 1; i <= m_nYStep; i ++) { for(j = 1; j <= 10; j ++) { if (k == 0) xe = GR + m_rM / 10; else xe = GR + m_rM / 20; yb = ye = GB - (int)(log10(j) * PY / m_nYStep + 1.0 * (i - 1) * PY / m_nYStep); if (j == 1) { value = (float)(pow(10.0, m_Scale.ymin) * pow(10.0, i - 1)); Format(m_nYDecimal, str, value); PrintString(GR + m_rM / 6, yb, 0, str); } if ((i != 1 || j != 1) && (i != m_nYStep || j != 10)) DrawLine(xb, yb, xe, ye); k = 1; } k=0; } value = (float)(pow(10.0, m_Scale.ymin) * pow(10.0, i - 1)); Format(m_nYDecimal, str, value); PrintString(GR + m_rM / 6, yb, 0, str); } } void CGraphics::Axes() { int bm = ::SetBkMode(m_hDC, TRANSPARENT); HPEN hPen = ::CreatePen(PS_SOLID, 0, m_nBorderColor); HPEN hOldPen = (HPEN)::SelectObject(m_hDC, hPen); DrawRectangle(GL, GT, GR, GB); m_LogFont.lfHeight = (int)(m_Size.cx / -25.0); if (m_LogFont.lfHeight > -10) m_LogFont.lfHeight = -10; m_LogFont.lfWeight = 500; m_LogFont.lfOrientation= 0; m_LogFont.lfEscapement = 0; m_Font = ::CreateFontIndirect(&m_LogFont); if (m_Font) { HFONT hOldFont = (HFONT)::SelectObject(m_hDC, m_Font); SetTextColor(m_hDC, m_nTickColor); Ticks(); RightYTick(); ::SelectObject(m_hDC, hOldFont); ::DeleteObject(m_Font); } ::SelectObject(m_hDC, hOldPen); ::DeleteObject(hPen); ::SetBkMode(m_hDC, bm); } void CGraphics::DrawMarker(int x, int y, int mode, int n) { if (m_bPrinting) n *= m_nPrintScale; switch(mode) { case CROSS: DrawLine(x - n, y, x + n, y ); DrawLine(x, y - n, x, y + n ); break; case STAR: DrawLine(x - n, y, x + n, y ); DrawLine(x - n / 2, (int)(y + n * sqrt(3.) / 2), x + n / 2, (int)(y - n * sqrt(3.) / 2)); DrawLine(x - n / 2, (int)(y - n * sqrt(3.) / 2), x + n / 2, (int)(y + n * sqrt(3.) / 2)); break; case FCIRCLE: DrawFilledCircle(x, y, n); break; case FTRIANGLE: { POINT p[3]; p[0].x = x - n; p[0].y = (int)(y + n * sqrt(3.) / 3); p[1].x = x + n; p[1].y = (int)(y + n * sqrt(3.) / 3); p[2].x = x; p[2].y = (int)(y - 2 * n * sqrt(3.) / 3); ::Polygon(m_hDC, p, 3); break; } case XCROSS: DrawLine((int)(x + n * sqrt(2.) / 2), (int)(y - n * sqrt(2.) / 2), (int)(x - n * sqrt(2.) / 2), (int)(y + n * sqrt(2.) / 2)); DrawLine((int)(x - n * sqrt(2.) / 2), (int)(y - n * sqrt(2.) / 2), (int)(x + n * sqrt(2.) / 2), (int)(y + n * sqrt(2.) / 2)); break; case CIRCLE: DrawCircle(x, y, n); break; case TRIANGLE: DrawLine(x - n, (int)(y + n * sqrt(3.) / 3), x + n, (int)(y + n * sqrt(3.) / 3)); DrawLine(x + n, (int)(y + n * sqrt(3.) / 3), x, (int)(y - 2 * n * sqrt(3.) / 3)); DrawLine(x, (int)(y - 2 * n * sqrt(3.) / 3), x - n, (int)(y + n * sqrt(3.) / 3)); break; case FSQUARE: ::Rectangle(m_hDC, x - n, y - n, x + n, y + n); break; case SQUARE: DrawRectangle(x - n, y - n, x + n, y + n ); break; case FDIAMOND: { POINT p[4]; p[0].x = x - n; p[0].y = y; p[1].x = x; p[1].y = y + n; p[2].x = x + n; p[2].y = y; p[3].x = x; p[3].y = y - n; ::Polygon(m_hDC, p, 4); break; } case DIAMOND: ::MoveToEx(m_hDC, x - n, y, NULL); ::LineTo(m_hDC, x, y + n); ::LineTo(m_hDC, x + n, y); ::LineTo(m_hDC, x, y - n); ::LineTo(m_hDC, x - n, y); break; } } void CGraphics::DrawShadow(int n) { HPEN m_CurPen = ::CreatePen(PS_SOLID, 0, RGB(127,127,127)); HPEN m_OldPen = (HPEN)::SelectObject(m_hDC, m_CurPen); HBRUSH hBrush = ::CreateSolidBrush(RGB(127,127,127)); HBRUSH hBrold = (HBRUSH)::SelectObject(m_hDC, hBrush); int w = (m_Rect.right - GR) / 20 + 1; int xb = GR + 2 * n; ::Rectangle(m_hDC, GR + (int)(2.2 * w), GT - m_LogFont.lfHeight, m_Rect.right - (int)(0.8 * w), GT - 2 * (n + 1) * m_LogFont.lfHeight); ::SelectObject(m_hDC, hBrold); ::DeleteObject(hBrush); ::SelectObject(m_hDC, m_OldPen); ::DeleteObject(m_CurPen); hBrush = ::CreateSolidBrush(RGB(255, 255, 255)); hBrold = (HBRUSH)::SelectObject(m_hDC, hBrush); ::Rectangle(m_hDC, GR + w, GT, m_Rect.right - 2 * w, GT - 2 * (n + 1) * m_LogFont.lfHeight + m_LogFont.lfHeight); ::SelectObject(m_hDC, hBrold); ::DeleteObject(hBrush); }