📄 barchart.cpp
字号:
/*********************************************************************
* BarChart.cpp
* implementation of
* CChartBar,
* CChartData,
* CChartPrinter,
* CChartGCalc,
* CGDIGrid,
*
* Auther: Hamed.M.
* EMail : HamedMosavi @ gmail.com
*
* CAUTION Disclaimer:
* This code is provided as is without any warranty of
* any kind. The author is not responsible for whatever
* problem or damages that may occur as aresault of using
* this code. Use this entirely at your own risk.
* So don't try to find me if this code made your dog
* Sound like a frog, or burned your car, or even made your
* girl/boy friend shout on you. I am not responsible ;)
*
*
********************************************************************/
/********************************************************************
* History:
*
* Released : 2007/01/11
*
* BugFixes:
* 2007/01/11
* unsigned long double converted to -> double
* Some scaling bugs fixed
* Tooltips added
*
* 2007/01/15
* Some function changed.
* Tooltip updated.
* Some comments added.
*
* 2007/01/20
* Tooltips now behave much like tooltips(!)
*
* 2007/01/24
* Database connectivity added.
*
* 2007/01/26
* Tooltip bug fixed (SetCapture added).
********************************************************************/
#include "stdafx.h"
#include "BarChart.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
///////////////////////////////////////////////////////////////////////
// CBarChart Class
//
// Represents a chart control. The chart shows some bars
// Each bar has a value. Bars heights will be calculated
// Regarding other bars. The bars are able to show a percentage
// Instead of a value. The bar with maximum value has 100% and
// Percentage of other bars will be calculated in accordance to
// This maximum value.
//
///////////////////////////////////////////////////////////////////////
CBarChart::CBarChart()
{
m_rctClient = CRect(0, 0, 0, 0);
SetBKColor(RGB(240, 240, 240));
m_pBmpBars = NULL;
m_pBmpOld = NULL;
ShowLabel(TRUE);
ShowGrid(TRUE);
ShowBarText(1, TRUE);
SetAutoScale(FALSE);
ShowTooltip(TRUE);
m_szTitle = "";
m_szLastErr = "";
}
CBarChart::~CBarChart()
{
if (m_brFrame.GetSafeHandle())
{
m_brFrame.DeleteObject();
}
if (m_pBmpOld)
{
m_dcMem.SelectObject(m_pBmpOld);
}
if (m_pBmpBars)
{
m_pBmpBars->DeleteObject();
delete m_pBmpBars;
m_pBmpBars = NULL;
}
if (m_dcMem.GetSafeHdc())
{
m_dcMem.DeleteDC();
}
}
BEGIN_MESSAGE_MAP(CBarChart, CWnd)
//{{AFX_MSG_MAP(CBarChart)
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_MOUSEMOVE()
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBarChart message handlers
// Creates the child control.
// Parameters:
// rect : Defines bounding rectangle of the control
// pParentWnd : A pointer to the window on which this control will be shown
// nControlID : Identifyer of the control
// szChartTitle: Defines the title at the bottom of the control, can be a simple description of the chart.
BOOL CBarChart::Create(const RECT &rect, CWnd *pParentWnd, UINT nControlID, CString szChartTitle)
{
if (GetSafeHwnd())
{
return FALSE;
}
m_rctClient = rect;
m_szTitle = szChartTitle;
BOOL bRes = CWnd::Create( NULL, NULL, WS_CHILD|WS_VISIBLE, rect, pParentWnd, nControlID );
if (TRUE == bRes)
{
InitToolTips();
}
return bRes;
}
BOOL CBarChart::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
void CBarChart::OnPaint()
{
CPaintDC dc(this);
GetClientRect(&m_rctClient);
if (m_dcMem.GetSafeHdc())
{
if (m_bAutoScale)
{
dc.StretchBlt(0, 0, m_rctClient.Width(), m_rctClient.Height(),
&m_dcMem, 0, 0, m_rctMemPic.Width(), m_rctMemPic.Height(), SRCCOPY);
}
else
{
dc.BitBlt(0, 0, m_rctClient.Width(), m_rctClient.Height(),
&m_dcMem, 0, 0, SRCCOPY);
}
}
else
{
RedrawChart(&dc);
}
}
// Prints the content of the child control (WYSIWYG)
// Parameters:
// bCompatible :
// Default is set to FALSE
// Set this TRUE if you have any difficaulty printing your chart.
// It's defined since some printers might not be able to print DDB
// Bitmaps, setting this to TRUE force the function to use DIB instead.
void CBarChart::Print(BOOL bCompatible)
{
CClientDC dc(this);
m_printer.Print(&dc, &m_dcMem, m_pBmpBars,
(CString)AfxGetAppName() + (CString)" - " + (CString)m_szTitle,
m_rctMemPic, m_bAutoScale, bCompatible);
}
void CBarChart::RedrawChart(CDC* pDC)
{
if (!m_dcMem.GetSafeHdc())
{
m_dcMem.CreateCompatibleDC(pDC);
}
// Deselect and destroy old bitmap, and create a new one
ResetBitmap(pDC);
Refresh();
}
void CBarChart::ResetBitmap(CDC* pDC)
{
// Deselect and destroy old bitmap
if (m_pBmpOld)
{
m_dcMem.SelectObject(m_pBmpOld);
}
if (m_pBmpBars)
{
m_pBmpBars->DeleteObject();
delete m_pBmpBars;
m_pBmpBars = NULL;
}
// Re create bitmap
m_rctMemPic.top = 0;
m_rctMemPic.left = 0;
m_rctMemPic.bottom = m_bars.GetBarHeight();
m_rctMemPic.right = m_bars.GetBarWidth();
if (m_rctMemPic.Width()<m_rctClient.Width())
{
m_rctMemPic.right = m_rctClient.Width();
}
if (m_rctMemPic.Height()<m_rctClient.Height())
{
m_rctMemPic.bottom = m_rctClient.Height();
}
m_pBmpBars = new CBitmap;
m_pBmpBars->CreateCompatibleBitmap(pDC, m_rctMemPic.right, m_rctMemPic.bottom);
m_pBmpOld = (CBitmap*)m_dcMem.SelectObject(m_pBmpBars);
}
// Sets/Resets the scale capability
// Parameters:
// bAutoScale :
// If set to TRUE force the chart to scale itself to the parent
// Window, regardless of it's initial bounding rectangle.
// If set to FALSE returns the size of the chart to the original
// Bounding rectangle.
// Note that chart saves it's initial state of creation.
void CBarChart::SetAutoScale(BOOL bAutoScale)
{
m_bAutoScale = bAutoScale;
}
// Sets the color of the background rectangle of the chart
// Parameters:
// colorBK :
// The color in COLORREF format(eg.RGB(250,250,250))
void CBarChart::SetBKColor(COLORREF colorBK)
{
// Reset background color
m_colorBK = colorBK;
// Reset frame brush
if (m_brFrame.GetSafeHandle())
{
m_brFrame.DeleteObject();
}
m_brFrame.CreateSolidBrush(DifColor(colorBK, CHART_BORDER_DARKNESS));
// Reset grid
m_grid.SetColor(DifColor(colorBK, 50));
// Redraw window, if it is created
if (GetSafeHwnd())
{
Invalidate();
}
}
// Adds a bar to the chart
// Parameters:
// udValue : Value of the bar
// szLabel : Label of the bar, will be shown under the bar
// color : Color of the bar. This color will be used to create a gradient.
// bRepaint: If set to TRUE, forces the chart to show changes on the screen
// Default is set to false. It is recommended to set it to true just
// For last Add bar of the chart, so the chart won't be forced to
// Show changes every time a single bar is added.
void CBarChart::AddBar(double udValue, CString szLabel, COLORREF color, BOOL bRepaint)
{
m_bars.AddBar(udValue, szLabel, color);
if (bRepaint)
{
CClientDC dc(this);
RedrawChart(&dc);
Invalidate();
}
}
// Shows/Hides the labels under the chart control
// Parameters:
// bShow : Set to TRUE to show labels
// bRedraw: If set to TRUE, forces the chart to show changes on the screen
// Default is set to false.
void CBarChart::ShowLabel(BOOL bShow, BOOL bRedraw)
{
m_bars.ShowLabel(bShow);
if(bRedraw)
{
Refresh();
}
}
// Shows/Hides the grid behind the chart control
// Parameters:
// bShow : Set to TRUE to show labels
// bRedraw: If set to TRUE, forces the chart to show changes on the screen
// Default is set to false.
void CBarChart::ShowGrid(BOOL bShow, BOOL bRedraw)
{
m_bShowGrid = bShow;
if(bRedraw)
{
Refresh();
}
}
// Shows/Hides the values at the top of the bars of the chart control
// Parameters:
// nType : This parameter can be 0 or 1. 0 indicates the chart should
// Display percentage of it's value as the top text which is also
// The default behavior. Set it to 1 to force the chart to show
// The exact VALUE instead of the percentage.
// bShow : Set to TRUE to show labels or FALSE to hide them
// bRedraw: If set to TRUE, forces the chart to show changes on the screen
// Default is set to false.
void CBarChart::ShowBarText(int nType, BOOL bShow, BOOL bRedraw)
{
m_bars.ShowBarText(nType, bShow);
if(bRedraw)
{
Refresh();
}
}
// Activates/Deactivates tooltips for bars
// Parameters:
// bShow : Set to TRUE to Activate tooltips
void CBarChart::ShowTooltip(BOOL bShow)
{
m_bShowTip = bShow;
}
// Draw bar chart
void CBarChart::DrawBars(CDC* pDC, CRect& rcBound)
{
m_bars.SetBkColor(m_colorBK);
m_bars.Draw(&m_dcMem, rcBound);
}
void CBarChart::DrawTitle(CDC* pDC)
{
//pDC->SetBkMode(TRANSPARENT);
pDC->SetBkColor(m_colorBK);
CRect rcTitle = CRect(m_rctMemPic.left ,
m_rctMemPic.bottom-CHART_TITLE_HEIGHT,
m_rctMemPic.right, m_rctMemPic.bottom);
pDC->FillSolidRect(rcTitle, m_colorBK);
// UNDONE : DEFAULT DEVICE CONTEXT FONT IS SELECTED, SHOUD CHANGE TO A CUSTOM DEFINED FONT
pDC->SetTextColor(RGB(200, 200, 200));
pDC->DrawText(m_szTitle,
CRect(rcTitle.left+2 ,rcTitle.top+2, rcTitle.right, rcTitle.bottom)
, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
pDC->SetTextColor(RGB(0,0,0));
pDC->DrawText(m_szTitle,rcTitle, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
}
// Sets the text(Title/Label) of the chart control. This is the text that will be diplayed
// At the bottom of the chart.
// Parameters:
// szNewTitle : A title string
void CBarChart::SetTitle(CString szNewTitle)
{
m_szTitle = szNewTitle;
}
// Forces chart to be redrawn. Redrawing does not affect the chart's bars or etc.
// It just makes the chart to redraw all it's content items.
void CBarChart::Refresh()
{
if (!GetSafeHwnd())
{
return;
}
// Draw background
if (m_dcMem.GetSafeHdc())
{
m_dcMem.FillSolidRect(&m_rctMemPic, m_colorBK);
}
else
{
return;
}
// Draw gridlines
if (m_bShowGrid)
{
m_rctMemPic.bottom -= (CHART_TITLE_HEIGHT +
(m_bars.IsLabelVisible() * BAR_TXT_LABEL_HEIGHT) + 3);
m_grid.Draw(&m_dcMem, m_rctMemPic);
m_rctMemPic.bottom += (CHART_TITLE_HEIGHT +
(m_bars.IsLabelVisible() * BAR_TXT_LABEL_HEIGHT) + 3);
}
// Draw bar chart
DrawBars(&m_dcMem, m_rctMemPic);
// Draw the chart title
DrawTitle(&m_dcMem);
// Draw a frame around the window
m_dcMem.FrameRect(&m_rctMemPic, &m_brFrame);
Invalidate();
}
// Removes all bars from the chart. The background remains unchanges
void CBarChart::RemoveAll()
{
m_bars.RemoveAll();
Refresh();
}
// Removes a bar with the zero index identified. Removing a bar does not force the other bars to
// Re calculate height or percentage. There is, however, workaround this as a new feature.
// Parameters:
// nIndex: Zero based index of the bar to remove.
void CBarChart::RemoveAt(int nIndex)
{
m_bars.RemoveAt(nIndex);
Refresh();
}
// Removes all bars, and forces the chart to be redrawn.
void CBarChart::Reset()
{
m_bars.RemoveAll();
m_rctMemPic = CRect(0, 0, 0, 0);
CClientDC dc(this);
RedrawChart(&dc);
}
void CBarChart::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
// m_rctClient.bottom = cy - m_rctClient.top;
// m_rctClient.right = cx - m_rctClient.left;
}
void CBarChart::OnMouseMove(UINT nFlags, CPoint point)
{
CWnd::OnMouseMove(nFlags, point);
if ( (m_bAutoScale && PtInRect(m_rctClient, point)) ||
(!m_bAutoScale&& PtInRect(m_rctMemPic, point)) )
{
if (this!=GetCapture())
{
SetCapture();
}
m_bars.DisplayToolTip(point, m_rctClient, m_rctMemPic, m_bAutoScale, m_szTip);
if (!m_szTip.IsEmpty())
{
m_toolTip.Pop();
}
else
{
m_toolTip.Hide();
}
}
else
{
m_toolTip.Hide();
if (this == GetCapture())
{
if (!ReleaseCapture())
{
// Retry
ReleaseCapture();
};
}
}
}
void CBarChart::InitToolTips()
{
m_toolTip.Create(this, &m_bShowTip, &m_szTip, 4000);
}
// Does nothing at the moment
// {
// //Empty body
// }
void CBarChart::RedrawAll()
{
// UNDONE : FORCE CHART TO RE CALCULATE ALL BAR HEIGHTS AND %
}
// WARNING : ODBC ONLY
// This function tryes to read chart data from a Table
BOOL CBarChart::ReadFromDatabase(CString szDSN, CString szTable, CString szFilter,
CString szLabelFieldName, CString szValueFieldName,
COLORREF colorBars,
CString szUsername, CString szPass)
{
CChartDatabase cDB;
if (!cDB.OpenTable(szDSN, szTable, szLabelFieldName, szValueFieldName,
szFilter, szUsername, szPass))
{
m_szLastErr = cDB.GetLastErrorMessage();
return FALSE;
};
CString szLabel;
double dVal;
while (!cDB.IsEOF())
{
cDB.GetRow(szLabel, dVal);
if (colorBars == RGB(0, 0, 0))
{
AddBar(dVal, szLabel, RGB(rand()%255, rand()%255, rand()%255));
}
else
{
AddBar(dVal, szLabel, colorBars);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -