If you do any Win32 programming in C++, then I strongly recommend you learn about GDI+. It’s been around for a while now, but not everybody knows about it. It can be great to have on hand even just to illustrate tests and prototypes.
Why is it so good? It provides an object-oriented way to draw graphics using the GDI, which is much nicer and easier to user than the basic C-style GDI functions and resources 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, such as proper alpha blending, matrix transformations, file input/output, and loads more. It’s quite easy to setup too, as I will explain…
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).
Setup 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, which just means going into your project properties page, select “C/C++” → “Preprocessor”, and beside “Preprocessor Definitions”, add “UNICODE”. Do this for Debug and Release configurations, 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.)
Last step in getting everything setup is to add in the code to initialise and cleanup the GDI+ system. Somewhere near the start of your WinMain function (before you create any windows), put the following code:
GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
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), put the following code (obviously making sure the “gdiplusToken” variable from above is still in scope):
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;
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);
And that’s just about it! We just need to tell our window to finish painting now (this bit isn’t GDI+):
As you can see, it’s fairly easy to setup and use GDI+ (although I guess that’s still probably a bit scary for novice Win32 programmers!). Fear not though! There is plenty of GDI+ documentation on MSDN.
I am also working on a fairly simple object-oriented windowing system at the moment, called “avidwin”. It will hopefully provide a really simple way to handle and manage Win32 windows, and there will be different class specialisations for things like GDI+ and OpenGL. (The idea is that you just inherit one of those classes to add some of your own functionality, and setup a very simple WinMain function, and that’s it. Easy!)