Click to See Complete Forum and Search --> : Help with memory leak in GDI+ double buffering


diehardii
March 29th, 2005, 08:13 PM
Hi everyone,

I've got a big, big memory leak. Its occurring in the CreateOffScreeenGraphics function below. I'm relatively new at GDI+, so I'm not sure what the problem is, I'm just trying to get this double buffering to work. Thanks for the help.


cHist::cHist(CWnd* pParent /*=NULL*/)
: CDialog(cHist::IDD, pParent)
{
for(int i = 0; i<16;i++)
{
histogram[i] = i;
}
m_pMemBitmap = NULL;
m_pCachedBitmap = NULL;
m_pMemGraphics = NULL;
m_bdirty = false;
}

cHist::~cHist()
{
}

void cHist::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(cHist, CDialog)
ON_WM_SIZING()
ON_WM_SIZE()
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_DESTROY()
END_MESSAGE_MAP()


// cHist message handlers

void cHist::OnSizing(UINT fwSide, LPRECT pRect)
{
CDialog::OnSizing(fwSide, pRect);
m_bdirty = true;
Invalidate();
// TODO: Add your message handler code here
}

void cHist::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
m_bdirty = true;
Invalidate();
// TODO: Add your message handler code here
}

void cHist::OnPaint()
{
CPaintDC dc(this); // device context for painting


RECT rect;
GetClientRect(&rect);
int nWidth = rect.right - rect.left + 1;
int nHeight = rect.bottom - rect.top + 1;

Graphics graphics(dc.m_hDC);

if ( ! m_pMemBitmap || m_bdirty)
{

CreateOffScreeenGraphics(nWidth, nHeight, &graphics);
m_bdirty = false;

}

// draw from cached bitmap to window
if ( graphics.DrawCachedBitmap(m_pCachedBitmap, 0, 0) != Ok )
{
// make bitmap again (display parameters are changed)
CreateOffScreeenGraphics(nWidth, nHeight, &graphics);
graphics.DrawCachedBitmap(m_pCachedBitmap, 0, 0);
}


// Graphics graphics2(dc);
//Pen pen(Color(255, 0, 0, 255));
//graphics2.DrawLine(&pen, 0, 0, 200, 100);
}


BOOL cHist::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default

//return CDialog::OnEraseBkgnd(pDC);
return TRUE;
}

BOOL cHist::OnInitDialog()
{
CDialog::OnInitDialog();

CClientDC dc(this); // device context for painting

//Initialize GDI+
GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);

return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}

void cHist::OnDestroy()
{
CDialog::OnDestroy();

//Shutdown GDI+

if ( m_pMemGraphics )
delete m_pMemGraphics;

if ( m_pMemBitmap )
delete m_pMemBitmap;

if ( m_pCachedBitmap )
delete m_pCachedBitmap;

GdiplusShutdown(m_gdiplusToken);

// TODO: Add your message handler code here
}


// create off-screen graphics and draw to it
void cHist::CreateOffScreeenGraphics(int nWidth, int nHeight, Graphics* pGraphics)
{
// Create off-screen bitmap
if(m_pMemBitmap)
{
delete m_pMemBitmap;
m_pMemBitmap = NULL;
}
m_pMemBitmap = new Bitmap(nWidth, nHeight);

// Create off-screen graphics

m_pMemGraphics = Graphics::FromImage(m_pMemBitmap);

// draw to off-screen graphics
Draw(m_pMemGraphics, nWidth, nHeight);

// Create cashed bitmap
if(m_pCachedBitmap)
{

delete m_pCachedBitmap;
m_pCachedBitmap = NULL;
}

m_pCachedBitmap = new CachedBitmap(m_pMemBitmap, pGraphics);

}


// draw lines to Graphics
void cHist::Draw(Graphics* pGraphics, int nWidth, int nHeight)
{
// fill background
SolidBrush solidBrush(Color(255, 255, 255));
pGraphics->FillRectangle(&solidBrush, 0, 0, nWidth, nHeight);

Pen pen(Color(255, 0, 0, 255));

int nStep, i;
int nLines = 2;

// draw horizontal lines
nStep = nHeight / nLines;

for ( i = 0; i < nLines; i++ )
{
pGraphics->DrawLine(&pen, 0, nStep*i, nWidth, nStep*i);
}


// draw vertical lines
nStep = nWidth / nLines;

for ( i = 0; i < nLines; i++ )
{
pGraphics->DrawLine(&pen, nStep*i, 0, nStep*i, nHeight);
}
}

chi_luci
March 30th, 2005, 02:02 AM
I'm using CMemDC with GDI+ to avoid flickering and so on.. maybe it helps you too.. :)

Andreas Masur
March 30th, 2005, 03:04 AM
[ Moved thread ]

diehardii
March 30th, 2005, 11:59 AM
Wow,

So many forums here. Anyways, I've figured it out. It turns out the Graphics::FromImage() acts as new.

So, add

if(m_pMemGraphics)
{
delete m_pMemGraphics;
m_pMemGraphics = NULL;
}

before FromImage. Thanks for the suggestions.

~Steve

andytim
April 8th, 2005, 01:30 AM
Hi,
I think you should add the following code at the head of method CreateOffScreeenGraphics:

if ( m_pMemGraphics )
delete m_pMemGraphics;
if ( m_pCachedBitmap )
delete m_pCachedBitmap;

This is a try!!
Andy
--------------------------------------------------------------------
XD++ MFC Library V9.0 -- http://www.********.net