Basic GDI Wrapper class library.

wyrd

Well-known member
Joined
Aug 23, 2002
Messages
1,408
Location
California
After pain staking hours figuring out how all this lovely GDI+ and Win32 GDI stuff worked and interacted together, I finally came up with a basic class library which you can just plug-n-play for faster drawing. Obviously theres room for improvement as it only implements a few basic Win32 functions for drawing, but its already proved useful in the game Im creating. :) If you find any bugs let me know.

Before getting to how to use the class library (its really a no-brainer), heres my initial tests on my 800mhz athlon, G2 MX, 256mb of RAM rig (yeah, nothin special).

Draw Area: 640x480
Images Drawn Per Frame: 336
Size Of Images: 32x32
FPS: 43
Increase Over GDI+: ~14 FPS

Draw Area: 480x360
Images Drawn Per Frame: 176
Size Of Images: 32x32
FPS: 74
Increase Over GDI+: ~25 FPS

I originally tried w/ letting .NET handle the backbuffer and all that with SetStyles. Unfortunately I didnt quite as good of a FPS boost. It seems like in this case youre better off doing your own backbuffer.

Okay, so heres how to use it. :)

C#:
GDIBitmap _image;
GDIBitmap _buffer;
Graphics _main;

public Constructor() 
{
   // Load images.
   _image = new GDIBitmap("hi.bmp");

   // Create buffer.
   _buffer = new GDIBitmap(this.Width, this.Height);
   
   // Create main drawing area.
   _main = this.CreateGraphics();
}

// Pretend this is a dispose pattern.
public void Dispose() {
   _image.Dispose();
   _buffer.Dispose();
   _main.Dispose();
}

// Some event to start the loop.
public void Event() 
{
   while (true) {
      _drawBuffer();
      _drawMain();

      this.DoEvents();
   }
}

private void _drawBuffer() 
{
   GDIDraw.BitBtl(_buffer.DeviceContext, 0, 0, _image.Width, _image.Height,
      _image.DeviceContext, 0, 0, RasterOperations.SrcCopy);
}

private void _drawMain() 
{
   IntPtr dcMain = _main.GetHdc();

   GDIDraw.BitBlt(dcMain, 0, 0, _buffer.Width, _buffer.Height,
      _buffer.DeviceContext, 0, 0, RasterOperations.SrcCopy);

   _main.ReleaseHdc(dcMain);
}

Just as easy as GDI+ (well, maybe not, you need to create your own backbuffer), and gives more speed. :) Ohhh yeah!

Ah, and one thing of note; not sure if I should of created a new thread for this, but it didnt exactly fit the topic of my other two posts (one was asking for help and the other was about speeding up GDI+). If this should of been posted in one of my other two threads then I apologize for wasting space. That wasnt my intention.
 

Attachments

Last edited by a moderator:
One thing to note about comparing the speed of plain old BitBlt and GDI+ is that BitBlt does not support transparency without using more BitBlt operations, while DrawImage and DrawImageUnscaled does.

You may want to do another test with just with GDI+ to see if making part of the image transparent slows does the speed of drawing or not. If it does not, then you are going to have to find out how to draw partial transparent images with BitBlt using masks before you can really do a "fair" comparison. I wanted to do that but have not gotten around to it yet.
 
You have a good point. However, my map is not drawn with transparent images. Even if transparency drawing is around the same speed (which I doubt it), using regular BitBlt over Graphics.DrawImage will still come in quite handy.

When I get around to drawing transparent images it shouldnt be any more difficult then just adding a reference to TransparentBlt and using that instead of BitBlt for images I want to draw transparently.

http://www.mentalis.org/apilist/TransparentBlt.shtml
 
TransparentBlt contains a memory leak in all operating systems preceding Windows 2000, and should be avoided like the plague. The only correct way to do transparent BitBlting is by creating the mask and using the SrcAnd/MergePaint combination.

Look at my BitBlt tutorial (GDI32 Part III) tutorial on EliteVB. Its in the Graphics section. Its for VB, but its fairly transferrable.
 
Anyone know where I can find out what the values for the pen styles are for CreatePen? ie; PS_SOLID, PS_DOT, etc. Ive searched up and down in the MSDN library and cant seem to find any information on their values.
 
Oh, you were looking for the values :).
Yes, I checked them in the VC++ compiler, they are 0-6 in the order they are shown on that page.
 
I also had a look at Wingdi.h, it seems to define more styles:
Code:
/* Pen Styles */
#define PS_SOLID            0
#define PS_DASH             1       /* -------  */
#define PS_DOT              2       /* .......  */
#define PS_DASHDOT          3       /* _._._._  */
#define PS_DASHDOTDOT       4       /* _.._.._  */
#define PS_NULL             5
#define PS_INSIDEFRAME      6
#define PS_USERSTYLE        7
#define PS_ALTERNATE        8
#define PS_STYLE_MASK       0x0000000F

#define PS_ENDCAP_ROUND     0x00000000
#define PS_ENDCAP_SQUARE    0x00000100
#define PS_ENDCAP_FLAT      0x00000200
#define PS_ENDCAP_MASK      0x00000F00

#define PS_JOIN_ROUND       0x00000000
#define PS_JOIN_BEVEL       0x00001000
#define PS_JOIN_MITER       0x00002000
#define PS_JOIN_MASK        0x0000F000

#define PS_COSMETIC         0x00000000
#define PS_GEOMETRIC        0x00010000
#define PS_TYPE_MASK        0x000F0000
 
You can use the API Viewer 2003 obtained from AllAPI to get API declares, constants and types from Win32 API. It even does its best to convert to VB.NET or C# if you want it to (though it doesnt do a great job).

Even for a .NET developer its a must-have in your utility box. :)
 
Back
Top