Resource Compiler Manual

by Jeremy Gordon

A "Go" development tool:
see http://www.GoDevTool.com

Introduction
Starting the Resource Compiler
Directives (eg. #define,#if,#include)
Other symbols
Numbers
Arithmetic
Strings and String Manipulation
Windows character set
Raw data resources (eg. cursor,bitmap,RCDATA etc)
Stringtable resource
Versioninfo resource
Accelerators resource
Menu resource
Dialog resource
Version and characteristics
Language
Capitalisation of nameIDs and types
Legal stuff

Introduction

This document assumes that the reader has some knowledge of resources, what they are and how they work.

This document is intended for use with the GoRC resource compiler. There are some slight differences in the permitted syntax between the Microsoft Resource compiler and GoRC. In general GoRC will accept all RC source files that the Microsoft Resource compiler will accept but is slightly more flexible in its syntax.

RC source files (those with an ".rc" extension) should be text without formatting codes, other than carriage return, linefeed or tabs, such as produced by most simple text editors. More sophisticated word processors can also produce such files if they are instructed to produce TXT files, ASCII or ANSI files.

The resource script and include files can be in Unicode format. If so, GoRC expects a Byte Order Mark (BOM). GoRC can read the UTF-8 Unicode format with BOM, or the UTF-16LE Unicode format with BOM.

GoRC can make two types of binary resource files from a resource script. It can make an OBJ file in COFF format, which is suitable for linking with other OBJ files to produce the final EXE or DLL. It can also produce a RES file, which is an intermediate file in binary format. GoRC can also convert a RES file to an OBJ file.
The OBJ file made by GoRC can either be in Win32 format (the default) or Win64 format if you specify the /machine AMD64 or /machine X64 switch in the command line.

Here are the syntax rules which are used in this reference:-

Normal text shows words as they actually appear in your source code.
Italic text describes only the type of entry in your source code- look for the description to see what can be put there.
[Text in square brackets means that the material is optional].



Starting the Resource Compiler
Back to top

The command line syntax is:-

GoRC [command line switches] filename[.ext]

Where,

filename is the name of the resource script

Command-line Switches
/h or /? help
/d define a word
/o create OBJ file
/r create RES file
/fo specify output file
/machine AMD64 or
/machine X64 object output file will be in 64-bit format
/ni no information messages
/ne no error messages
/nw no warning messages
/no no output messages at all

Input and Output files
The default action of GoRC is RC > RES and OBJ
If no extension is given in the command line and GoRC cannot find filename.RC then it looks for filename.RES. If found, this results in the action RES > OBJ.

The default action can be overridden to achieve RC > RES in the following ways:-

The default action can be overridden to achieve RC > OBJ in the following ways:- Using the /fo switch and giving a filename with the OBJ extension

You can ensure the action is RES > OBJ by giving the input file with the extension RES.

By default, the output filenames will be the same as those of the input file, but you can use the /fo switch to change this. This is used as follows:-

By default, the output files will be placed in the same directory as the input file. You can specify a full path for the output files when using the /fo switch.
You can enclose the filenames in quotes to permit the use of filenames with spaces and other unusual characters.

GoRC can work with Unicode input and output filenames, but the extensions used must be as set out above.

Errors and Warnings
Errors will cause the Resource Compiler to stop and no output files will be made. The console then shows the nature of the error and where it occurred. (unless the command line switch /ne has been specified). The Resource Compiler will also return with a code of 1, which will be likely to halt the build process if you are using a make file.

Warnings do not stop the Resource Compiler. A warning will be given (unless the command line switch /nw has been specified) if:-

A warning will also be given if an expression has been defined more than once in the command line, resource script or in a non ".h" include file. This is because it would be unusual to define an expression more than once and it may be that this is a programming error. It is perfectly permissible to cancel a previous definition using #undef so that the expression can be redefined. In that case no warning is given. Also, because the Resource Compiler does not always need to look into ".h" files to evaluate an expression, and because it is presumed that such ".h" files ought to be free of such errors, no check of previous definitions in header files is carried out.



Directives
Back to top

Directives are words in the resource script which give instructions to the Resource Compiler.

There are 3 types of directives:-

Defining directives
Include directive
Conditional directives

The Defining Directives

Evaluating types
These are #define macros which evaluate to a number or to a quoted string

#define name value

From this point when name is encountered in the resource script it is replaced by value

Examples

#define IDC_BUTTON 0x20
#define DLGCONTROL 0x20 | 0x40
#define DLGTEXT "Hello world"
#define OTHER DLGCONTROL + IDC_BUTTON
#define WINNT

(this sets the name WINNT to a value of 1, that is, TRUE)

The RC compiler automatically defines RC_INVOKED, so that you can use the conditional directives to skip over unwanted resource script text Example
#ifndef RC_INVOKED
skipped text
#endif


You can define a name from the command line:-

Examples
GoRC /d WINVER=400h mainres
This compiles the resource script mainres, on the basis that WINVER is equal to hex 400 throughout.

GoRC /d WINNT mainres
This compiles the resource script mainres, on the basis that WINNT has the value of 1 (that is, TRUE)

GoRC /d WINNT=55h /d good=0x44 mainres
Example of more than one definition.

GoRC /d WINNT=330, good=0x44 mainres
Example of more than one definition using comma.

#undef name From this point in the resource script any earlier value for the name given by a #define is no longer used

Examples
#undef IDC_BUTTON
#undef DLGCONTROL


Non evaluating types
These are #define macros which do not evaluate to a single result

#define name value1 value2 value3 ……

From this point when name is encountered in the resource script it is replaced by value1 value2 value3 Example
#define GRASSHOPPER Deep Influences On Us
#define FILENAME README
#define EXTENSION TXT
FILENAME.EXTENSION (becomes README.TXT)


Macros with arguments
These are #define macros which use the arguments supplied when the macro is used

Syntax for the macro in which the arguments are declared:-
#define  name(arg1,arg2,arg3….)   use of arguments
Syntax to supply the arguments:-
name(arg1,arg2,arg3….)

Examples
#define NIM($a,$b) $a+$b
NIM(23,45)
(result is 68)
#define NIMROD($a,$b) #$a
NIMROD (HANG,OVER)

(result is "hang")

Note that the number of arguments which are supplied must exactly match the number of arguments declared, but they need not all be used. When an argument is declared there must be no space between the macro name and the arguments, but there can be spaces when the argument is supplied or used.

The Include Directive

#include path\filename

This will cause the Resource Compiler to load and look at the specified file if necessary.

path\filename can be either:-

a quoted string
a non-quoted string
a string in less-than and greater-than characters
The Resource Compiler will look for the file using the path specified. If no path is specified it will look in the current directory. If the file is not found it will look for it in the path given by the INCLUDE environment string. You can set the INCLUDE environment string using the SET command in the MSDOS window, or by calling the SetEnvironmentVariable API. You can also use control panel, system, advanced, environment if your operating system will permit this, followed by a reboot. Note: there may be a different environment string for each folder or sub-folder. Ensure the environment string you wish to use is in the current directory.

To the Resource Compiler there are two types of #include files.

There are "header" files, with the file extension ".h". These files are not treated as part of the resource script, but are regarded only as containing defining directives. This enables the Resource Compiler to work more quickly because it will not bother to search an ".h" file unless it has an expression which it is trying to evaluate. Any ordinary resource script statements in an ".h" file will be ignored by the Resource Compiler.

Note that the Resource Compiler is itself aware of most if not all of the usual styles and expressions used in a resource script. For this reason it will not normally be necessary to include any header files. However you will need to define your own expressions and identifiers if you wish to use those.

The second type of #include files are non ".h" files. These are treated as part of the resource script itself by the Resource Compiler. When an #include directive if found for a non ".h" file, the Resource Compiler will divert its attention to the #include file and when it has finished looking at that file it will return to the original script where it left off.

You can nest #include files but it is probably good practice to avoid this as far as possible.

Definition Priority
A #define directive in an ".h" include file is regarded as of lower priority than a #define directive in the command line, resource script or in a non ".h" include file. Therefore if there is any conflict between the #defines, the #define in the ".h" include file will be ignored.

The Conditional Directives

With these directives you can select at compile-time that part of the resource script or of the defining directives which you want to be compiled. This may be useful if, for example, you want to make different versions of your program from the same resource script.

The syntax of the basic structure of a conditional directive in its simplest form is as follows:-

#if condition
text A
#endif

Here if the condition is TRUE text A will be compiled. If, however, the condition is FALSE, the compiler will jump over text A and will continue compiling from the #endif.

You can add something to do if the condition is FALSE as follows:-

#if condition
text A
#else
text B
#endif

Here if the condition is TRUE, text A will be compiled, but text B will not be compiled.

If, however, the condition is FALSE, text A will be jumped over but text B will be compiled.

The #endif indicates the end of the conditional frame, so that all text after that will be compiled.

The #else statement must always be next before the #endif.

You can add a further condition to the frame:-

#if condition1
text A
#elif condition2
text B
#endif

Here if condition1 is TRUE, text A will be compiled, but text B will be jumped over and compilation will continue from the #endif. If, however, condition1 is FALSE, text A will be jumped over to the #elif when condition2 will be tested. If then condition2 is TRUE, text B will be compiled. "#elif" is the same as "#elseif".

Adding the #else to the above conditional frame produces:-
#if condition1
text A
#elif condition2
text B
#else
text C
#endif

Here if condition1 is TRUE, text A will be compiled, but text B and text C will be jumped over and compilation will continue from the #endif. If, however, condition1 is FALSE, text A will be jumped over to the #elif when condition2 will be tested. If then condition2 is TRUE, text B will be compiled, and text C will be ignored; if, however condition2 is FALSE text B will be jumped over to the #else and text C will be compiled.

You can have as many #elifs as you like in each conditional frame, but there can only be one #else per frame, and each #if must have a corresponding #endif. Some programmers nest the conditional frames, but this can become very confusing and may not be good programming practice. If this is done it is recommended that you label each #endif with a comment so that you can see to which #if it refers.

Types of #if statements

#ifdef expression

where expression is a word which may be defined in the resource script or in a header file. This statement returns TRUE if the expression is defined and FALSE if it is not defined. expression must be a word and not a number nor a quoted string.

#ifndef expression as above but this statement returns FALSE if the expression is defined and TRUE if it is not defined.

#if 0 this statement always returns FALSE and so it can be used to jump over text which ought to be ignored

#if expression1 relational-operator expression2 expression1 must be a word which is defined elsewhere in the file, in an include file or in the command line. It cannot be a number.

the relational operator can be one of the following:-
>= greater than or equals
<= less than or equals
== equals
= equals
!= not equal
> greater than
< less than

expression2 can be a number or a word which is defined elsewhere in the file, in an include file or in the command line, which evaluates to a number.

For example, #if WINVER>=400h

will return TRUE if WINVER is defined as 400h or more.

#if ! this reverses the result of the condition, so that (for example) #if!0 would return TRUE

#if not same as #if !

Other symbols
Back to top

These are some other symbols which may be used in the resource script or a header file and which have a special meaning to the Resource Compiler.

; or // a comment line - everything after this to the end of the line is ignored
;;......;; or
/*.........*/ a continuous comment - everything between the marks is ignored
\ (at the end of a line or just before a comment) - the material is continuing on the next line (cannot be used in quoted strings or filenames)
{ same as BEGIN
} same as END
-number means the number is negative eg. -22h if a dword becomes 0FFFFFFDEh
~number means the number is inverted eg. ~22h if a dword becomes 0FFFFFFDDh
+ plus eg. 22h + 3h produces 25h
- minus eg. 22h - 3h produces 1Fh
| or ¦ bitwise OR eg. 22h | 3h produces 23h
& bitwise AND eg. 22h & 3h produces 2h
!value in arithmetic this causes the value to be inverted and then ANDed with the existing and is the same minus value
NOT value same as above

# in a #define macro, this causes quotes to be added to what follows
eg. #HELLO becomes "HELLO"
eg. #(MAJOR.MINOR) becomes "MAJOR.MINOR"

## in a #define macro, this joins two elements, removing all spaces in between
eg. PATCH ## WORK becomes PATCHWORK

(…..) in a #define macro the material within the parentheses is evaluated first

Numbers
Back to top

The Resource Compiler recognises the following types of numbers, for example:-

6666666h a hex number
3434343H a hex number
9999999D a decimal number
22553388d a decimal number
34567789 a decimal number
0x456789 a hex number
456L specifies the number is to be recorded as a dword where otherwise it would be a word

Arithmetic
Back to top

The resource compiler can perform limited arithmetic on the following:-

identifiers, styles, flags and dialog and control positions and dimensions
defining directives
expressions in conditional directives

Examples of arithmetic
66h+2h CURSOR first.cur
#define BELLS 200h | 22h + 1h
BELLS+1000h ICON icon1.ico
BELLS-1h ICON icon1.ico
STYLE WS_TABSTOP | WS_GROUP | WS_DISABLED
DIALOG 0x34+2,0x20,0x300-0x60,400-200


The Resource Compiler cannot resolve more complex formulae involving for example logical operators, decimal points, multiplication or division.

Strings and String Manipulation
Back to top

Quoted strings in the stringtable resource and in all text for dialogs and menus must be kept in the binary resource files and in the EXE in Unicode. If the resource script is an ANSI text file, however, the strings will be in ANSI characters. In that case the Resource Compiler converts them to Unicode using the API MultiByteToWideChar. This API uses the current codepage for this conversion, so you need to ensure that at compile time your machine is set to use the same codepage as was used when the source script was made.

If the resource script is a Unicode file, then codepages are not used: the strings are used as they appear in the resource script.

The strings are put in the RES file (or OBJ file) in Unicode whether or not you use the "C" style Unicode indicator L"string". The Resource Compiler regards the L"string" indicator as implicit for these types of strings. So there is no need to use that indicator in your resource script (unless you want to insert special Unicode characters - see below).

There is no implicit L"string" indicator for quoted strings in the raw data resources (eg. RCDATA). Therefore in an ANSI file such strings are not converted to Unicode unless L"string" is specified.

All quoted strings may contain escape sequences which are dealt with in a special way by the Resource Compiler:-

& in menu title strings this causes the system at run-time to create an accelerator for the menu item using the character following the ampersand. If you need an ampersand include it twice eg. &&.
"""" Double-up the quotation marks to retain them. For example """Hello there""" will be kept as "Hello there" and "He said ""Hello there"" quickly" will be kept as He said "Hello there" quickly.
"" an empty string (useful for example in static controls where the text is to be inserted during run-time later.
\t tab (converted to the 9h TAB character)
\a alert (converted to the 8h BELL character)
    (in menus this is used to align all the following text to the right)
\n new line (converted to the 0Ah LINEFEED character)
\r return (converted to the 0Dh CARRIAGE RETURN character)
\\ converted to one backslash only
\number see below
\other the backslash is regarded as an ordinary backslash

\number to produce a special character

In all quoted strings which are converted by the Resource Compiler you can have:-
\number
This then will cause the character represented by number to be inserted in the text
For example, "Copyright \251 2005" inserts a © symbol in the text.
Strange! The © symbol, as everybody knows, is ANSI value 169, or A9 in hex.

However, the Resource Compiler uses octal numbers in this feature rather than decimal, ie. all digits are to base 8. Why? This is simply to provide compatibility with existing resource scripts.

Sometimes \number can look rather odd. For example "The entrance fee was \4423", is converted to "The entrance fee was $23". Here the Resource Compiler does not try to find character 442 octal or 4423 octal because it knows that this value is too high. This works fine for characters above 38 octal, but for characters with values less than this, for example 12 octal which is the value 0Ah (linefeed) there could be confusion, for example "We found on average about\1223 flies in each of the soups". This should be written "We found on average about\01223 flies in each of the soups". This is because the Resource Compiler will only look at 3 octal digits and no more, so it stops after the \012 (linefeed), and the value 23 is kept in the text properly. Of course you could use \n instead to ensure there is no chance of confusion and this would be better.

\number in hex rather than in octal

You can also use hex values when entering \number, by including x after the backslash. For example the hex version "Copyright \xA9 2005" is the same as "Copyright \251 2005" which is the octal version. Again the Resource Compiler will not look beyond the second hex digit for the value, so ensure that where small values are used you insert the zero if there is any danger of confusion. For example in "The capacitor had a value of 3\xb5farads" the Resource Compiler does not take the hex number b5f, but looks only at b5 hex. However, in the string "It returned to Earth\x0aafter 44 years with 5 more people on board", the zero is required to avoid using the hex number aa as the special character.

\number in Unicode strings

The Resource Compiler looks at up to four hex digits in \number if the string is expressly declared to be a Unicode string. You can do this by using the "C"-style indicator L"string" for the string. So, for example to create a string for a dialog button which displays a Shekel you would use the following string:-

L"\x20AA"

This creates the Unicode special character 20AAh (the Shekel sign).

You would not need to do this if you used Unicode format files, since you could display the Shekel normally and it would be coded properly by the Resource Compiler.


The Windows Character Set

Back to top

The character set used when the string is written to the screen by the menu, dialog or other method, depends on which character set is in use in the computer running the EXE. For computers used in English this is usually the Windows Character Set. A table of octal values may be difficult to find so one is provided here on the next page for your use, and on the following page a table of hex values.




The Windows Character Set and octal values

Space!"#$% &'()*+ ,-
404142434445 464750515253 5455
./01234 56789:;
565760616263 646566677071 7273
<=>?@AB CDEFGHI
74757677100101 102103104105106107 110111
JKLMNOP QRSTUVW
112113114115116117 120121122123124125 126127
XYZ[\]^ _`abcde
130131132133134135 136137140141142143 144145
fghijkl mnopqrs
146147150151152153 154155156157160161 162163
tuvwxyz {|}~
164165166167170171 172173174175176177 200201
ƒˆ ŠŒ
202203204205206207 210211212213214215 216217
˜šœ
220221222223224225 226227230231232233 234235
Ÿ¡¢£¤ ¥¦§¨© ª«
236237240241242243 244245246247250251 252253
¬®¯° ±²³´ µ·¸ ¹
254255256257260 261262263264265 266267270271
º»¼½ ¾¿ÀÁ ÂÃÄÅ ÆÇ
272273274275276277 300301302303304305 306307
ÈÉÊË ÌÍÎÏ ÐÑÒÓ ÔÕ
310311312313314315 316317320321322323 324325
Ö×ØÙ ÚÛÜÝ Þßàá âã
326327330331332333 334335336337340341 342343
äåæç èéêë ìíîï ðñ
344345346347350 351352353354355 356357360361
òóôõ ö÷øù úûüý þÿ
362363364365366367 370371372373374375 376377

The Windows Character Set and hex values

Space!"#$% &'()*+ ,-
202122232425 262728292A2B 2C2D
./01234 56789:;
2E2F30313233 343536373839 3A3B
<=>?@AB CDEFGHI
3C3D3E3F4041 424344454647 4849
JKLMNOP QRSTUVW
4A4B4C4D4E4F 505152535455 5657
XYZ[\]^ _`abcde
58595A5B5C5D 5E5F60616263 6465
fghijkl mnopqrs
666768696A6B 6C6D6E6F7071 7273
tuvwxyz {|}~
747576777879 7A7B7C7D7E7F 8081
ƒˆ ŠŒ
828384858687 88898A8B8C8D 8E8F
˜šœ
909192939495 969798999A9B 9C9D
Ÿ¡¢£¤ ¥¦§¨© ª«
9E9FA0A1A2A3 A4A5A6A7A8A9 AAAB
¬®¯° ±²³´ µ·¸ ¹
ACADAEAFB0 B1B2B3B4B5 B6B7B8B9
º»¼½ ¾¿ÀÁ ÂÃÄÅ ÆÇ
BABBBCBDBEBF C0C1C2C3C4C5 C6C7
ÈÉÊË ÌÍÎÏ ÐÑÒÓ ÔÕ
C8C9CACBCCCD CECFD0D1D2D3 D4D5
Ö×ØÙ ÚÛÜÝ Þßàá âã
D6D7D8D9DADB DCDDDEDFE0E1 E2E3
äåæç èéêë ìíîï ðñ
E4E5E6E7E8 E9EAEBECED EEEFF0F1
òóôõ ö÷øù úûüý þÿ
F2F3F4F5F6F7 F8F9FAFBFCFD FEFF



Resource statements

Resource statements are the instructions to the Resource Compiler which contain the information from which the output file is actually made. They fall into four main categories:-

Raw data resource types (a) taking data from a file
Back to top

With these resources the Resource Compiler merely takes raw data from an input file and adds it to the output file (sometimes with some extra processing). Hence the data from these files makes its way to the EXE, when the file is linked, for use during run-time. This is a convenient way to keep the data from such files in the EXE. An alternative would be to ship the individual files with the product for loading at run-time, but this runs the risk that those files may get lost.

The data (as raw data) can be used at run-time by calling the FindResource and LoadResource APIs, but there are some specific APIs which also provide manipulation of the data. The various raw data resource types which work using files, their resource type numbers, and the specific API (if any) to load them during run-time are:-

CURSOR 1 LoadCursor or LoadImage
BITMAP 2 LoadBitmap or LoadImage
ICON 3 LoadIcon or LoadImage
FONT 8 no longer in use
RCDATA 10
MESSAGETABLE 11 FormatMessage
PLUGPLAY 19
VXD 20
ANICURSOR 21
ANIICON 22
HTML 23
MANIFEST 24
User-defined resource

The User defined resource is a resource holding raw data only, which is of the type defined by the user. It can be defined by name, for example, MyRes, or by number, which can be any 16-bit number above 0FFh. The numbers 1 to 0FFh are reserved for the system defined resources.

The general syntax for these resource types in the resource script (using CURSOR as an example) is:-

nameID CURSOR filename

Where, in the normal case,

nameID can be either:-

a 16-bit number of value 1 to 7FFFh
an expression which evaluates to that number
a name (except for FONT)

A FONT resource cannot identified by name, so in the case of a FONT,

nameID can be either:-

a 16-bit number of value 1 to 7FFFh
an expression which evaluates to that number

filename can be either:- a quoted string
a non-quoted string
a string in less-than and greater-than characters
unless the file is in the current directory, the full path should be given Examples
2 CURSOR happy.cur
0x6666 BITMAP c:\bitmaps\happy.bmp
MyIcon ICON "happy.ico"
#define ID_MINE 22
ID_MINE ICON <happier.ico>
44h RCDATA happy.txt
ID_MINE RCDATA happier.txt
1 MANIFEST "YourApp.manifest"
788h MYRES happier.txt      ;(a user-defined resource)
MY_CAT WAVE sounds/cat.wav  ;(a user-defined resource)
788h 100h happier.txt       ;(a user-defined resource)

Raw data resource types (b) taking data from resource script

These resources allow you to insert raw data into the EXE via the binary resource file. The Resource Compiler makes no alteration to the raw data. Unless use is being made of the ability of the system to distinguish between resources of different languages, assembler programmers would probably not find much use for this as it is so simple to use the data segment to keep data..

The data (as raw data) can be used at run-time by calling the FindResource and LoadResource APIs.

This type of resource is RCDATA (type number 10) when used with BEGIN and END, and not with a filename. Alternatively you can choose any name for the resource in which case it works the same way as RCDATA except that the resource type has a name. This is called a user-defined resource. Alternatively you can also simply provide any 16 bit number above 0FFh for the resource type.

The syntax for RCDATA used in this way is:-
nameID RCDATA
[defining-statements]
BEGIN
raw-data
END

Or, in the case of a user-defined resource:-
nameID type
[defining-statements]
BEGIN
raw-data
END

Where,

nameID can be either:-

a 16-bit number of value 1 to 7FFFh
an expression which evaluates to that number
a name

defining-statements need not be present, but can be either:- a VERSION statement
a CHARACTERISTICS statement
a LANGUAGE statement

see below for details

type can be either:- a 16-bit number greater than 0FFh
an expression which evaluates to a 16-bit number greater than 255
a name in characters

raw-data can be either:- an ANSI quoted string
a Unicode quoted string starting L"
a numerical value stored as a word
a numerical value stored as a dword (ending in L)

Examples
0x3333 RCDATA
BEGIN "Hello world"
"Hello world (zero terminated)\0"
L"A Unicode version of the above\0"
0x9999  ;hex number stored as a word
END

MyRes RCDATA
BEGIN

1034  ;decimal number stored as a word END

MyRes MyResType
BEGIN

10456L  ;decimal number stored as a dword
1234L,56666L,99999L  ;decimal numbers stored as dwords
END

34h 100h
BEGIN

33hL,34hL,35hL,36hL  ;hex numbers stored as dwords
0x37L,0x38L,0x39L,0x40L  ;C-style hex numbers stored as dwords
END




The STRINGTABLE resource
Back to top

The STRINGTABLE resource enables strings to be kept in the EXE to be recovered when needed at run time. For assembler programmers this would be an alternative to keeping the strings in the data segment. Even if you need to use Unicode strings, if you are using GoAsm as your assembler it is usually easier to keep the strings in data rather than to use the STRINGTABLE resource.
If the source file is in ANSI format, strings in the STRINGTABLE resource are automatically converted to Unicode by the Resource Compiler, so there is no need to use the "C" style Unicode indicator L"string". The Resource Compiler regards the L"string" indicator as implicit. The conversion is carried out using the API MultiByteToWideChar. This API uses the current codepage for this conversion, so you need to ensure that at compile time your machine is set to use the same codepage as was used when the source script was made.
If the source file is in Unicode format, then no conversion takes place and codepages are not used: the strings are used as they appear in the resource script.

One reason why the assembler programmer might wish to keep strings in a STRINGTABLE resource rather than in the data segment would be to take advantage of the ability of the system to distinguish strings of different languages at run-time.

The strings are kept in blocks of 16 strings. Each block will have the same language and also the same upper 12-bits of the ID which was specified in the resource script. The least significant 4 bits are blanked out and are not be recorded because it is assumed that the IDs run in sequence in each block from 0 to 0Fh. To make this assumption valid, if the string IDs are not in sequence the Resource Compiler has to insert empty strings. To reduce space requirements, therefore, it is best to keep the identifiers sequential.

To recover one of the strings call LoadString giving the string identifier. It will then be copied into a buffer with a nul terminator.

The syntax for the STRINGTABLE resource is as follows:-

STRINGTABLE
[defining-statements]
BEGIN
stringID "string"
.........
END

Where,
stringID is

a 16 bit number which identifies the string
an expression which resolves to that number
"string" is a quoted string of not more than 4097 characters, or an expression which is defined elsewhere as a string.

If the string straddles more than one line the Resource Compiler inserts a space and a line feed character (ASCII 0Ah) at the line break and all leading spaces on the next line in your resource script are suppressed.

Information resource types

These types of resources are used to keep information about the EXE in a certain format, for use by tools or for information to the user.

There are two types of such resources.

Firstly DLGINCLUDE (resource type17) which contains a filename which is read by the Microsoft Dialog Editor. This filename is that of the include file containing definitions when making dialogs. This information is not actually kept in the EXE, and is disgarded by the linker.

Its syntax is:-
nameID DLGINCLUDE filename

Where,
nameID can be either:-

a 16-bit number of value 1 to 7FFFh
an expression which evaluates to that number
a name

filename can be either:- a quoted string
a non-quoted string
a string in less-than and greater-than characters
unless the file is in the current directory, the full path should be given



The VERSIONINFO resource
Back to top

Secondly, the VERSIONINFO resource (resource type 16), which is used to keep information about the version of the EXE, which may be required during its installation or if it is updated.

The version information can be retrieved in various ways using the APIs GetFileVersionInfo, GetFileVersionInfoSize, and VerQueryValue. Also it is the information which appears in the "Version" property sheet when looking at the "Properties" of an Executable file in Windows.

The syntax for this resource is:-

1 VERSIONINFO [fixed-info statements]
BEGIN
BLOCK "StringFileInfo" BEGIN BLOCK lang-charset
BEGIN
string-value statements
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation"
lang/char statements
END
END

Where,

fixed-info statements can be one or more of the following statements with data as in the following examples. The data is used by the Resource Compiler to fill a structure of 13 dwords which is kept in the binary resource file and therefore in the EXE file (the VS_FIXEDFILEINFO structure) FILEVERSION 3h,0Ah,0,3Dh
this value needs to be written as four 16-bit values which are in fact recorded as two dwords: in this example the first dword (most significant) is 3000Ah and the second dword (least significant) is 3Dh, producing a version value of 3000A 0000003Dh.
PRODUCTVERSION 6666h,0000h,0000h,7777h
defines a product version of 66660000 00007777h
FILEFLAGSMASK 3Fh
specifies which bits in the next parameter are valid
FILEFLAGS fileflags
which can be one or more of the following flags or values VS_FF_DEBUG (1= the file contains debugging information)
VS_FF_PATCHED (4= the version information has been changed from original shipping version)
VS_FF_PRERELEASE (2= the file is a development version only and not commercially available)
VS_FF_PRIVATEBUILD (8= the file was not built using standard release procedures)
VS_FF_SPECIALBUILD (20h= the file was built using standard release procedures but is a variation of the standard file of the same version number)

FILEOS fileos
where fileos specifies the operating system for which the file was designed and can be one of the following values VOS_UNKNOWN (value zero - unknown)
VOS_DOS (1000h= file designed for DOS)
VOS_NT (4000h= file designed for Windows NT)
VOS__WINDOWS32 (4= file designed for 32 bit Windows)
VOS_NT_WINDOWS32 (40004h= file designed for 32 bit Windows running under Windows NT)
FILETYPE filetype where filetype specifies the general type of the file and can be one of the following values VFT_UNKNOWN (value zero=unknown)
VFT_APP (1= it’s an application)
VFT_DLL (2= it’s a DLL)
VFT_DRV (3= it’s a device driver)
VFT_FONT (4= it’s a font)
VFT_VXD (5= it’s a virtual device)
VFT_STATIC_LIB (7= it’s a static link library)
FILESUBTYPE subtype where subtype specifies more information about the type of file, and if filetype is VFT_DRV can be one of the following values VFT2_UNKNOWN (value zero -unknown)
VFT2_PRINTER (1= it’s a printer driver)
VFT2_KEYBOARD (2= it’s a keyboard driver)
VFT2_LANGUAGE (3= it’s a language driver)
VFT2_DISPLAY (4= it’s a display driver)
VFT2_MOUSE (5= it’s a mouse driver)
VFT2_NETWORK (6= it’s a network driver)
VFT2_SYSTEM (7= it’s a system driver)
VFT2_DRV_INSTALLABLE (8= it’s an installable driver)
VFT2_DRV_SOUND (9= it’s a sound driver)
VFT2_DRV_COMM (0Ah= it’s a communications driver)
if filetype is VFT_FONT it can be one of the following values VFT2_FONT_RASTER (1= a raster font)
VFT2_FONT_VECTOR (2= a vector font)
VFT2_FONT_TRUETYPE (3= a TrueType font)
if filetype is VFT_VXD this value must be the virtual-device identifier included in the virtual-device control block

The names of the fixed-info statements are fixed and are used by the Resource Compiler to decide where in the VS_FIXEDFILEINFO structure to put the specified value. As you can see, certain values have definite meanings reserved by Microsoft, but there seems to be no reason why you cannot use your own values which may have a special meaning to your application.

lang-charset is a quoted string containing (in numbers) a hex number which gives the language and character set used in the string-value statements which follow. The most common value found here is "040904E4" meaning US English + Windows, multilingual character set

lang/char statements are two 16-bit numbers separated by a comma. The first represents a language and the second a character set supported by the application. If a lang/char statement is included in the VERSIONINFO resource, the system will initialise the "Version" property sheet found when looking at the "Properties" of the executable file, and will include a "Language" key. The most common value found is 0x409,1252 which is US English + Windows, multilingual character set, the latter being given in its decimal value, but 4E4h would do just as well

string-value statements are a series of statements containing two quoted strings with the following syntax:-

"name", "value"

"name" is a string which would be given to the API VerQueryValue in order to retrieve the value

The following strings are looked for by the system when showing the "Version" property sheet:-

"FileVersion", "FileDescription" and "LegalCopyright", and the value appears at the top of the property sheet adjacent to the words "File Version", "Description" and "Copyright" respectively.

Other strings appear in listboxes in the property sheet. You can use whatever string you like, although there if they are too long they are truncated in the property sheet and they always appear in alphabetical order.

You often see one of the following strings being used - "Comments" "CompanyName" "InternalName" "LegalTradmarks" "OriginalFilename" "PrivateBuild" "ProductName" "ProductVersion" "SpecialBuild"

"value" is a user defined value in a quoted string which corresponds to one of the standard strings and will be returned by VerQueryValue.

Example of a VERSIONINFO resource
1 VERSIONINFO
FILEVERSION 2,0,0,0
PRODUCTVERSION 2,0,0,0
FILEFLAGSMASK 0x0000003FL
FILEFLAGS 0x0000000BL
FILEOS 0x00010001L
FILETYPE 0x00000001L
FILESUBTYPE 0x00000000L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "MySoftware Company"
VALUE "Contact e-mail", "MySoftware@ether.com"
VALUE "FileDescription","MySoftware.Exe"
VALUE "FileVersion", "3.45"
VALUE "DevelopmentFile","Dev345.asm"
VALUE "LegalCopyright","Copyright\251 2005 Co"
VALUE "Resources made using","GoRC.Exe"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409,1252
END
END




Resources for the user-interface

These types of resources make it easy to create accelerators, menus, and dialogs - three basic ingredients for the user interface. In each case it is possible to use the APIs instead of using the resource file, but this is normally much less convenient, and no advantage can be taken of the system being able automatically to discriminate between menus and dialogs of different languages.

In order to use these resources, in a single language application a specific API is called to obtain a handle to the resource.

The five resource types under this heading, the resource type numbers and the APIs used to use the resources are:-

ACCELERATORS 9 LoadAccelerators
MENU 4 LoadMenu
MENUEX 4 LoadMenu
DIALOG 5 CreateDialogParam, DialogBoxParam
DIALOGEX 5 CreateDialogParam, DialogBoxParam


The ACCELERATORS resource
Back to top

The syntax for the ACCELERATORS resource is:-
nameID ACCELERATORS
[defining-statements]
BEGIN
event, result [,type/options]
...........
END

Where,
nameID can be either:-

a 16-bit number of value 1 to 7FFFh
an expression which evaluates to that number
a name

defining-statements need not be present, but can be either:- a VERSION statement
a CHARACTERISTICS statement
a LANGUAGE statement
see below for details

event specifies the keystroke which will cause result to be sent to the message loop of the process which loaded the accelerators. It can be either:- a single character enclosed in quotes eg. "a" meaning the key "a"
a single character preceded by a caret eg. "^A" meaning the key is a Crtl key (if ^ is used the character must be an upper case letter
a 16 bit number
an expression which evaluates to a 16-bit number. Commonly, the expressions which are used are the VK_ names listed in Winuser.h.

result can be either:- a 16-bit number
an expression which evaluates to a 16-bit number

type/options can be any of the following values, separated by commas:- ASCII (value zero, meaning that the event value refers to an ASCII character value)
VIRTKEY (value 1, meaning that the event value refers to a virtual key value)
(if neither ASCII nor VIRTKEY are specified, then ASCII is assumed)
SHIFT (4= event only occurs if Shft key is pressed)
CONTROL (8= event only occurs if Crtl key is pressed)
ALT (10h= event only occurs if Alt key is pressed)
NOINVERT (2= do not highlight a top level menu item if possible when an accelerator is used)

Example of ACCELERATORS resource
0x20 ACCELERATORS
BEGIN "N", 20h, CONTROL
"^A", 0x1111
"K", 0x2222
"k", 0x3333, ALT
98, 0x4444, ASCII
66, 0x5555, ASCII
"g", 0x6666
"G", 0x7777
"K", 0x2222, VIRTKEY
67, 0x5556, VIRTKEY
68, 0x5557, VIRTKEY, NOINVERT
VK_F1, 0x8888, VIRTKEY
VK_F2, 0x8889, CONTROL, VIRTKEY
VK_F3, 0x888A, SHIFT, VIRTKEY
VK_LBUTTON, 0x888B, ALT, VIRTKEY
VK_NUMPAD4, 0x888C, ALT, SHIFT,VIRTKEY
VK_SPACE, 0x888D, CONTROL, SHIFT,VIRTKEY
VK_END, 0x888E, ALT, CONTROL,VIRTKEY
END



The MENU resource
Back to top

The syntax for the MENU resource is:-
nameID MENU
[defining-statements]
BEGIN
MENUITEM "text", id [,type/state]
POPUP "text" [,type/state]
BEGIN
MENUITEM "text", id [,type/state]
END
MENUITEM SEPARATOR
...........
END

The syntax for the MENUEX resource is:-
nameID MENUEX [,helpID]
[defining-statements]
BEGIN
MENUITEM "text", id [,type/state]
POPUP "text", [id] [,type/state] [,helpID]
BEGIN

MENUITEM "text", id [,type/state] END
MENUITEM SEPARATOR
END Where, nameID can be either:- a 16-bit number of value 1 to 7FFFh
an expression which evaluates to that number
a name

defining-statements need not be present, but can be either:- a VERSION statement
a CHARACTERISTICS statement
a LANGUAGE statement
see below for details

"text" is a quoted string containing the text for the menu or popup item. It can contain \t which inserts a tab, or \a which aligns to the right all text which follows it. An ampersand tells the system to use the following character as an accelerator key. Use two ampersands to write &. You can have a menu item without any text by having "" in this field, but this simply gives the same result as having a SEPARATOR. If you want a completely empty menu line use " " instead (giving the menu item a string which contains only a space). id is the value which is sent to the window procedure of the window which owns the menu.

It can be:-
a 16-bit number (MENU) or a 32-bit number (MENUEX)
an expression which evaluates to the above number

type/state is one or more of the following words separated by spaces or the | (OR) operator:- MENUBREAK (type value 40h - puts the next menu item on a new line or in a new column in the case of popup menus)
MENUBARBREAK (type value 20h - same as above but includes a separator line)
OWNERDRAW (type value 100h - process is responsible for drawing the menu)
RADIOCHECK (type value 200h - radio button used instead of check-mark for checked items)
RIGHTJUSTIFY (type value 4000h - right justifies menu text only, not popups)
HELP (type value 4000h- identifies a help item)
SEPARATOR (type value 800h - for popups only)
CHECKED (state value 8h - checks the menu item)
GRAYED (state value 3h - disables and greys the menu item)
DISABLED (state value 3h - same as above)
INACTIVE (state value 2h - menu item not greyed but cannot be selected)
HILITE (state value 80h - highlights the menu item)
DEFAULT (state value 1000h - displays text in bold - enter key will act in the same way as a mouse click on this item)

Instead of using the type/state words, you can use the values instead but ensure that they are inserted as follows: type,state or type+type,state+state (type values are first, then comma, then state values)

helpID which is used in MENUEX only, is a value sent to the window procedure of the window which owns the menu if F1 is pressed when the menu is active. It can be:-

a 32-bit number

an expression which evaluates to a 32 bit number

important - in the POPUP statement, to ensure that the helpID is properly identified, make sure there are a total of 3 commas between id and helpID. This tells the Resource Compiler that helpID is not a type nor a style value.

MENUITEM SEPARATOR creates a horizontal line in the menu which is useful for separating different types of menu items

Example of MENU resource
#define IDM_NEW 10h
#define IDM_OPEN 20h
GENERIC MENU
BEGIN

POPUP "&File"
BEGIN MENUITEM "&New...", IDM_NEW,GRAYED
MENUITEM "&Open...", IDM_OPEN,GRAYED
MENUITEM SEPARATOR
POPUP "Send to"
BEGIN MENUITEM "Drive a:" END
END
POPUP "View"
BEGIN MENUITEM "Toolbar\tCrtl+T", 33h, CHECKED,HILITE END
END

Example of MENUEX resource
#define IDM_NEW 10h
#define IDM_OPEN 20h
GENERIC MENUEX 99999999h
BEGIN

POPUP "nice day", 0x100, CHECKED,,6666666h
BEGIN MENUITEM "&New...",IDM_NEW,GRAYED,MENUBREAK
MENUITEM "&Open...", IDM_OPEN,GRAYED
MENUITEM SEPARATOR
POPUP "Send to"
BEGIN MENUITEM "Drive a:" END
END
POPUP "View"
BEGIN MENUITEM "Toolbar", 33h, CHECKED| HILITE END
END


The DIALOG resource
Back to top

The syntax for the DIALOG resource is:-

nameID DIALOG x, y, width, height

[defining-statements] [dialog-statements]
BEGIN
iconcontrol
textcontrol
non-textcontrol
generic-control
END

The syntax for the DIALOGEX resource is:-

nameID DIALOGEX x, y, width, height [,helpID]
[defining-statements]
[dialog-statements]
BEGIN
iconcontrol
textcontrol [,helpID]
non-textcontrol [,helpID]
generic-control [,helpID]
END

Where,
nameID can be either:-

a 16-bit number of value 1 to 7FFFh
an expression which evaluates to that number
a name

x is the horizontal position of the dialog in dialog units
y is the vertical position of the dialog in dialog units
width is the width of the dialog in dialog units
height is the height of the dialog in dialog units helpID which is used in DIALOGEX only, is a value which is sent to the dialog procedure if F1 is pressed when the dialog is active. A helpID specified for a control is sent if the user clicks the control after having dragged the help question mark. helpID can be:- a 32-bit number
an expression which evaluates to a 32 bit number

defining-statements need not be present, but can be either:- a VERSION statement
a CHARACTERISTICS statement
a LANGUAGE statement
see below for details

dialog-statements need not be present, but can be one or more of the following:- CAPTION "text"
where "text" is the title of the dialog to insert in the title bar

CLASS class
this statement is used if you have registered your own private window class for the dialog because you want to intercept dialog messages before they go to the system’s default dialog window procedure. class can be:-
a 16-bit number
a quoted string

EXSTYLE exstyle allows an extended style to be specified see window types and styles

FONT pointsize, "typeface" ;if DIALOG
FONT pointsize, "typeface" [,weight, italic, charset] ;if DIALOGEX
this statement must be present if the dialog has the DS_SETFONT style and it contains the information which the system uses to write the text within the dialog box and its controls. If this statement is present the dialog box is given the style DS_SETFONT automatically.
pointsize is a 16 bit number giving the size of the font
typeface is a quoted string giving the name of the typeface
weight (DIALOGEX only) is either:-

a 16 bit number
an expression which evaluates to a 16 bit number
one of the words known to the Resource Compiler set out below (the weight is given in the second column) FW_DONTCARE 0
FW_THIN 100
FW_EXTRALIGHT 200
FW_LIGHT 300
FW_NORMAL 400
FW_MEDIUM 500
FW_SEMIBOLD 600
FW_BOLD 700
FW_EXTRABOLD 800
FW_HEAVY 900
if this parameter is omitted it is set to zero (don’t care)

italic (DIALOGEX only) indicates whether italics should be used and is either:- the number 0 or the word FALSE to indicate not italic, or
the number 1 or the word TRUE to indicate italic
if this parameter is omitted it is set to zero (non-italic)

charset (DIALOGEX only) indicates the character set for the dialog and is either:- an 8 bit number
an expression which evaluates to an 8 bit number
one of the words known to the Resource Compiler set out below (the value is given in the second column) ANSI_CHARSET 0
DEFAULT_CHARSET 1
SYMBOL_CHARSET 2
SHIFTJIS_CHARSET 128
HANGEUL_CHARSET 129
HANGUL_CHARSET 129
GB2312_CHARSET 134
CHINESEBIG5_CHARSET 136
OEM_CHARSET 255
JOHAB_CHARSET 130
HEBREW_CHARSET 177
ARABIC_CHARSET 178
GREEK_CHARSET 161
TURKISH_CHARSET 162
VIETNAMESE_CHARSET 163
THAI_CHARSET 222
EASTEUROPE_CHARSET 238
RUSSIAN_CHARSET 204
MAC_CHARSET 77
BALTIC_CHARSET 186
if this parameter is omitted it is set to zero (don’t care)

MENU menuname
this statement if present specifies a menu for the dialog box and menuname is either:-
a 16-bit number identifying the menu. This would be the number given as the nameID of the menu resource.
an expression which evaluates to that number, or
the name of a menu resource if the nameID of the menu was a name

STYLE styles
this statement is used to change the default dialog box style which is:-
WS_POPUP | WS_BORDER | WS_SYSMENU, which is the same as 80000000h | 800000h | 80000h
To remove an unwanted default style you can use the word NOT or !, for example
STYLE NOT SYSMENU
or
STYLE !80000h
would produce a dialog box with a style of WS_POPUP and WS_BORDER only.
The following styles and their respective values can be used in this statement:-

DS_MODALFRAME (value 80h) creates a dialog box with a modal dialog frame (can be combined with WS_CAPTION and WS_SYSMENU styles)
DS_SYSMODAL (value 2h) gives the dialog box the WS_EX_TOPMOST style
WS_BORDER (value 800000h) creates a dialog box with a border
WS_DLGFRAME (value 400000h) creates a modal dialog box type of frame for the dialog but no title bar
WS_OVERLAPPED (value zero) see window types and styles
WS_OVERLAPPEDWINDOW see window types and styles
WS_POPUPWINDOW see window types and styles
WS_CAPTION (value 0C00000h) combination of WS_BORDER and WS_DLGFRAME see window types and styles
WS_POPUP (value 80000000h) see window types and styles
WS_CHILD (value 40000000h) see window types and styles
WS_CLIPCHILDREN (value 2000000h) see window types and styles
WS_CLIPSIBLINGS (value 4000000h) see window types and styles
WS_MINIMIZEBOX (value 20000h) dialog box has a minimizebox in the title bar
WS_MAXIMIZEBOX (value 10000h) dialog box has a maximizebox in the title bar
WS_HSCROLL (value 100000h) creates a dialog with a horizontal scroll bar
WS_VSCROLL (value 200000h) creates a dialog box with a vertical scroll bar
WS_SIZEBOX (value 40000h) creates a dialog box with a thick frame for resizing
WS_MINIMIZE (value 20000000h) dialog box is created minimized
WS_MAXIMIZE (value 1000000h) dialog box is creates maximized
WS_SYSMENU (value 80000h) creates a dialog box with a system menu in its title bar
WS_DISABLED (value 8000000h) dialog is initially disabled
DS_NOIDLEMSG (value 100h) suppresses WM_ENTERIDLE messages that the system would otherwise send to the owner of the dialog box
DS_ABSALIGN (value 1h) - the co-ordinates of the dialog box are screen co-ordinates as opposed to client co-ordinates
DS_CENTER (value 800h) centre the dialog box as far as possible on the screen
DS_CENTERMOUSE (value 1000h) centre the mouse cursor in the dialog box
DS_CONTEXTHELP (value 2000h) add a question mark to the title bar for help processing
DS_CONTROL (value 400h) make the dialog box work like the child window of another dialog box
DS_FIXEDSYS (value 8h) use the system’s fixed font rather than the proportional font
DS_SETFONT (value 40h) look for the FONT statement for the font to use for the controls and for text in the dialog box
DS_NOFAILCREATE (value 10h) make the dialog box even if there are errors in making the controls
DS_SETFOREGROUND (value 200h) system to call SetForegroundWindow when the dialog is created

an iconcontrol displays an icon in the dialog box

The syntax for an iconcontrol is:-
ICON nameID, id, x, y
Where, nameID is the identifier of an ICON resource and it is either:-

a 16-bit number of value 1 to 7FFFh
an expression which evaluates to that number
a quoted string containing the name of the ICON if the icon is identified by name

x is the horizontal position of the icon
y is the vertical position of the icon id can be:-
a 16-bit number (DIALOG) or a 32-bit number (DIALOGEX)
an expression which evaluates to the above number

a textcontrol is a dialog control which contains text and which has a name which is recognised by the Resource Compiler. The name of the type of control causes the Resource Compiler to give the control the correct class and a default style. To remove a default style you will need to use the NOT specifier, as you would to remove a default style for the dialog itself.

The syntax for a textcontrol is:-
textcontrol "text", id, x, y, width, height, [,style [,extendedstyle]]
BEGIN
data-elements
END
Where,
"text" is the text to appear in the control

id can be:-
a 16-bit number (DIALOG) or a 32-bit number (DIALOGEX)
an expression which evaluates to the above number

x is the horizontal position of the control in dialog units
y is the vertical position of the control in dialog units
width is the width of the control in dialog units
height is the height of the control in dialog units data-elements are one or more elements of data, called "Creation data". A pointer to this data is sent to the dialog procedure in the lParam parameter of the WM_CREATE message when the control is created. The data is made using the same format as for the RCDATA resource.


The various textcontrols and their classes are given below, together with the default styles LTEXT - static class, default style SS_LEFT and WS_GROUP creating a static control with left aligned text
CTEXT - static class, default style SS_CENTER and WS_GROUP creating a static control with centred text
RTEXT- static class, default style SS_RIGHT and WS_GROUP creating a static control with right-aligned text
GROUPBOX - button class, default style BS_GROUPBOX creates a labelled rectangle in the dialog box inside which other controls can be grouped
CHECKBOX - button class, default style BS_CHECKBOX and WS_TABSTOP which creates a check box control (small rectangle with text next to it)
AUTOCHECKBOX - button class, default style BS_AUTOCHECKBOX and WS_TABSTOP which creates check box control which automatically changes to checked or unchecked when the user clicks in the control
STATE3 - button class, default style BS_3STATE and WS_TABSTOP which creates a check box control which has 3 states - checked, unchecked and disabled (greyed)
AUTO3STATE - button class, default style BS_AUTO3STATE and WS_TABSTOP which creates a STATE3 control which automatically toggles when clicked between the 3 states
RADIOBUTTON - button class, default style BS_RADIOBUTTON and WS_TABSTOP which creates a radio button control
AUTORADIOBUTTON - button class, default style BS_AUTORADIOBUTTON and WS_TABSTOP which creates an automatic radio button
PUSHBUTTON - button class, default style BS_PUSHBUTTON and WS_TABSTOP creates an ordinary push button control containing text
DEFPUSHBUTTON - button class, default style BS_DEFPUSHBUTTON and WS_TABSTOP creates an ordinary push button control containing text and showing as the default if the user presses enter
PUSHBOX - button class, default style BS_USERBUTTON, BS_CHECKBOX and WS_TABSTOP giving a flat appearance to the button

a non-textcontrol is similar to a textcontrol except that it does not contain text in the first instance (this must be added at run-time).

The syntax for a non-textcontrol is:-
non-textcontrol id, x, y, width, height, [,style [,extendedstyle]]
BEGIN
data-elements
END

The id, x, y, width, height, style and extend style parameters are the same as for the text-control
The various non-textcontrols and their classes are given below, together with the default styles

EDITTEXT - edit class, default style ES_LEFT, WS_BORDER and WS_TABSTOP which creates a simple edit control
HEDIT handwriting edit (pen) control
IEDIT ink edit (pen) control
LISTBOX - listbox class, default style LBS_NOTIFY and WS_BORDER creating a basic listbox
SCROLLBAR - scrollbar class, default style SBS_HORZ creating a basic scrollbar
COMBOBOX - combobox class, default style CBS_SIMPLE creating a basic combobox control

a generic-control is a control where you explicitly specify the class of the control. It is mainly used for those control classes which do not come into the button, edit, static, listbox, scrollbar or combobox classes. However, you can use the generic-control syntax to make those controls too.

The syntax for the generic-control is as follows:-
CONTROL "text", id, class, style, x, y,width,height [,extended style] [,helpID]

BEGIN
data-elements
END

The id, x, y, width, height, style and extend style parameters are the same as for the text-control
"text" is:- a quoted string containing the text for the control or "" if it has no text
in the case of a control of the static class which has the SS_BITMAP style, "text" can be a 16 bit number representing the bitmap concerned
an expression which evaluates to the above text or number

class is:- (if one of the first six in the list below) a 16-bit number of value 80h to 85h
an expression which evaluates to the above number
a quoted string containing the name of the class shown in the second column of the list below, or
a word shown in the first column of the list below
or (for a user-defined class) a quoted string
The class can therefore be one of the following:- BUTTON "Button" ;value 80h
EDIT "Edit" ;value 81h
STATIC "Static" ;value 82h
LISTBOX "Listbox" ;value 83h
SCROLLBAR "Scrollbar" ;value 84h
COMBOBOX "ComboBox" ;value 85h
WC_HEADER "SysHeader32"
WC_LISTVIEW "SysListView32"
WC_TREEVIEW "SysTreeView32"
HOTKEY_CLASS "msctls_hotkey32"
UPDOWN_CLASS "msctls_updown32"
ANIMATE_CLASS "SysAnimate32"
WC_COMBOBOXEX "ComboBoxEx32"
WC_TABCONTROL "SysTabControl32"
MONTHCAL_CLASS "SysMonthCal32"
PROGRESS_CLASS "msctls_progress32"
REBARCLASSNAME "ReBarWindow32"
TOOLTIPS_CLASS "tooltips_class32"
TRACKBAR_CLASS "msctls_trackbar32"
STATUSCLASSNAME "msctls_statusbar32"
TOOLBARCLASSNAME "ToolbarWindow32"
DATETIMEPICK_CLASS "SysDateTimePick32"
WC_IPADDRESS "SysIPAddress32"
WC_PAGESCROLLER "SysPager"
WC_NATIVEFONTCTL "NativeFontCtl"
DRAGLISTMSGSTRING "commctrl_DragListMsg"

For the controls which do not normally take initial text, (see non-textcontrols above) you must include an empty text string by specifying "", for the text parameter.
style and extendedstyle are chosen to suit the particular control being made. Note that there are no default styles, other than WS_CHILD and WS_VISIBLE.

Example of a DIALOGEX resource
0x45 DIALOGEX 0x30, 0x20, 0x200, 0x400,0x98
CAPTION "goodbye"
MENU mymenu
FONT 10,"Times New Roman",FW_NORMAL,1
BEGIN

CTEXT "hello", 0x20,0x10,0x10,0x10,0x10,
,WS_EX_PALETTEWINDOW, 0x333
COMBOBOX 0x456,30005,4560,300,20
BEGIN 0x888888L
L"hello folks"
0x99,0x67,0x5555
END CONTROL "ducks",0x460,"ComboBoxEx32",0x100,30005,4560,300,20 CONTROL "drakes",0x461,0x85,0x100,30005,4560,300,20
CONTROL "hens",0x462,"Button",0x100,30005,4560,300,20 CONTROL "and",0x463,"Own class",0x100,30005,4560,300,20
CONTROL "chickens",0x464,STATUSCLASSNAME, 0x100,30005,4560,300,20
ICON "ANI_ICON",0x465, 6, 9, 18, 20
END


Example of a DIALOG resource
AboutBox DIALOG 100, 100, 160, 72
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
FONT 8,"MS Sans Serif"
CAPTION "About it"
BEGIN CTEXT "Application" -1, 0, 8, 160, 8
CTEXT "Version 1.2" -1, 0, 16, 160, 8
DEFPUSHBUTTON "OK" IDOK, 55,52,50,14
CONTROL 23h,-1,"Static",SS_BITMAP,9,6,125,41
ICON "MyIcon" -1, 20, 10,0,0
END

Defining statements

defining-statements give some further definition to each resource.
There are three types of defining-statement:- VERSION statement
CHARACTERISTICS statement
LANGUAGE statement

Each defining-statement is specific to the resource to which it refers, however if LANGUAGE is specified outside a specific resource it will apply to all resources thereafter.


Version and Characteristics
Back to top

The syntax for these is the same:-
VERSION value
CHARACTERISTICS value
Where, value is:-
a 32-bit number
an expression which evaluates to a 32-bit number
value is stored only in the RES file and not in the OBJ file nor in the EXE, so it cannot be recovered at run-time. However it could be read by tools which work with the RES file, such as the some linkers.


Language
Back to top

The syntax of the LANGUAGE statement is:-
LANGUAGE language, sublanguage

This statement can appear anywhere in the script (outside a BEGIN...END section). In that case the specified language applies to all resources thereafter.
It can also appear between the resource statement itself and the BEGIN...END section as a defining-statement. In that case the specified language only applies to the resource in which it appears. The actual values for language and sublanguage appear in WINNT.H.
The most common values for language are LANG_ENGLISH (value 9h), and for sublanguage are SUBLANG_ENGLISH_US (value 1h), SUBLANG_ENGLISH_UK (value 2h), SUBLANG_ENGLISH_AUS (value 3h) and SUBLANG_ENGLISH_CAN (value 4h).
If no language is specified in your resource script the Resource Compiler uses the system language and inserts that in the binary resource file.

Making different language versions of a resource
If your product is to be used in more than one language, you will need to provide different menu and dialog text, warning and error messages to suit the language. The combined features of the Resource Compiler and the API make it reasonably easy to achieve this. The exact way this is achieved, in the context of resources, depends on whether you want:-

The first can be achieved by having different resource scripts, or by use of the conditional directives, which would instruct the Resource Compiler to compile only those parts of the resource script relevant to the desired language (see conditional directives above).

The second is possible because the API FindResource will automatically return the handle of the resource which suits the default system language for the computer which is running the program. FindResource does this by obtaining the default system language and then calling FindResourceEx. If you want to specify the language of the resource to be found, rather than relying on the system default language, then you can call FindResourceEx directly giving the language ID.

FindResource can be used as follows:-

PUSH resource type   ;by type number or by name if a user-defined resource
PUSH resource nameID   ;use only a name identifier not a number
PUSH hModule   ;this is hInst or zero to use current process
CALL FindResource

FindResourceEx can be used as follows

PUSH resource language   ;see below
PUSH resource nameID   ;use only a name identifier not a number
PUSH resource type   ;by type number or by name if a user-defined resource
PUSH hModule   ;this is hInst or zero to use current process
CALL FindResourceEx
Note that the nameID and type parameters are reversed for FindResourceEx!
The resource language is a 32-bit value made up as follows:-
Least significant 10 bits - the primary language value:
Next 6 bits - the secondary language value
Most significant 16 bits - zero
For a list of the language values see WINNT.h

The return from FindResource and FindResourceEx is the handle which is needed for the call to LoadResource.. You can have several versions of a menu or dialog, for example, with the same nameID but with different languages specified. FindResource will return the handle of the correct one.

Language specific menus
Since the FindResource (or FindResourceEx) and LoadResource combination provide an address to the resource data itself, in order to load a language specific menu, you need to pass that address as the menu template to LoadMenuIndirect. You cannot use LoadMenu to load a language specific menu.

Language specific dialogs
Similarly, to make a language specific dialog box you need to pass the address of the dialog template returned by LoadResource to DialogBoxIndirect (modal) or CreateDialogIndirect (non-modal) rather than using the CreateDialog and DialogBox APIs. Other language specific components which are needed in your dialog should either be given a unique nameID or loaded at run-time. For example, if you have a French version of your dialog and want to include a French menu by using the MENU defining-statement in the resource script, a nameID must be given in the MENU statement which uniquely refers to the French menu. Alternatively if you have several language versions of the menu all with the same nameID you could load the menu at run-time upon the INIT_DIALOG message. This would be done by calling FindResource or FindResourceEx, then LoadResource (to get and address for the menu template of the correct menu), LoadMenuIndirect (to get the menu handle) and then SetMenu (to load the menu into the dialog box).

Language specific strings and raw data
When loading language specific strings, you can use LoadString directly. This loads a string to suit the system default language. Alternatively the address of the string itself can be obtained using FindResource, or FindResourceEx and LoadResource.
The same method works for RCDATA and for a user-defined resource (and indeed for any resource which can be used by obtaining an address of the raw data of the resource).

Examples for viewing
Testbug.Exe provides examples of loading language specific menus, dialogs, strings and raw data. The relevant functions to look at with the debugger are:-
Menus, dialogs and raw data example, click "use of resources/different language versions/various resources in English" or "same showing French versions" in the menu, watching with the debugger the functions RESOURCES_IN_ENGLISH and RESOURCES_IN_FRENCH, which create dialog boxes using the dlg wndproc called MDLangDlgProc.
Strings, click "Language specific string" in the menu, watching with the debugger the function STRINGTABLES_BY_LANGUAGE.

Language search criteria
When searching for language specific resources, the system looks for a language match but has certain defaults if an exact match is not found. The system carries out the search for a resource of the correct type and ID in this order, moving down the list if the resource is not yet found:-

Clearly if the exact specified language is not present in the EXE, FindResourceEx will provide some output provided the resource type and ID match. So there is no need to worry that your product will not work in the Land of the Wizard if you use language specific resources.

Own language values
You can specify your own language values if you wish, and by this method it would be possible to make several versions of menus, dialogs and strings for your product in the same language if you wished, using the automatic language selection referred to above. To keep the system happy, ensure that your language value is between 200h and 3FFh, and the sublanguage value is between 20h and 3Fh. These values are carefully chosen. The actual languageID inserted in the binary resource file and kept in the EXE is only 16 bits long, the language value occupying the most significant 10 bits (hence a maximum value of 3FFh) and the sublanguage value occupying the least significant 6 bits (hence a maximum value of 3Fh).

Example of the LANGUAGE statement
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
456h RCDATA
BEGIN "Hello world (in English)\0" END

456h RCDATA
LANGUAGE LANG_FRENCH, SUBLANG_FRENCH
BEGIN

"Bonjour le monde (en Français)\0" END

STRINGTABLE
BEGIN

55h "An English string" END

LangMenu MENU
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
BEGIN

MENUITEM "English menu item" 22h END

LangMenu MENU
LANGUAGE LANG_FRENCH, SUBLANG_FRENCH
BEGIN
MENUITEM "Version française" 22h
END


Capitalisation of nameIDs and types
Back to top

We have seen that a resource nameID can either be a string of characters or a number. For each type of resource with a particular language the nameID must be unique. Ie. two dialogs can have the same nameID provided they have different language values.
We have also seen that a user-defined resource will have a resource type identified by a string of characters or a number.

Now, the Resource Compiler will always convert the nameID or type to upper case when inserting them in the RES file or OBJ file. The reason for this is that this is expected by Windows. In practice this does not affect the way you use the resource because the system will also capitalise any nameIDs or types given to the resource APIs. For example suppose you have a dialog with a nameID of "MyDlg". Then to use the dialog you would pass the string "MyDlg" to the API CreateDialog. But in fact, the system converts the string to MYDLG and then looks for that string (as converted) in the executable.

This has two implications which you may need to be aware of.

Firstly it means that there would be a conflict in the above example if you had a second dialog (with the same language value) called MYDLG. This would be picked up at link-time by the linker.

Secondly, the Resource Compiler must ensure that not only English nameIDs or user-defined types are converted properly to upper case. So the Resource Compiler relies on the API CharUpper to do this conversion. This API can handle a number of languages properly, but it does rely on language mapping. Ensure that the machine used for compiling does support the language used in the nameIDs and user-defined types. Many languages do not actually have an upper case at all, in which case no conversion will take place.
Back to top

Legal stuff

Copyright

GoRC is Copyright © Jeremy Gordon 1997-2006 [MrDuck Software] - all rights reserved.

GoRC - licence and distribution

You may use GoRC for any purpose including making commercial programs. You may redistribute it freely (but not for payment nor for use with a program or any material for which the user is asked to pay). You are not entitled to hide or deny my copyright.

Disclaimer

I have made every effort to ensure that GoRC's output is accurate, but you do use it entirely at your own risk. I cannot accept any liability for it failing to work properly or giving the wrong output nor for any errors in this manual.