|
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!
|
|
|
|
|
See:
PRB: Clipping Doesn't Work Correctly in Print Preview (Q128334)
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q128334
MS says it affects only VC 4.0 and prior versions.
However, this "behaviour" exists also in 6.0.
Few lines must be inserted to have correct clipping.
Adios
|
|
|
|
|
I already tried to use this solution but it sill doesn't work either.
|
|
|
|
|
first I like to say that I love it.
I'm using it for research on high energy astrophysics, and the multi graph/multi axis is great for me.
I've seen that if I try to use a range of say, 1E50 to +1E53 it does'nt work
I didn't have time to fix it. also the auto scale for numbers smaller than 0.1 doesn't work.
for now I've bypassed it, but when I'll fix it I'll post it here.
|
|
|
|
|
In my opinion, some values have truncated.
That is, fDummy = (double)((int)fEnd).
Of course, fDummy and fEnd are double variables.
This must be fDummy = (double((INT64)fEnd) to correct it.
Here is some fix;
---------------------------------------------------------
typedef INT64 myint64;
void CXGraphAxis::AdaptAxis(double* fStart, double* fEnd, double fStep)
{
myint64 iDummy;
myint64 iModulo;
double fDivisor;
double fDummy;
fDivisor = 1.0;
while ((myint64)fStep == 0)
{
fStep *= 10.0;
fDivisor *= 10.0;
}
*fStart *= fDivisor;
*fEnd *= fDivisor;
iModulo = ((myint64) *fStart - (myint64) fStep) % (myint64)fStep;
if (iModulo == 0)
{
if (((double) ((myint64) *fStart) == *fStart) &&
(((myint64) *fStart % (myint64)fStep) == 0))
fDummy = (double)((myint64)*fStart);
else
fDummy = (double)((myint64) *fStart - (myint64) fStep);
}
else
{
iDummy = (myint64) *fStart / (myint64) fStep;
if (*fStart < 0)
fDummy = (double) ((iDummy-1) * (myint64)fStep);
else
fDummy = (double) ((iDummy) * (myint64)fStep);
}
*fStart = fDummy / fDivisor;
iModulo = ((myint64) *fEnd + (myint64) fStep) % (myint64)fStep;
if (iModulo == 0)
{
if (((double) ((myint64) *fEnd) == *fEnd) &&
(((int) *fEnd % (myint64)fStep) == 0))
fDummy = (double)((myint64)*fEnd);
else
fDummy = (double)((myint64) *fEnd + (myint64) fStep);
}
else
{
iDummy = (myint64) *fEnd / (myint64) fStep;
if (*fEnd < 0)
fDummy = (double) ((iDummy-1) * (myint64)fStep);
else
fDummy = (double) ((iDummy+1) * (myint64)fStep);
}
*fEnd = fDummy / fDivisor;
}
|
|
|
|
|
Using INT64 in AdaptAxis won't work either since casting large doubles to INT64 still produces 0 values (INT64 -> 9.223E +/- 18 whereas double -> 1.7E +/- 308).
For now i provide the following fix to overcome this problem, i'll introduce it in the next version.
// bypass fmod problem (results unexpected due to binary representation)
double saveFmod(double x, double y)
{
double fRes = 0.0;
while ((fRes+y) <= fabs(x))
fRes += y;
if (x < 0.0)
return x + fRes;
else
return x - fRes;
}
void CXGraphAxis::AdaptAxis(double* fStart, double* fEnd, double fStep)
{
double fRemainder;
fRemainder = saveFmod(*fStart-fStep, fStep);
if (fRemainder != 0.0)
*fStart -= fRemainder + fStep;
fRemainder = saveFmod(*fEnd+fStep, fStep);
if (fRemainder != 0.0)
*fEnd -= fRemainder - fStep;
}
|
|
|
|
|
Nice work.
While playing with it I found a bug in the CXGraph::DrawCursorLegend method. It crashes in cursor mode, if the x-axis is in a datetime mode. A bad format string is passed to CString::Format.
Here is the fix:
void CXGraph::DrawCursorLegend (CDCEx* pDC)
{
int i;
double fVal;
CString cLabel = "", cFmt, cItem;
m_CursorLabel.m_bVisible = true;
for (i = 0; i < m_XAxis.size(); i++)
{
//CHANGED: bugfix, correct handling of X axis in time mode
fVal = m_XAxis[i].GetValueForPos (m_CurrentPoint.x);
if(m_XAxis[i].m_bDateTime)
{
cFmt = "X[%02d] : " + COleDateTime(fVal).Format(m_XAxis[i].m_cDisplayFmt) + " %s";
cItem.Format(cFmt, i+1, m_XAxis[i].m_cLabel);
cLabel += (" " + cItem + "\r\n");
}
else
{
cFmt = "X[%02d] : " + m_XAxis[i].m_cDisplayFmt + " %s";
cItem.Format(cFmt, i+1, fVal, m_XAxis[i].m_cLabel);
cLabel += (" " + cItem + "\r\n");
}
//ENDCHANGES
}
for (i = 0; i < m_YAxis.size(); i++)
{
fVal = m_YAxis[i].GetValueForPos (m_CurrentPoint.y);
cFmt = "Y[%02d] : " + m_YAxis[i].m_cDisplayFmt + " %s";
cItem.Format(cFmt, i+1, fVal, m_YAxis[i].m_cLabel);
cLabel += (" " + cItem + "\r\n");
}
if (m_nSnappedCurve != -1)
{
//CHANGED: bugfix, correct handling of X axis in time mode
CString cXFmt = m_XAxis[m_Data[m_nSnappedCurve].m_nXAxis].m_cDisplayFmt;
CString cYFmt = m_YAxis[m_Data[m_nSnappedCurve].m_nYAxis].m_cDisplayFmt;
if(m_XAxis[m_Data[m_nSnappedCurve].m_nXAxis].m_bDateTime)
{
cFmt = "%s[%02d] : " + COleDateTime(m_fSnappedXVal).Format(cXFmt) + ", " + cYFmt;
cItem.Format(cFmt, m_Data[m_nSnappedCurve].m_cLabel, m_nSnappedCurve + 1, m_fSnappedYVal);
cLabel += (" " + cItem + "\r\n");
}
else
{
cFmt = "%s[%02d] : " + cXFmt + ", " + cYFmt;
cItem.Format(cFmt, m_Data[m_nSnappedCurve].m_cLabel, m_nSnappedCurve + 1, m_fSnappedXVal, m_fSnappedYVal);
cLabel += (" " + cItem + "\r\n");
}
//ENDCHANGES
}
m_CursorLabel.m_cText = cLabel;
m_CursorLabel.Draw (pDC);
}
Sonork 100.15206;PavelK
|
|
|
|
|
Thanks for that. I've posted a new version.
|
|
|
|
|
Did you try root ? (root.cern.ch)
Jonathan de Halleux, Belgium.
|
|
|
|
|
Well done,
it needs a bit of work still,
Regardz
Colin J Davies
Sonork ID 100.9197:Colin
Testing Current Sig
<marquee><marquee behavior="alternate" scrollamount="12">< >
|
|
|
|
|
Indeed, feel free to advance this one
Regards
Gunnar
|
|
|
|
|