402 lines
12 KiB
C++
402 lines
12 KiB
C++
// GraphView.cpp : 实现文件
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include <math.h>
|
|
#include "DrawGraph.h"
|
|
|
|
|
|
// CDrawGraph
|
|
|
|
IMPLEMENT_DYNAMIC(CDrawGraph, CWnd)
|
|
//========================================================
|
|
CDrawGraph::CDrawGraph()
|
|
{
|
|
//注册控件类
|
|
RegisterCtrlClass();
|
|
|
|
m_nMarginLeft = 40;
|
|
m_nMarginTop = 15;
|
|
m_nMarginRight = 15;
|
|
m_nMarginBottom = 30;
|
|
|
|
m_dbResolutionX = 1;
|
|
m_dbResolutionY = 1;
|
|
m_nDivisionX = 10;
|
|
m_nDivisionY = 10;
|
|
|
|
m_dbStartX = m_dbStartY = 0;
|
|
m_dbEndX = m_dbEndY = 100;
|
|
|
|
//颜色表
|
|
m_clrCoordBkg = RGB(255, 255, 255);
|
|
m_clrFrame = RGB(0, 0, 0);
|
|
m_clrWave = RGB(0, 0, 255);
|
|
}
|
|
//========================================================
|
|
CDrawGraph::~CDrawGraph()
|
|
{
|
|
}
|
|
//========================================================
|
|
void CDrawGraph::RegisterCtrlClass()
|
|
{
|
|
HINSTANCE hInstance = AfxGetInstanceHandle();
|
|
|
|
WNDCLASS wndclsCtrl;
|
|
ZeroMemory(&wndclsCtrl, sizeof(WNDCLASS));
|
|
|
|
if(::GetClassInfo(hInstance, STR_CLASS_NAME, &wndclsCtrl))
|
|
return;
|
|
|
|
//设置控件类信息
|
|
wndclsCtrl.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
|
wndclsCtrl.lpfnWndProc = ::DefWindowProc;
|
|
wndclsCtrl.cbClsExtra = 0;
|
|
wndclsCtrl.cbWndExtra = 0;
|
|
wndclsCtrl.hInstance = hInstance;
|
|
wndclsCtrl.hIcon = NULL;
|
|
wndclsCtrl.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
|
|
wndclsCtrl.hbrBackground = NULL;
|
|
wndclsCtrl.lpszMenuName = NULL;
|
|
wndclsCtrl.lpszClassName = STR_CLASS_NAME;
|
|
|
|
//注册控件类
|
|
AfxRegisterClass(&wndclsCtrl);
|
|
}
|
|
//========================================================
|
|
void CDrawGraph::SetViewFont(const CString& strFont, int nPointSize, int nWeight, BOOL bIsRedraw)
|
|
{
|
|
int nCount;
|
|
LOGFONT lf;
|
|
memset(&lf, 0, sizeof(LOGFONT));
|
|
|
|
//设置字体样式
|
|
nCount = sizeof(lf.lfFaceName)/sizeof(TCHAR);
|
|
COPYSTRING(lf.lfFaceName, nCount, strFont);
|
|
lf.lfHeight = nPointSize;
|
|
lf.lfWeight = nWeight;
|
|
lf.lfCharSet = GB2312_CHARSET;
|
|
|
|
//清楚已有样式
|
|
if(m_fontView.GetSafeHandle())
|
|
m_fontView.DeleteObject();
|
|
|
|
//设置字体
|
|
m_fontView.CreateFontIndirect(&lf);
|
|
|
|
if(bIsRedraw)
|
|
Invalidate();
|
|
}
|
|
//========================================================
|
|
void CDrawGraph::SetCoordinateLabel(const CString& _XAxis,const CString& _YAxis)
|
|
{
|
|
m_XAxisLabel=_XAxis;
|
|
m_YAxisLabel=_YAxis;
|
|
}
|
|
//========================================================
|
|
void CDrawGraph::SetMargin(int nLeft, int nTop, int nRight, int nBottom, BOOL bIsRedraw)
|
|
{
|
|
m_nMarginLeft = nLeft;
|
|
m_nMarginTop = nTop;
|
|
m_nMarginRight = nRight;
|
|
m_nMarginBottom = nBottom;
|
|
|
|
if(bIsRedraw)
|
|
Invalidate();
|
|
}
|
|
//========================================================
|
|
bool CDrawGraph::SetGraphyView(double dbStartX, double dbEndX, double dbStartY, double dbEndY, int nDivisionX, int nDivisionY, BOOL bIsRedraw)
|
|
{
|
|
if(nDivisionX<=1||nDivisionY<=1)
|
|
return false;
|
|
|
|
m_dbStartX = dbStartX;
|
|
m_dbEndX = dbEndX;
|
|
m_dbStartY = dbStartY;
|
|
m_dbEndY = dbEndY;
|
|
m_nDivisionX = nDivisionX;
|
|
m_nDivisionY = nDivisionY;
|
|
|
|
if(bIsRedraw)
|
|
Invalidate();
|
|
|
|
return true;
|
|
}
|
|
//========================================================
|
|
void CDrawGraph::SetResolution(double dbResolutionX, double dbResolutionY, BOOL bIsRedraw)
|
|
{
|
|
m_dbResolutionX = dbResolutionX;
|
|
m_dbResolutionY = dbResolutionY;
|
|
|
|
if(bIsRedraw)
|
|
Invalidate();
|
|
}
|
|
//========================================================
|
|
void CDrawGraph::RedrawGraph(BOOL bIsRedraw)
|
|
{
|
|
if(bIsRedraw)
|
|
Invalidate();
|
|
};
|
|
//========================================================
|
|
void CDrawGraph::LoadGraphyXAxisData(DataBuff& dataShow)
|
|
{
|
|
double dbData;
|
|
INT_PTR nCount = dataShow.GetCount();
|
|
|
|
if(nCount==0)
|
|
return;
|
|
|
|
m_dataGraphX.RemoveAll();
|
|
m_dataGraphX.SetSize(nCount);
|
|
for(int i=0; i<nCount; i++)
|
|
{
|
|
dbData = dataShow.ElementAt(i);
|
|
|
|
m_dataGraphX.SetAt(i, dbData);
|
|
}
|
|
//Invalidate();
|
|
}
|
|
//========================================================
|
|
void CDrawGraph::LoadGraphyYAxisData(DataBuff& dataShow)
|
|
{
|
|
double dbData;
|
|
INT_PTR nCount = dataShow.GetCount();
|
|
|
|
if(nCount==0)
|
|
return;
|
|
|
|
m_dataGraphY.RemoveAll();
|
|
m_dataGraphY.SetSize(nCount);
|
|
for(int i=0; i<nCount; i++)
|
|
{
|
|
dbData = dataShow.ElementAt(i);
|
|
|
|
m_dataGraphY.SetAt(i, dbData);
|
|
}
|
|
Invalidate();
|
|
}
|
|
//========================================================
|
|
void CDrawGraph::AddGraphyData(double _data)
|
|
{
|
|
m_dataGraphY.Add(_data);
|
|
Invalidate();
|
|
}
|
|
//=======================================================
|
|
void CDrawGraph::RemoveGraphyData(BOOL bIsRedraw)
|
|
{
|
|
m_dataGraphX.RemoveAll();
|
|
m_dataGraphY.RemoveAll();
|
|
if(bIsRedraw)
|
|
Invalidate();
|
|
};
|
|
|
|
//========================================================
|
|
void CDrawGraph::DrawCoordinate(CDC* pDC, CRect rectCoord)
|
|
{
|
|
CString strCoord;
|
|
CRect rectTemp;
|
|
int i, nSection, nOffset;
|
|
CSize szText, szUnit;
|
|
double dbTemp, dbTempStartY, dbTempStartX,
|
|
dbRangX = m_dbEndX-m_dbStartX,
|
|
dbRangY = m_dbEndY-m_dbStartY;
|
|
|
|
dbTempStartX = m_dbStartX;
|
|
dbTempStartY = m_dbStartY;
|
|
|
|
pDC->FillSolidRect(rectCoord, m_clrCoordBkg);
|
|
nOffset = 2;
|
|
for(i=0; i<=m_nDivisionX; i++)
|
|
{
|
|
dbTemp = dbTempStartX+dbRangX*i/m_nDivisionX;
|
|
strCoord.Format(_T("%.2f"), dbTemp);
|
|
|
|
nSection = rectCoord.Width()*i/m_nDivisionX;
|
|
szText = pDC->GetTextExtent(strCoord, strCoord.GetLength());
|
|
|
|
rectTemp.SetRect(rectCoord.left+nSection-szText.cx/2, rectCoord.bottom+nOffset, rectCoord.left+nSection+szText.cx/2, rectCoord.bottom+szText.cy+nOffset);
|
|
pDC->MoveTo(rectCoord.left+nSection, rectCoord.top);
|
|
pDC->LineTo(rectCoord.left+nSection, rectCoord.bottom);
|
|
pDC->DrawText(strCoord, strCoord.GetLength(), rectTemp, DT_CENTER);
|
|
}
|
|
|
|
nOffset = 2;
|
|
for(i=0; i<=m_nDivisionY; i++)
|
|
{
|
|
dbTemp = dbTempStartY+dbRangY*i/m_nDivisionY;
|
|
strCoord.Format(_T("%.2f"), dbTemp);
|
|
|
|
nSection = rectCoord.Height()*i/m_nDivisionY;
|
|
szText = pDC->GetTextExtent(strCoord, strCoord.GetLength());
|
|
|
|
rectTemp.SetRect(rectCoord.left-szText.cx-nOffset, rectCoord.bottom-nSection-szText.cy*2/3, rectCoord.left-nOffset, rectCoord.bottom-nSection+szText.cy/3);
|
|
pDC->MoveTo(rectCoord.left, rectCoord.top+nSection);
|
|
pDC->LineTo(rectCoord.right+1, rectCoord.top+nSection);
|
|
pDC->DrawText(strCoord, strCoord.GetLength(), rectTemp, DT_CENTER);
|
|
}
|
|
LOGFONT lf;
|
|
::ZeroMemory (&lf, sizeof (lf));
|
|
//lf.lfHeight = 160;
|
|
//lf.lfWeight = FW_BOLD;
|
|
lf.lfEscapement = 900;
|
|
lf.lfOrientation = 900;
|
|
|
|
CFont font;
|
|
font.CreatePointFontIndirect (&lf);
|
|
|
|
CFont* pOldFont = pDC->SelectObject (&font);
|
|
pDC->TextOut(rectCoord.left-40,rectCoord.top+(rectCoord.Height()/2)+30,m_YAxisLabel);//旋转90°输出
|
|
pDC->SelectObject (pOldFont);
|
|
pDC->TextOut(rectCoord.left-20+(rectCoord.Width()/2),rectCoord.bottom+15,m_XAxisLabel);
|
|
|
|
nOffset = 4;
|
|
rectTemp.SetRect(rectCoord.left+nOffset, rectCoord.top+1, rectCoord.right, rectCoord.bottom-nOffset);
|
|
pDC->FillSolidRect(rectTemp, m_clrCoordBkg);
|
|
}
|
|
//========================================================
|
|
void CDrawGraph::DrawActualCurve(CDC *pDC, CRect rectCoord)
|
|
{
|
|
CRect rectView;
|
|
CRgn rgnTemp, rgnView;
|
|
CPen penLine, *pOldPen;
|
|
INT_PTR nCountX = m_dataGraphX.GetCount();
|
|
INT_PTR nCountY = m_dataGraphY.GetCount();
|
|
|
|
if(nCountX==0 || nCountY==0 || nCountX<nCountY)
|
|
return;
|
|
|
|
double dbDataX(0.0),dbDataY(0.0);
|
|
int nOffsetX(0), nOffsetY(0),nOriginX(0),nOriginY(0);
|
|
dbDataX = m_dataGraphX.ElementAt(0);
|
|
dbDataY = m_dataGraphY.ElementAt(0);
|
|
nOriginX = rectCoord.left;
|
|
nOriginY = rectCoord.bottom;;
|
|
nOffsetX = static_cast<int>(m_dbResolutionX*(rectCoord.Width())*(dbDataX-m_dbStartX));
|
|
nOffsetY = static_cast<int>(m_dbResolutionY*(rectCoord.Height())*(dbDataY-m_dbStartY));
|
|
|
|
rgnTemp.CreateRectRgnIndirect(rectCoord);
|
|
pDC->SelectObject(rgnTemp);
|
|
penLine.CreatePen(PS_SOLID, 1, m_clrWave);
|
|
pOldPen = pDC->SelectObject(&penLine);
|
|
|
|
|
|
pDC->MoveTo(nOriginX+nOffsetX, nOriginY-nOffsetY);
|
|
|
|
for(int i=1; i<nCountY; i++)
|
|
{
|
|
dbDataX = m_dataGraphX.ElementAt(i);
|
|
dbDataY = m_dataGraphY.ElementAt(i);
|
|
nOffsetX = static_cast<int>(m_dbResolutionX*(rectCoord.Width())*(dbDataX-m_dbStartX));
|
|
nOffsetY = static_cast<int>(m_dbResolutionY*(rectCoord.Height())*(dbDataY-m_dbStartY));
|
|
pDC->LineTo(nOriginX+nOffsetX, nOriginY-nOffsetY);
|
|
}
|
|
pDC->SelectObject(pOldPen);
|
|
GetClientRect(rectView);
|
|
rgnView.CreateRectRgnIndirect(rectView);
|
|
pDC->SelectObject(rgnView);
|
|
}
|
|
//========================================================
|
|
void CDrawGraph::DrawIdealCurve(CDC *pDC, CRect rectCoord)
|
|
{
|
|
CRect rectView;
|
|
CRgn rgnTemp, rgnView;
|
|
CPen penLine, *pOldPen;
|
|
INT_PTR nCount = m_dataGraphY.GetCount();
|
|
|
|
if(nCount==0)
|
|
return;
|
|
|
|
double dbData;
|
|
int nOffsetX, nOffsetY;
|
|
int nRangX = abs(int((m_dbEndX-m_dbStartX)*m_dbResolutionX)),
|
|
nRangY = abs(int((m_dbEndY-m_dbStartY)*m_dbResolutionY));
|
|
int nCoordWith = rectCoord.Width(),
|
|
nCoordHeight = rectCoord.Height(),
|
|
nOriginX = rectCoord.left-int(m_dbStartX*nCoordWith/nRangX),
|
|
nOriginY = rectCoord.bottom+int(m_dbStartY*nCoordHeight/nRangY);
|
|
|
|
|
|
rgnTemp.CreateRectRgnIndirect(rectCoord);
|
|
pDC->SelectObject(rgnTemp);
|
|
penLine.CreatePen(PS_SOLID, 1, m_clrWave);
|
|
pOldPen = pDC->SelectObject(&penLine);
|
|
|
|
dbData = m_dataGraphY.ElementAt(0);
|
|
nOffsetY = int(nCoordHeight*dbData/nRangY);
|
|
pDC->MoveTo(nOriginX, nOriginY-nOffsetY);
|
|
|
|
for(int i=1; i<nCount; i++)
|
|
{
|
|
dbData = m_dataGraphY.ElementAt(i);
|
|
nOffsetX = int(nCoordWith*(i+1)/nRangX);
|
|
nOffsetY = int(nCoordHeight*dbData/nRangY);
|
|
|
|
pDC->LineTo(nOriginX+nOffsetX, nOriginY-nOffsetY);
|
|
}
|
|
pDC->SelectObject(pOldPen);
|
|
GetClientRect(rectView);
|
|
rgnView.CreateRectRgnIndirect(rectView);
|
|
pDC->SelectObject(rgnView);
|
|
}
|
|
//========================================================
|
|
BEGIN_MESSAGE_MAP(CDrawGraph, CWnd)
|
|
ON_WM_PAINT()
|
|
ON_WM_ERASEBKGND()
|
|
END_MESSAGE_MAP()
|
|
|
|
// CDrawGraph 消息处理程序
|
|
//========================================================
|
|
void CDrawGraph::PreSubclassWindow()
|
|
{
|
|
CWnd::PreSubclassWindow();
|
|
|
|
SetViewFont(_T("宋体"), 12, FW_NORMAL);
|
|
}
|
|
//========================================================
|
|
void CDrawGraph::OnPaint()
|
|
{
|
|
CPaintDC dc(this);
|
|
int nMode;
|
|
CRect rectClient, rectCoord, rectInfo, rectTemp;
|
|
CString strCaption, strOutputInfo;
|
|
CBitmap bitmapTemp, *pOldBitmap;
|
|
CFont* pOldFont;
|
|
CDC* pMemDC = new CDC;
|
|
|
|
//获取控件信息
|
|
GetClientRect(rectClient);
|
|
GetWindowText(strCaption);
|
|
|
|
//创建位图内存
|
|
bitmapTemp.CreateCompatibleBitmap(&dc, rectClient.Width(), rectClient.Height());
|
|
pMemDC->CreateCompatibleDC(&dc);
|
|
pOldBitmap = pMemDC->SelectObject(&bitmapTemp);
|
|
pOldFont = pMemDC->SelectObject(&m_fontView);
|
|
nMode = pMemDC->SetBkMode(TRANSPARENT);
|
|
|
|
//填充客户区
|
|
pMemDC->FillSolidRect(&rectClient, GetSysColor(COLOR_BTNFACE));
|
|
//绘制视图标题
|
|
pMemDC->DrawText(strCaption, strCaption.GetLength(), rectClient, DT_CENTER);
|
|
//绘制坐标框
|
|
rectCoord.SetRect(rectClient.left+m_nMarginLeft, rectClient.top+m_nMarginTop, rectClient.right-m_nMarginRight, rectClient.bottom-m_nMarginBottom);
|
|
DrawCoordinate(pMemDC, rectCoord);
|
|
//绘制波形
|
|
DrawActualCurve(pMemDC, rectCoord);
|
|
|
|
dc.BitBlt(0, 0, rectClient.Width(), rectClient.Height(), pMemDC, 0, 0, SRCCOPY);
|
|
|
|
pMemDC->SetBkMode(nMode);
|
|
pMemDC->SelectObject(pOldFont);
|
|
pMemDC->SelectObject(pOldBitmap);
|
|
ReleaseDC(pMemDC);
|
|
delete pMemDC;
|
|
}
|
|
|
|
//================================================================================================
|
|
BOOL CDrawGraph::OnEraseBkgnd(CDC* pDC)
|
|
{
|
|
//UNREFERENCED_PARAMETER(pDC);
|
|
//return TRUE;
|
|
return CWnd::OnEraseBkgnd(pDC);
|
|
} |