|
Ron,
I'll try to reproduce this problem as well because I want to fix my code also if there's an issue. It's possible that my application doesn't grow the number of digits across the range of temperature I'm dealing with so maybe that's why I didn't see the problem.
Just to make sure I understand your description....
The problem happens when your Y-axis values get larger such that the number of digits increases. And when you say leading edge you mean that some of the values on the right side of the plot are not showing up until they scroll into view.
I'll take a look at the code when I get home tonight.
Gil Jones
|
|
|
|
|
Hi Gil,
Thanks for the fast response!
Yes, the problem happens when the number of y-axis digits increase. This results in a shrinking of the plot rectangle.
By leading edge I mean:
My waveform is progressing from right to left. When the resizing happens, instead of the currently displayed trace rescaling, it vanishes. At this point, the trace has progressed only partly across the plot rectangle. The remainder of the trace progresses noramlly, no increase in digits happens in the case at hand. These are electrical waveforms, current in this case. I start out at +/- 10 Amps. In this case, current eventually reaches ~1100A. So, autoranging increases the digit count twice.
So, I'm guessing: we store the currently displayed values, adjust the range, rescale the values and re-write them to the plot rectangle. In this case, they don't get re-written, or re-displayed.
Hope this helps!
ronpeters
|
|
|
|
|
Ron,
Sorry it took me so long to respond. I've been writing all the firmware and window application for a new focuser product for telescopes as a side project and we've been down to the wire finishing up in time for christmas. Here's a link to check it out...there are some software screenshots at the bottom:
http://www.threebuttes.com/focuser.htm
Anyways...I think I have a fix for this issue...
Replace the code I had added to COScopeCtrl::InvalidateCtrl() with the following:
if(m_nPlotWidth/m_nShiftPixels != m_nBufferSize )
{
double *m_pdblSavedDataPoints = m_pdblDataPoints;
int nOldBufferSize = m_nBufferSize;
m_nBufferSize = m_nPlotWidth/m_nShiftPixels;
m_pdblDataPoints = new double[m_nBufferSize];
int nPointsToCopy = 0;
bool bNewWrapFlag = false;
if( m_pdblSavedDataPoints != NULL )
{
if(m_nBufferSize >= nOldBufferSize)
{
if(m_bWrapped)
nPointsToCopy = nOldBufferSize;
else
nPointsToCopy = m_nDataIndex;
}
else
{
if(m_bWrapped || (m_nBufferSize < m_nDataIndex))
{
nPointsToCopy = m_nBufferSize;
bNewWrapFlag = true;
}
else
nPointsToCopy = m_nDataIndex;
}
}
if( nPointsToCopy > 0 )
{
for( int i = nPointsToCopy-1; i >= 0; --i )
{
if(m_nDataIndex == 0)
m_nDataIndex = nOldBufferSize-1;
else
m_nDataIndex--;
m_pdblDataPoints[i] = m_pdblSavedDataPoints[m_nDataIndex];
}
}
if( m_pdblSavedDataPoints != NULL )
delete m_pdblSavedDataPoints;
if( bNewWrapFlag )
m_nDataIndex = 0;
else
m_nDataIndex = nPointsToCopy;
m_bWrapped = bNewWrapFlag;
}
If anyone finds any issues with this or any improvements feel free to let me know.
Thanks,
Gil Jones
|
|
|
|
|
Thanks Gil,
Works great!!!
I checked out your screen shots. Very nice!
Regards,
Ron Peters
|
|
|
|
|
Gil,
Thanks for the code, works great! There's a little memory leak though. Use operator delete[] In InvalidateCtrl():
delete [] m_pdblSavedDataPoints;
Also put the same line in destructor.
az0te
|
|
|
|
|
I meant this line in destructor:
delete [] m_pdblDataPoints;
- not -
delete [] m_pdblSavedDataPoints;
az0te
|
|
|
|
|
az0te,
This could be a difference in compilers because I just tried recompiling with and without the "[]" and my OScopeCtrl.obj file and my project file (.exe) came out exactly the same with only a difference in blanks. It doesn't show up as a memory leak when I run in the VC++ 6.0 debugger.
Gil
|
|
|
|
|
|
But the fact is that my object file comes out the same so the compiler must be smart enough to know that it was an array pointer and uses the delete[] operator either way.
Gil
|
|
|
|
|
I just verified this in the debugger. It doesn't matter whether I use "delete" or "delete[]"...when I step into the delete call it jumps to the same place as shown below. The debugger doesn't detect a memory leak either way. Did you actually detect a memory leak or did you just look at the code and assume there was one? I agree that's what the msdn library says to do but in reality it's not making a difference.
void __cdecl operator delete(void* p)
{
#if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG)
_free_dbg(p, _NORMAL_BLOCK);
#else
free(p);
#endif
}
Gil
|
|
|
|
|
There is a HUGE difference. As huge as a difference between different runtimes (especially debug and release versions). Operators new and delete not necessary have to be implemented in terms of free and malloc. Here example of code, which hopefully will convince you to use delete[] with new[]. Build release version and run it from the command line. You will see that while 8 objects were constructed (and each allocated 128 bytes in constructor), only 1 was properly deleted (destructor was called). You have 128 x 7 = 896 bytes memory leak. Now add [] after delete, recomplile and see the difference.
=========== cut here ================
#include <iostream>
using std::cout;
using std::endl;
class CTest
{
public:
CTest() : m_p(new char[128])
{
cout << "Constructor" << endl;
}
~CTest()
{
cout << "Destructor" << endl;
delete[] m_p;
}
private:
char* m_p;
};
int main(int argc, char* argv[])
{
CTest* p = new CTest[8];
delete p; // OOPS!!!
return 0;
}
=========== cut here ================
az0te
|
|
|
|
|
I already changed my code to use delete[] but I just wanted to track down why I hadn't seen a memory leak in the OScope code. I talked to our C++ expert here at work and I now understand why. While using delete[] with new[] is the proper method it doesn't automatically mean you have a memory leak if you don't use delete[]....it depends on the array type. I agree that your example will cause a memory leak because the array type is a class that allocates memory with a destructor to free up that memory. But my code was using a built-in type so the compiler allocates a block of memory for the array and using delete will properly free up that entire memory block. Why don't you try your example using a double instead of the CTest class and see if you still have a memory leak?
Gil Jones
|
|
|
|
|
If you use double instead of CTest you won't have a memory leak. But this is true for only runtimes shipped with Visual Studio 6.0 and earlier. You cannot be 100% sure that this will be same for all other platforms and compilers. BTW, already in VS 7.1 if you write code like:
char* pch = new char[32];
delete pch;
and run it under debugger you will get an exception. Another scenario, when you overloading both new and delete operators and writing you own allocators.
As for the changes you made to OScope. The buffer you was allocating in InvalidateCtrl() wasn't freed and this was the source of the leak. This is why I wrote that you have to free it in destructor.
az0te
|
|
|
|
|
az0te is right.
delete []m_pdblDataPoints;
should be added to the destructor.
And add delete [] m_pdblSavedDataPoints; to InvalidateCtrl() as given below:
....
// copy the points
if( nPointsToCopy > 0 )
{
for( int i = nPointsToCopy-1; i >= 0; --i )
{
if(m_nDataIndex == 0)
m_nDataIndex = nOldBufferSize-1;
else
m_nDataIndex--;
m_pdblDataPoints[i] = m_pdblSavedDataPoints[m_nDataIndex];
}
// release the memory for the old data points
if( m_pdblSavedDataPoints != NULL )
delete [] m_pdblSavedDataPoints;
// reset the flags
if( bNewWrapFlag )
m_nDataIndex = 0;
else
m_nDataIndex = nPointsToCopy;
m_bWrapped = bNewWrapFlag;
}
else
if( m_pdblSavedDataPoints != NULL )
delete [] m_pdblSavedDataPoints;
....
|
|
|
|
|
Hi!
Autoranging !!
Great idea
Could you please forward me the changes.
e_mail:chen_ylu@yahoo.com.cn
Many thanx
chen_ylu
|
|
|
|
|
Hi! Autoranging !! Great idea Could you please forward me the changes.
Many thanx
Ike Bosch
|
|
|
|
|
Thanks for this great control, it works fine.
But I have a big application made with WTL Librairies, and I would like to know if some people have ported this control to a WTL control ? (I try it, but I'm not an expert and my project doesn't want compile )
Thanks in advance
Have a nice day
|
|
|
|
|
This is not a problem with your code, but is a problem that I face which affects the display of your code.
My program controls a multimeter type device and retrieves data from said device. I use your code to display the data in a nice form. But the problem is that when another window (let's call this window B) obscures the graphing window, and then window B is then minimized to un-obscure the graphing window, the graphing window does not repaint itself. More specifically, the whole graphing window is the shade of gray which is the background of the graphing window.
The pseudocode of part of my program is like this:
Cmd_send_Set_mulitmeter();
Cmd_send_Read_multimeter();
Is there a function I can call after the Read_multimeter() function which will repaint the graphing window so when some other window obscures it, the graphing window will repaint itself? I've used Invalidate() and InvalidateRect() without success. BTW, my program's main window is a dialog box, so the graph is in one corner of the main window. I am new to win32 programming, so please be kind! thanks!
|
|
|
|
|
I am playing with the program by changing the background, grid and plot colors.
If I set the following colors for background grid and plot, the grid cannot be drawn:
m_OScopeCtrl.SetBackgroundColor(RGB(0, 128, 128)) ;
m_OScopeCtrl.SetGridColor(RGB(0, 0, 0)) ;
m_OScopeCtrl.SetPlotColor(RGB(255, 0, 0)) ;
Can anyone tell me why?
Thanks.
Ke
|
|
|
|
|
The issue is most likely due to the combining of bitmaps. The control was written such that the grid is one bitmap and the plot is generated as another bitmap. The color depth of the bitmap may be an issue, or possibly the combination of bitmaps is wiping it out.
- Mark
|
|
|
|
|
Thanks for your kindly reply.
How can I solve it?
Regards,
Ke
|
|
|
|
|
you can use
memDC.BitBlt(0, 0,
m_nClientWidth, m_nClientHeight,
&m_dcPlot, 0, 0, SRCAND);
instead of
memDC.BitBlt(0, 0,
m_nClientWidth, m_nClientHeight,
&m_dcPlot, 0, 0, SRCPAINT);
in OnPaint() function
|
|
|
|
|
memDC.BitBlt(0, 0,
m_nClientWidth, m_nClientHeight,
&m_dcPlot, 0, 0, SRCAND); //SRCAND
doesn't work either.
Ke
|
|
|
|
|
thank you for your control....
but, it's memory leak..
um.... InvalidateCtrl();
maybe, it's serious memory leak????
|
|
|
|
|
Yes, the memory leaks can be found by using up
static CMemoryState oldstate, newstate, diffstate;
But I cannot find any clues to remove the leaks. Can anyone help?
Thanks.
|
|
|
|