Topic : Using Resources in Win32 Programs
Author : Joseph Farrell
Page : 1 Next >>
Go to page :


Introduction
Welcome back! As you may have guessed by the title, in this article I'm going to show you how to use resources in your Windows programs. Simply put, resources are binary data that's appended to your .EXE file after the actual program code. Using resources is easy to learn and has a lot of advantages. It allows the developer to consolidate a lot of data into one file, include custom icons and such things with their programs, and prevent users from altering that data. Windows supports a large number of resource types, so I'm just going to cover the ones I think are most convenient and easiest to learn: bitmaps, cursors, icons, menus, and string tables. After that, I'll show you how to create a custom resource type, so you can include anything you want.
Again, all you need to understand this article is a basic understanding of the C language. C++ always helps since Windows itself is object-oriented, but most of my code is straight C. Also, I will assume that you have read my previous article, "Beginning Windows Programming," or have the equivalent knowledge. I use and recommend the Microsoft Visual C++ compiler, but if you're using a different one, it's not a big deal. Ready? Here we go!
Resource Scripts
Before we get into any of the specific resource types, we need to go over the method used to tell the compiler what resources to include, and how. This method is to use a special file called a resource script, which is simply a text file either written by the developer or automatically generated by Visual C++, or whatever IDE you happen to be using. Your script file should have the file extension .rc. Most of a script file is taken up by lines which define or specify the resources to include. The simplest of these lines is used by several resource types, and looks like this:
[identifier]  [resource type]  [filename]
The identifier can be one of two things: a string representing the resource, or a numeric constant that's #defined in a header file meant to accompany the resource script file. If you use numeric constants, which is usually a good idea, you can use the #include directive in your script file to include the header that corresponds to it. You can also use C-style comments to make things a little easier to understand. That said, here's what a very simple resource script file might look like:

#include "resource.h"

// icons
ICON_MAIN     ICON    myicon.ico

// bitmaps
IMG_TILESET1  BITMAP  tileset.bmp
IMG_TILESET2  BITMAP  tileset2.bmp


That's not too bad, right? There's one thing that can be confusing, though. Just by looking at my brief example, you can't tell if ICON_MAIN and IMG_TILESET are meant to be strings or numeric constants. The file would appear the same no matter which case were true. At compile time, your compiler will look at the identifiers you're using and search through your header files looking for their definitions. If no matching #define statements are found, it's assumed that you're using string identifiers.
Don't worry about the actual lines themselves just yet; I'll explain each type of entry when I get to that particular resource. If you don't want to bother with resource scripting at all, you can just insert the resources from your IDE (in Visual C++, go to "Resource..." under the Insert menu) and a resource script will be generated automatically. I prefer to do it myself with good old Notepad, but don't ask me why because I can't think of a good reason. :) Now that you know the basics of creating a resource script, let's get started on the specific resource types.

Icons and Cursors
Most of the Windows programs you use every day have their own icons built in, and now you know how it works: they're simply resources included in the EXE file. Custom cursors that are used by those programs are also included as resources. You've already seen an example of the script line that includes an icon resource, and the line for cursors is very similar. Here they are:
[identifier]  CURSOR  [filename]
[identifier]  ICON    [filename]
After adding a line such as this to your script file -- make sure to include the script file in your project -- the icon or cursor specified by [filename] will be included as a resource in your EXE file. That's all there is to it! You can use any icon/cursor editor to generate the files you want to include. I use the one that's included in Visual C++.
Including the resources doesn't do a whole lot for your program, though, because you don't know how to use them yet! To get an idea for how icon and cursor resources are utilized in a program, let's revisit the window class we developed in the last article:


WNDCLASSEX sampleClass;                                          
// declare structure variable

sampleClass.cbSize =        sizeof(WNDCLASSEX);                   // always use this!
sampleClass.style =         CS_DBLCLKS | CS_OWNDC |
                            CS_HREDRAW | CS_VREDRAW;              // standard settings
sampleClass.lpfnWndProc =   MsgHandler;                           // message handler function
sampleClass.cbClsExtra =    0;                                    // extra class info, not used
sampleClass.cbWndExtra =    0;                                    // extra window info, not used
sampleClass.hInstance =     hinstance;                            // parameter passed to WinMain()
sampleClass.hIcon =         LoadIcon(NULL, IDI_WINLOGO);          // Windows logo
sampleClass.hCursor =       LoadCursor(NULL, IDC_ARROW);          // standard cursor
sampleClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);  // a simple black brush
sampleClass.lpszMenuName =  NULL;                                 // no menu
sampleClass.lpszClassName = "Sample Class"                        // class name
sampleClass.hIconSm =       LoadIcon(NULL, IDI_WINLOGO);          // Windows logo again


You remember this, don't you? The hIcon field specifies the icon to be used to represent the program, and the hIconSm field is the icon used on the Start Menu and the window's title bar. The hCursor field sets the cursor to be used when the mouse is within the boundaries of the window you create. I promised you we'd take a look at the functions used to fill these fields a little more closely, so here are their prototypes:

HICON LoadIcon(
    HINSTANCE hInstance,  // handle to application instance
    LPCTSTR lpIconName    // icon-name string or icon resource identifier
);

HCURSOR LoadCursor(
    HINSTANCE hInstance,   // handle to application instance
    LPCTSTR lpCursorName   // name string or cursor resource identifier
);


The return type is a handle to the cursor you're loading. The parameters are very straightforward:
HINSTANCE hInstance: This is a handle to the instance of your application. To load resources from your program, just pass the HINSTANCE that is passed to your WinMain() function when the program is executed. To use standard Windows resources like we did in the window class above, set this to NULL.
LPCTSTR lpIconName, lpCursorName: This is a string identifier that identifies the resource you want to load. If your script file refers to resources by string, simply pass the string. But if you're using numeric constants, the Windows header

Page : 1 Next >>