|
Hi ,
I did a test app with your class C2DPushGraph. I was just learning about printing. I need to add a print functionality to my test application, wherein I can give either save the image of the graph control as a BMP or print. Could you help me?
Thanks in Advance !
|
|
|
|
|
I just wanted to thank your for this extraordinary documentation.
|
|
|
|
|
I'd like to use this in my commercial product, do you require licensing to be followed regarding this component?
|
|
|
|
|
I want to store painted graph to BMP or JPEG file.
Is no there method?
e-mail : eldran@empal.com
Thanks...
|
|
|
|
|
I can get successfull compiling result in RELEASE mode.But I got the following output in DEBUG mode.What is wrong ????I am using VC++ 6.0 with SP6 on WinXP platform.
--------------------Configuration: C2DPushGraph - Win32 Debug--------------------
Compiling...
CpuUsage.cpp
d:\program files\microsoft visual studio\vc98\include\xmemory(55) : error C2220: warning treated as error - no object file generated
d:\program files\microsoft visual studio\vc98\include\xmemory(55) : warning C4100: '_P' : unreferenced formal parameter
d:\program files\microsoft visual studio\vc98\include\xmemory(57) : warning C4100: '_P' : unreferenced formal parameter
d:\program files\microsoft visual studio\vc98\include\vector(267) : warning C4663: C++ language change: to explicitly specialize class template 'vector' use the following syntax:
template<> class vector<bool,class std::allocator<unsigned="" int=""> > ...
d:\program files\microsoft visual studio\vc98\include\vector(172) : warning C4018: '<' : signed/unsigned mismatch
d:\program files\microsoft visual studio\vc98\include\vector(172) : while compiling class-template member function 'void __thiscall std::vector<unsigned int,class="" std::allocator<unsigned="" int=""> >::insert(unsigned int *,unsigned int,const unsig
ned int &)'
d:\program files\microsoft visual studio\vc98\include\vector(184) : warning C4018: '<' : signed/unsigned mismatch
d:\program files\microsoft visual studio\vc98\include\vector(172) : while compiling class-template member function 'void __thiscall std::vector<unsigned int,class="" std::allocator<unsigned="" int=""> >::insert(unsigned int *,unsigned int,const unsig
ned int &)'
d:\temp\c2dpushgraph_demo\demo\perfcounters.h(238) : warning C4018: '==' : signed/unsigned mismatch
d:\temp\c2dpushgraph_demo\demo\perfcounters.h(222) : while compiling class-template member function '__int64 __thiscall CPerfCounters<__int64>::GetCounterValueForProcessID(struct _PERF_OBJECT_TYPE *,unsigned long,unsigned long)'
d:\temp\c2dpushgraph_demo\demo\perfcounters.h(271) : warning C4244: '=' : conversion from '__int64' to 'int', possible loss of data
d:\temp\c2dpushgraph_demo\demo\perfcounters.h(222) : while compiling class-template member function '__int64 __thiscall CPerfCounters<__int64>::GetCounterValueForProcessID(struct _PERF_OBJECT_TYPE *,unsigned long,unsigned long)'
d:\temp\c2dpushgraph_demo\demo\perfcounters.h(272) : warning C4018: '==' : signed/unsigned mismatch
d:\temp\c2dpushgraph_demo\demo\perfcounters.h(222) : while compiling class-template member function '__int64 __thiscall CPerfCounters<__int64>::GetCounterValueForProcessID(struct _PERF_OBJECT_TYPE *,unsigned long,unsigned long)'
d:\program files\microsoft visual studio\vc98\include\xmemory(53) : warning C4100: '_P' : unreferenced formal parameter
d:\program files\microsoft visual studio\vc98\include\xmemory(84) : see reference to function template instantiation 'void __cdecl std::_Destroy(unsigned int *)' being compiled
Error executing cl.exe.
C2DPushGraph.exe - 1 error(s), 9 warning(s)
Any suggestion???
-- modified at 21:56 Tuesday 6th September, 2005
|
|
|
|
|
MSDN said below...
warning treated as error - no object file generated
When the compiler option /WX is used, the first warning generated by the compiler causes this error message to be displayed.
Either correct the condition that caused the warning or compile at a lower warning level or without /WX.
|
|
|
|
|
I had memeory problem on Windows xp. I tried your version of the code.
It didn't help.
Yours
Nuray
Ps: Compiler errors & warnings
2DPushGraph.cpp
c:\mfc\c2dpushgraph_demo\demo\2dpushgraph.h(51) : error C2955: 'CList' : use of class template requires template argument list
c:\program files\microsoft visual studio\vc98\mfc\include\afxtempl.h(653) : see declaration of 'CList'
c:\mfc\c2dpushgraph_demo\demo\2dpushgraph.h(51) : fatal error C1903: unable to recover from previous error(s); stopping compilation
C2DPushGraph.cpp
c:\mfc\c2dpushgraph_demo\demo\2dpushgraph.h(51) : error C2955: 'CList' : use of class template requires template argument list
c:\program files\microsoft visual studio\vc98\mfc\include\afxtempl.h(653) : see declaration of 'CList'
c:\mfc\c2dpushgraph_demo\demo\2dpushgraph.h(51) : fatal error C1903: unable to recover from previous error(s); stopping compilation
C2DPushGraphDlg.cpp
c:\mfc\c2dpushgraph_demo\demo\2dpushgraph.h(51) : error C2955: 'CList' : use of class template requires template argument list
c:\program files\microsoft visual studio\vc98\mfc\include\afxtempl.h(653) : see declaration of 'CList'
c:\mfc\c2dpushgraph_demo\demo\2dpushgraph.h(51) : fatal error C1903: unable to recover from previous error(s); stopping compilation
CpuUsage.cpp
c:\program files\microsoft visual studio\vc98\include\xmemory(39) : error C2220: warning treated as error - no object file generated
c:\program files\microsoft visual studio\vc98\include\xmemory(39) : warning C4100: '_P' : unreferenced formal parameter
c:\program files\microsoft visual studio\vc98\include\xmemory(41) : warning C4100: '_P' : unreferenced formal parameter
c:\program files\microsoft visual studio\vc98\include\vector(249) : warning C4663: C++ language change: to explicitly specialize class template 'vector' use the following syntax:
template<> class vector<bool,class std::allocator<unsigned="" int=""> > ...
c:\program files\microsoft visual studio\vc98\include\vector(156) : warning C4018: '<' : signed/unsigned mismatch
c:\program files\microsoft visual studio\vc98\include\vector(156) : while compiling class-template member function 'void __thiscall std::vector<unsigned int,class="" std::allocator<unsigned="" int=""> >::insert(unsigned int *,unsigned int,const unsig
ned int &)'
c:\program files\microsoft visual studio\vc98\include\vector(167) : warning C4018: '<' : signed/unsigned mismatch
c:\program files\microsoft visual studio\vc98\include\vector(156) : while compiling class-template member function 'void __thiscall std::vector<unsigned int,class="" std::allocator<unsigned="" int=""> >::insert(unsigned int *,unsigned int,const unsig
ned int &)'
c:\mfc\c2dpushgraph_demo\demo\perfcounters.h(238) : warning C4018: '==' : signed/unsigned mismatch
c:\mfc\c2dpushgraph_demo\demo\perfcounters.h(222) : while compiling class-template member function '__int64 __thiscall CPerfCounters<__int64>::GetCounterValueForProcessID(struct _PERF_OBJECT_TYPE *,unsigned long,unsigned long)'
c:\mfc\c2dpushgraph_demo\demo\perfcounters.h(271) : warning C4244: '=' : conversion from '__int64' to 'int', possible loss of data
c:\mfc\c2dpushgraph_demo\demo\perfcounters.h(222) : while compiling class-template member function '__int64 __thiscall CPerfCounters<__int64>::GetCounterValueForProcessID(struct _PERF_OBJECT_TYPE *,unsigned long,unsigned long)'
c:\mfc\c2dpushgraph_demo\demo\perfcounters.h(272) : warning C4018: '==' : signed/unsigned mismatch
c:\mfc\c2dpushgraph_demo\demo\perfcounters.h(222) : while compiling class-template member function '__int64 __thiscall CPerfCounters<__int64>::GetCounterValueForProcessID(struct _PERF_OBJECT_TYPE *,unsigned long,unsigned long)'
c:\program files\microsoft visual studio\vc98\include\xmemory(37) : warning C4100: '_P' : unreferenced formal parameter
c:\program files\microsoft visual studio\vc98\include\xmemory(68) : see reference to function template instantiation 'void __cdecl std::_Destroy(unsigned int *)' being compiled
Generating Code...
Error executing cl.exe.
C2DPushGraph.exe - 7 error(s), 9 warning(s)
|
|
|
|
|
It seems that some text got filtered away when I submited the file into the replay box. (I forgot the check "Do not treat <'s as HTML tags")
The Line with CList should read
CList<int,int> aMagnitudes;
and the line with the CArray
CArray<PushGraphLine*, PushGraphLine*> m_aLines;
cheers
<font color="#FF0000" size="1">bb |~ bb</font>
|
|
|
|
|
Hi Stuart,
Nice control, used it in a Windows CE apllication, but got a lot
of errors which I have fixed now.
Small Error:
Changed in PushGraphLine the CArray into a CList to prevent
the thing beeing a memory hog: CArray::RemoveAt(0) does not
delete the memory. Its also much faster when you dont need
to copy the values in the list.
Big Error:
Changed these 2 functions:
CDC& internal_InitBackBuffer( CPaintDC &dc );
void internal_FreeBackBuffer( CPaintDC &dc, bool bDelete) ;
They create the second device contexts only once. If the CDC is
created multiple times the
dc.SelectObject(m_pOldBitmap);
causes massive resource leaks. Its also faster now.
I also made it Windows CE compatible using a quick hack
just scan for _WIN32_WCE ...
OK: Here is the modified source code:
Cheers
Harald
//*************************************************************
/* ===================================================================
C2DPushGraph Control (2DPushGraph.h and 2DPushGraph.cpp)
Author: Stuart Konen
Contact: skonen@gmail.com (Job information welcome)
Description: A push graph control similiar to the graph control located
in Microsoft's Task Manager.
====================================================================*/
#if !defined(AFX_2DPUSHGRAPH_H_INCLUDED)
#define AFX_2DPUSHGRAPH_H_INCLUDED
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <windows.h>
#include "afxtempl.h"
/////////////////////////////////////////////////////////////////////////////
// C2DPushGraph window
// ===================================================================
struct GraphColor
{
GraphColor() { bRed = bGreen = bBlue = 0; }
operator COLORREF() { return RGB(bRed, bGreen, bBlue); }
BYTE bRed, bGreen, bBlue;
};
// ===================================================================
struct PushGraphLine
{
// Daten
COLORREF crLine;
UINT uiID;
bool bShowAsBar;
UINT uiLineWidth;
// CHANGE HK: CArray -> CList: Prevent Memory Hog
CList<int, int=""> aMagnitudes;
// Konstruktoren
PushGraphLine(UINT uiLineID)
{
crLine = RGB(0, 255, 0);
uiID = uiLineID;
uiLineWidth= 1;
bShowAsBar = false;
}
};
// ===================================================================
class C2DPushGraph : public CWnd
{
/* Internal data members */
private:
COLORREF m_crTextColor;
COLORREF m_crBGColor;
COLORREF m_crGridColor;
CString m_strMaxLabel;
CString m_strMinLabel;
bool m_bShowMinMax;
bool m_bShowGrid;
bool m_bStylesModified;
int m_nMoveOffset;
int m_nMaxCoords;
int m_nMaxPeek;
int m_nMinPeek;
int m_nGridSize;
int m_nPeekOffset;
CBitmap *m_pOldBitmap; // Original bitmap
CBitmap m_bmBack; // Bitmap for backbuffering
CDC m_dcBack;
bool m_bInitdcBack;
unsigned short m_usLineInterval;
CArray<pushgraphline*, pushgraphline*=""> m_aLines;
public:
C2DPushGraph();
virtual ~C2DPushGraph();
bool CreateFromStatic( UINT nStaticID, CWnd* pParent );
/* Functions that retrieve attributes */
LPCTSTR GetLabelForMax() const;
LPCTSTR GetLabelForMin() const;
COLORREF GetBGColor() const;
COLORREF GetGridColor() const;
COLORREF GetLineColor( UINT uiLineID );
COLORREF GetTextColor() const;
int GetGridSize() const;
int GetMaxPeek() const;
int GetMinPeek() const;
unsigned short GetInterval() const;
/* Functions that set attributes */
void SetBGColor(COLORREF crColor);
void SetGridColor(COLORREF crColor);
void SetTextColor(COLORREF crColor);
void SetGridSize( unsigned short usWidthAndHeight );
void SetMaxPeek(int nMax);
void SetMinPeek(int nMin);
void SetPeekRange(int nMin, int nMax);
void SetLabelForMax( LPCTSTR lpszLabel );
void SetLabelForMin( LPCTSTR lpszLabel );
void SetInterval( unsigned short usInterval );
bool SetLineColor( COLORREF crColor, UINT uiLineID );
/* Line control functions */
bool AddLine( UINT uiLineID, COLORREF crColor, UINT uiLineWidth =1 );
void RemoveLine( UINT uiLineID );
bool Push( int nMagnitude, UINT uiLineID );
void ShowAsBar( UINT uiLineID, bool bAsBar );
void Update();
/* Visibility Functions */
inline void ShowGrid( bool bShow = true)
{ m_bShowGrid = bShow; }
inline void ShowLabels( bool bShow = true)
{ m_bShowMinMax = bShow; }
CRect& getClientRect();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(C2DPushGraph)
//}}AFX_VIRTUAL
// Generated message map functions
protected:
//{{AFX_MSG(C2DPushGraph)
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnPaint();
afx_msg void OnSizing(UINT fwSide, LPRECT pRect);
afx_msg void OnSize(UINT nType, int cx, int cy);
//}}AFX_MSG
static BOOL m_bRegistered;
static BOOL RegisterClass();
DECLARE_MESSAGE_MAP()
private:
virtual void internal_DrawGrid( CDC &dc, CRect &rect );
virtual void internal_DrawLines( CDC &dc, CRect &rect );
virtual void internal_DrawBar( CDC &dc, CRect &rect,
PushGraphLine& rLine );
virtual void internal_DrawMinMax( CDC &dc, CRect& rect);
CDC& internal_InitBackBuffer( CPaintDC &dc );
void internal_FreeBackBuffer( CPaintDC &dc, bool bDelete );
public:
PushGraphLine* internal_LineFromID( UINT uiLineID );
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_2DPUSHGRAPH_H_INCLUDED)
//*************************************************************
//*************************************************************
//*************************************************************
//*************************************************************
//*************************************************************
//*************************************************************
//*************************************************************
/* ===================================================================
C2DPushGraph Control (2DPushGraph.h and 2DPushGraph.cpp)
Author: Stuart Konen
Contact: skonen@gmail.com (Job information welcome)
Description: A push graph control similiar to the graph control located
in Microsoft's Task Manager.
====================================================================*/
#include "stdafx.h"
#include "2DPushGraph.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define PUSHGRAPH_MAX(num, max, type) \
((num > max) ? (type)(max) : (type)(num))
#define PUSHGRAPH_MIN(num, min, type) \
((num < min) ? (type)(min) : (type)(num))
/* Self-Register */
BOOL C2DPushGraph::m_bRegistered = C2DPushGraph::RegisterClass();
/////////////////////////////////////////////////////////////////////////////
// C2DPushGraph
C2DPushGraph::C2DPushGraph()
{
m_nMaxCoords = -1;
m_nMoveOffset = 0;
m_nPeekOffset = 0;
m_bStylesModified = false;
m_usLineInterval = 2;
m_pOldBitmap = NULL;
m_bInitdcBack = false;
ShowGrid(true);
ShowLabels(false);
SetPeekRange(0, 100);
SetLabelForMax(_T("100%"));
SetLabelForMin(_T("0%"));
SetGridSize(15);
SetBGColor ( RGB(0, 0, 0) );
SetGridColor( RGB(0, 150, 0) );
SetTextColor( RGB(255, 255, 0) );
}
// ===================================================================
C2DPushGraph::~C2DPushGraph()
{
while (m_aLines.GetSize())
{
delete m_aLines[0];
m_aLines.RemoveAt(0);
}
}
// ===================================================================
BOOL C2DPushGraph::RegisterClass()
{
/* Static function to automatically register this class */
WNDCLASS wc;
ZeroMemory(&wc, sizeof(WNDCLASS));
wc.lpfnWndProc = ::DefWindowProc;
wc.hInstance = (HINSTANCE)::GetModuleHandle(NULL);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszClassName = _T("C2DPushGraph");
return AfxRegisterClass(&wc);
}
BEGIN_MESSAGE_MAP(C2DPushGraph, CWnd)
//{{AFX_MSG_MAP(C2DPushGraph)
ON_WM_ERASEBKGND()
ON_WM_PAINT()
// ON_WM_SIZING()
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// ===================================================================
bool C2DPushGraph::CreateFromStatic( UINT nStaticID, CWnd* pParent )
{
CStatic wndStatic;
if (pParent == NULL || !wndStatic.SubclassDlgItem(nStaticID, pParent))
{
return false;
}
/* Get the static windows rectangle and transform it into
parent client coordinates, instead of screen coordinates */
CRect rectStatic;
wndStatic.GetWindowRect(&rectStatic);
pParent->ScreenToClient(&rectStatic);
if ( !CreateEx( wndStatic.GetExStyle(),
NULL, NULL, WS_CHILD | WS_VISIBLE | wndStatic.GetStyle(),
rectStatic, pParent, nStaticID, NULL))
{
wndStatic.DestroyWindow();
return false;
}
wndStatic.DestroyWindow();
return true;
}
// ==========================================================================
// Functions for Setting and Retrieving attributes
// ==========================================================================
COLORREF C2DPushGraph::GetGridColor() const
{
return m_crGridColor;
}
// ===================================================================
void C2DPushGraph::SetGridColor( COLORREF crColor )
{
m_crGridColor = crColor;
}
// ===================================================================
COLORREF C2DPushGraph::GetTextColor() const
{
return m_crTextColor;
}
// ===================================================================
void C2DPushGraph::SetTextColor( COLORREF crColor )
{
m_crTextColor = crColor;
}
// ===================================================================
COLORREF C2DPushGraph::GetBGColor() const
{
return m_crBGColor;
}
// ===================================================================
void C2DPushGraph::SetBGColor( COLORREF crColor )
{
m_crBGColor = crColor;
}
// ===================================================================
int C2DPushGraph::GetGridSize() const
{
return m_nGridSize;
}
// ===================================================================
void C2DPushGraph::SetGridSize( unsigned short usWidthAndHeight )
{
m_nGridSize = PUSHGRAPH_MIN(usWidthAndHeight, 3, int);
}
// ===================================================================
int C2DPushGraph::GetMaxPeek() const
{
return m_nMaxPeek;
}
// ===================================================================
void C2DPushGraph::SetMaxPeek( int nMax )
{
m_nMaxPeek = nMax;
}
// ===================================================================
LPCTSTR C2DPushGraph::GetLabelForMax() const
{
return (LPCTSTR)m_strMaxLabel;
}
// ===================================================================
void C2DPushGraph::SetLabelForMax( LPCTSTR lpszLabel )
{
m_strMaxLabel = lpszLabel;
}
// ===================================================================
int C2DPushGraph::GetMinPeek() const
{
return m_nMinPeek;
}
// ===================================================================
void C2DPushGraph::SetMinPeek( int nMin )
{
if (nMin < 0)
{
m_nPeekOffset = 0 - nMin;
}
else
{
m_nPeekOffset = 0;
}
m_nMinPeek = nMin;
}
// ===================================================================
LPCTSTR C2DPushGraph::GetLabelForMin() const
{
return (LPCTSTR)m_strMinLabel;
}
// ===================================================================
void C2DPushGraph::SetLabelForMin( LPCTSTR lpszLabel )
{
m_strMinLabel = lpszLabel;
}
// ===================================================================
void C2DPushGraph::SetPeekRange( int nMin, int nMax )
{
ASSERT(nMin < nMax);
SetMinPeek(nMin);
SetMaxPeek(nMax);
}
// ===================================================================
unsigned short C2DPushGraph::GetInterval() const
{
return m_usLineInterval;
}
// ===================================================================
void C2DPushGraph::SetInterval( unsigned short usInterval )
{
m_usLineInterval = usInterval;
m_nMaxCoords = -1; // Forces reset
}
// ===================================================================
bool C2DPushGraph::AddLine( UINT uiLineID, COLORREF crColor, UINT uiLineWidth)
{
PushGraphLine *pNewLine = new PushGraphLine(uiLineID);
if (!pNewLine)
{
ASSERT(pNewLine && "Out of memory");
return false;
}
pNewLine->crLine = crColor;
pNewLine->uiLineWidth = uiLineWidth;
m_aLines.Add(pNewLine);
return true;
}
// ===================================================================
void C2DPushGraph::RemoveLine( UINT uiLineID )
{
for (int n = m_aLines.GetSize()-1; n >= 0; --n)
{
if (m_aLines[n]->uiID == uiLineID)
{
delete m_aLines[n];
m_aLines.RemoveAt(n);
--n; // Because we removed a line
}
}
}
// ===================================================================
bool C2DPushGraph::SetLineColor( COLORREF crColor, UINT uiLineID )
{
PushGraphLine *pLine = internal_LineFromID(uiLineID);
if (pLine == NULL)
{
return false;
}
pLine->crLine = crColor;
return true;
}
// ===================================================================
COLORREF C2DPushGraph::GetLineColor( UINT uiLineID )
{
PushGraphLine *pLine = internal_LineFromID(uiLineID);
return (pLine) ? pLine->crLine : RGB(0, 0, 0);
}
// ===================================================================
bool C2DPushGraph::Push( int nMagnitude, UINT uiLineID )
{
PushGraphLine *pLine = internal_LineFromID(uiLineID);
if (pLine == NULL)
{
return false;
}
/* Now add the magnitude (push point) to the array of push points, but
first restrict it to the peek bounds */
if (nMagnitude > m_nMaxPeek) {
nMagnitude = m_nMaxPeek;
}
else if (nMagnitude < m_nMinPeek) {
nMagnitude = m_nMinPeek;
}
nMagnitude -= m_nMinPeek;
nMagnitude += m_nPeekOffset;
pLine->aMagnitudes.AddTail(nMagnitude);
return true;
}
// ===================================================================
void C2DPushGraph::ShowAsBar( UINT uiLineID, bool bAsBar )
{
PushGraphLine *pLine = internal_LineFromID(uiLineID);
if (pLine)
{
pLine->bShowAsBar = bAsBar;
}
}
// ===================================================================
void C2DPushGraph::Update()
{
int nGreatest = 0; // Largest push point count
for (int n=0; n < m_aLines.GetSize(); ++n)
{
if (nGreatest < m_aLines[n]->aMagnitudes.GetCount())
{
nGreatest = m_aLines[n]->aMagnitudes.GetCount();
}
}
if (nGreatest >= m_nMaxCoords)
{
m_nMoveOffset =
(m_nMoveOffset - (((nGreatest-m_nMaxCoords)+1)*m_usLineInterval))
% m_nGridSize;
}
RedrawWindow();
}
// ===================================================================
void C2DPushGraph::OnPaint()
{
CPaintDC paintDC(this);
/* First we create the back buffer */
CDC &dc = internal_InitBackBuffer(paintDC);
/* Ensure we don't draw out of our client rectangle */
CRect &rectClient = getClientRect();
dc.IntersectClipRect(&rectClient);
/* Fill the background */
dc.FillSolidRect(&rectClient, m_crBGColor);
dc.SetBkMode(TRANSPARENT);
if (m_bShowMinMax)
{
/* Show maximum and minimum labels */
internal_DrawMinMax(dc, rectClient);
}
if (m_bShowGrid)
{
/* Show the grid overlay */
internal_DrawGrid(dc, rectClient);
}
internal_DrawLines(dc, rectClient);
internal_FreeBackBuffer(paintDC,false);
if (m_bStylesModified)
{
/* Reset styles if resized */
GetParent()->ModifyStyle(WS_CLIPCHILDREN, 0);
ModifyStyle(WS_CLIPSIBLINGS, 0);
m_bStylesModified = false;
}
}
// ===================================================================
CDC& C2DPushGraph::internal_InitBackBuffer(CPaintDC &dc)
{
// Change HK: Create the dc and bm only once.
// in order to prevent memory leaks.
if(!m_bInitdcBack)
{
/* Create the offscreen DC and associated bitmap */
m_dcBack.CreateCompatibleDC(&dc);
m_bmBack.CreateCompatibleBitmap(&dc,
getClientRect().Width(),
getClientRect().Height());
m_pOldBitmap = m_dcBack.SelectObject(&m_bmBack);
m_bInitdcBack = true;
}
return m_dcBack;
}
// ===================================================================
void C2DPushGraph::internal_FreeBackBuffer(CPaintDC &dc, bool bDelete)
{
/* Copy the offscreen buffer to the onscreen CPaintDC.
Then free the back buffer objects. */
dc.BitBlt(getClientRect().left, getClientRect().top,
getClientRect().Width(), getClientRect().Height(),
&m_dcBack, getClientRect().left, getClientRect().top,
SRCCOPY);
if(bDelete)
{
dc.SelectObject(m_pOldBitmap);
m_bmBack.DeleteObject();
m_dcBack.DeleteDC();
}
}
// ===================================================================
PushGraphLine* C2DPushGraph::internal_LineFromID( UINT uiLineID )
{
/* Find the corresponding line to the passed ID */
for (int n = m_aLines.GetSize()-1; n >= 0; --n)
{
if (m_aLines[n]->uiID == uiLineID)
{
return m_aLines[n];
}
}
return NULL;
}
// ===================================================================
void C2DPushGraph::internal_DrawMinMax( CDC &dc, CRect& rect)
{
#ifndef _WIN32_WCE
CSize MaxSize = dc.GetTextExtent(m_strMaxLabel);
CSize MinSize = dc.GetTextExtent(m_strMinLabel);
int nTextWidth =
((MaxSize.cx > MinSize.cx) ? MaxSize.cx : MinSize.cx) + 6;
/* Draw the labels (max: Top) (min: Bottom) */
dc.SetTextColor(m_crTextColor);
dc.TextOut(nTextWidth/2-(MaxSize.cx/2), 2, m_strMaxLabel);
dc.TextOut(nTextWidth/2-(MinSize.cx/2), rect.Height()-MinSize.cy-2, m_strMinLabel);
/* Draw the bordering line */
CPen penBorder(PS_SOLID, 1, m_crGridColor);
CPen *pOldPen = dc.SelectObject(&penBorder);
dc.MoveTo(nTextWidth + 6, 0);
dc.LineTo(nTextWidth + 6, rect.Height());
dc.SelectObject(pOldPen);
/* Offset the graph rectangle so it doesn't overlap the labels */
rect.left = nTextWidth + 6;
#endif
}
// ===================================================================
void C2DPushGraph::internal_DrawLines( CDC &dc, CRect& rect)
{
CPen penLine;
CPen *pOldPen = NULL;
int nGreatest = 0;
if (m_nMaxCoords == -1)
{
/* Maximum push points not yet calculated */
m_nMaxCoords = (rect.Width() / m_usLineInterval) + 2
+ (rect.Width()%m_usLineInterval ? 1 : 0);
if (m_nMaxCoords <= 0)
{
m_nMaxCoords = 1;
}
}
for (int n=0; n < m_aLines.GetSize(); ++n)
{
if (nGreatest < m_aLines[n]->aMagnitudes.GetCount())
{
nGreatest = m_aLines[n]->aMagnitudes.GetCount();
}
}
if (nGreatest == 0)
{
return; // No lines to draw
}
for (n = 0; n < m_aLines.GetSize(); ++n)
{
/* If the line has less push points than the line with the greatest
number of push points, new push points are appended with
the same magnitude as the previous push point. If no push points
exist for the line, one is added with the least magnitude possible. */
PushGraphLine *pLine = m_aLines[n];
if (!pLine->aMagnitudes.GetCount())
{
pLine->aMagnitudes.AddTail(m_nMinPeek);
}
while (pLine->aMagnitudes.GetCount() < nGreatest)
{
pLine->aMagnitudes.AddTail(pLine->aMagnitudes.GetTail());
}
while (m_aLines[n]->aMagnitudes.GetCount() >= m_nMaxCoords)
{
m_aLines[n]->aMagnitudes.RemoveHead();
}
if (!m_aLines[n]->aMagnitudes.GetCount())
{
/* No push points to draw */
return;
}
/* Now prepare to draw the line or bar */
penLine.CreatePen(PS_SOLID, m_aLines[n]->uiLineWidth, m_aLines[n]->crLine);
pOldPen = dc.SelectObject(&penLine);
if (pLine->bShowAsBar)
{
dc.MoveTo(rect.left, rect.Height());
}
else
{
dc.MoveTo(rect.left, nGreatest == 1 ? rect.Height() :
rect.Height()-(pLine->aMagnitudes.GetHead() *
rect.Height()/(m_nMaxPeek-m_nMinPeek)));
}
POSITION aMagPos = pLine->aMagnitudes.GetHeadPosition();
for (int n2 = 0; n2 < pLine->aMagnitudes.GetCount(); ++n2)
{
if (pLine->bShowAsBar)
{
/* The line is set to be shown as a bar graph, so
first we get the bars rectangle, then draw the bar */
CRect rectBar;
rectBar.left = rect.left + (n2*(m_usLineInterval)) + 1;
rectBar.right = rectBar.left + GetInterval() - 1;
rectBar.bottom = rect.Height();
rectBar.top = rect.Height() -
(pLine->aMagnitudes.GetNext(aMagPos) * rect.Height() /
(m_nMaxPeek-m_nMinPeek));
internal_DrawBar(dc, rectBar, *pLine);
}
else
{
/* Draw a line */
dc.LineTo(rect.left + (n2*m_usLineInterval),
rect.Height() -
(pLine->aMagnitudes.GetNext(aMagPos) * rect.Height() /
(m_nMaxPeek-m_nMinPeek)) );
/*
dc.FillSolidRect(rect.left + (n2*m_usLineInterval) - 2,
rect.Height() -
(pLine->aMagnitudes[n2] * rect.Height() /
(m_nMaxPeek-m_nMinPeek)) - 2, 4, 4, m_aLines[n]->crLine); */
}
}
dc.SelectObject(pOldPen);
}
}
// ===================================================================
void C2DPushGraph::internal_DrawBar( CDC &dc, CRect& rect,
PushGraphLine& rLine )
{
COLORREF &crFill = rLine.crLine;
GraphColor gcTopLeft, gcBottomRight;
/* gcTopLeft is the left and top frame color, gcBottomRight
is the right and bottom frame color */
if (GetRValue(crFill))
{
gcTopLeft.bRed = PUSHGRAPH_MAX(GetRValue(crFill)+40, 255, BYTE);
gcBottomRight.bRed = PUSHGRAPH_MIN(GetRValue(crFill) - 40, 0, BYTE);
}
if (GetBValue(crFill))
{
gcTopLeft.bBlue = PUSHGRAPH_MAX(GetBValue(crFill)+40, 255, BYTE);
gcBottomRight.bBlue = PUSHGRAPH_MIN(GetBValue(crFill) - 40, 0, BYTE);
}
if (GetGValue(crFill))
{
gcTopLeft.bGreen = PUSHGRAPH_MAX(GetGValue(crFill)+40, 255, BYTE);
gcBottomRight.bGreen = PUSHGRAPH_MIN(GetGValue(crFill) - 40, 0, BYTE);
}
dc.FillSolidRect(&rect, rLine.crLine);
dc.Draw3dRect(&rect, gcTopLeft, gcBottomRight);
}
// ===================================================================
void C2DPushGraph::internal_DrawGrid( CDC &dc, CRect& rect)
{
/* Draw the grid overlay.
We use rect.left as our x offset instead of zero because
if m_bShowMinMax is true, then rect.left is set to the
first pixel after the labels. */
CPen GridPen( PS_SOLID, 1, m_crGridColor );
CPen *pOldPen = dc.SelectObject(&GridPen);
for (int n = rect.Height()-1; n >= 0; n -= m_nGridSize)
{
dc.MoveTo(rect.left, n);
dc.LineTo(rect.right, n);
}
for (n = rect.left + m_nMoveOffset; n < rect.right; n += m_nGridSize)
{
if (n < rect.left)
{
continue;
}
dc.MoveTo(n, 0);
dc.LineTo(n, rect.Height());
}
dc.SelectObject(pOldPen);
}
// ===================================================================
CRect& C2DPushGraph::getClientRect()
{
static CRect rectClient;
return (GetClientRect(&rectClient), rectClient);
}
// ===================================================================
BOOL C2DPushGraph::OnEraseBkgnd(CDC*)
{
return FALSE;
}
// ===================================================================
void C2DPushGraph::OnSizing(UINT fwSide, LPRECT pRect)
{
if (GetParent()->GetStyle() & ~WS_CLIPCHILDREN)
{
/* Eliminate flickering */
m_bStylesModified = true;
GetParent()->ModifyStyle(0, WS_CLIPCHILDREN);
}
ModifyStyle(0, WS_CLIPSIBLINGS);
// CWnd::OnSizing(fwSide, pRect);
(m_nMaxCoords = -1, Invalidate());
}
// ===================================================================
void C2DPushGraph::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
(m_nMaxCoords = -1, Invalidate());
}
bb |~ bb
|
|
|
|
|
Hmmm, some humble critics to the original author (not to Harald Krause). This class was very handy and helped me quick to visualise meassured data! But this is also the 4th or 5th time that a nice class on codeproject is not updated with bugfixes. I did send patches to the author, in the end nothing did happen. Some authors don't answer, seems not to read the message boards of their article or simply don't have the time to incooperate udpates.
Don't understand me wrong, I am very gratefull to learn from articles and be able to reuse classes in my software. I also understand that not every author has time to answer emails within a few weeks (and not everybody writing feedback is friendly). On the other hand, when someone took some time to be nice to the coding human race by working out an programming article (or just to boost your own CV with a publication on Code Project), why not spend some more time and maintain the project here and there?
Probably one reason why open source or wikipedia are working well is like this: You love to use something and then are able to improve it further with others. Nothing is more rewarding than working on something that you enjoy and see it grow better over time! Perhaps it would be good for a site like Code Project to release a) all articles under a dual license that allows updating source code and article text, b) assign an active maintainer that tests and checks in bugfixes, improves quality by removing errors, memory leaks, etc. Please understand my posting as constructive critics, hope it helps.
|
|
|
|
|
Function to show or hide line.
struct PushGraphLine
{
PushGraphLine(UINT uiLineID)
{
...
visible = true;
...
}
...
bool visible;
...
}
void ShowLine(UINT uiLineID, bool show = true);
void C2DPushGraph::ShowLine(UINT uiLineID, bool show)
{
PushGraphLine *pLine = internal_LineFromID(uiLineID);
if (pLine)
{
pLine->visible = show;
}
}
void C2DPushGraph::internal_DrawLines( CDC &dc, CRect& rect)
{
...
for (n = 0; n < m_aLines.GetSize(); ++n)
{
...
PushGraphLine *pLine = m_aLines[n];
if(!pLine->visible) continue;
...
}
|
|
|
|
|
I have tried this control on win xp and it work fine(3 MB fixed memory occupation) but in windows ce (in both real device and emulator) after some Push() memory goes low a nd control stop to draw line. Please help me!!!
|
|
|
|
|
I don't know CE at all, but assuming it's memory constrained, one thing this Push does is continually add onto the line's CArray of points. Only the call to RedrawWindow() or Update() (which calls RedrawWindow() and thus OnPaint()) will delete the array members that won't be shown on the screen.
The way it gets removed is with the RemoveAt(0) function, which removes the 0-indexed array element but does not delete the memory, so I don't know if doing an Add() and RemoveAt(0) many times actually grows the memory heap or not.
You may be better off changing the PushGraphLine struct to using a CList linked list.
|
|
|
|
|
Thanks, I had a similar problem.
When I visited a server after a long period Update() was called.
The cpu sky rocketed, because it was in the while loop of RemoveAt(0).
I fixed it by Removing extra dots at every push.
|
|
|
|
|
Thanks it is easy to use!
Added a Clear() method (sent to you by email) and intialised some more data memmbers in constructor.
I am using your control in a resizeable dialog. What I don't understand is m_bStylesModified, it seams to be some anti flickering thingie when control is being resized? I have disabled the corresponindg code in OnPaint() and OnSizing() without seeing any difference. *curious*
/Moak
|
|
|
|
|
Hi, the control is great and works fine on Debug Build. But, when I build on Release Build the grid lines disappear... Did I do something wrong?
|
|
|
|
|
There is nothing in the supplied C2DPushGraph code that would cause the lines not to appear in a release build (the demo is a release build). Therefore, it must be an issue within your code. If you post the code online somewhere I can attempt to locate your problem.
|
|
|
|
|
I had the same problem.
Try to use
graph.ShowGrid();
|
|
|
|
|
The grid line variables are not setup in the constructor of the control. It relies on the fact that the debug build inits these variables to cdcdcd. However in release these are not initilised and can be anything.
Either update the controls contructor to fix the problem or call the setup functions to set them to a known value.
|
|
|
|
|
Hi There,
As Phil mentioned you need to correctly initialize these variables in the constructor or make specified calls to the set methods for these variables.
In my case I modified the ctor, as having the grid lines and labels is standard.
C2DPushGraph::C2DPushGraph
: m_bShowMinMax(TRUE)
, m_bShowGrid(TRUE)
{
...
...
}
Maybe if Stuart has time he can update the downloadable code for this control.
Regards, Michael.
|
|
|
|
|
Pretty nifty control. I played with your demo for a bit i would like to offer one quick suggestion. I admist not looking at the source in great details, so excuse me if this is there and i didn't see it, but you may want to allow the ability to set the thickness of each line being displayed. This allows greater flexibility in the end as we can choose to allow one series to stand out more than another.
Very cool control though! Just need to find a good use for it now so I can have an excuse to play with it more
Joseph Dempsey
joseph_r_dempsey@yahoo.com
|
|
|
|
|
Thanks for the positive feedback. The practicality of such a function is high, so you can expect to see it in the next release.
|
|
|
|
|