(GDI) Resource leak and double-buffered windows

Started by
4 comments, last by chollida1 19 years, 1 month ago
I'm creating a Win32 GDI 'wrapper' of sorts, and I'm using a secondary DC to do double buffering. This was working fine until I realised I had to resize objects, in which case I couldn't really find a good way to resize the DC without deleting it and creating a new one each time something on the window changed. Problem is, I appear to be leaking resources at an alarming rate from creating and deleting the secondary DC:

if(requireUpdate)
{
	DeleteDC(m_drawDC);
	m_drawDC = CreateCompatibleDC(m_hDC);
	HBITMAP tmpBitmap = CreateCompatibleBitmap(m_hDC, m_width, m_height);
	DeleteObject(SelectObject(m_drawDC, tmpBitmap));
	// Draw object...
}
BitBlt(m_hDC, 0, 0, m_width, m_height, m_drawDC, 0, 0, SRCCOPY);

Just for note, an m_drawDC is created during the window initialisation, just in case it seems wierd that I'm destroying it before creating it. First off, what's causing the resource leak? If I comment this section out and just let it use the originally created m_drawDC it works fine, but this method causes my machine to chew up about 20 megs after a few seconds of resizing the window. Secondly, is there a better way to do this with the GDI? Deleting and re-creating the DC every time makes it slow as hell comparitivly, and although I could probably just make it recreate the DC on resize, I'm a sucker for a smoothly resizing window.
Advertisement
Quote:Original post by PlayfulPuppy
First off, what's causing the resource leak? If I comment this section out and just let it use the originally created m_drawDC it works fine, but this method causes my machine to chew up about 20 megs after a few seconds of resizing the window.

You don't need to free the DC, only the associated bitmap. Also, you're calling DeleteObject() on a HBITMAP owned by the GDI, which probably isn't doing anything. Try this:
// You'll need this as a member variable of the class:// HBITMAP m_hOldBmp;if(requireUpdate){   // Put the old bitmap back. We should get our bitmap out   HBITMAP hMyBitmap = SelectObject(m_drawDC,m_hOldBmp);   // Delete and re-create   DeleteObject(hMyBitmap);   HBITMAP tmpBitmap = CreateCompatibleBitmap(m_hDC, m_width, m_height);   // Select the new bitmap in, and store the GDI one   m_hOldBmp = (HBITMAP)SelectObject(m_drawDC, tmpBitmap)   // Draw object...}

It may be "better" to store the HBITMAP that you create as another member variable, and ignore the return value of the first SelectObject() call there.

Quote:Original post by PlayfulPuppy
Secondly, is there a better way to do this with the GDI? Deleting and re-creating the DC every time makes it slow as hell comparitivly, and although I could probably just make it recreate the DC on resize, I'm a sucker for a smoothly resizing window.

This should be slightly faster (You only re-create the HBITMAP now). You could try allocating a slightly larger bitmap, so if the screen is 300x200, you coukld allocate 450x300. Then, if the window is resized, you don't need to do anything until it gets to 450x300. Of course it'll use up more resources, but its the usual speed vs memory tradeoff.
Ah brilliant, thanks, and you're right, it's quite significantly faster!
That's a dangerous piece of code that your using.

// Put the old bitmap back. We should get our bitmap out
HBITMAP hMyBitmap = SelectObject(m_drawDC,m_hOldBmp);

// Delete and re-create
DeleteObject(hMyBitmap);

Your deleting a bitmap that you may not own!! Dont do this, or atleast realize that you may delete soemthing you don't own by doing this.

CHeers
Chris
CheersChris
Quote:Original post by chollida1
That's a dangerous piece of code that your using.

// Put the old bitmap back. We should get our bitmap out
HBITMAP hMyBitmap = SelectObject(m_drawDC,m_hOldBmp);

// Delete and re-create
DeleteObject(hMyBitmap);

Your deleting a bitmap that you may not own!! Dont do this, or atleast realize that you may delete soemthing you don't own by doing this.

CHeers
Chris

Actually, that bitmap is owned ;)
We create a bitmap, and then select it into the DC. When this piece of code runs, we put the old bitmap back and get the bitmap we own out of it. Although I don't like it, which is why I said:
Quote:Original post by Evil Steve
It may be "better" to store the HBITMAP that you create as another member variable, and ignore the return value of the first SelectObject() call there.
My mistake, I didn't see any code that created teh bitmap so I assumed it was teh one that came from the DC:)

Cheers
Chris
CheersChris

This topic is closed to new replies.

Advertisement