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

📄 graph.cpp

📁 经过扩展的CGraph类及示例工程源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	{
		//determine width of barchart data blocks每个系列占等宽,好象有缺陷
		if(graphHasLegend)
			seriesSpace = (xAxisWidth - legendWidth - 10) / graphSeries->GetCount();
		else
			seriesSpace = xAxisWidth / graphSeries->GetCount();
		barWidth = (seriesSpace * .6) / seriesSize;
		dataPlotSize = seriesSize * barWidth;//图块区占.6

		pos = graphSeries->GetHeadPosition();

		for(int x = 1; x <= graphSeries->GetCount(); x++)
		{
			tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);

			tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace/2));

			for(int s = 0; s < seriesSize; s++)
			{
				barHeight = 0.00;
				//to allow scalability (height may be less than tickRange)
				double dataScale = 0.00;
				if(tickRange > yAxisHeight)
					dataScale = (yAxisHeight * 1.00) / (tickRange * 1.00);
				else dataScale = 1;
				if(tickRange > tmpSeries->GetData(s))
					barHeight = (tmpSeries->GetData(s) * 1.00) * dataScale;
				else barHeight = tickRange * dataScale;
				if(m_DrawMode==RELATIVEMODE)
				{
					barHeight =(tmpSeries->GetData(s)*1.00)*m_nUnits/(tickSpace * 1.00);
				if(tmpSeries->GetData(s)>=tickRange)
					barHeight=yAxisHeight;//警告,此时数据可能越界,截断越界高度

				}
				barL = tickXLocation - (dataPlotSize / 2) + (s * barWidth);
				barT = yApexPoint - barHeight;
				barR = barL + barWidth;
				barB = yApexPoint;
				
				COLORREF barColor;
				barColor = GetColor(s);
				CBrush brush (barColor);
				CBrush* pOldBrush;
				pOldBrush = pDC->SelectObject(&brush);
				pDC->Rectangle(barL, barT, barR, barB);
				pDC->SelectObject(pOldBrush);
			}
		}
	}

	if(graphType == 1)  //line
	{
		int lastXLoc, lastYLoc;
		BOOL samsaratag=FALSE;//用于绘制线段标题时其位置的轮换
		
		int Count=graphSeries->GetCount();
		POINT linepoints[10][50];//储存所有顶点
		for (int i=0;i<10;i++)
			for(int j=0;j<50;j++)
			{
				linepoints[i][j].x=0;
				linepoints[i][j].y=0;
			}

		for(int s = 0; s < seriesSize; s++)
		{
			//determine width of barchart data blocks
			 
			if(graphHasLegend)
				seriesSpace = (xAxisWidth - legendWidth - 10) / graphSeries->GetCount();
			else
				seriesSpace = xAxisWidth / graphSeries->GetCount();
			barWidth = (seriesSpace * .6) / seriesSize;
			dataPlotSize = seriesSize * barWidth;

			pos = graphSeries->GetHeadPosition();
            
			for(int x = 1; x <= graphSeries->GetCount(); x++)
			{
				tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);

				tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
				
				barHeight = 0.00;
				//to allow scalability (height may be less than tickRange)
				double dataScale = 0.00;
				if(tickRange > yAxisHeight)
					dataScale = (yAxisHeight * 1.00) / (tickRange * 1.00);
				else dataScale = 1;
				barHeight = (tmpSeries->GetData(s) * 1.00) * dataScale;
                if(m_DrawMode==RELATIVEMODE)
				{
                     barHeight = (tmpSeries->GetData(s)*1.00)*m_nUnits/(tickSpace * 1.00);
					 if(tmpSeries->GetData(s)>=tickRange)
					    barHeight=yAxisHeight;//警告,此时数据可能越界,截断越界高度
				}
				int yDataLocation = yApexPoint - barHeight;
				
				//now have x and y location of center of ellipse
				COLORREF barColor;
				barColor = GetColor(s);
				CBrush brush (barColor);
				CBrush* pOldBrush;
				pOldBrush = pDC->SelectObject(&brush);
				//draw line back to last data member
				if(x > 1)
				{
					CPen* pOldPen;
					CPen linePen (PS_SOLID, 1, barColor);
					pOldPen = pDC->SelectObject(&linePen);
					pDC->MoveTo(lastXLoc + 2, lastYLoc - 1);
					pDC->LineTo(tickXLocation - 3, yDataLocation - 1);
					
                    linepoints[s][x-1].x =tickXLocation;
                    linepoints[s][x-1].y =yDataLocation;
					if(x==graphSeries->GetCount())
					{//以下为调整linetitle,避免它们互相重叠
						CString title;
						if (s>0)
						{
							for(int i=0;i<=s-1;i++)
							{
							  if( abs(tickXLocation -linepoints[i][graphSeries->GetCount()-1].x)<30&&abs(yDataLocation -linepoints[i][graphSeries->GetCount()-1].y)<30)//标题间区域至少(30,30)
							  {
								samsaratag=TRUE;//需要调整
								break;
							  }
							}
						}

						if(samsaratag==FALSE)//默认绘在线段的末尾	
						{
							
							title=CGraphSeries::GetLineTitle(s);
						    pDC->SetTextColor(barColor);
							if( CGraphSeries::GetTitleFlag()!=FALSE)
						    pDC->TextOut(tickXLocation + 6, yDataLocation - 8,title);
						
						}
						else 
						{
						
						   POINT ptext;
						   ptext.x =linepoints[s][graphSeries->GetCount()-2].x;
						   ptext.y =linepoints[s][graphSeries->GetCount()-2].y;
						   linepoints[s][graphSeries->GetCount()-1].x=ptext.x;
						   linepoints[s][graphSeries->GetCount()-1].y=ptext.y;
							for(int i=0;i<=s-1;i++)
							{
							  if( abs(ptext.x  -linepoints[i][graphSeries->GetCount()-1].x)<30&&abs(ptext.y  -linepoints[i][graphSeries->GetCount()-1].y)<30)
							  {
								
								     
								      BOOL exitflag=TRUE;
									  ptext.x =linepoints[s][graphSeries->GetCount()-3-i].x;
									  ptext.y =linepoints[s][graphSeries->GetCount()-3-i].y;
								  
								     linepoints[s][graphSeries->GetCount()-1].x=ptext.x;
									 linepoints[s][graphSeries->GetCount()-1].y=ptext.y;
						             for(int j=0;j<s;j++)
									 {
								       if( abs(ptext.x  -linepoints[j][graphSeries->GetCount()-1].x)<30&&abs(ptext.y  -linepoints[j][graphSeries->GetCount()-1].y)<30)
						                   exitflag=FALSE;
										   
									 }
									 if(exitflag)
										 break;
							  }
							}
                            
							
							title=CGraphSeries::GetLineTitle(s);
						    pDC->SetTextColor(barColor);
							if( CGraphSeries::GetTitleFlag()!=FALSE)
						    pDC->TextOut(ptext.x  + 6, ptext.y  - 8,title);
                            samsaratag=FALSE;
						    
						 }//调整完毕
						


						
						
					}
				
					pDC->SelectObject(pOldPen);
				}
				//now draw ellipse...
				pDC->Ellipse(tickXLocation - 3, yDataLocation - 3,
					tickXLocation + 3, yDataLocation + 3);
				linepoints[s][x-2].x= lastXLoc = tickXLocation;
				linepoints[s][x-2].y=lastYLoc = yDataLocation;
				pDC->SelectObject(pOldBrush);
			}
		}
	}

	if(graphType == 2)  //pie
	{
		double dataSum = 0.00;  //for storing cumulative sum
		int lastXLocation, lastYLocation;
		int newXLocation, newYLocation;
		double percent = 0.00;
		int degrees;
		double totalSum = 0.00;
		int deltaXY;
		int radius;
			
		lastXLocation = 0;
		lastYLocation = 0;

		//determine width of pie display area
		if(graphHasLegend)
			if(((xAxisWidth - legendWidth/* - 10*/) / graphSeries->GetCount())
					> (yAxisHeight - 10))
				seriesSpace = (yAxisHeight - 10)/* / graphSeries->GetCount()*/;
			else
				seriesSpace = (xAxisWidth - legendWidth/* - 10*/) / graphSeries->GetCount();
		else
			if(xAxisWidth > yAxisHeight)
				seriesSpace = yAxisHeight / graphSeries->GetCount();
			else
				seriesSpace = xAxisWidth / graphSeries->GetCount();
		double tmpD = (seriesSpace - /*60*/20)* .8;  //max width of any pie
		radius = tmpD / 2;  

		int centerYPie = (yAxisHeight + 60) / 2;
		
		pos = graphSeries->GetHeadPosition();
		for(int x = 1; x <= graphSeries->GetCount(); x++)
		{
			tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
			totalSum = 0;
			for(int s = 0; s < 10; s++)
				totalSum += tmpSeries->GetData(s);
			int pieLeft, pieRight;
			if(graphSeries->GetCount() == 1)
			{
				pieLeft = ((xAxisWidth - legendWidth - 10) / 2) - radius/* - 25*/;
			}
			else
			{
				pieLeft = xApexPoint + 15 + (x * /*50*/20) + ((x - 1) * (2 * radius));
			}
			pieRight = pieLeft + (2 * radius);
			CRect pieRect (pieLeft, 
					centerYPie - radius,
					pieRight, 
					centerYPie + radius);
			int centerXPie = pieLeft + radius;

			//plot series label
			pDC->TextOut(centerXPie - ((tmpSeries->GetLabel().GetLength() * 8) / 2),
						centerYPie + radius + 15, tmpSeries->GetLabel());
			lastXLocation = pieLeft;
			lastYLocation = centerYPie;
			
			dataSum = 0;
			for(s = 0; s < 10; s++)
			{
				if(tmpSeries->GetData(s) > 0)
				{
					dataSum += tmpSeries->GetData(s);
					percent = (dataSum * 100) / totalSum;
					degrees = (360 * percent) / 100;

						//degress / 90 will never exceed 4.
						//this can tell us the quadrant of destination
					deltaXY = (degrees * radius) / 90;
						//deltaXY is change from start point of pie 0
						//this value is total change.  so if radius is 300
						//and degrees is 270, delta is 300.  The change 
						//would move both x and y 300 pixels.  For x, 100
						//to right is center, another 100 to right edge,
						//100 back to center.  For y, 100 to bottom, 100
						//back to center, 100 to top. thus gives 270 degree
						//rotation.

					//determine destination quadrant...
						//and set newXLocation and newYLocation values...
					int quadrant = degrees / 90;  //truncates decimal
					switch(quadrant)
					{
						//in the computations below, the remarked line is
						//the original computation.  The line above it, for
						//actual use, is the simplified line, and gives the
						//exact same result
						case 0 : newXLocation = pieLeft + deltaXY;
								 newYLocation = centerYPie + deltaXY;
								 break;
						case 1 : newXLocation = pieLeft + deltaXY;
								 newYLocation = centerYPie + (2 * radius) - deltaXY;
//								 newYLocation = centerYPie + radius - (deltaXY - radius);
								 break;
						case 2 : newXLocation = pieLeft + (4 * radius) - deltaXY;
//								 newXLocation = pieLeft + (2 * radius) - (deltaXY - (2 * radius));
								 newYLocation = centerYPie + (2 * radius) - deltaXY;
//								 newYLocation = centerYPie - (deltaXY - (2 * radius));
								 break;
						case 3 : newXLocation = pieLeft + (4 * radius) - deltaXY;
//								 newXLocation = pieLeft + radius - (deltaXY - (3 * radius));
								 newYLocation = centerYPie - (4 * radius) + deltaXY;
//								 newYLocation = centerYPie - radius + (deltaXY - (3 * radius));
								 break;
						case 4 : newXLocation = pieLeft;
								 newYLocation = centerYPie - 1;
								 break;
					}
					
					if(s == 0)
						lastYLocation -= 1;

					CPoint p1 (lastXLocation, lastYLocation);
					CPoint p2 (newXLocation, newYLocation);
					COLORREF barColor;
					barColor = GetColor(s);
					CBrush brush (barColor);
					CBrush* pOldBrush;
					pOldBrush = pDC->SelectObject(&brush);
					pDC->Pie(pieRect, p1, p2); 
					pDC->SelectObject(pOldBrush);

					lastXLocation = newXLocation;
					lastYLocation = newYLocation;
				}
			}
			
		}
	}

}

void CGraph::SetLegend(int datagroup, CString label)
{
	graphLegend.SetLegendText(datagroup, label);
	graphHasLegend = TRUE;
}

void CGraph::DrawLegend(CDC* pDC)
{
	//determine size of legend
	//12 chars per seriesSize + 6 for spacing (3 top and bottom) 
	//+ 1 set for label title(3+12+6) + rectangle (2 chars) + 3 for final bottom buffer
	int legendHeight = 23 + (seriesSize * 18) + 3;
	int legendL, legendT, legendR, legendB;
	int barL, barT, barR, barB;

	legendT = (maxHeight / 2) - (legendHeight / 2);
	legendB = legendT + legendHeight;
	legendR = maxWidth - 5;
	legendL = legendR - ((graphLegend.GetLegendLength() * (legendFontSize * .66)) + 25);
		//allows 50 pixels for display of legend bar 45 + 5 space.
	legendWidth = legendR - legendL;

	pDC->Rectangle(legendL, legendT, legendR, legendB);
	pDC->TextOut(legendL + (legendWidth / 2) - 24, 
					legendT + 3, "图例");//Legend
	for(int i = 0; i < seriesSize; i++)
	{
		//top "Legend" text will use 12 + 3 top + 6 bottom (21 total)
		//each legend label will need 3 chars on top, so the 24 in the offset
		//each label than uses 12 + 3 below + 3 above next label, so 18
		// in the i * offset.  
		CFont legendFont;
		legendFont.CreateFont(legendFontSize, 0, 0, 0, 700, FALSE, FALSE, 0,
			ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
			DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
		CFont* pOldFont = (CFont*) pDC->SelectObject(&legendFont);

		pDC->TextOut(legendL + 5, legendT + 24 + (i * 18), graphLegend.GetLegendText(i));

		pDC->SelectObject(pOldFont);

		//draw bar
		COLORREF barColor;
		barColor = GetColor(i);
		CBrush brush (barColor);
		CBrush* pOldBrush;
		pOldBrush = pDC->SelectObject(&brush);

		barL = legendL + 5 + (graphLegend.GetLegendText(i).GetLength() * 6) + 5;
		barT = legendT + 24 + (i * 18) + 1, graphLegend.GetLegendText(i);
		barR = legendR - 5;
		barB = barT + 12;
		pDC->Rectangle(barL, barT, barR, barB);

		pDC->SelectObject(pOldBrush);

	
	}

}

void CGraph::SetGraphTitle(CString title)
{
	graphTitle = title;
}

void CGraph::SetXTickFontSize(int size)
{
	xTickFontSize = size;
}

void CGraph::SetYTickFontSize(int size)
{
	yTickFontSize = size;
}

void CGraph::SetLegendFontSize(int size)
{
	legendFontSize = size;
}


int CGraph::PrintGraph(CDC* pDC, CPrintInfo* pInfo)
{
	CString		str;
	char		tmpStr[10];
	CFont		graphTitleFont, textFont;
	TEXTMETRIC	tm;
	CString tickLabel;

    //titleFont is 24 point, bold
	graphTitleFont.CreateFont(-480, 0, 0, 0, 700, FALSE, FALSE, 0, ANSI_CHARSET,
			OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
			DEFAULT_QUALITY, DEFAULT_PITCH || FF_ROMAN,
			"Times New Roman");

	//textFont is 12 point
	textFont.CreateFont(-240, 0, 0, 0, 400, FALSE, FALSE, 0, ANSI_CHARSET,
			OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
			DEFAULT_QUALITY, DEFAULT_PITCH || FF_ROMAN,
			"Times New Roman");

	pDC->SetMapMode(MM_TWIPS);
	if(pInfo->m_nCurPage == 1)
	{
		CFont* pOldFont = (CFont*) pDC->SelectObject(&graphTitleFont);
		pDC->GetTextMetrics(&tm);

		int charWidth = tm.tmMaxCharWidth;
		//next line is centered....trust me !!
		pDC->TextOut(((graphTitle.GetLength() / 2) * charWidth) - (leftMargin / 2), pGraphT, graphTitle);

		pDC->SelectObject(pOldFont);
		
		//draw legend
		if(graphHasLegend)
			PrintLegend(pDC);

		maxHeight = pGraphT - pGraphB; 
		maxWidth = pGraphR - pGraphL - 2200; 
		if(graphType == 2)  //pie
		{

			//since pie does not have axis lines, set to full size minus 5 on each side
			//these are needed for legend to plot itself
			xAxisWidth = pGraphR - pGraphL - legendWidth - 200;
			yAxisHeight = maxHeight - 200;  //100 buffer and 200 for title
			xApexPoint = pGraphL + 1500;
			yApexPoint = pGraphB + maxHeight + 500;
		}
		else
		{
			
			tickLabel.Format("%d", tickRange);

⌨️ 快捷键说明

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