⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 graphiteview.cpp

📁 这是在wince下面可以跑的一个画函数的软件
💻 CPP
字号:
//
//	Graphite For WinCE(Pocket PC)
//  Initially Written By Hyouck "Hawk" Kim, peakhunt@yahoo.com
//	2002, All Rights Reserved
//
//	This is GPLed, open source based, software development project.
//	For more question about GPL,
//	visit http://www.gnu.org/licenses/gpl.txt
//
//	
//	Revision History
//	Nov/30/2002,		Initial Release		hkim	
//
//

// graphiteView.cpp : implementation of the CGraphiteView class
//

//////////////////////////////////////////////////////////////////////
//
// This is View implementation of Graphite.
//
// If you are familiar with Win32 Memory DC and related stuffs,
// I guess to read this code would be pretty easy.
//
// But still, we have a few challenging, I guess, issues. 
//
// First of all,
// Because of limited screen resolution, it's impossible to map each and every
// unique logical position to an unique screen pixel point.
// Because of this, sometimes, an ugly effect happens.
//
// Second of all,
// We have a performance issue.
// For example, for X axis, if the range is 8
// and if you want to use 0.01 value level X delta,
// It takes quite a time to draw the graph.
// For this problem, I guess we have no easy solution.
// Use of thread might look like a solution. But wait a minute.
// It doesn't solve any problem, that is, it doesn't make things faster.
//
// I guess the wise solution is just accept the fact and
// show some progress dialog while drawing graph.
//
//
// But Don't be so frustrated. Here are some good news.
// If we don't update screen because of mathematical change, that is, document change
// then we don't have to write a new same graph.
// That's because of I save all graph image in a memory device context.
//
// Here are some improvements need to be done.
// 1>We need scroll function.
//   Currently, if an user scrolls left/right/up/down,
//   the code reclaculates all points with a new X/Y values.
//   But we don't have to do that.
//   Better way is to draw only newly added area as a side effect of scrolling.
//
// Happy Graphying!!!
// H.Kim
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "graphite.h"

#include "graphiteDoc.h"
#include "graphiteView.h"
#include <math.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CGraphiteView

IMPLEMENT_DYNCREATE(CGraphiteView, CView)

BEGIN_MESSAGE_MAP(CGraphiteView, CView)
	//{{AFX_MSG_MAP(CGraphiteView)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGraphiteView construction/destruction

CGraphiteView::CGraphiteView()
{
	// TODO: add construction code here
	m_crBack	= RGB(255, 255, 255);	//white
	m_crEdge	= RGB(  0,   0,   0);	//black
	m_crTitle	= RGB(  0,   0,   0);	//black
	m_crDotLine	= RGB(255, 255,   0);
	m_crPlot	= RGB(255,   0,   0);	//red
	m_crXY		= RGB(0  ,   0,   0);

	m_xTitle	=  L"X ";
	m_yTitle	=  L"Y ";

	m_brush.CreateSolidBrush(m_crBack);
}

CGraphiteView::~CGraphiteView()
{
}

BOOL CGraphiteView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CGraphiteView drawing

void CGraphiteView::OnDraw(CDC* pDC)
{
	CGraphiteDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	// TODO: add draw code for native data here
	CRect rect;
	GetClientRect(rect);

	if(m_backDC.GetSafeHdc() == NULL)
		DrawBackGround(pDC);

	if(m_xyTitleDC.GetSafeHdc() == NULL)
		DrawXYTitle(pDC);

	if(m_graphDC.GetSafeHdc() == NULL)
		DrawGraph(pDC);

	pDC->BitBlt(0,0, rect.Width(), rect.Height(),
		&m_graphDC, 0, 0, SRCCOPY);
}

/////////////////////////////////////////////////////////////////////////////
// CGraphiteView diagnostics

#ifdef _DEBUG
void CGraphiteView::AssertValid() const
{
	CView::AssertValid();
}

void CGraphiteView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CGraphiteDoc* CGraphiteView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CGraphiteDoc)));
	return (CGraphiteDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CGraphiteView message handlers

void CGraphiteView::DrawBackGround(CDC *dc)
{
	CRect	rect;
	CPen	penDot;
	CPen	penNormal;
	CRect	edge;
	CPen	*oldPen;
	CGraphiteDoc* pDoc = GetDocument();

	GetClientRect(rect);

	if(m_backDC.GetSafeHdc() == NULL)
	{
		// first time
		m_backDC.CreateCompatibleDC(dc);
		m_backBitmap.CreateCompatibleBitmap(dc,
			rect.Width(), rect.Height());
		m_backDC.SelectObject(&m_backBitmap);
	}
	m_backDC.SetBkColor(m_crBack);
	m_backDC.FillRect(rect, &m_brush);

	//Draw Edge
	GetPlotRect(edge, rect);
	{
		CPen	penEdge;
		penEdge.CreatePen(PS_SOLID, 0, m_crEdge);
		oldPen = m_backDC.SelectObject(&penEdge);
		m_backDC.DrawFocusRect(edge);
		m_backDC.SelectObject(oldPen);
	}

	int cx, cy;
	cx = (edge.left + edge.right)/2;
	cy = (edge.top  + edge.bottom)/2;

	//draw dotted line
	{
		CPen penDot;
		int  pix_inc = edge.Width()/(NUM_MEASURE_PER_PAGE);

		penDot.CreatePen(PS_DASH, 0, m_crDotLine);
		oldPen = m_backDC.SelectObject(&penDot);
		for(int i = 1; i < NUM_MEASURE_PER_PAGE; i++)
		{
			m_backDC.MoveTo(edge.left + i*pix_inc, edge.top);
			m_backDC.LineTo(edge.left + i*pix_inc, edge.bottom);
			m_backDC.MoveTo(edge.left,  edge.top + i*pix_inc);
			m_backDC.LineTo(edge.right, edge.top + i*pix_inc);
		}
		m_backDC.SelectObject(oldPen);
	}
}

void CGraphiteView::GetPlotRect(CRect& edge, CRect& rect)
{
	edge = rect;

	edge.top	+= TOP_SPACE_IN_PIXEL;
	edge.left	+= SIDE_SPACE_IN_PIXEL;
	edge.right	-= SIDE_SPACE_IN_PIXEL;
	edge.bottom	-= BOTTOM_SPACE_IN_PIXEL;

	// practcally
	// on wince
	// it's impossible for width to be bigger than height.
	if(edge.Width() < edge.Height())
	{
		int diff = edge.Height() - edge.Width();
		edge.bottom -= diff;
	}
}

int CGraphiteView::physicalX(double vx)
{
	CGraphiteDoc* pDoc = GetDocument();
	int x;
	double range = (pDoc->m_maxX - pDoc->m_minX);
	double diff = (vx - pDoc->m_minX);
	double pct;
	CRect rect,edge;

	GetClientRect(rect);
	GetPlotRect(edge, rect);

	pct = (diff/range)*100;
	if(pct < 0 || pct > 100)
		return -1;

	if(pct == 100)
		x = edge.right;
	else
		x = edge.left + (int)((edge.Width())*pct/100);
	return x;
}

int CGraphiteView::physicalY(double vy)
{
	CGraphiteDoc* pDoc = GetDocument();
	int y;
	double range = (pDoc->m_maxY - pDoc->m_minY);
	double diff = (vy - pDoc->m_minY);
	double pct;
	CRect rect,edge;

	GetClientRect(rect);
	GetPlotRect(edge, rect);

	pct = (diff/range)*100;
	if(pct < 0 || pct > 100)
		return -1;
	if(pct == 100)
		y = edge.top;
	else
		y = edge.bottom - (int)((edge.Height())*pct/100);
	return y;
}

void CGraphiteView::addPoint(double x, double y)
{
	int px, py;

	px = physicalX(x);
	py = physicalY(y);
	if(px < 0 || py < 0)
		return;
}

void CGraphiteView::DrawXYTitle(CDC *pDC)
{
	CRect rect;
	CGraphiteDoc* pDoc = GetDocument();

	GetClientRect(rect);

	if(m_xyTitleDC.GetSafeHdc() == NULL)
	{
		// first time
		m_xyTitleDC.CreateCompatibleDC(pDC);
		m_xyTitleBitmap.CreateCompatibleBitmap(pDC,
			rect.Width(), rect.Height());
		m_xyTitleDC.SelectObject(&m_xyTitleBitmap);
	}
	m_xyTitleDC.SetBkColor(m_crBack);
	m_xyTitleDC.FillRect(rect, &m_brush);
	m_xyTitleDC.BitBlt(0, 0,
		rect.Width(), rect.Height(),
		&m_backDC, 0, 0, SRCCOPY);
	
	//draw XY axis
	CPen penXY, *oldPen;
	CRect edge;

	GetPlotRect(edge, rect);

	penXY.CreatePen(PS_SOLID, 0, m_crXY);
	oldPen = m_xyTitleDC.SelectObject(&penXY);
		
	if(physicalY(0) != -1)
	{
		m_xyTitleDC.MoveTo(edge.left, physicalY(0));
		m_xyTitleDC.LineTo(edge.right,physicalY(0));
	}
	
	if(physicalX(0) != -1)
	{
		m_xyTitleDC.MoveTo(physicalX(0), edge.top);
		m_xyTitleDC.LineTo(physicalX(0), edge.bottom);
	}

	m_xyTitleDC.SelectObject(oldPen);

	// draw title
	{
		CFont font, *oldFont;
		CRect txtRect;

		font.CreateFont(9,4,0, 0, 300,
			FALSE, FALSE, 0, ANSI_CHARSET,
			OUT_DEFAULT_PRECIS,
			CLIP_DEFAULT_PRECIS,
			DEFAULT_QUALITY,
			DEFAULT_PITCH, L"Arial");

		// draw title
		oldFont = m_xyTitleDC.SelectObject(&font);
		m_xyTitleDC.SetTextColor(m_crTitle);
		txtRect.top    = rect.top + 10;
		txtRect.bottom = edge.bottom ;
		txtRect.left   = edge.left;
		txtRect.right  = edge.right;
		m_xyTitleDC.DrawText(pDoc->m_plotTitle,
			txtRect, DT_CENTER | DT_TOP);

		// draw y title
		txtRect.top = edge.bottom + 1;
		txtRect.bottom = rect.bottom;
		m_xyTitleDC.DrawText(m_yTitle,
			txtRect, DT_CENTER | DT_TOP);

		// draw min, max X
		CString str;
		txtRect.left = edge.left;
		txtRect.right = edge.right;
		str.Format(L"%5.2f", pDoc->m_minX);
		m_xyTitleDC.DrawText(str,
			txtRect, DT_LEFT | DT_TOP);
		str.Format(L"%5.2f", pDoc->m_maxX);
		m_xyTitleDC.DrawText(str,
			txtRect, DT_RIGHT | DT_TOP);
		
		// draw x title and y values
		txtRect.top = edge.top;
		txtRect.left = rect.left;
		txtRect.right = edge.left;
		txtRect.bottom = edge.bottom;

		m_xyTitleDC.DrawText(m_xTitle,
			txtRect, 
			DT_LEFT | DT_VCENTER | DT_SINGLELINE);

		str.Format(L"%5.2f", pDoc->m_minY);
		m_xyTitleDC.DrawText(str,
			txtRect,  DT_LEFT | DT_BOTTOM | DT_SINGLELINE);

		str.Format(L"%5.2f", pDoc->m_maxY);
		m_xyTitleDC.DrawText(str,
			txtRect, DT_LEFT | DT_TOP | DT_SINGLELINE);

		m_xyTitleDC.SelectObject(oldFont);
	}
}

void CGraphiteView::DrawGraph(CDC *pDC)
{
	CRect rect;
	CGraphiteDoc* pDoc = GetDocument();

	GetClientRect(rect);

	if(m_graphDC.GetSafeHdc() == NULL)
	{
		// first time
		m_graphDC.CreateCompatibleDC(pDC);
		m_graphBitmap.CreateCompatibleBitmap(pDC,
			rect.Width(), rect.Height());
		m_graphDC.SelectObject(&m_graphBitmap);
	}
	m_graphDC.SetBkColor(m_crBack);
	m_graphDC.FillRect(rect, &m_brush);
	m_graphDC.BitBlt(0, 0,
		rect.Width(), rect.Height(),
		&m_xyTitleDC, 0, 0, SRCCOPY);

	if(pDoc->validDoc())
	{
		double x,y;
		int prevX, prevY;
		bool prevValid = false;
		CPen	penPlot, *oldPen;
		penPlot.CreatePen(PS_SOLID, 0, m_crPlot);
		oldPen = m_graphDC.SelectObject(&penPlot);

		for(x = pDoc->m_minX; x <= pDoc->m_maxX; x += pDoc->m_deltaX)
		{
			int px, py;

			y = pDoc->f(x);
			px = physicalX(x);
			py = physicalY(y);

			if(px < 0 || py < 0)
			{
				prevValid = false;
				continue;
			}
			else if(prevValid)
			{
				m_graphDC.MoveTo(prevX, prevY);
				m_graphDC.LineTo(px, py);

				prevX = px;
				prevY = py;
				prevValid = true;
			}
			else
			{
				//m_graphDC.MoveTo(px, py);
				//m_graphDC.LineTo(px, py);
				prevX = px;
				prevY = py;
				prevValid = true;
			}
		}
		m_graphDC.SelectObject(oldPen);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -