Win32 API programming with C - Using resources

Resources in Win32 are predefined, application-defined data that the system stores in executable files. These can include various types of data such as icons, bitmaps, strings, menus or dialog box templates. This article will guide you through the process of adding, using, and managing these resources in a C program.

Define resources

The first step is to define your resources in a resource script file .rc. This file is a plain text file where you declare your resources and assign them unique identifiers. Resource Compiler (RC) converts resource script files into binary resource files .res, which are then linked into the application's executable.

Let's add an icon four our app and also let's add the menu that we programmatically created in the last article using resource files.

For this we define the following resource script MyApp.rc:

#include "resource.h"

IDI_MYICON ICON "appicon.ico"

IDR_MYMENU MENU
BEGIN
    POPUP "File"
    BEGIN
        MENUITEM "About",                       ID_FILE_ABOUT
        MENUITEM "Exit",                        ID_FILE_EXIT
    END
END

Visual Studio has a visual resource editor which allows you to create resources without manually editing this file but sometimes editing it is the only way to go, especially if your compiler has no visual editor.

The resource.h file contains the definitions of the resource identifiers used in the .rc file:

#define IDR_MYMENU                      101
#define IDI_MYICON                      102
#define ID_FILE_ABOUT                   40002
#define ID_FILE_EXIT                    40003

Compile resources

Use the Resource Compiler to compile the .rc file into a .res file. This can typically be done using a command like:

rc /fo MyApp.res MyApp.rc

Link the compiled .res file to your application. If you are using a command-line compiler like GCC, the linking step might look like this:

gcc -o MyApp.exe MyApp.obj MyApp.res

Load and use resources

In our C code we can use Win32 API functions to load and use the resources. When registering our window class we can load the app icon and the menu that we just defined like this:

//Step 1: Register the Window Class
wc.cbSize         = sizeof(WNDCLASSEX);                                                                   
// ...                                                                               
wc.hIcon         = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON));                                                                        
wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MYMENU);                                                                                          
wc.hIconSm         = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON), IMAGE_ICON, 32, 32, 0);