Using GDI+ in C++ Win32 programming

If you do any Win32 programming in C++ then I strongly recommend you learn about GDI+. Although it’s been around for a while now, it doesn’t seem to be well known. It can be great to have on hand even just to illustrate tests and prototypes though. As it’s object-oriented, it’s much nicer and easier to use than the basic C-style GDI that used to be the norm. It also provides a lot of additional functionality which otherwise was not possible (or at least not easy) with the regular GDI functions alone. For example, such as proper alpha blending, matrix transformations, file input/output, and loads more. It’s quite easy to setup too.

Unicode!

One thing to be aware of first: GDI+ requires Unicode to be enabled. That means that all string literals need to be preceded by “L” (without the quotes), or encased in a “TEXT(..)” macro. It also means that you might find you need to change any string classes or functions. It can be a nightmare to port existing code, but it’s alright once you get there (or if you’re starting from scratch).

Configure the Project

I’m using Visual C++ Express Edition 2008, which is free to download and use. The best thing to do is setup a simple windows application first. Just create a basic window, and your regular message pump/handler. Next, you need to make sure Unicode is enabled for your code. To do that, go into your project properties page, select “C/C++” → “Preprocessor”, and beside “Preprocessor Definitions”, add “UNICODE”. Do this for Debug and Release modes, or whatever your configurations are.

Next, you need to link to the Gdiplus library. Still in Project Properties, go to “Linker” → “Input”, and beside “Additional Dependencies”, add “gdiplus.lib”. (Once again, do it for all configurations.)

Initialisation and cleanup

Now you need to add the code to initialise and cleanup the GDI+ system. Put the following code somewhere near the start of your WinMain function (before you create any windows):

GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

Next, put the following code somewhere near the end of your WinMain function, after ALL other GDI+ objects you might be using has been deleted or fallen out of scope:

GdiplusShutdown(gdiplusToken);

Somewhere near the top of your source code file(s) where you will be using GDI+, you’ll want to put this:

#include <gdiplus.h>
using namespace Gdiplus;

Using It!

You’ll usually want to use GDI+ in your window’s “paint” event (although it can be used to write out to files too if you want). The main class you’ll be working with is the Graphics class, which handles most of your drawing. You have to start by getting a Graphics object linked to the device context of your window so it can draw to it safely. There’s lots of ways to handle a paint event, but I’ll follow my preferred approach here (remember to make sure you’re window area is invalidated before doing this):

// Assuming you've got your window handle in "hWnd":
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
Graphics g(hdc);

Just like with the regular GDI, you draw and paint using pens and brushes, but thankfully these are much easier. We will fill in a rectangle with a red brush, and draw a green circle inside it:

SolidBrush redBrush(Color::Red);
Pen greenPen(Color::Green, 2.0);
g.FillRectangle(&redBrush, 20, 20, 100, 100);
g.DrawEllipse(&greenPen, 30, 30, 80, 80);

Finally, we need to tell our window to finish painting now (this bit isn’t GDI+):

EndPaint(hWnd, &ps);

Documentation

As you can see, it’s fairly easy to setup and use GDI+. I recommend looking at the GDI+ documentation on MSDN to help you get going.

5 comments on “Using GDI+ in C++ Win32 programming

  1. I’ve literally implemented this piece of code but it seems it does nothing, literally nothing. I used GDI at first but switched to GDI+ for more C++ style usability. Any idea what to do when nothing shows up ?

  2. Sorry to hear you’re having trouble. I’ve just checked the code in the original post, and it definitely works if it’s in the right place.

    Unfortunately there’s lots of potential reasons why it wouldn’t seem to work. If your GDI drawing code was working before, then perhaps you’re not initialising GDI+?

    Other things to check are:

    1. Make sure your drawing code is getting executed in the WM_PAINT handler (it won’t work anywhere else).
    2. Make sure you’re using the correct window handle (hWnd).
    3. Make sure you call InvalidateRect() on your window regularly if you want to redraw constantly.

    If you still can’t get it working, then feel free to send me your code and I’ll take a look. You can use the “Contact Me” form on the main menu. :)

  3. I’ve wasted a lot of time with my unresolved symbols problems,… thank you much, your post gave me the solution… (gdiplus.lib)

  4. how can i compare 1 color?

    Gdiplus::Color clrBackColor =Gdiplus::Color::Transparent;
    if (clrBackColor == Gdiplus::Color(Gdiplus::Color::Transparent))

    i get an error:
    “no match for ‘operator==’ (operand types are ‘Gdiplus::Color’ and ‘Gdiplus::Color’)”
    why these error?

    • That error means an equality operator (==) hasn’t been declared for the Color class. Instead, I think you could compare the underlying values directly by using the GetValue() method:

      Color c1, c2;
      if (c1.GetValue() == c2.GetValue()) {
          // colors are the same
      }
      

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.