|
Yes, I also have problems with menu etc in a dialog.
Did you ever manage to fix it?
Cheers,
/Martin
|
|
|
|
|
Sorry, it's been six months, so I don't remember. I ended up handing that project off to somebody else to complete, so I don't know what came of it.
|
|
|
|
|
As many before me I have to say it's an awesome library!
Though I've found a "problem":
In my app I just Create() the control in the window and wait til you load a file which will add a graph. If you (for some reason) left double click the control it:
-in debug, asserts in GetYAxis()
-in release, crashes somewhere in MFC libraries.
Are there anyone else having this problem or hav a solution?
I would really appreciate it!
|
|
|
|
|
This usually happens if you dblckick on an empty graph (no axes or curves).
|
|
|
|
|
Modify CChartPage::OnInitDialog as following:
...
if (m_pGraphAxis == NULL)
{
if(m_pGraph->GetYAxisCount()>0)
m_pGraphAxis = &m_pGraph->GetYAxis (0);
}
else
nPageSelect = 1;
if (m_pGraphDataSerie == NULL)
{
if(m_pGraph->GetCurveCount()>0)
m_pGraphDataSerie = &m_pGraph->GetCurve (0);
}
else
nPageSelect = 2;
m_pChart->m_pGraph = m_pGraph;
m_pCurve->m_pSerie = m_pGraphDataSerie;
m_pAxis->m_pAxis = m_pGraphAxis;
tabItem.mask = TCIF_PARAM | TCIF_TEXT;
tabItem.lParam = (LPARAM)m_pChart;
VERIFY(m_pChart->Create(CChartDlg::IDD, &m_Tab));
tabItem.pszText = "Chart";
m_Tab.InsertItem(0,&tabItem);
if(m_pGraph->GetYAxisCount()>0)
{
tabItem.lParam = (LPARAM)m_pAxis;
VERIFY(m_pAxis->Create(CAxisDlg::IDD, &m_Tab));
tabItem.pszText = "Axis";
m_Tab.InsertItem(1,&tabItem);
}
if(m_pGraph->GetCurveCount()>0)
{
tabItem.lParam = (LPARAM)m_pCurve;
VERIFY(m_pCurve->Create(CCurveDlg::IDD, &m_Tab));
tabItem.pszText = "Curve";
m_Tab.InsertItem(2,&tabItem);
}
...
|
|
|
|
|
sorry but this doesn't work!
|
|
|
|
|
I'm using VS.NET and a new version of XGraph received from the author last week (thanks a lot, even works with .NET).
If I doubleclicked a curve or an axis, the VS.NET run time checks reported stack corruption around the variable dc in CurveDlg::OnDrawItem() and AxisDlg::OnDrawItem(). Not very strange if one study the typecast to CDCEx* in these methods.
QuickAndDirtyFix:
In CurveDlg::OnDrawItem() and AxisDlg::OnDrawItem(), change the lines (three different places)
CDC dc;
to
CDCEx dc;
That does it for me, at least.
|
|
|
|
|
had a VERIFY problem with a horizontal line
wound up changing CXGraphAxis::SetRange and SetCurrentRange
if (fMin >= fMax) return false
to
if (fMin > fMax) return false
so far this has been a fantastic control
chris
|
|
|
|
|
The problem is still existing.I fix this as following:
Modify CXGraph::SetData
...
GetMinMaxForData(m_Data[nCurve], fxMin, fxMax,fyMin,fyMax);
if(fxMax==fxMin)
{
fxMax++;
fxMin--;
}
if(fyMax==fyMin)
{
fyMax++;
fxMin--;
}
// Set axis ranges
VERIFY(m_XAxis[nXAxis].SetRange(fxMin, fxMax));
VERIFY(m_YAxis[nYAxis].SetRange(fyMin, fyMax));
...
|
|
|
|
|
Thanks for the fix - i just encountered the problem at the same time
you posted.
I changed it a little to just nudge the max and min. Also I think you
have a typo comparing the y max and min
if (fxMax == fxMin)
{
fxMax += 0.01;
fxMin -= 0.01;
}
if (fyMax == fyMin)
{
fyMax += 0.01;
fyMin -= 0.01;
}
|
|
|
|
|
First of all: congratulation to this nice job! It's a really useful class for me.
But unfortunately I have problems with resizing the apps. My own application and your test app both hang when they are resized to smaller windows. Then they can only be killed via the task manager. (my OS is Win2k)
My other questing is, is it possible to rotate the y-axis label? And to move the x-axis label beneath the x-axis?
One again: well done!
|
|
|
|
|
Hello z_usi,
we had the same problem on W2K and Win98. After debugging the code we see, that during sizing the windows a division by zero happens.
So we fixed the problem by inserting the lines
void CXGraphAxis::AutoScale(CDCEx *pDC)
{
int nScaleTicks;
if (m_AxisKind == yAxis)
{
m_fSpareRange = (2 * m_nArcSize);
m_fMarkerSpareSize = DrawCurveMarkers(pDC, false);
int nTop = m_pGraph->m_clInnerRect.top + m_fSpareRange + m_fMarkerSpareSize;
int nBottom = m_pGraph->m_clInnerRect.bottom;
int nHeight = GetMaxLabelHeight(pDC);
int nRange = nBottom - nTop;
nScaleTicks = (int)((double) nRange / (double) nHeight);
}
else
{
m_fSpareRange = (4 * m_nArcSize);
m_fMarkerSpareSize = DrawCurveMarkers(pDC, false);
int nLeft = m_pGraph->m_clInnerRect.left;
int nRight = m_pGraph->m_clInnerRect.right - m_fSpareRange - m_fMarkerSpareSize;
int nWidth = GetMaxLabelWidth(pDC);
int nRange = nRight - nLeft;
nScaleTicks = (int)((double) nRange / (double) nWidth);
}
// new code !!!!
// Manfred Peter ... otherwise division by zero !!!!
if(nScaleTicks <= 0)
nScaleTicks = 1;
// and so on and so on
.
.
.
After that the sizing works correct.
Please let me know if that helps ..
Manfred Peter
(Alligator Company)
http://www.alligatorsql.com
webmaster@alligatorsql.com
|
|
|
|
|
Hello Peter,
thanks for your help.
But unfortunately this doesn't work too. When I inserted your line to avoid division by zero, the program XGraphTest crashes. So I changed
if(nScaleTicks <= 0) nScaleTicks = 1;
to
if(nScaleTicks == 0) nScaleTicks = 1;
Then the program doesn't crash but the problem is still there. In my opinion there must be an endless loop anywhere but I have less time at the moment to get a little bit closer to this.
So I just avoid resizing....
Chris
|
|
|
|
|
I Have a splitter with multiple views, and add a view with the control XGraph, and then, My program crash. What happen?
Victor Bravo
Venezuela
|
|
|
|
|
Can you describe the problem a bit more in detail ?
|
|
|
|
|
I use AW_CMultiViewSplitter Class (see Codeproject.com or Codeguru.com). A
splitter with multiple views, and I add ScientificGraph View and then crash.
Thanks
Victor Bravo
|
|
|
|
|
if you have a Release-Version of the Dll and Test-Application and you start the program, choose a label with a left-click, then make a right-click on a label and choose properties (only properties is available). In the properties dialog choose the background-color button. After the color-popup is open, you just have to move the mouse in it, and the application will crash!
|
|
|
|
|
I've located the problem and will post an update next week.
|
|
|
|
|
Hi
It seem powerful lib
I had this error when i tryed compilling demo code
" The system cannot find the path specified.
0 file(s) copied.
Error executing c:\winnt\system32\cmd.exe."
May you help me
i need it
|
|
|
|
|
I get the same error
Graham W Griffiths
|
|
|
|
|
1. Download source into separate directory, compile and copy the resulting lib directory (containing XGraph10.lib, etc) to your XGraphTest directory.
2. You should then be able to compile XGraphTest.exe successfully
Program should then run.
Good luck.
Graham
======
Graham W Griffiths
|
|
|
|
|
Error executing f:\winnt\system32\cmd.exe.
|
|
|
|
|
The problem is in the project settings.
You have to set the right path in the linker pre-stage setting:
"copy ..\lib\xgraph10.dll .\release"
|
|
|
|
|
Very nice job! I'd like to use it, but it does not compile on VC7! Here's a log of the errors issued. Any hint for removing them?
XGRAPH.cpp
d:\Vcpp\Test\XGraph\XGRAPH.cpp(426) : error C2440: 'static_cast' : cannot convert from 'BOOL (__thiscall CXGraph::* )(CDCEx *)' to 'BOOL (__thiscall CWnd::* )(CDC *)'
None of the functions with this name in scope match the target type
LabelDlg.cpp
d:\Vcpp\Test\XGraph\LabelDlg.cpp(55) : error C2440: 'static_cast' : cannot convert from 'void (__thiscall CLabelDlg::* )(void)' to 'LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)'
None of the functions with this name in scope match the target type
CurveDlg.cpp
d:\Vcpp\Test\XGraph\CurveDlg.cpp(76) : error C2440: 'static_cast' : cannot convert from 'UINT (__thiscall CCurveDlg::* )(UINT,LONG)' to 'LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)'
None of the functions with this name in scope match the target type
ColourPopup.cpp
d:\Vcpp\Test\XGraph\ColourPopup.cpp(228) : error C2440: 'static_cast' : cannot convert from 'void (__thiscall CColourPopup::* )(BOOL,HTASK)' to 'void (__thiscall CWnd::* )(BOOL,DWORD)'
None of the functions with this name in scope match the target type
ChartDlg.cpp
d:\Vcpp\Test\XGraph\ChartDlg.cpp(66) : error C2440: 'static_cast' : cannot convert from 'UINT (__thiscall CChartDlg::* )(UINT,LONG)' to 'LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)'
None of the functions with this name in scope match the target type
AxisDlg.cpp
d:\Vcpp\Test\XGraph\AxisDlg.cpp(95) : error C2440: 'static_cast' : cannot convert from 'UINT (__thiscall CAxisDlg::* )(UINT,LONG)' to 'LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)'
None of the functions with this name in scope match the target type
d:\Vcpp\Test\XGraph\AxisDlg.cpp(103) : error C2440: 'static_cast' : cannot convert from 'void (__thiscall CAxisDlg::* )(void)' to 'void (__thiscall CCmdTarget::* )(NMHDR *,LRESULT *)'
None of the functions with this name in scope match the target type
d:\Vcpp\Test\XGraph\AxisDlg.cpp(104) : error C2440: 'static_cast' : cannot convert from 'void (__thiscall CAxisDlg::* )(void)' to 'void (__thiscall CCmdTarget::* )(NMHDR *,LRESULT *)'
None of the functions with this name in scope match the target type
d:\Vcpp\Test\XGraph\AxisDlg.cpp(105) : error C2440: 'static_cast' : cannot convert from 'void (__thiscall CAxisDlg::* )(void)' to 'void (__thiscall CCmdTarget::* )(NMHDR *,LRESULT *)'
None of the functions with this name in scope match the target type
d:\Vcpp\Test\XGraph\AxisDlg.cpp(106) : error C2440: 'static_cast' : cannot convert from 'void (__thiscall CAxisDlg::* )(void)' to 'void (__thiscall CCmdTarget::* )(NMHDR *,LRESULT *)'
None of the functions with this name in scope match the target type
d:\vcpp\test\xgraph\xgraphaxis.cpp(117) : error C4716: 'CXGraphAxis::operator=' : must return a value
d:\vcpp\test\xgraph\xgraphdataserie.cpp(86) : error C4716: 'CXGraphDataSerie::operator=' : must return a value
d:\vcpp\test\xgraph\xgraphobjectbase.cpp(51) : error C4716: 'CXGraphObject::operator=' : must return a value
|
|
|
|
|
I've found some issues with the time axis.
This is how I fixed it:
(file: XGraphAxis.cpp)
void CXGraphAxis::FitTimeScale(double *fStepWidth, int nBestCount, double fStart, double fEnd)
{
COleDateTime cStart, cEnd;
COleDateTimeSpan cSpan;
double fStep;
double fSpan;
cStart = fStart;
cEnd = fEnd;
cSpan = cEnd - cStart;
fSpan = cSpan.GetTotalSeconds ();
if(nBestCount > 0) // <------------ avoid divide by zero!
{
fStep = fSpan / (double)nBestCount;
}
else
{
fStep = 0;
}
for (int i = 1; TimeStepTable[i] != -1; i++)
{
if (fStep > TimeStepTable[i-1] && fStep <= TimeStepTable[i])
{
fStep = TimeStepTable[i];
break;
}
}
*fStepWidth = fStep;
*fStepWidth /= 24.0 * 3600;
}
//--------------------------------------------------------------------------------
void CXGraphAxis::AdaptTimeAxis(double * pfStart, double * pfEnd, double fStep)
{
double fDummy;
unsigned long iDummy;
int iModulo = 0;
COleDateTimeSpan cSpan;
COleDateTime cOffset,
cStart,
cEnd;
double lSeconds;
cOffset.SetDateTime (1970, 1, 1, 0, 0, 0);
fStep *= 24 * 3600;
cStart = *pfStart;
cSpan = cStart - cOffset;
lSeconds = cSpan.GetTotalSeconds ();
if(fStep > 0.0)
{
iModulo = ((long) lSeconds - (long) fStep) % (long)fStep;
}
if (iModulo == 0)
{
;//*pfStart = *pfStart - fStep / 24.0 / 3600.0;
}
else
{
iDummy = (unsigned long) lSeconds / (unsigned long) fStep;
fDummy = (double) ((iDummy) * (unsigned long)fStep);
*pfStart = (DATE)(COleDateTime(fDummy / 24.0 / 3600.0)) + cOffset ;
}
cEnd = *pfEnd;
cSpan = cEnd - cOffset;
lSeconds = cSpan.GetTotalSeconds ();
if(fStep > 0.0) // <------------ avoid divide by zero!
{
iModulo = ((long) lSeconds - (long) fStep) % (long)fStep;
}
else
{
iModulo = 0;
}
if (iModulo == 0)
{
;//*pfEnd = *pfEnd + fStep / 24.0 / 3600.0;
}
else
{
iDummy = (unsigned long) lSeconds / (unsigned long) fStep;
fDummy = (double) ((iDummy) * (unsigned long)fStep);
*pfEnd = (DATE)(COleDateTime(fDummy / 24.0 / 3600.0)) + cOffset ;
}
}
//-------------------------------------------------------------------------------------
void CXGraphAxis::Draw(CDCEx* pDC)
{
m_fRange = m_fCurMax - m_fCurMin;
if (m_bAutoScale)
AutoScale(pDC);
if (m_AxisKind == yAxis)
{
m_fSpareRange = (2*m_nArcSize);
m_fMarkerSpareSize = DrawCurveMarkers(pDC);
if (pDC->m_bMono)
pDC->SetBkColor(RGB(255,255,255));
else
pDC->SetBkColor(m_pGraph->m_crGraphColor);
pDC->SetBkMode(OPAQUE);
int nChartTop = m_clChart.top + m_fMarkerSpareSize;
int nTop = m_pGraph->m_clInnerRect.top + m_fSpareRange + m_fMarkerSpareSize;
int nBottom = m_pGraph->m_clInnerRect.bottom;
//m_nRange = nBottom - nTop;
if (m_cLabel != "")
{
CSize titleSize;
{
CFontSelector fs(&m_TitleFont, pDC, false);
titleSize = GetTitleSize(pDC);
m_fSpareRange += titleSize.cy;
}
CFontSelector fs(&m_TitleFont, pDC);
if (m_Placement == apLeft)
{
CRect clTitle(m_nLeft - titleSize.cx - m_nTickSize, nChartTop, m_nLeft - m_nTickSize, nChartTop + titleSize.cy);
pDC->DrawText(m_cLabel, clTitle, DT_RIGHT);
}
else
{
CRect clTitle(m_nLeft + m_nTickSize, nChartTop, m_nLeft + titleSize.cx + m_nTickSize, nChartTop + titleSize.cy);
pDC->DrawText(m_cLabel, clTitle, DT_LEFT);
}
}
m_nRange = m_nTop - nChartTop - m_fSpareRange; // <------------ calc m_nRange BEFORE drawing the scale divisions!
double fSteps = (m_fCurMax - m_fCurMin) / m_fStep;
double fStep = ((double)m_nRange / fSteps);
double fnY = m_nTop;
CString cTxt;
CSize csText;
for (double fY = m_fCurMin; fY <= m_fCurMax; fY += m_fStep, fnY -= fStep)
{
{
CFontSelector fs(&m_Font, pDC, false);
if (m_bDateTime)
cTxt = COleDateTime(fY).Format(m_cDisplayFmt);
else
cTxt.Format(m_cDisplayFmt, fY);
csText = GetTextExtentEx (pDC, cTxt);
}
CFontSelector fs(&m_Font, pDC);
if (m_Placement == apLeft)
{
CRect crText(m_nLeft - csText.cx - m_nTickSize, fnY - csText.cy / 2, m_nLeft - m_nTickSize, fnY + csText.cy / 2);
pDC->DrawText(cTxt, crText, DT_RIGHT);
CPenSelector ps(m_crGridColor, 1, pDC, m_nGridStyle);
pDC->MoveTo(m_nLeft - m_nTickSize, fnY);
// Spare last gridline to prevent axis to be overdrawn
if (!m_bShowGrid || (int)fnY == m_nTop)
pDC->LineTo(m_nLeft, fnY);
else
pDC->LineTo(m_pGraph->m_clInnerRect.right, fnY);
}
if (m_Placement == apRight)
{
CRect crText(m_nLeft + m_nTickSize, fnY - csText.cy / 2, m_nLeft + csText.cx + m_nTickSize, fnY + csText.cy / 2);
pDC->DrawText(cTxt, crText, DT_LEFT);
CPenSelector ps(m_crGridColor, 1, pDC, m_nGridStyle);
pDC->MoveTo(m_nLeft + m_nTickSize, fnY);
// Spare last gridline to prevent axis to be overdrawn
if (!m_bShowGrid || (int)fnY == m_nTop)
pDC->LineTo(m_nLeft, fnY);
else
pDC->LineTo(m_pGraph->m_clInnerRect.left, fnY);
}
}
CPenSelector ps(m_crColor, 1, pDC);
pDC->MoveTo (m_nLeft, m_nTop);
pDC->LineTo (m_nLeft, nChartTop);
DrawArc(pDC, CPoint(m_nLeft, nChartTop), up, m_nArcSize);
m_clRect.SetRect(m_nLeft - 5, nChartTop, m_nLeft + 5, m_nTop);
}
else
{
m_fSpareRange = (4*m_nArcSize);
m_fMarkerSpareSize = DrawCurveMarkers(pDC);
pDC->SetBkColor(m_pGraph->m_crGraphColor);
pDC->SetBkMode(OPAQUE);
int nChartRight = m_pGraph->m_clInnerRect.right - m_fMarkerSpareSize; //m_clChart.right - m_fMarkerSpareSize;
int nLeft = m_pGraph->m_clInnerRect.left;
int nRight = m_pGraph->m_clInnerRect.right - m_fSpareRange - m_fMarkerSpareSize;
if (m_cLabel != "")
{
CSize titleSize;
{
CFontSelector fs(&m_TitleFont, pDC, false);
titleSize = GetTitleSize(pDC);
m_fSpareRange += titleSize.cx;
}
CFontSelector fs(&m_TitleFont, pDC);
CRect clTitle(nChartRight - titleSize.cx, m_nTop + m_nTickSize, nChartRight, m_nTop + m_nTickSize + titleSize.cy);
pDC->DrawText(m_cLabel, clTitle, DT_LEFT);
}
m_nRange = nChartRight - m_nLeft - m_fSpareRange; // <------------ calc m_nRange BEFORE drawing the scale divisions!
double fSteps = ((m_fCurMax - m_fCurMin) / m_fStep);
double fStep = ((double)m_nRange / fSteps);
double fnX = m_nLeft;
CString cTxt;
CSize csText;
for (double fX = m_fCurMin; fX <= m_fCurMax; fX += m_fStep, fnX += fStep)
{
if (m_bDateTime)
cTxt = COleDateTime(fX).Format(m_cDisplayFmt);
else
cTxt.Format(m_cDisplayFmt, fX);
{
CFontSelector fs(&m_Font, pDC, false);
csText = GetTextExtentEx (pDC, cTxt);
}
CFontSelector fs(&m_Font, pDC);
CRect crText(fnX - csText.cx / 2, m_nTop + m_nTickSize, fnX + csText.cx / 2, m_nTop + csText.cy + m_nTickSize);
pDC->DrawText(cTxt, crText, DT_CENTER);
CPenSelector ps(m_crGridColor, 1, pDC, m_nGridStyle);
pDC->MoveTo(fnX, m_nTop + m_nTickSize);
// Spare last gridline to prevent axis to be overdrawn
if (!m_bShowGrid || (int)fnX == m_nLeft)
pDC->LineTo(fnX, m_nTop);
else
pDC->LineTo(fnX, m_clChart.top);
}
CPenSelector ps(m_crColor, 1, pDC);
pDC->MoveTo (m_nLeft, m_nTop);
pDC->LineTo (nChartRight, m_nTop);
DrawArc(pDC, CPoint(nChartRight, m_nTop), right, m_nArcSize);
m_clRect.SetRect(m_nLeft, m_nTop - 5, nChartRight, m_nTop + 5);
}
if (m_bSelected)
pDC->DrawFocusRect (m_clRect);
DrawColorRanges(pDC);
}
Otherwise - thxs for this control - great work!
|
|
|
|
|