Compiling and Binding Resources


Modern applications separate the visual aspects of an application from the code. The means by which this is achieved is resources. These resources are coded in a resource file (suffix .rc) and compiled using a separate resource compiler into object format (suffix .res). The resource compiler is rc.exe; although, the resource compiler is also built into Visual Studio.

A .res file contains resources in binary format. The resources that may be compiled are:

The resource compiler recognises certain C preprocessor directives including:

C and C++ style comments are also recognised. Unfortunately, C++ constants in the form of enumerations are not recognised by the resource compiler.

Icons and Cursors

By way of an example of resources, the program of this section makes use of an icon and a cursor. The resources that are used are shown below.

An icon
A cursor

The output of this program is shown below.

The full source code of the resource specification is shown below.

// win+ -- resource_1.rc -- icon and cursor Demonstration Program no. 1

#include "resource_1.h"

FrameIdentity ICON   "resource_1.ico"
FrameIdentity CURSOR "resource_1.cur"

STRINGTABLE
{
 FrameIdentity, "icon and cursor Demonstration"
}

An icon may be loaded and passed when registering the window class. Also passed is a cursor. The main routine is shown below.

int __stdcall WinMain(handle module_handle,
                     handle Reserved,
                     character* command_line,
                     int show_command)
{
 window_class<character> wclass;

 wclass.style     = class_style::horizointal_redraw | class_style::vertical_redraw;
 wclass.procedure = client;
 wclass.Extra     = 0;
 wclass.window    = 0;
 wclass.module    = module_handle;
 wclass.icon      = load_icon(module_handle,(const character*)FrameIdentity);
 wclass.cursor    = load_cursor(module_handle,(const character*)FrameIdentity);
 wclass.brush     = (handle)(system_color::window+1);
 wclass.name      = name;

 atom nameAtom = register_class(&wclass);

 handle window_handle = create_window((const character*)nameAtom,
                                    resourceString(FrameIdentity));

 show_window(window_handle,show_command);

 queue queue_message;
 while (get_message(&queue_message))
  {
   translate_message(&queue_message);
   dispatch_message(&queue_message);
  }

 return queue_message.parameter1;
}

The icon is used later to paint the background of the client window - as shown below.

case message::paint:
 {
  paint paint_struct;
  handle device_context = begin_paint(window, &paint_struct);

  handle IconHandle = get_class_pointer(window,class_offset::icon);

  for (int y=heightOfIcon; y<height_of_client; y += 2*heightOfIcon)
   for (int x=WidthOfIcon; x<width_of_client; x += 2*WidthOfIcon)
    draw_icon(device_context,x,y,IconHandle);

  end_paint(window,&paint_struct);
 }
 break;

The handle of the icon of a window is held in the class memory associated with the window at offset class_offset::icon. This icon is the one used to paint the window as shown in the code above.

Icons Resources in Detail

Associated with the application of this section are two files containing an icon and a cursor resource - these are: Resource1.ico and Resource1.cur. These resources may be created via an image editor. An icon resource file may contain several bitmaps for a given size - for different display resolutions. For a given display resolution, an icon comes in two different sizes, standard and small. For VGA resolution, standard icons are 32x32 pixels and small icons are 16x16 pixels. Small icons are used:

Large icons are used on the desktop. The size of an icon may be queried via the system metrics system_metric::IconWidth and system_metric::Iconheight. The system metrics system_metric::small_iconWidth and system_metric::small_iconheight may be used to determine the dimensions of small icons for the resolution of the system currently in vogue. Similarly, the system metrics system_metric::CursorWidth and system_metric::Cursorheight may be used to ascertain the dimensions of cursors for the current display resolution. The system is able to create a small icon from a large icon by dropping every second row and column.

An individual icon actually consists of two bitmaps -

  1. a monochromatic mask bitmap and
  2. a monochromatic or color bitmap image.

Of course, icons are always rectangular, but having a mask bitmap allows icons to appear as non-rectangular shapes. The mask bitmap allows for part of the background of the icon to be visible. An icon can also contain a portion which inverts the background.

Icons may also be loaded via the function load_icon. The line within the resource file that declares the icon is shown below.

FrameIdentity ICON Resource1.ico

where in this case, FrameIdentity was declared in the header as:

#define FrameIdentity 10

In this example, the identity of the icon is a numeric value. Icons may also be declared with string identities as:

myicon ICON iconfile.ico

where myicon is a string value. When this is the case, the icon may be loaded as follows.

handle icon = load_icon(module,(int)"myicon");

When a string is being used to identify the icon, the resource compiler converts the string to upper case - so the case that is used in the name is irrelevant. The approach of naming a resource using an integer identity is the preferred approach. A system supplied icon may also be loaded via a call to the function load_icon with a zero module handle being specified.

Cursors

A cursor may be defined in a resource file as shown below.

cursor_name CURSOR filename.cur

Like icons, the name of the cursor ('cursor_name') may be either a string name or an integer resource identity. A cursor resource may be loaded through the function load_cursor.