Click here to Skip to main content
15,886,026 members
Articles / Desktop Programming / MFC

GraphFX - A graph framework

Rate me:
Please Sign up or sign in to vote.
3.34/5 (30 votes)
9 Nov 2000 228K   4.5K   104  
A Doc/View framework for displaying graphical data
// Item.cpp: implementation of the CItem class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Graph.h"
#include "Item.h"
#include "GraphViewFX.h"

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

extern "C"
{

	void DrawGradientFill(CDC* pDC, CRect* prc, int nSegs,
						   COLORREF crStart, COLORREF crEnd, BOOL bSemiFormat, CRect* prcFull);

}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

#include <time.h>

CItem::CItem(CWnd* pWnd)
{
	m_bSelect = false;
	m_nOrdinal = -1;

	m_pWnd = dynamic_cast<CGraphViewFX*>(pWnd);

	
	m_strName = "Default Item";

	// Usually this is be zero
	// m_nPercentage = 0;
	m_nHiWaterMark = 0;
	
}

CItem::~CItem()
{
}

void CItem::SetItemText(const CString& strItem)
{
	m_strName = strItem;
}

CString	CItem::GetTipText()
{
	return CString("Some Text");
}

void CItem::SetPercentage(UINT nPercentage)
{
	if (nPercentage > m_nHiWaterMark)
		m_nHiWaterMark = nPercentage;

	m_nPercentage = nPercentage;
}
void CItem::Unselect()
{
	if (m_bSelect == TRUE)
	{
		m_bSelect = FALSE;
		m_pWnd->InvalidateRect(NULL,FALSE);
	}
}

void CItem::Select()
{
	if (m_bSelect == FALSE)
	{
		m_bSelect = TRUE;
		m_pWnd->InvalidateRect(NULL,FALSE);
	}
}



CRect CItem::GetBoundingRect()
{
	CRect rc;

	if (GetLogicalPos())
		rc.UnionRect(CRect(0,m_rcText.top,LeftMargin,m_rcText.bottom),m_rcText);

	return rc;
}

void CItem::SetOrdinal(int nPos)
{
	m_nOrdinal = nPos;
}

void CItem::Invalidate()
{
	m_pWnd->InvalidateRect(m_rcBounds,FALSE);
}

BOOL CItem::GetLogicalPos()
{
	UINT nItems = m_pWnd->GetItemsPerPage();
	UINT nScrollPos = m_pWnd->GetScrollPos();

	// Is item on this page	
	if ((UINT) m_nOrdinal >= nScrollPos && (UINT)m_nOrdinal < (nScrollPos +  nItems))
	{
		int nLogPos = m_nOrdinal - nScrollPos;

		int nY = (nLogPos * BarSize) + TopLine;

		// Set up the Rects
		// TextRect | Bar Rect         | Graph Rect
		CRect rcClient;
		m_pWnd->GetClientRect(rcClient);

		m_rcGraph = rcClient;

		m_rcGraph.top = nY;
		m_rcGraph.bottom = nY+BarSize;
		m_rcGraph.right -= RightMargin; 
		m_rcGraph.left = m_rcGraph.right - GraphWidth;

		int nWidth = rcClient.Width() - GraphWidth;


		CRect rcTotal;
		// Rectangle for bar 
		rcTotal.SetRect(0,nY,nWidth,nY+BarSize);

		rcTotal.left += LeftMargin;
		rcTotal.right -= RightMargin;
		
		// Rectangle for bar 
		m_rcBar = rcTotal;
		m_rcBar.bottom = m_rcBar.top + m_rcBar.Height();


		// Rectangle for text
		m_rcText= rcTotal;
		m_rcText.left = 4 + 16;
		m_rcText.right = LeftMargin - 14;


		return TRUE;
	}

	return FALSE;
}


void CItem::Draw(CDC* pDC)
{
	//////////////////////////////////
	// Draw Out the percentage bar
	//////////////////////////////////
	if (GetLogicalPos())
	{

		DrawBar(pDC);
		DrawGraph(pDC);

		CFont* pOldFont = pDC->SelectObject(m_bSelect ? m_pWnd->GetBoldFont() : m_pWnd->GetFont());
		//////////////////////////////////
		// Draw out Text
		//////////////////////////////////
		pDC->SetTextColor( RGB (255, 255, 255) );
		pDC->SetBkMode(TRANSPARENT);
		
		pDC->DrawText(m_strName,m_rcText,DT_SINGLELINE|DT_VCENTER|DT_LEFT|DT_END_ELLIPSIS);

		pDC->SelectObject(pOldFont);
	}
}

void CItem::DrawGraph(CDC* pDC)
{
	CPen procpen(PS_SOLID,1,RGB(0,255,0));
	
	CPen* pPen = pDC->SelectObject(&procpen);

	int nX = m_rcGraph.left;

	int nFrac = 4;	
	int nInc = 0;

	pDC->SetROP2(R2_MERGEPEN); 


	for (int i = MAX_POINTS-(MAX_POINTS/nFrac); i < MAX_POINTS;i++)
	{
		int nPos = int((m_rcGraph.Height() * m_lStats[i]) / 100.0);

		double dInc = (m_rcGraph.Width() * nInc) / MAX_POINTS;
		nInc+=nFrac;

		if (i == MAX_POINTS-(MAX_POINTS/nFrac))
			pDC->MoveTo(nX,m_rcGraph.bottom - nPos);
		else
			pDC->LineTo((int)((double)nX+dInc),m_rcGraph.bottom - nPos);


	}
		
	 pDC->SelectObject(pPen);
}


void CItem::DrawBar(CDC* pDC)
{
	CRect rc;
	CFont* pOldFont;
	int nPercent = GetPercentage();

	if (nPercent > 0)
	{
		double lFill = m_rcBar.Width() * nPercent /100.0;

	
		pDC->SetBkMode(TRANSPARENT);

		CString strNum;
		CString strFormat;

		pOldFont = pDC->SelectObject(m_pWnd->GetSmallFont());
		//////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////
		rc = m_rcBar;
		rc.right = (int)((double)m_rcBar.left +  lFill);

		if (GetPercentage() > 1)
			strFormat = "%d%%";
		else
			strFormat = "%d";

			
		strNum.Format(strFormat,GetPercentage());

		pDC->SetTextColor(RGB(0,0,0));

		rc.InflateRect(1,0);
		pDC->Draw3dRect(rc,GetSysColor(COLOR_3DLIGHT),GetSysColor(COLOR_3DSHADOW));
		rc.DeflateRect(1,0);

		DrawGradientFill(pDC, &rc, 100, RGB(255,255,255), RGB(0,0,255) , TRUE ,&m_rcBar);

		pDC->SelectObject(m_pWnd->GetFont());
		
		CRect trc(rc);
		pDC->DrawText(strNum,trc,DT_SINGLELINE|DT_VCENTER|DT_CENTER);

		//////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////
		
	}
	

	////////////////////////////////////////////
	// Draw in high water mark for this item
	////////////////////////////////////////////

	if (m_nHiWaterMark)
	{
		long lPosition = MulDiv(m_rcBar.Width(), m_nHiWaterMark, 100);
		
		CPen pen;
		pen.CreatePen(PS_SOLID,3,GetSysColor(COLOR_3DLIGHT));
		CPen* pPenOld = pDC->SelectObject(&pen);
		rc = m_rcBar;
		rc.right = m_rcBar.left + lPosition;
		rc.DeflateRect(-1,4);
		pDC->MoveTo(rc.right,rc.top);
		pDC->LineTo(rc.right,rc.bottom);
		pDC->SelectObject(pPenOld);
	}
}


UINT CItem::GetPercentage()
{
	return m_nPercentage;
}

void DrawGradientFill(CDC* pDC, CRect* prc, int nSegs,
						   COLORREF crStart, COLORREF crEnd, BOOL bSemiFormat, CRect* prcFull)
{
	// Get the starting RGB values and calculate the incremental
	// changes to be applied.

	COLORREF cr;
	int iR = GetRValue(crStart);
	int iG = GetGValue(crStart);
	int iB = GetBValue(crStart);

	int ieB = GetBValue(crEnd);
	int ieG = GetGValue(crEnd);
	int ieR = GetRValue(crEnd);

	int iSegments = nSegs;
	int iColorSegments = nSegs;

	if(iSegments > prc->Width())
	{
		iSegments = prc->Width();
		iColorSegments = iSegments;
	}

	
	if (bSemiFormat)
	{
		iColorSegments = nSegs;
		if (iColorSegments > prcFull->Width())
			iColorSegments = prcFull->Width();
	}

	int iDiffR = (ieR - iR);
	int iDiffG = (ieG - iG);
	int iDiffB = (ieB - iB);

	int idR = 256 * (iDiffR) / (max(iColorSegments,1));
	int idG = 256 * (iDiffG) / (max(iColorSegments,1));
	int idB = 256 * (iDiffB) / (max(iColorSegments,1));

	iR *= 256;
	iG *= 256;
	iB *= 256;

	ieR *= 256;
	ieG *= 256;
	ieB *= 256;


	int icx = prc->Width() / max(iSegments,1);
	if (bSemiFormat)
	{
		icx = prcFull->Width() / max(iColorSegments,1);
	}
	

	int iLeft = prc->left;
	int iRight;
	pDC->SelectStockObject(NULL_PEN);

	for (int i = 0; i < iSegments; i++, iR += idR, iG += idG, iB += idB)
	{
		// Use special code for the last segment to avoid any problems
		// with integer division.

		if (i == (iSegments - 1))
		{
			iRight = prc->right;
		}
		else
		{
			iRight = iLeft + icx;
			if (bSemiFormat &&
				iRight > prc->right)
				iRight = prc->right;
		}

		cr = RGB(iR / 256, iG / 256, iB / 256);
		
		{
			// Perform the drawing and restore the DC; the objects
			// will be freed automatically.

			CBrush br(cr);
			CBrush* pbrOld = pDC->SelectObject(&br);
			pDC->Rectangle(iLeft, prc->top, iRight + 1, prc->bottom);
			pDC->SelectObject(pbrOld);
		}

		// Reset the left side of the drawing rectangle.

		iLeft = iRight;
	}
}


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior) Software Kinetics
United Kingdom United Kingdom




Software Kinetics
are experts in developing customised and bespoke applications and have expertise in the development of desktop, mobile and internet applications on Windows.


We specialise in:

  • User Interface Design
  • Desktop Development
  • Windows Phone Development
  • Windows Presentation Framework
  • Windows Forms
  • Windows Communication Framework
  • Windows Services
  • Network Applications
  • Database Applications
  • Web Development
  • Web Services
  • Silverlight
  • ASP.net


Visit Software Kinetics

Comments and Discussions