5

I'm dealing with code that goes something like this (from here)

using (var bmp = new System.Drawing.Bitmap(1000, 1000)) 
{
    IntPtr hBitmap = bmp.GetHbitmap(); 
    var source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
        hBitmap, IntPtr.Zero, Int32Rect.Empty,
        System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
}

and MSDN says that whenever I call Bitmap.GetHbitmap() I have to call DeleteObject() on the hBitmap to release the unmanaged resources.

All the answers I've seen and MSDN say I have to P/Invoke the DeleteObject() function. This looks a bit insane because I obtained the hBitmap without P/Invoke and now I suddenly need to use P/Invoke to proper get rid of it.

Is there indeed no other way except P/Invoke to have DeleteObject() called for my hBitmap?

Community
  • 1
  • 1
sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • They make [`DeleteObject()`](http://referencesource.microsoft.com/#System.Drawing/misc/GDI/DeviceContext.cs,0ec286748b35196a), which needs [`GdiObjectType.Bitmap`](http://referencesource.microsoft.com/#System.Drawing/misc/GDI/GdiObjectType.cs,1f181904379350ac,references) as parameter. But they are `internal`... – Sinatr Jan 29 '15 at 15:35
  • 2
    I don't think there is other way... Even [FromHbitmap](https://msdn.microsoft.com/en-us/library/vstudio/system.drawing.image.fromhbitmap.aspx) creates copy and requires `DeleteObject` on original. But the whole point of obtaining HBITMAP is to do interop - not sure if one additional method is soo bad (even shown in the link you've posted) . – Alexei Levenkov Jan 29 '15 at 15:46
  • What's the problem with having to P/Invoke? You've already had to pass the barrier to entry (`UnmanagedCode`) when you called `GetHBitmap`. – Damien_The_Unbeliever Jan 30 '15 at 13:24
  • 1
    @Damien_The_Unbeliever: The problem is I suddenly need to craft a proxy method decorated with `DllImport` which doesn't look neat. – sharptooth Jan 30 '15 at 13:36
  • You've already taken on interop by calling GetHBitmap. In for a penny, in for a pound. – David Heffernan Jan 30 '15 at 14:50
  • 1
    @DavidHeffernan: I've called a Bitmap.GetHBitmap() method which was declared in the .NET Framework and now I suddenly have to craft a proxy just to get rid of what that method returned. This is kinda weird. – sharptooth Jan 30 '15 at 14:54
  • So don't call `GetHBitmap` then. Oh wait, you did that because you want to do some interop..... – David Heffernan Jan 30 '15 at 14:58
  • 1
    @DavidHeffernan: I pass `hBitmap` into `CreateBitmapSourceFromHBitmap()` which is also a method of a class in .NET Framework. I would be just as happy to `Bitmap` reference in there but for whatever reason that thing requires an `IntPtr` representing an unmanaged object. – sharptooth Jan 30 '15 at 15:01

1 Answers1

5

I don't think that there's any way to call DeleteObject from C# other than using p/invoke.

So, if you want to avoid this undesired trip into unmanaged code then you should avoid calling GetHbitmap in the first place. You can do that readily enough. You want to make a BitmapSource. Do that with a call to BitmapSource.Create.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490