0

I am trying to BitBlt from an HBITMAP to a GDI+ bitmap. I tried this, but nothing happens:

Bitmap Buffer = New Bitmap(608, 392)
Graphics BufferGraphics = Graphics.FromImage(Buffer);
IntPtr hBufferDC = BufferGraphics.GetHdc();

...

BitBlt(hBufferDC, x, y, width, height, hInputDC, 0, 0, SRCCOPY);

EDIT: Apparently the hDC doesn't work if I acquire it and then much later use it with BitBlt. I needed to make sure the hDC was still valid. This is the solution:

Bitmap Buffer = New Bitmap(608, 392)
Graphics BufferGraphics = Graphics.FromImage(Buffer);

...

IntPtr hBufferDC = BufferGraphics.GetHdc();
BitBlt(hBufferDC, x, y, width, height, hInputDC, 0, 0, SRCCOPY);
BufferGraphics.ReleaseHdc(hBufferDC);

Does anyone know why this change is necessary? Why might it not work to use an hDC that was gotten earlier as in the first example?

jnm2
  • 7,960
  • 5
  • 61
  • 99

1 Answers1

0

Check the sample at the end of this page on pinvoke.net. The additional calls to CreateCompatibleDC and SelectObject might make your sample work.

Alternatively, you can consider using Graphics.DrawImageUnscalled which would allow you to implement your code only on the .Net side and would still offer a pretty good performance.

Update (Due to updated question)
I don't know exactly why the hDC becomes invalid after a while, but according to MSDN you call GetHdc and ReleaseHdc in pairs and group the calls to GDI+ code between them: "Calls to the GetHdc and ReleaseHdc methods must appear in pairs. During the scope of a GetHdc and ReleaseHdc method pair, you usually make only calls to GDI functions."

So according to the documentation, the way you did in your second sample is the way to go and you shouldn't cache and reuse values from the GetHdc method.

Florin Dumitrescu
  • 8,182
  • 4
  • 33
  • 29
  • I think I may have discovered the problem, but I'm still working on it. DrawImageUnscaled is no faster. It actually just calls DrawImage. You can see for yourself with a dissasembler. – jnm2 Jan 01 '11 at 16:54
  • @jnm2, you are right, DrawImageUnscalled calls DrawImage, but it calls an overload version of it that does not do any image resizing which is much faster than the overloads that do. Also, I didn't say that DrawImageUnscalled is faster than BitBlt, I said that it "offers a pretty good performance". – Florin Dumitrescu Jan 01 '11 at 17:04
  • The information I need is in an HBITMAP and I can't change that, so I'll have to use FromHBitmap or BitBlt (faster) to get it into GDI+. Then I'm planning to draw the image with bilinear stretching. But I didn't know that about DrawImage. That'll be useful. Thanks for letting me know! – jnm2 Jan 01 '11 at 17:11