BitBlt DoubleBuffer

Cags

Well-known member
Joined
Feb 19, 2004
Messages
690
Location
Melton Mowbray, England
I wasnt sure whether to place this in the Graphics section or the Interop section, but eventually decided on here.

My problem is as follows, the following code works as I expect it to....
C#:
this.Capture = true;
formHandle = GetCapture();
this.Capture = false;

formDC = GetDC(formHandle);

spriteDC = CreateCompatibleDC(formDC);
spriteBitmap = SHLoadDIBitmap(@"\My Documents\Cags\Bitmap.bmp");
SelectObject(spriteDC, spriteBitmap);

// draw sprite to form
BitBlt(formDC, 0, 0, 25, 25, spriteDC, 0, 0, SRCCOPY);
It copies a small section of the Bitmap.bmp to the screen. After getting this working I decided to try and buffer it before blitting it to the screen. So I amended the code as follows.
C#:
this.Capture = true;
formHandle = GetCapture();
this.Capture = false;

formDC = GetDC(formHandle);

memoryDC = CreateCompatibleDC(formDC);
memoryBitmap = CreateCompatibleBitmap(memoryDC, this.Width, this.Height);
SelectObject(memoryDC, memoryBitmap);

spriteDC = CreateCompatibleDC(formDC);
spriteBitmap = SHLoadDIBitmap(@"\My Documents\Cags\Bitmap.bmp");
SelectObject(spriteDC, spriteBitmap);

// draw sprite to buffer
BitBlt( memoryDC, 25, 25, 25, 25, spriteDC, 26, 26, SRCCOPY );

// draw buffer to form
BitBlt( formDC, 25, 25, 25, 25, memoryDC, 25, 25, SRCCOPY);
The problem is this section of code simply draws a black square rather than a small section of the Bitmap.bmp as I expected. Has anyone got any idea what Im doing wrong here?

Before I forget the API methods are declared as follows, Im pretty sure they are all right so I dont think thats the problem.
C#:
[DllImport("coredll.dll")]
public static extern int BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);

[DllImport("coredll.dll")]
public static extern IntPtr SHLoadDIBitmap(string szFileName);

[DllImport("coredll.dll")]
static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);

[DllImport("coredll.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);


[DllImport("coredll.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);

[DllImport("coredll.dll")]
public static extern IntPtr GetCapture();

[DllImport("coredll.dll")]
static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

const int SRCCOPY	= 0x00CC0020;
 
Well Ive managed to solved the problem myself after much hair pulling.
C#:
// changing this line of code
memoryBitmap = CreateCompatibleBitmap(memoryDC, this.Width, this.Height);
// to this, solved the problem
memoryBitmap = CreateCompatibleBitmap(formDC, this.Width, this.Height);
Im not going to pretend to fully understand why this works, but at least it did. I personally would have thought that since the memoryDC was being created to be compatible with formDC, that creating something compatible with memoryDC would have also been compatible with formDC, but apparently not. Now to try and understand the tidying up code :S
 
GDI+ in .Net 2.0 is faster that in version 1.x in some scenarios, but classic GDI still wins when it comes to performance. It seems that GDI+ seems to take the biggest performance hit when you draw lots of small images. (Try drawing a 256x256 32-bit bitmap from 16x16 8-bit graphic tiles. I wrote my own BitBlt method, in managed code, and it performed at least 100 times better that GDI+. No lie.)
 
As you say marble_eater drawing lots of small images is really slow which is what I have been doing. With more calculations it would undoubtably be possible to increase my performance using GDI+, but I decided to have a go at writing my own wrapper. DrawString is also horrendous in terms of speed. I have a few questions about the best way to proceed with a game Im working on. Ill probably make a seperate thread about it tomorrow.
 
Back
Top