Overview
Sometimes it is desirable to mix GDI and GDI+ drawing operations in the same code path. When you write code that allows GDI and GDI+ to interoperate, there are a few things to keep in mind. This article outlines these considerations and provides additional information to help you write this type of code successfully.
More information
While it is possible to mix GDI and GDI+ code, certain rules must be followed. In general, you shouldn't interleave GDI and GDI+ calls on one target object. For example, HDC
wrapping an Graphics
object around is fine, but Graphics
you shouldn't access it directly from GDI until the object is destroyed HDC
.
This article describes four main scenarios for interoperability between GDI and GDI+:
- Using GDI on screen-backed GDI+ graphics objects
- Using GDI on GDI+ graphics objects backed by bitmaps
- Using GDI+ on GDI HDC
- Using GDI+ on GDI memory HBITMAP
Using GDI on screen-backed GDI+ graphics objects
An example of using GDI on a screen-backed GDI+ Graphics object is to draw a "rubber band" or "focus" rectangle. GDI+ does not currently support raster operations (ROPs), so if R2_XOR
pen operations are required, GDI must be used directly. In this case, you can use Graphics::GetHDC()
to get what GDI output points to HDC
. GDI+ output should not be HDC
attempted on graphics objects with a lifetime (that is, until called Graphics::ReleaseHDC()
).
Using GDI on GDI+ Graphics Objects Supported by Bitmaps
When called for a bitmap-backed Graphics
object instead of a screen Graphics::GetHDC()
, a memory is created HDC
, and a new one is created HBITMAP
and selected into memory HDC
. Instead of using the original bitmap's image to initialize this new in-memory bitmap, it uses a marker mode that allows GDI+ to track changes to the bitmap. Any changes made to the memory bitmap by using GDI code will become apparent in the changes to the sentinel mode. When Graphics::ReleaseHDC()
called, these changes are copied back to the original bitmap. Since the memory bitmap is not initialized with the bitmap's image, the one obtained this way HDC
should be considered "write-only" and therefore not suitable for use with ROP, whose use requires the ability to read the target, eg R2_XOR
. Also, this approach has a high performance cost, as GDI+ has to copy the changes back to the original bitmap.
HDC
Using GDI+ over GDI
It is convenient to use GDI+ on it by using the Graphics constructor HDC
that takes an argument. HDC
The drawing members of the Graphics class can draw on this way HDC
. Once a Graphics object is attached , no GDI operations should be performed on it until HDC
the Graphics
object is destroyed or goes out of scope . HDC
If you HDC
need GDI output on , you can either HDC
destroy the Graphics
object before using the original, or use Graphics::GetHDC()
get the new one HDC
, then interoperate according to the rules described earlier in this article, while in GDI+ purposes.
HBITMAP
Using GDI+ on GDI memory
The GDI+ bitmap constructor that takes an HBITMAP as a parameter does not use the actual source HBITMAP as the backing image for the bitmap. Instead, a copy of the image is created in the constructor and changes are not written back to the original bitmap even during the execution of the destructor. New bitmaps can be thought of as "copy-on-create", so in order for GDI+ to grab HBITMAP
memory from GDI and apply these changes to HBITMAP
something like:
- List content
- Create one
DIBSection
. - will
DIBSection
select into memoryHDC
. - To draw with GDI+
DIBSection
, wrap anGraphics
object around the HDC. - To draw with GDI
DIBSection
, destroy theGraphics
object, then useHDC
. - Destroy the graphic object, then clear
HDC
theDIBSection
options in .
Later, if desired, you can DIBSection
construct a bitmap from it and use it as Graphics::DrawImage()
the source image in .