Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

public static void DrawBitBlt(Graphics g, Bitmap bmp, ref Rectangle destRec)
{
IntPtr hDC= g.GetHdc();
IntPtr offscreenDC= a.Api.CreateCompatibleDC(hDC);
a.Api.SelectObject(offscreenDC, bmp.GetHbitmap());
if(bmp.Width==destRec.Width && bmp.Height==destRec.Height)
	a.Api.BitBlt(hDC, destRec.X, destRec.Y, destRec.Width, destRec.Height, offscreenDC, 0, 0, SrcCopy);
else
	a.Api.StretchBlt(hDC, destRec.X, destRec.Y, destRec.Width, destRec.Height, offscreenDC, 0, 0, bmp.Width, bmp.Height, SrcCopy);
a.Api.DeleteDC(offscreenDC);
g.ReleaseHdc(hDC);
}

I am hoping someone here can pinpoint where it is.

C#
  • *Experts*
Posted

Try replacing this like:

a.Api.SelectObject(offscreenDC, bmp.GetHbitmap());

with this:

a.Api.DeleteObject(a.Api.SelectObject(offscreenDC, bmp.GetHbitmap()));

Define DeleteObject if it's not already part of your API class. :)

 

Also, you can use

if (bmp.Size.Equals(destRect.Size)) {

I believe, for your size check.

Posted

This doesn't make sense!

 

Why is the IntPtr returned here:

IntPtr objectPtr= a.Api.SelectObject(offscreenDC, bmp.GetHbitmap());

different from the one returned below?

C#
Posted

public static void DrawBitBlt(Graphics g, Bitmap bmp, ref Rectangle destRec)
		{
			IntPtr hDC= g.GetHdc();
			IntPtr offscreenDC= a.Api.CreateCompatibleDC(hDC);
			IntPtr objectPtr= a.Api.SelectObject(offscreenDC, bmp.GetHbitmap());
			if(bmp.Width==destRec.Width && bmp.Height==destRec.Height)
				a.Api.BitBlt(hDC, destRec.X, destRec.Y, destRec.Width, destRec.Height, offscreenDC, 0, 0, SrcCopy);
			else
				a.Api.StretchBlt(hDC, destRec.X, destRec.Y, destRec.Width, destRec.Height, offscreenDC, 0, 0, bmp.Width, bmp.Height, SrcCopy);
			a.Api.DeleteObject(objectPtr);
a.MB.ShowDialog(objectPtr+"  "+a.Api.SelectObject(offscreenDC, bmp.GetHbitmap()));
			a.Api.DeleteDC(offscreenDC);
			g.ReleaseHdc(hDC);
		}

My custom messageBox (MB) shows the results.

C#
  • *Experts*
Posted

Because you've already selected the new object into it.

 

At first, you are returning the handle to the bitmap stored in the DC into a variable. Then you are replacing the handle in the DC with a new bitmap's handle. So it's like this:

 

Before

objectPtr is nothing

Handle in offscreenDC = xxxxxx

Handle of bmp = yyyyyy

 

Your 'objectPtr = ' statement here

 

After

objectPtr = xxxxx

Handle in offscreenDC = yyyyyy

Handle of bmp = yyyyyy

 

So naturally, when you retrieve the handle in offscreenDC it will be different than it initially was. The second time around it returns the handle of bmp, instead of the handle of the placeholder in offscreenDC.

Posted

THE LEAK IS BACK!

 

I don't know how or why.

public static void DrawBitBlt(Graphics g, Bitmap bmp, ref Rectangle destRec)
{
IntPtr hDC= g.GetHdc();
IntPtr offscreenDC= a.Api.CreateCompatibleDC(hDC);
a.Api.SelectObject(offscreenDC, bmp.GetHbitmap());
if(bmp.Size.Equals(destRec.Size))
	a.Api.BitBlt(hDC, destRec.X, destRec.Y, destRec.Width, destRec.Height, offscreenDC, 0, 0, SrcCopy);
else
	a.Api.StretchBlt(hDC, destRec.X, destRec.Y, destRec.Width, destRec.Height, offscreenDC, 0, 0, bmp.Width, bmp.Height, SrcCopy);
			a.Api.DeleteObject(a.Api.SelectObject(offscreenDC, bmp.GetHbitmap()));
a.Api.DeleteDC(offscreenDC);
g.ReleaseHdc(hDC);
}

C#
Posted

THE LEAK IS BACK!

 

I don't know how or why.

public static void DrawBitBlt(Graphics g, Bitmap bmp, ref Rectangle destRec)
{
IntPtr hDC= g.GetHdc();
IntPtr offscreenDC= a.Api.CreateCompatibleDC(hDC);
a.Api.SelectObject(offscreenDC, bmp.GetHbitmap());
if(bmp.Size.Equals(destRec.Size))
	a.Api.BitBlt(hDC, destRec.X, destRec.Y, destRec.Width, destRec.Height, offscreenDC, 0, 0, SrcCopy);
else
	a.Api.StretchBlt(hDC, destRec.X, destRec.Y, destRec.Width, destRec.Height, offscreenDC, 0, 0, bmp.Width, bmp.Height, SrcCopy);
a.Api.DeleteObject(a.Api.SelectObject(offscreenDC, bmp.GetHbitmap()));
a.Api.DeleteDC(offscreenDC);
g.ReleaseHdc(hDC);
}

The return value of DeleteObject is 1 meaning success.

C#
  • *Experts*
Posted
Replace the first SelectObject line with the second one, and then remove the second one from the bottom; once you use SelectObject, the handle in the DC changes, so SelectObject() will not return the same thing it did last time you used it. It basically sticks what you tell it to into the DC and returns what used to be there. If you don't do anything with it, you can't get it back later, because the new object is now in the DC, so SelectObject will return that.
Posted

It's done and it works but it takes a while for the dumped memory to show up in the task manager.

Let me see if I understand this correctly. When I call SelectObject, deleting it in the same statement it only deletes an extra object I don't need and the other it placed into the back buffer DC.

Correct?

C#
  • *Experts*
Posted

Yes, that's correct.

 

And also, don't worry about the memory taking awhile to show up; memory allocated within a .NET app probably won't be really free until the Garbage Collector frees it up.

Posted

That creates a major problem. When I use DrawImageUnscaled my ram stays at around 12000kb but using BitBlt it jacks up to over 40k before it is removed! Making the animation very choppy.

 

How can I prevent this?

C#
Posted
public static void DrawBitBlt(Graphics g, Bitmap bmp, ref Rectangle destRec)
		{
			IntPtr hDC= g.GetHdc();
			IntPtr offscreenDC= a.Api.CreateCompatibleDC(hDC);
			a.Api.DeleteObject(a.Api.SelectObject(offscreenDC, bmp.GetHbitmap()));
			if(bmp.Size.Equals(destRec.Size))
				a.Api.BitBlt(hDC, destRec.X, destRec.Y, destRec.Width, destRec.Height, offscreenDC, 0, 0, SrcCopy);
			else
				a.Api.StretchBlt(hDC, destRec.X, destRec.Y, destRec.Width, destRec.Height, offscreenDC, 0, 0, bmp.Width, bmp.Height, SrcCopy);
			a.Api.DeleteDC(offscreenDC);
			g.ReleaseHdc(hDC);
			GC.Collect(); //a desparate attempt, that failed.
		}

C#
  • *Experts*
Posted
Well, it seems like it should be alright... perhaps using the API so much (I assume you are using it in some sort of loop, meaning calling it very often) it taking its toll on .NET... it is unmanaged afterall. divil would know better than I on this one, I think.
Posted (edited)

Here is the whole project. Maybe you will get different results. It is very simple. Not much code in the main form. At the bottom of Form1 (the main form) you will see this:

//a.Api.DrawBitBlt(e.Graphics, B, ref this.posRec);

e.Graphics.DrawImageUnscaled(B, this.posRec);

 

Just alternate them to test.

 

You will notice also, that the form closes 50 times faster when the api is not used.

game.zip

Edited by aewarnick
C#
  • *Gurus*
Posted

Here's the correct way of doing it, making sure everything used is cleaned up properly.

 

public static void DrawBitBlt(Graphics g, Bitmap bmp, ref Rectangle destRec)
{
// Get DC handle and create a compatible one
IntPtr hDC= g.GetHdc();
IntPtr offscreenDC= a.Api.CreateCompatibleDC(hDC);

// Select our bitmap in to DC, recording what was there before
IntPtr hBitmap = bmp.GetHbitmap();
IntPtr oldObject = a.Api.SelectObject(offscreenDC, hBitmap);

// Perform blt
if(bmp.Size.Equals(destRec.Size))
	a.Api.BitBlt(hDC, destRec.X, destRec.Y, destRec.Width, destRec.Height, offscreenDC, 0, 0, SrcCopy);
else
	a.Api.StretchBlt(hDC, destRec.X, destRec.Y, destRec.Width, destRec.Height, offscreenDC, 0, 0, bmp.Width, bmp.Height, SrcCopy);

// Select our bitmap object back out of the DC
a.Api.SelectObject(offscreenDC, oldObject);

// Delete our bitmap
a.Api.DeleteObject(hBitmap);

// Delete memory DC and release our DC handle
a.Api.DeleteDC(offscreenDC);
g.ReleaseHdc(hDC);
}

MVP, Visual Developer - .NET

 

Now you see why evil will always triumph - because good is dumb.

 

My free .NET Windows Forms Controls and Articles

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...