If you've been with me for the last two articles, you've probably been asking yourself when I'm going to show you something useful. Well, the wait is over! Today I'll be showing you the basics of Windows GDI (Graphical Device Interface), and a few other things along the way, like responding to user input and dealing with some more of the messages that Windows generates. As far as actually displaying graphics, I'm going to go over three basic topics: showing text, plotting pixels, and displaying bitmaps. Before getting into too much of that though, I'm going to cover several more Windows messages in detail so you will be sure to know what's going on when the user starts messing with things. They always do. :)
As always, you need only a basic knowledge of the C language, and the information that was covered in previous articles of this series. Since this article will enable you to make some working graphical demos, there is a sample program available along with the article. The code used for this program was written and compiled in Visual C++, but it is simple enough that you shouldn't have to change it to get it working with other compilers. All right, enough with the disclaimers, and on to the fun stuff!
In the first article in this series, we defined and registered a window class. One of the lines in that definition, giving the window's capabilities, was this:
Three of those attributes are fairly self-explanatory, but the other -- CS_OWNDC -- requires some explanation. If you recall, I told you that this attribute allowed for the window to have its own unique device context, and that device contexts would not be covered just yet. Well, grasshopper, the time has come.
A device context is a structure that represents a group of graphic objects and their attributes, as well as some output device and its attributes and settings. Using device contexts allows you to manipulate graphics in a very straightforward manner, without having to worry about a lot of low-level details. Windows GDI is a graphics-rendering system which takes Windows graphics calls and passes the information to the appropriate device driver. To make use of GDI graphics, you must use device contexts. Thankfully, it's very easy to do. You can get a device context for a window using a simple function call:
That looks pretty harmless, doesn't it? All you do is pass a handle to the window for which you want a device context (or DC), and the return value is a handle to that device context. If you pass NULL, the handle returned is for a DC to the entire screen. If the function call fails, the return value is NULL.
Now is a good place to mention that device contexts are a little more general than dealing with graphics calls only. The type of DC we'll be talking about is called a display device context, because it deals with displaying graphics. In addition, there are printer device contexts, which use a printer as the output device; memory device contexts, which allow for manipulation of bitmap data; and information device contexts, for retrieving data for a specified device. Don't worry if this all sounds complicated. It's Windows -- its primary function is to confuse people. :) Once we get into some code, I think you'll find that it's actually not that difficult.
When you're finished with a device context, you have to release it. This frees up any memory that was being used by the object -- you'll come across the concept of releasing objects a lot more in the future. Once again, this is done by using a simple function call:
The return value is 1 if the DC was successfully released, or 0 if something went wrong. The parameters are self-explanatory, but I'll list them here anyway.
HWND hWnd: This is the handle to the window which is referred to by the DC you're trying to release. If you have a DC for the whole desktop, pass NULL.
HDC hDC: The handle to the device context you want to release.
Before we get into doing some graphics displays with device contexts and GDI, I want to talk about some of the important messages you'll encounter when creating a windowed application. The four messages I want to cover briefly are WM_MOVE, WM_SIZE, WM_ACTIVATE, and WM_PAINT.