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

📄 barchart.cpp

📁 a bar chart,a good refernce for the control
💻 CPP
📖 第 1 页 / 共 4 页
字号:

		cDB.MoveNext();
	}

	Refresh();

	return TRUE;
}
// This function tryes to read chart data from an Stored Procedure or Query
BOOL CBarChart::ReadFromDatabase(CString szDSN, CString szSPName, CString szParameterList,
					  COLORREF colorBars, CString szUsername, CString szPass)
{
	CChartDatabase cSP;
	
	if (!cSP.OpenProc(szDSN, szSPName, szParameterList, szUsername, szPass))
	{
		m_szLastErr = cSP.GetLastErrorMessage();
		return FALSE;
	};

	CString szLabel;
	double dVal;

	while (!cSP.IsEOF())
	{
		cSP.GetRow(szLabel, dVal);
		if (colorBars == RGB(0, 0, 0))
		{
			AddBar(dVal, szLabel, RGB(rand()%255, rand()%255, rand()%255));
		}
		else
		{
			AddBar(dVal, szLabel, colorBars);
		}

		cSP.MoveNext();
	}

	Refresh();
	return TRUE;
}

CString CBarChart::GetLastDatabaseErrMessage()
{
	return m_szLastErr;
}

CString CBarChart::GetLastErrorMessage()
{
	return GetLastDatabaseErrMessage();
}

BOOL CBarChart::SaveToFile(CString szPath)
{
	// to return results
	BOOL bRes = TRUE;

	// If chart is not ready
	if ( m_dcMem.GetSafeHdc() == NULL )
	{
		return FALSE;
	}

	// If no path specified, ask for a path
	if (szPath=="")
	{
		if ( !PromptForFile(szPath, _T("Bitmap file"), _T("*.Bmp")) )
		{
			m_szLastErr = "Canceled by user";
			return FALSE;
		}
	}

    BITMAPINFOHEADER    *pBMI ;
	BITMAPFILEHEADER	hdr;
    DWORD		dwTotal;              // total count of bytes 
    DWORD		cb;                   // incremental count of bytes 
	CPalette	pal;
	DWORD		dwWritten = 0;
	LPBYTE		hp;

	// Prepare for converting DDB to DIB
	UINT        nSize   = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 );
	LOGPALETTE* pLP     = (LOGPALETTE*)new BYTE[nSize];
	pLP->palVersion     = 0x300;
	pLP->palNumEntries = (unsigned short)GetSystemPaletteEntries( 
		m_dcMem.GetSafeHdc(), 0, 255,
		pLP->palPalEntry );

	// Create the palette
	pal.CreatePalette( pLP );

	// Free memory
	delete[] pLP;

	// Do convert DDB to DIB
    HANDLE hDib = DDBToDIB( m_pBmpBars, BI_RGB, &pal );

	// Prepare Bitmap Info Header
    pBMI = (BITMAPINFOHEADER*)GlobalLock(hDib) ;
    int nColors = 0;
    if (pBMI->biBitCount <= 8)
	{
		nColors = (1 << pBMI->biBitCount);
	}

	// Prepare FileHeader
    hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M" 
    hdr.bfReserved1 = 0; 
    hdr.bfReserved2 = 0; 

    // Compute the size of the entire file. 
    hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
                 pBMI->biSize + pBMI->biClrUsed
                 * sizeof(RGBQUAD) + pBMI->biSizeImage); 

    // Compute the offset to the array of color indices. 
    hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
                    pBMI->biSize + pBMI->biClrUsed 
                    * sizeof (RGBQUAD); 

    // Create the .BMP file. 
    HANDLE hf = CreateFile(szPath, 
                   GENERIC_READ | GENERIC_WRITE, 
                   (DWORD) 0, 
                    NULL, 
                   CREATE_ALWAYS, 
                   FILE_ATTRIBUTE_NORMAL, 
                   (HANDLE) NULL); 
    if (hf == INVALID_HANDLE_VALUE) 
	{
		m_szLastErr = "Cannot create file";
		bRes = FALSE;
		goto CLEANUP;
	}

    // Copy the BITMAPFILEHEADER into the .BMP file. 
    if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), 
        (LPDWORD) &dwWritten,  NULL)) 
    {
		m_szLastErr = "Cannot write to file";
		bRes = FALSE;
		goto CLEANUP;
    }

    // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. 
    if (!WriteFile(hf, (LPVOID) pBMI, sizeof(BITMAPINFOHEADER) 
                  + pBMI->biClrUsed * sizeof (RGBQUAD), 
                  (LPDWORD) &dwWritten, ( NULL)) )
	{
		m_szLastErr = "Cannot write to file";
		bRes = FALSE;
		goto CLEANUP;
	}

	// Copy the array of color indices into the .BMP file. 
	dwTotal = cb = pBMI->biSizeImage; 
	hp = (LPBYTE)pBMI + (pBMI->biSize + nColors * sizeof(RGBQUAD)); 
	if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwWritten,NULL)) 
	{
		m_szLastErr = "Cannot write to file";
		bRes = FALSE;
		goto CLEANUP;
	}

CLEANUP:;

	// free resources
    GlobalUnlock(hDib) ;
    GlobalFree(hDib) ;

	// Close the .BMP file. 
	if ( hf != INVALID_HANDLE_VALUE )
	{
		if (!CloseHandle(hf))
		{
			m_szLastErr = "Cannot close file";
			return FALSE;
		}
	}

	return bRes;
}

BOOL CBarChart::PromptForFile(CString& szPath, CString szFilterName, CString szFilter)
{
	CString szFltr;
	szFltr.Format(_T("%s|%s||"), szFilterName, szFilter);

	// If path did not set, ask for a path
	CFileDialog fileSDlg(
		FALSE,				// Not an open file dialog
		_T("bmp"),			// This is to save bitmap files
		NULL,				// No default file name
		OFN_ENABLESIZING | 
		//OFN_FORCESHOWHIDDEN | 
		OFN_LONGNAMES | 
		OFN_OVERWRITEPROMPT | 
		OFN_PATHMUSTEXIST,
		szFltr);

	if ( fileSDlg.DoModal() != IDOK )
	{
		return FALSE;
	}

	szPath = fileSDlg.GetPathName();

	return TRUE;

}

void CBarChart::SetGridLines(int nHorLineCount, int nVerLineCount, 
							 BOOL bFixedSize, int nFixedSize)
{
	m_grid.SetLineCount(nVerLineCount, nHorLineCount, bFixedSize, nFixedSize);
}
 ///////////////////////////////////////////////////////////////////////
 //	  CGDIGrid Class											 
 //	 															 
 //	 		Draws a grid behind the chart.						 
 //	 		UNDONE: The grid class should act better. instead of 
 //	 		drawing horizontal lines from top, it should start	 
 //	 		from the line under the bars. (Logical y = 0 axe)	 
 //
 ///////////////////////////////////////////////////////////////////////
void CBarChart::CGDIGrid::Draw(CDC* pDC, CRect& rcBound)
{
	if (m_penGrid.GetSafeHandle()) {
		m_pPenOld= pDC->SelectObject(&m_penGrid);

		// |||
		int nGapSize = (m_nVLineCount==0?m_nFixedSize:
					   (rcBound.Width()-2*GRID_MARGIN_WIDTH)/m_nVLineCount);
		if (nGapSize<=0)
		{
			nGapSize = 1;
		}
		for (i=rcBound.left+GRID_MARGIN_WIDTH ;i<rcBound.right-2*GRID_MARGIN_WIDTH;
			i+=nGapSize)
		{
			pDC->MoveTo(i, GRID_MARGIN_WIDTH);
			pDC->LineTo(i, rcBound.Height());
		}

		// ===
		nGapSize = (m_nHLineCount==0?m_nFixedSize:
				   (rcBound.Height()-GRID_MARGIN_WIDTH)/m_nHLineCount);
		if (nGapSize<=0)
		{
			nGapSize = 1;
		}
		for (i=rcBound.bottom ; i>=rcBound.top+GRID_MARGIN_WIDTH ; 
			 i-=nGapSize)
		{
			pDC->MoveTo( GRID_MARGIN_WIDTH, i);
			pDC->LineTo( rcBound.Width() - 2*GRID_MARGIN_WIDTH, i);
		}
	}

	// Cleanup
	pDC->SelectObject(m_pPenOld);
};

CBarChart::CGDIGrid::CGDIGrid()
{
	m_nVLineCount  = 0;
	m_nHLineCount = 0;
	m_nFixedSize = GRID_DEFAULT_SIZE;
	m_pPenOld = NULL;
};

CBarChart::CGDIGrid::~CGDIGrid()
{
	if (m_penGrid.GetSafeHandle())
	{
		m_penGrid.DeleteObject();
	}
};

void CBarChart::CGDIGrid::SetLineCount(UINT nVLineCnt, UINT nHLineCnt, BOOL bFixedSize, UINT nFixedSize)
{
	if (bFixedSize)
	{
		if (nFixedSize==0)
		{
			m_nFixedSize = GRID_DEFAULT_SIZE;
		}
		else
		{
			m_nFixedSize = nFixedSize;
		}
		m_nVLineCount = 0;
		m_nHLineCount = 0;
	}
	else
	{
		if (nVLineCnt!=0) m_nVLineCount = nVLineCnt;
		if (nHLineCnt!=0) m_nHLineCount = nHLineCnt;
	}
};

void CBarChart::CGDIGrid::SetColor(COLORREF color)
{
	// Reset grid pen
	if (m_penGrid.GetSafeHandle())
	{
		m_penGrid.DeleteObject();
	}
	m_penGrid.CreatePen(PS_SOLID, 1, color);
}


 ///////////////////////////////////////////////////////////////////////
 // CChartBar Class
 //
 //	 		This class is responsible for for drawing bars and   
 //	 		performing required calculation for the job.         
 //
 ///////////////////////////////////////////////////////////////////////

CBarChart::CChartBar::CChartBar()
{
	m_nBarWidth = BAR_DEFAULT_WIDTH;
	m_nBarGap = BAR_DEFAULT_GAP;
	m_sBarPicSize = CSize(0, 0);
	m_sBarPicSize.cy = 0;
	m_colorChartBK = RGB(255, 255, 255);

	m_pFontOld = NULL;
	ZeroMemory(&m_lf, sizeof(m_lf));

	CreateLabelFont();
}

CBarChart::CChartBar::~CChartBar()
{
	m_chartData.RemoveAll();

	if (m_font.GetSafeHandle())
	{
		m_font.DeleteObject();
	}
}

void CBarChart::CChartBar::RemoveAll()
{
	m_chartData.RemoveAll();
	m_sBarPicSize.cx = 0;
	m_sBarPicSize.cy = 0;
}

void CBarChart::CChartBar::RemoveAt(int nIndex)
{
	m_chartData.RemoveAt(nIndex);
	m_sBarPicSize.cx = m_chartData.GetCount() * (m_nBarWidth + m_nBarGap);
}

void CBarChart::CChartBar::CreateLabelFont()
{
	if (m_font.GetSafeHandle())
	{
		m_font.DeleteObject();
	}

	strcpy(m_lf.lfFaceName,"Tahoma");
	m_lf.lfHeight=-10;
	m_lf.lfWidth=0;
	m_lf.lfEscapement = 0;
	m_lf.lfOrientation = 0;
	m_lf.lfItalic = 0;
	m_lf.lfUnderline = 0;
	m_lf.lfStrikeOut = 0;
	m_lf.lfWeight = 400;
	m_lf.lfCharSet = ARABIC_CHARSET;
	m_lf.lfOutPrecision = OUT_STROKE_PRECIS;
	m_lf.lfClipPrecision=2;
	m_lf.lfQuality=1;
	m_lf.lfPitchAndFamily=2;

	// Create font
	m_font.CreateFontIndirect(&m_lf);
}

void CBarChart::CChartBar::AddBar(double udValue,CString szLabel, COLORREF color)
{
	m_chartData.Add(szLabel, udValue, color);
	m_sBarPicSize.cx = m_chartData.GetCount() * (m_nBarWidth + m_nBarGap);
}

void CBarChart::CChartBar::Draw(CDC* pDC, CRect& rcBound)
{
	m_sBarPicSize.cy = rcBound.Height()-GRID_FRAME_HEIGHT;

	// Draw all bars and labels one by one
	DrawBars(pDC, rcBound);
}

void CBarChart::CChartBar::SetBkColor(COLORREF color)
{
	m_colorChartBK = color;
}

int CBarChart::CChartBar::GetBarHeight()
{
	return m_sBarPicSize.cy;
}

int CBarChart::CChartBar::GetBarWidth()
{
	return m_sBarPicSize.cx;
}

void CBarChart::CChartBar::DrawBars(CDC* pDC, CRect& rcBound)
{
	double nHeight = 0;
    int r1,g1,b1;
    int r2,g2,b2;
	int r,g,b;
	COLORREF colorG, colorEnd, colorSmooth, colorBorder;
	int x = 0, y = 0;
	CString str;
	
	int cy = m_sBarPicSize.cy;
//  If there is a title
//	if ()
//	{
		cy -= CHART_TITLE_HEIGHT;
//	}

	if (m_bShowBarText)
	{
		cy -= BAR_TXT_PERCENT_HEIGHT;
	}
	if (m_bShowLabel)
	{
		cy -= BAR_TXT_LABEL_HEIGHT;

		pDC->FillSolidRect(rcBound.left, 
			rcBound.bottom - BAR_TXT_LABEL_HEIGHT - CHART_TITLE_HEIGHT -1,
			rcBound.right,
			rcBound.bottom - CHART_TITLE_HEIGHT, m_colorChartBK);
	}

	for (int i = 0; i<m_chartData.GetCount();i++)
	{
		colorBorder = DifColor(m_chartData.GetColor(i), CHART_BORDER_DARKNESS);
		colorEnd	= DifColor(m_chartData.GetColor(i), CHART_BORDER_DARKNESS - 14);
		colorSmooth = OrColor (colorBorder, m_colorChartBK, 40);	// A correction color to smooth top 2 rounded edges of the border

		nHeight = (m_chartData.GetValue(i) * cy)/
			(m_chartData.GetMaxValue());
		
		x = i*(m_nBarWidth + m_nBarGap);
		y = m_sBarPicSize.cy - (int) nHeight -
			(m_bShowLabel*BAR_TXT_LABEL_HEIGHT) - CHART_TITLE_HEIGHT;

		// Center bars
		m_rMargin = (double)(rcBound.Width() - m_sBarPicSize.cx)/2.0;
		x += (int)m_rMargin;

		pDC->FillSolidRect( x, y,
			m_nBarWidth,(int)nHeight,
			colorBorder);

		// Draw a gradient, thanks to Nishant.S
		r1 = GetRValue(colorEnd);
		g1 = GetGValue(colorEnd);
		b1 = GetBValue(colorEnd);

		r2 = GetRValue(m_chartData.GetColor(i));
		g2 = GetGValue(m_chartData.GetColor(i));
		b2 = GetBValue(m_chartData.GetColor(i));

		// Don't corrupt border by over painting the gradient
		nHeight-=2;

		// Draw gradient
		for(int j=1;j<=m_nBarWidth-2;j++)
		{ 
			r = r1 + (j * (r2-r1) / m_nBarWidth);
			g = g1 + (j * (g2-g1) / m_nBarWidth);
			b = b1 + (j * (b2-b1) / m_nBarWidth);

			if (j<m_nBarWidth/2) {
				colorG = OrColor(RGB(r,g,b),RGB(255,255,255),(BAR_REFLECT_AMOUNT + 5*j)>100?
					100:(BAR_REFLECT_AMOUNT + 5*j));
			} else  {
				colorG = RGB(r,g,b);
			}

			pDC->FillSolidRect(j + x, y+1, 1,(int)nHeight,colorG);
		}

		// Return borders to usual
		nHeight+=2;

		// Do some Corrections
		pDC->SetPixel(x, y, m_colorChartBK);
		pDC->SetPixel(x + m_nBarWidth-1, y,m_colorChartBK);

		// Smooth these pixels
		pDC->SetPixel(x + 1, y, colorSmooth);
		pDC->SetPixel(x, y+1, colorSmooth);

		pDC->SetPixel(x + m_nBarWidth-2, y, colorSmooth);
		pDC->SetPixel(x + m_nBarWidth-1, y+1, colorSmooth);

		// Repair these pixels
		pDC->SetPixel(x + m_nBarWidth-2, y + 1, colorBorder);
		pDC->SetPixel(x + 1, y + 1,colorBorder);


		// Add a Percentage/Value at the top of each bar
		if (m_bShowBarText || m_bShowLabel)
		{
			pDC->SetBkMode(TRANSPARENT);
			m_pFontOld = (CFont*) pDC->SelectObject(&m_font);

			if (m_bShowBarText)
			{
				// If we shall display percentage
				if (m_nBarTextType== 0 )
				{
					str.Format("%0.01f%%", (m_chartData.GetValue(i)*100)/m_chartData.GetMaxValue());
					pDC->DrawText(str, CRect(x, y - BAR_TXT_PERCENT_HEIGHT, x+ m_nBarWidth + m_nBarGap-1, y),
						DT_LEFT | DT_SINGLELINE | DT_VCENTER);
				}
				else if (m_nBarTextType==1)		// Draw value at the top of the bar
				{
					str.Format("%0.02f", m_chartData.GetValue(i));
					pDC->DrawText(str, CRect(x, y - BAR_TXT_PERCENT_HEIGHT, x+ m_nBarWidth+ m_nBarGap-1, y),
						DT_LEFT | DT_SINGLELINE | DT_VCENTER);
				}
			}

			if (m_bShowLabel)
			{
				str = m_chartData.GetLabel(i);
				pDC->DrawText(str, CRect(x, y + (int)nHeight , x+ m_nBarWidth+ m_nBarGap-1, y + (int)nHeight + BAR_TXT_LABEL_HEIGHT),
					DT_LEFT | DT_SINGLELINE | DT_VCENTER);

				// If displaying a % at the top of each bar
			/*	if (m_nBarTextType==0)
				{
					str.Format("%0.02f", m_chartData.GetValue(i));
					pDC->DrawText(str, CRect(0, y - BAR_TXT_PERCENT_HEIGHT, BAR_TXT_VLABEL_MARGIN, y),
						DT_LEFT | DT_SINGLELINE | DT_VCENTER);
				}*/
			}

			pDC->SelectObject(m_pFontOld);
		}
	}
}

void CBarChart::CChartBar::ShowLabel(BOOL bShow)
{
	m_bShowLabel = bShow;
}

⌨️ 快捷键说明

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