Interoperability between GDI and GDI+
It's sometimes desirable to mix Windows Graphics Device Interface (GDI) and GDI+ drawing operations in the same code path. This article provides tips to help you write code that allows GDI and GDI+ to work together.
Original product version: Windows Graphics Device Interface
Original KB number: 311221
Certain rules apply when mixing GDI and GDI+ code. For example, you shouldn't interleave GDI and GDI+ calls on one target object. It's okay to wrap a Graphics object around an HDC, but you shouldn't access the HDC directly from GDI until the Graphics object is destroyed.
Four primary scenarios for interoperability between GDI and GDI+ are covered in this article:
- Using GDI on a GDI+ Graphics object backed by the screen
- Using GDI on a GDI+ Graphics object backed by a bitmap
- Using GDI+ on a GDI HDC
- Using GDI+ on a GDI memory
HBITMAP(a handle to a bitmap object)
Using GDI on a GDI+ Graphics object backed by the screen
One example of a need to use GDI on a GDI+ Graphics object backed by the screen would be to draw a rubber band or focus rectangle. GDI+ currently has no direct support for raster operations (ROPs), so GDI must be used directly if R2_XOR pen operations are required. In this case, you would use
Graphics::GetHDC() to obtain an HDC to which the GDI output would be directed. GDI+ output shouldn't be attempted on the Graphics object for the life of the HDC (that is, until
Graphics::ReleaseHDC() is called).
Using GDI on a GDI+ Graphics object backed by a bitmap
Graphics::GetHDC() is called for a Graphics object that is backed by a bitmap rather than the screen, a memory HDC is created and a new
HBITMAP is created and selected into the memory HDC. This new memory bitmap isn't initialized with the original bitmap's image but rather with a sentinel pattern, which allows GDI+ to track changes to the bitmap. Any changes that are made to the memory bitmap through the use of GDI code become apparent in changes to the sentinel pattern. When
Graphics::ReleaseHDC() is called, those changes are copied back to the original bitmap. Because the memory bitmap isn't initialized with the bitmap's image, an HDC that is obtained in this way should be considered write only and is therefore not suitable for use with ROPs, the use of which requires the ability to read the target, like R2_XOR. Also, there's a performance cost to this approach because GDI+ must copy the changes back to the original bitmap.
Using GDI+ on a GDI HDC
You can facilitate the use of GDI+ on an HDC by using the Graphics constructor that takes an HDC as a parameter. The drawing members of the Graphics class can be used to draw on the HDC in this way. Once the Graphics object is attached to the HDC, no GDI operations should be performed on the HDC until the Graphics object is destroyed or goes out of scope. If GDI output is required on the HDC, either destroy the Graphics object before using the original HDC or use
Graphics::GetHDC() to get a new HDC and then follow the rules described earlier in this article for interoperability while using GDI on a GDI+ object.
Using GDI+ on a GDI memory HBITMAP
The GDI+ Bitmap constructor that takes an
HBITMAP as a parameter doesn't use the actual source
HBITMAP as the backing image for the bitmap. Rather, a copy of the image is made in the constructor, and changes aren't written back to the original bitmap, even during execution of the destructor. The new bitmap can be thought of as copy on creation, so to get GDI+ to draw on a memory
HBITMAP from GDI and have the changes apply to the
HBITMAP, an approach like the following is needed instead:
- Create a
- Select the
DIBSectioninto a memory HDC.
- To use GDI+ to draw to the
DIBSection, wrap a Graphics object around the HDC.
- To use GDI to draw to/from the
DIBSection, destroy the Graphics object, and use the HDC.
- Destroy the Graphics objects, and then clear the
DIBSectionselection from the HDC. Later, a bitmap can be constructed from the
DIBSectionand used as a source image in