Click here to Skip to main content
15,879,535 members
Articles / Desktop Programming / MFC
Article

CStatic-derived histogram control

Rate me:
Please Sign up or sign in to vote.
5.00/5 (11 votes)
9 Jan 2000 89K   3.5K   45   2
A simple histogram control for displaying data
  • Download demo project - 20 Kb
  • Download source files - 2 Kb
  • Sample Image - alexf_histogram.jpg

    The CAlexfStaticHistogram control is a lightweight class suitable for displaying histograms. You can add new columns, additional text, change text orientation and direction of motion (if you change data at runtime).

    Using CAlexfStaticHistogram in a dialog is quite simple:

    1. Include CAlexfStaticHistogram.h in your dialog class' header file.
    2. Add member variables of type CAlexfStaticHistogram for every static text control you want to subclass.
    3. Subclass the static text controls in your dialog's OnInitDialog() method and set the controls' style.
    m_sHistogram.SetTextWidth(50); // Set text width (0 - no text)
    m_sHistogram.SetTextLines(5);  // Set number of text lines (0 - none)
    m_sHistogram.text[0] = "Z1";   // Set text (too easy to create special
    m_sHistogram.text[1] = "Zz2";  // function for that)
    // ...
    m_sHistogram.SetMaxValue(99.9) // Set relatival maximum
    m_sHistogram.Add(50);          // Add new column to histogram

    If you want "dynamic" histogram - you can owerride, for example, OnTimer() and simply call:

    m_sHistogram.Add(/*Value*/);

    Please feel free to send me any suggestions about this control.

    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
    Web Developer SEO
    Russian Federation Russian Federation
    AlexF's Blog in Russian
    Owner Spy competition analysis
    Rating Burner Rating of blogs

    Comments and Discussions

     
    GeneralCode update Pin
    Fred Ackers15-Oct-06 12:32
    Fred Ackers15-Oct-06 12:32 
    I tried sending this to the author but the included email address is no longer in existance.

    Basically, i added color and changed the offset to cover more of the control properly.

    Here is the cpp file.
    /////////////////////////////////////////////////////////////////////////////
    // Copyright (C) 1999 by Alexander Fedorov
    // All rights reserved
    //
    // Distribute and use freely, except:
    // 1. Don't alter or remove this notice.
    // 2. Mark the changes you made
    //
    // Send bug reports, bug fixes, enhancements, requests, etc. to:
    //    alexander.fedorov@usa.net
    // updated by FNA - Fred Ackers - aqiruse@gmail.com
    /////////////////////////////////////////////////////////////////////////////
    
    // AlexfStaticHistogram.cpp : implementation file
    
    #include "stdafx.h"
    #include "AlexfStaticHistogram.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    /////////////////////////////////////////////////////////////////////////////
    // CAlexfStaticHistogram
    
    CAlexfStaticHistogram::CAlexfStaticHistogram()
    {
    	m_bOK = FALSE;
    	m_lTextLines = 0;
    	m_lTextWidth = 0;
    	m_lStack = 0;
    	m_dMaxValue = 100;
    	m_bTextLeft = TRUE;
    	m_bNeedFullRedraw = FALSE;
    	m_bMotionLToR = TRUE;
    	m_clr = GetSysColor(COLOR_BTNHIGHLIGHT);//FNA
    	m_clrBack = GetSysColor(COLOR_BTNFACE); //FNA
    
    	m_lArraySize = GetSystemMetrics(SM_CXSCREEN);
    	m_pdArray = new DOUBLE[m_lArraySize];
    	if (!m_pdArray) return;
    	ZeroMemory(m_pdArray, m_lArraySize * sizeof(DOUBLE));
    	m_bOK = TRUE;
    }
    
    CAlexfStaticHistogram::~CAlexfStaticHistogram()
    {
    	if (m_pdArray) delete [] m_pdArray;
    }
    
    
    BEGIN_MESSAGE_MAP(CAlexfStaticHistogram, CStatic)
    	//{{AFX_MSG_MAP(CAlexfStaticHistogram)
    	ON_WM_PAINT()
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // CAlexfStaticHistogram message handlers
    
    void CAlexfStaticHistogram::OnPaint() 
    {
    	if (!m_bOK)
    	{
    		CStatic::OnPaint();
    		return;
    	}
    	CPaintDC dc(this); // device context for painting
    	CRect cr;
    	GetClientRect(&cr);
    	if (m_bNeedFullRedraw)
    	{
    		m_bNeedFullRedraw = FALSE;
    		dc.FillRect(cr, & CBrush(GetSysColor(COLOR_BTNFACE)));
    	}
    	CRect cr1(cr);
    	if (m_bTextLeft) cr1.right = cr1.left + m_lTextWidth;
    	else cr1.left = cr1.right - m_lTextWidth;
    // text
    	dc.SetBkMode(TRANSPARENT);
    	dc.SetTextColor(GetSysColor(COLOR_BTNTEXT));
    	int hh = 0;
    	if (m_lTextLines != 0) hh = cr.Height() / m_lTextLines;
    	cr1.right = cr1.left + m_lTextWidth;
    	dc.FillRect(cr1, & CBrush(GetSysColor(COLOR_BTNFACE)));
    	cr1.bottom = cr1.top + hh;
    	CFont* pOldFont = dc.SelectObject(GetFont());
    	int i = 0;//FNA - fix for VS2005
    	for (i = 0; i < m_lTextLines; i++)
    	{
    		dc.DrawText(text[i], (LPRECT)&cr1,
    		DT_WORDBREAK | DT_CENTER | DT_VCENTER);
    		cr1.OffsetRect(0, hh);
    	}
    	dc.SelectObject(pOldFont);
    // graph
    	if (m_dMaxValue == 0) return;
    	if (m_bTextLeft) cr.left += m_lTextWidth;
    	else cr.right -= m_lTextWidth;
    	cr1 = cr;
    	if (m_bMotionLToR) cr1.right = cr1.left + 2;
    	else cr1.left = cr1.right - 2;
    	i = m_lStack;
    	cr1.bottom -= 1;
    	int h = cr.Height() - 2;
    	int nOffset = (int)((cr.right-cr.left)/m_lStack+0.5f);//FNA - Changed Offset to display in as much of full space as possible
    	while (TRUE)
    	{
    		int h1 = 0;
    		if (m_dMaxValue != 0) h1 = (int)((DOUBLE) h * m_pdArray[i] / m_dMaxValue);
    		if (h1 > h) h1 = h;
    		cr1.top = cr.top;
    		cr1.bottom = cr.bottom - h1;
    		dc.FillRect(cr1, & CBrush(m_clrBack));
    		cr1.top = cr.bottom - h1;
    		cr1.bottom = cr.bottom;
    		dc.FillRect(cr1, & CBrush(m_clr));//FNA - Changed to custom Color
    		if (m_bMotionLToR) cr1.OffsetRect(nOffset+(i%1?1:0), 0);//FNA - Changed Offset to display in as much of full space as possible
    		else cr1.OffsetRect(-(nOffset+(i%1?1:0)), 0);//FNA - Changed Offset to display in as much of full space as possible
    		if (i == 0) break;//FNA - was looping infinitely with new offset
    		i--;
    		if (m_bMotionLToR)
    		{
    			if (cr1.left > cr.right - 3) break;
    		}
    		else
    		{
    			if (cr1.left < cr.left) break;
    		}
    	}
    	// Do not call CStatic::OnPaint() for painting messages
    }
    
    BOOL CAlexfStaticHistogram::Add(DOUBLE dValue)
    {
    	if (!m_bOK) return FALSE;
    	m_lStack++;
    	if (m_lStack >= m_lArraySize) m_lStack = 0;
    	m_pdArray[m_lStack] = dValue;
    	RedrawWindow();
    	return TRUE;
    }
    
    BOOL CAlexfStaticHistogram::SetTextLeft(BOOL bSet)
    {
    	if (!m_bOK) return FALSE;
    	m_bTextLeft = bSet;
    	m_bNeedFullRedraw = TRUE;
    	RedrawWindow();
    	return TRUE;
    }
    
    BOOL CAlexfStaticHistogram::SetTextWidth(LONG lWidth)
    {
    	if (!m_bOK) return FALSE;
    	m_lTextWidth = lWidth;
    	m_bNeedFullRedraw = TRUE;
    	RedrawWindow();
    	return TRUE;
    }
    
    BOOL CAlexfStaticHistogram::SetTextLines(LONG lLines)
    {
    	if (!m_bOK) return FALSE;
    	m_lTextLines = lLines;
    	m_bNeedFullRedraw = TRUE;
    	RedrawWindow();
    	return TRUE;
    }
    
    BOOL CAlexfStaticHistogram::SetMotionLtoR(BOOL bSet)
    {
    	if (!m_bOK) return FALSE;
    	m_bMotionLToR = bSet;
    	m_bNeedFullRedraw = TRUE;
    	RedrawWindow();
    	return TRUE;
    }
    
    BOOL CAlexfStaticHistogram::SetMaxValue(DOUBLE dValue)
    {
    	if (!m_bOK) return FALSE;
    	m_dMaxValue = dValue;
    	m_bNeedFullRedraw = TRUE;
    	RedrawWindow();
    	return TRUE;
    }


    And here is the header file:
    /////////////////////////////////////////////////////////////////////////////
    // Copyright (C) 1999 by Alexander Fedorov
    // All rights reserved
    //
    // Distribute and use freely, except:
    // 1. Don't alter or remove this notice.
    // 2. Mark the changes you made
    //
    // Send bug reports, bug fixes, enhancements, requests, etc. to:
    //    alexander.fedorov@usa.net
    /////////////////////////////////////////////////////////////////////////////
    
    #if !defined(AFX_ALEXFSTATICHISTOGRAM_H__EE1F7AD3_2661_11D3_9865_868E4C4284CA__INCLUDED_)
    #define AFX_ALEXFSTATICHISTOGRAM_H__EE1F7AD3_2661_11D3_9865_868E4C4284CA__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // AlexfStaticHistogram.h : header file
    //
    
    /////////////////////////////////////////////////////////////////////////////
    // CAlexfStaticHistogram window
    
    class CAlexfStaticHistogram : public CStatic
    {
    // Construction
    public:
    	CAlexfStaticHistogram();
    
    // Attributes
    public:
    
    // Operations
    public:
    
    // Overrides
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CAlexfStaticHistogram)
    	//}}AFX_VIRTUAL
    
    // Implementation
    public:
    	BOOL Add(DOUBLE dValue);
    	BOOL IsOK() {return m_bOK;}
    	BOOL SetTextLeft(BOOL bSet = TRUE);
    	BOOL SetMotionLtoR(BOOL bSet = TRUE);
    	BOOL SetTextWidth(LONG lWidth);
    	BOOL SetTextLines(LONG lLines);
    	BOOL SetMaxValue(DOUBLE dValue);
    	void SetColor(COLORREF clr) { m_clr = clr; }//FNA
    	void SetBackColor(COLORREF clr) { m_clrBack = clr; }//FNA
    	CString text[10];		// text strings
    	virtual ~CAlexfStaticHistogram();
    
    	// Generated message map functions
    protected:
    	COLORREF m_clr;
    	COLORREF m_clrBack;
    	BOOL m_bOK;				// control operational
        LONG m_lTextLines;		// number of text lines
    	LONG m_lTextWidth;		// width of text field
        LONG m_lStack;
        DOUBLE m_dMaxValue;		// maximum value
        DOUBLE * m_pdArray;		// array of values
        LONG m_lArraySize;		// array size
    	BOOL m_bTextLeft;		// text placed at ledt corner
    	BOOL m_bNeedFullRedraw;	//
    	BOOL m_bMotionLToR;		// motion from left to right
    
    
    	//{{AFX_MSG(CAlexfStaticHistogram)
    	afx_msg void OnPaint();
    	//}}AFX_MSG
    
    	DECLARE_MESSAGE_MAP()
    };
    
    /////////////////////////////////////////////////////////////////////////////
    
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
    
    #endif // !defined(AFX_ALEXFSTATICHISTOGRAM_H__EE1F7AD3_2661_11D3_9865_868E4C4284CA__INCLUDED_)







    Nothing is impossible, It's merely a matter of finding an answer to the question of HOW? ... And answering that question is usually the most difficult part of the job!!!

    GeneralNice article Pin
    Georgi Petrov31-Jul-06 2:23
    Georgi Petrov31-Jul-06 2:23 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.