Character Strings and Memory Space

Character string resources usually save memory space, but the amount of space saved depends on how efficiently they're used. When the RC.EXE resource compiler adds strings to the .EXE file, the strings are grouped into different segments depending on the ID numbers of the strings. Each segment contains a maximum of 16 strings. Strings with ID numbers from 0 to 15 are stored in one segment, from 16 to 31 are in another, and so forth. Because of this grouping into segments, your .EXE file will be shorter if you use consecutive numbers for your string IDs.

When you use LoadString to copy a string resource into memory, however, Windows loads the entire segment (containing up to 16 strings) into memory as a resource. Windows then also copies the content of the string specified in the LoadString call to a buffer in your program's data segment. So when string resources are loaded into memory, they initially occupy less memory if you do not use consecutive numbers for the string IDs. Probably the worst way to use string resources is to load all the strings into separate global static arrays during program initialization in WinMain. If you do that, you don't use any less space than if you had included the strings in your C source code. In fact, you'll use more space, because you'll set the size of these arrays somewhat larger than the actual string lengths. Here are some general rules for using string resources:

Assign string ID numbers according to logical groupings. For instance, if five strings are involved in one section of your program and six strings are involved in another section, you might use ID numbers 0 to 4 for the first group of strings and 16 to 21 for the second group.

Whenever possible, load the strings into automatic local variables within functions, thus freeing up the space when the function is exited. (The OkMessage function shown above uses this approach.)

Alternatively, reuse a single static array for loading strings.

Here's an example of the last approach. Let's assume that your program never requires more than one string at a time. You can define a function that loads the string and returns a pointer to a static variable containing the string:

char *String (WORD wID)

{

static szBuffer [256] ;

LoadString (hInst, wID, szBuffer, 255) ;

return buffer ;

}

If you want to use DrawText to display the string with ID number 45, you use this statement:

DrawText (hdc, String (45), -1, &rect, DT_LEFT) ;

Each call to String destroys the contents of the static buffer. If you require access to (for example) three strings at one time, you can modify String as follows:

char *String (WORD wID, short n)

{

static szBuffer [3][256] ;

LoadString (hInst, wID, szBuffer [n], 255) ;

return szBuffer [n] ;

}

When you call String now, you pass an ID number and a second parameter that is either 0, 1, or 2.