Few questions about using Windows API.

wyrd

Well-known member
Joined
Aug 23, 2002
Messages
1,408
Location
California
Edit: I got the answers to my questions.. http://www.codeproject.com/csharp/flicker_free.asp

I was looking at the Windows API functions for drawing. It looks easy enough (get handle from Bitmap, use it w/ BitBlt, DeleteObject on handle when done).

I assume Id have to do my own double buffering if I used the Windows API right? Also I take it putting the Bitmap.GetHbitmap() and DeleteObject() inside a loop would be bad right? I just want to clarify that its not just getting a reference to a handle, but actually creating the object in memory THEN giving you the handle reference to that object? If thats the case, can I do Bitmap.Dispose() after Bitmap.GetHBitmap() w/o effecting it? That way I dont have two objects in memory of the same bitmap (assuming GetHbitmap is creating another object in memory).

Lots of silly questions, but Im unfamiliar with the Windows API. I just want to make sure I fully understand what its doing so I can use it efficiently.

Thanks in advance.
 
Last edited by a moderator:
Okay.. I think I understand now (maybe, heh). I was wondering if someone could answer the questions in the comments below, and also double check to see if everything *might* possibly work correctly.

C#:
// DllImport Win32 API functions here.

Bitmap _image;
IntPtr _imgH;

IntPtr _oldH;

Bitmap _bitbuf;
Graphics _buffer;

Graphics _main;

public Form() 
{
   // Create display area.
   _main = this.CreateGraphics();

   // Create backbuffer.
   _bitbuf = new Bitmap(this.Width, this.Height);
   _buffer = Graphics.FromImage(_bitbuf);

   // Load image to draw.
   _image = new Bitmap("somefile.bmp");
   _imgH = _image.GetHbitmap(); // Does this create a new copy or just reference?!

   // Select DC for image, which should be the DC Im 
   // going to draw it to, correct?
   IntPtr dc = _buffer.GetHdc();
   _oldH = SelectObject(dc, _imgH);
   _buffer.ReleaseHdc(dc);

   _image.Dispose(); 
   // Dispose GDI+ image here or does it have to stay in memory?!
   // Im confused as to whether GetHbitmap creates a stand alone
   // object or not.
}

// At some point a keydown event will trigger this.
private void _run() 
{
   // Imagine a game loop. :P
   while (true) {
      _drawBuffer();
      _drawMain();
   }
}

// Draws images to buffer.
private void _drawBuffer()
{
   IntPtr bufferDC = _buffer.GetHdc();

   BitBlt(bufferDC, dstX, dstY, dstWidth, dstHeight, 
      _imgH, srcX, srcY, srcWidth, srcHeight, 
      RasterOperation);

   _buffer.ReleaseHdc(bufferDC);
}

// Draws buffer to main.
private void _drawMain() 
{
   IntPtr _buffer.GetHdc();
   IntPtr mainDC = _main.GetHdc();

   BitBlt(mainDC, 0, 0, this.Width, this.Height, 
      bufferDC, 0, 0, _bitbuf.Width, _bitbuf.Height, 
      RasterOperation);

   _buffer.ReleaseHdc(bufferDC);
   _main.ReleaseHdc(mainDC);
}

// This would obviously be in Dispose but I dont want 
// to write out the whole Dispose pattern.
~Form() 
{
   IntPtr dc = _buffer.GetHdc();

   // Return old handle to DC.
   // I do have do to this right? Thats what the docs say...
   // It doesnt say why though?
   // Also, it should be returning my image handle right?
   // Or do I not accept the return handle at this point?
   _imgH = SelectObject(dc, _oldH); 

   _buffer.ReleaseHdc(dc);   

   // Delete image.
   DeleteObject(_imgH);

   // Dispose of backbuffer.
   _buffer.Dispose();
   _bitbuf.Dispose();

   // Dispose of display surface.
   _main.Dispose();
}

Thanks in advance. :)
 
Last edited by a moderator:
GetHBitmap gets the bitmap handle of the bitmap. When you dispose of the image, the handle becomes invalid.
 
Another question;
Is the speed of SelectObject fast, or should I use it sparingly?

VF:
The MSDN says it actually creates an HBITMAP object in memory, then gives you a pointer to its handle. I tested this out because it seemed rather odd to me. I loaded a bitmap like normal, then created HBITMAP with Bitmap.GetHbitmap(). After that I did Bitmap.Dispose() followed by GC.Collect() to make sure the Bitmap was no longer in memory. After all that, the IntPtr to HBITMAP was still valid (I was able to use it until I did DeleteObject())

Maybe my tests were inaccurate or I did something wrong to produce fantasy results. If your or someone else would like to confirm or deny this Id appreciate it.
 
Well, the MSDN would know better than I, so I must be mistaken. Seems rather odd though.

SelectObject should be used whenever you need it. There really is no way to go overboard with it, or conserve its use. Whenever you need to put a font or a pen into a DC, you need it.
 
Back
Top