A "Go" development tool:
http://www.GoDevTool.com
by Jeremy Gordon -
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
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:-
The command line syntax is:-
GoRC [command line switches] filename[.ext]
Where,
command line switches can be one or more of the following:- /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 /ne no error messages /ni no information messages /nw no warning messages /nu no warning message for a user-defined resource type /no no output messages at all filename is the name of the resource script ext is the extension of the filename of the resource script
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:-
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 are words in the resource script which give instructions to the Resource Compiler.
There are 3 types of directives:-
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 a 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.
To remove the value for a definition and have name undefined, use #undef:
#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
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)
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 will cause the Resource Compiler to load and look at the specified file:-
#include path\filename
Where,
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:-
You can nest #include files but it is probably good practice to avoid this as far as possible.
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.
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.
#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. The 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 where, expression1 must be a word which is defined elsewhere in the file, in an include file or on the command line. It cannot be a number. 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 on 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 ! expression this reverses the result of the condition, so #if is not the same as #if !. For example, #if!0 would return TRUE.
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.
; single line comment - everything after this to the end of the line is ignored // single line comment - everything after this to the end of the line is ignored ;; ... block comment - can span several lines and everything between the leading ... ;; and trailing marks is ignored /* ... block comment - can span several lines and everything between the leading ... */ and trailing marks is ignored \ line continuation - at the end of a line or just before a comment, allows processing to continue with the material 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 for addition (eg. 22h + 3h produces 25h) - minus for subtraction (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 as 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
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
The resource compiler can perform limited arithmetic on the following:-
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.
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
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.
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.
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 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 as follows for your use, along with another table afterwards with the hex values.
Space | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - |
40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 50 | 51 | 52 | 53 | 54 | 55 |
. | / | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; |
56 | 57 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 70 | 71 | 72 | 73 |
< | = | > | ? | @ | A | B | C | D | E | F | G | H | I |
74 | 75 | 76 | 77 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 110 | 111 |
J | K | L | M | N | O | P | Q | R | S | T | U | V | W |
112 | 113 | 114 | 115 | 116 | 117 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 |
X | Y | Z | [ | \ | ] | ^ | _ | ` | a | b | c | d | e |
130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 140 | 141 | 142 | 143 | 144 | 145 |
f | g | h | i | j | k | l | m | n | o | p | q | r | s |
146 | 147 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 160 | 161 | 162 | 163 |
t | u | v | w | x | y | z | { | | | } | ~ | | ||
164 | 165 | 166 | 167 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 200 | 201 |
‚ | ƒ | „ | … | † | ‡ | ˆ | ‰ | Š | ‹ | Œ | |||
202 | 203 | 204 | 205 | 206 | 207 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 |
‘ | ’ | | | • | | | ˜ | ™ | š | › | œ | ||
220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 230 | 231 | 232 | 233 | 234 | 235 |
Ÿ | ¡ | ¢ | £ | ¤ | ¥ | ¦ | § | ¨ | © | ª | « | ||
236 | 237 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 250 | 251 | 252 | 253 |
¬ | ® | ¯ | ° | ± | ² | ³ | ´ | µ | ¶ | · | ¸ | ¹ | |
254 | 255 | 256 | 257 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 270 | 271 |
º | » | ¼ | ½ | ¾ | ¿ | À | Á | Â | Ã | Ä | Å | Æ | Ç |
272 | 273 | 274 | 275 | 276 | 277 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 |
È | É | Ê | Ë | Ì | Í | Î | Ï | Ð | Ñ | Ò | Ó | Ô | Õ |
310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 320 | 321 | 322 | 323 | 324 | 325 |
Ö | × | Ø | Ù | Ú | Û | Ü | Ý | Þ | ß | à | á | â | ã |
326 | 327 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 340 | 341 | 342 | 343 |
ä | å | æ | ç | è | é | ê | ë | ì | í | î | ï | ð | ñ |
344 | 345 | 346 | 347 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 360 | 361 |
ò | ó | ô | õ | ö | ÷ | ø | ù | ú | û | ü | ý | þ | ÿ |
362 | 363 | 364 | 365 | 366 | 367 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 |
Space | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 2A | 2B | 2C | 2D |
. | / | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; |
2E | 2F | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 3A | 3B |
< | = | > | ? | @ | A | B | C | D | E | F | G | H | I |
3C | 3D | 3E | 3F | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
J | K | L | M | N | O | P | Q | R | S | T | U | V | W |
4A | 4B | 4C | 4D | 4E | 4F | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 |
X | Y | Z | [ | \ | ] | ^ | _ | ` | a | b | c | d | e |
58 | 59 | 5A | 5B | 5C | 5D | 5E | 5F | 60 | 61 | 62 | 63 | 64 | 65 |
f | g | h | i | j | k | l | m | n | o | p | q | r | s |
66 | 67 | 68 | 69 | 6A | 6B | 6C | 6D | 6E | 6F | 70 | 71 | 72 | 73 |
t | u | v | w | x | y | z | { | | | } | ~ | | ||
74 | 75 | 76 | 77 | 78 | 79 | 7A | 7B | 7C | 7D | 7E | 7F | 80 | 81 |
‚ | ƒ | „ | … | † | ‡ | ˆ | ‰ | Š | ‹ | Œ | |||
82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 8A | 8B | 8C | 8D | 8E | 8F |
‘ | ’ | | | • | | | ˜ | ™ | š | › | œ | ||
90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 9A | 9B | 9C | 9D |
Ÿ | ¡ | ¢ | £ | ¤ | ¥ | ¦ | § | ¨ | © | ª | « | ||
9E | 9F | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | AA | AB |
¬ | ® | ¯ | ° | ± | ² | ³ | ´ | µ | ¶ | · | ¸ | ¹ | |
AC | AD | AE | AF | B0 | B1 | B2 | B3 | B4 | B5 | B6 | B7 | B8 | B9 |
º | » | ¼ | ½ | ¾ | ¿ | À | Á | Â | Ã | Ä | Å | Æ | Ç |
BA | BB | BC | BD | BE | BF | C0 | C1 | C2 | C3 | C4 | C5 | C6 | C7 |
È | É | Ê | Ë | Ì | Í | Î | Ï | Ð | Ñ | Ò | Ó | Ô | Õ |
C8 | C9 | CA | CB | CC | CD | CE | CF | D0 | D1 | D2 | D3 | D4 | D5 |
Ö | × | Ø | Ù | Ú | Û | Ü | Ý | Þ | ß | à | á | â | ã |
D6 | D7 | D8 | D9 | DA | DB | DC | DD | DE | DF | E0 | E1 | E2 | E3 |
ä | å | æ | ç | è | é | ê | ë | ì | í | î | ï | ð | ñ |
E4 | E5 | E6 | E7 | E8 | E9 | EA | EB | EC | ED | EE | EF | F0 | F1 |
ò | ó | ô | õ | ö | ÷ | ø | ù | ú | û | ü | ý | þ | ÿ |
F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | FA | FB | FC | FD | FE | FF |
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:-
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,
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 be identified by 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.
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)
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 with 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 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 can be either:- a 16-bit number which identifies the string an expression which resolves to that number
"string" can be either:- a quoted string of not more than 4097 characters 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.
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
Secondly, the VERSIONINFO resource (resource type 16), which is used to keep information about the version of the EXE and 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:-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, with 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 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.VS_FF_DEBUG (1= the file contains debugging information) VS_FF_PATCHED (4= the version information has been changed from the original shipping version) VS_FF_PRERELEASE (2= the file is a development version only and is 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
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
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 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 eg. the commonly used 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 (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 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, which can also contain:- \t which inserts a tab \a which aligns to the right all text which follows it & the system uses 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:- type MENUBREAK 40h puts the next menu item on a new line or in a new column in the case of popup menus MENUBARBREAK 20h same as above but includes a separator line OWNERDRAW 100h process is responsible for drawing the menu RADIOCHECK 200h radio button used instead of check-mark for checked items RIGHTJUSTIFY 4000h right justifies menu text only, not popups HELP 4000h identifies a help item SEPARATOR 800h for popups only state CHECKED 8h checks the menu item GRAYED 3h disables and greys the menu item DISABLED 3h same as above INACTIVE 2h menu item not greyed but cannot be selected HILITE 80h highlights the menu item DEFAULT 1000h displays text in bold and the 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 their respective value 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 (MENUEX only) is the 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, MENUBREAK | GRAYED 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 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 (DIALOGEX only) is the 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. The helpID can be either:- 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 either:- a 16-bit number a quoted string EXSTYLE exstyle allows an extended style to be specified, which can be one or more of the following extended styles or their respective value separated by the | (OR) operator:- WS_EX_DLGMODALFRAME 1h has a double border WS_EX_NOPARENTNOTIFY 4h when window is created or destroyed, does not send the WM_PARENTNOTIFY message to the parent window WS_EX_TOPMOST 8h place above all non-topmost windows and stay above them WS_EX_ACCEPTFILES 10h accept drag-drop files WS_EX_TRANSPARENT 20h sibling window(s) beneath the window get painted first WS_EX_MDICHILD 40h a MDI child window WS_EX_TOOLWINDOW 80h for use as a floating toolbar WS_EX_WINDOWEDGE 100h border has a raised edge WS_EX_CLIENTEDGE 200h border has a sunken edge WS_EX_OVERLAPPEDWINDOW 300h which is the same as WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE WS_EX_PALETTEWINDOW 188h which is the same as WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST WS_EX_CONTEXTHELP 400h title bar include a question mark for use with WM_HELP message processing to display help WS_EX_LEFT 0h default left-aligned properties WS_EX_RIGHT 1000h right-align properties for shell languages supporting reading-order alignment WS_EX_LTRREADING 0h default left-to-right reading-order properties WS_EX_RTLREADING 2000h right-to-left reading-order properties for shell languages supporting reading-order alignment WS_EX_RIGHTSCROLLBAR 0h default position to the right of the client area WS_EX_LEFTSCROLLBAR 4000h positioned to the left of the client area for shell languages supporting reading-order alignment WS_EX_CONTROLPARENT 10000h child windows are included in dialog box navigation WS_EX_STATICEDGE 20000h border has a three-dimensional style WS_EX_APPWINDOW 40000h top-level window when visible shows on taskbar WS_EX_LAYERED 80000h a layered window generally with a complex/animated shape or alpha blending WS_EX_NOINHERITLAYOUT 100000h window layout does not get passed to child windows WS_EX_LAYOUTRTL 400000h horizontal origin on right edge of window for shell languages supporting reading-order alignment WS_EX_COMPOSITED 2000000h descendants of the window get painted in bottom-to-top order using double-buffering WS_EX_NOACTIVATE 8000000h if a top-level window, does not become the foreground window or show on the taskbar 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)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 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 id can be either:- 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 icon y is the vertical position of the icon 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, textcontrol is one of the names given below, listed here with their class and default style:- LTEXT static class, SS_LEFT | WS_GROUP creates a static control with left aligned text CTEXT static class, SS_CENTER | WS_GROUP creates a static control with centred text RTEXT static class, SS_RIGHT | WS_GROUP creates a static control with right-aligned text GROUPBOX button class, BS_GROUPBOX creates a labelled rectangle in the dialog box inside which other controls can be grouped CHECKBOX button class, BS_CHECKBOX | WS_TABSTOP creates a check box control (small rectangle with text next to it) AUTOCHECKBOX button class, BS_AUTOCHECKBOX | WS_TABSTOP creates a check box control which automatically changes to checked or unchecked when the user clicks in the control STATE3 button class, BS_3STATE | WS_TABSTOP creates a check box control which has 3 states checked, unchecked, and disabled (greyed) AUTO3STATE button class, BS_AUTO3STATE | WS_TABSTOP creates a STATE3 control which automatically toggles when clicked between the 3 states RADIOBUTTON button class, BS_RADIOBUTTON | WS_TABSTOP creates a radio button control AUTORADIOBUTTON button class, BS_AUTORADIOBUTTON | WS_TABSTOP creates an automatic radio button PUSHBUTTON button class, BS_PUSHBUTTON | WS_TABSTOP creates an ordinary push button control containing text DEFPUSHBUTTON button class, BS_DEFPUSHBUTTON | WS_TABSTOP creates an ordinary push button control containing text and showing as the default if the user presses enter PUSHBOX button class, BS_USERBUTTON | BS_CHECKBOX | WS_TABSTOP giving a flat appearance to the button "text" is the text to appear in the control id can be either:- 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 style see above for details extendedstyle see above for details 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. 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 Where the id, x, y, width, height, style and extendstyle parameters are the same as for the text-control. non-textcontrol is one of the names given below, listed here with their class and default style:- EDITTEXT edit class, ES_LEFT | WS_BORDER | WS_TABSTOP creates a simple edit control HEDIT handwriting edit (pen) control IEDIT ink edit (pen) control LISTBOX listbox class, LBS_NOTIFY | WS_BORDER creates a basic listbox SCROLLBAR scrollbar class, SBS_HORZ creates a basic scrollbar COMBOBOX combobox class, CBS_SIMPLE creates a basic combobox control 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 a generic-control is as follows:- CONTROL "text", id, class, style, x, y, width, height [,style,[extendedstyle]] BEGIN data-elements END Where the id, x, y, width, height, style and extendstyle parameters are the same as for the text-control. Note that here there are no default styles, other than WS_CHILD and WS_VISIBLE, so style and extendedstyle should be chosen to suit the particular control being made. "text" can be either:- a quoted string containing the text for the control or "" if it has no text in the case of a STATIC class control 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 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. class can be either:- a 16-bit number of value 80h to 85h (if one of the first six in the list below) 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 a word shown in the first column of the list below a quoted string (for a user-defined class) The class can therefore be one of the following:- BUTTON "Button" 80h EDIT "Edit" 81h STATIC "Static" 82h LISTBOX "Listbox" 83h SCROLLBAR "Scrollbar" 84h COMBOBOX "ComboBox" 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"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 the ! symbol. For example STYLE NOT SYSMENU or STYLE !80000h would produce a dialog box with the style of WS_POPUP and WS_BORDER only. The following dialog styles and their respective values can be used in this statement:- DS_ABSALIGN 1h the co-ordinates of the dialog box are screen co-ordinates as opposed to client co-ordinates DS_SYSMODAL 2h gives the dialog box the WS_EX_TOPMOST style DS_FIXEDSYS 8h use the system’s fixed font rather than the proportional font DS_NOFAILCREATE 10h make the dialog box even if there are errors in making the controls DS_SETFONT 40h looks for the FONT statement for the font to be used for the controls and for text in the dialog box DS_MODALFRAME 80h creates a dialog box with a modal dialog frame which can be combined with WS_CAPTION and WS_SYSMENU styles DS_NOIDLEMSG 100h suppresses WM_ENTERIDLE messages that the system would otherwise send to the owner of the dialog box DS_SETFOREGROUND 200h system to call SetForegroundWindow when the dialog is created DS_CONTROL 400h make the dialog box work like the child window of another dialog box DS_CENTER 800h centre the dialog box as far as possible on the screen DS_CENTERMOUSE 1000h centre the mouse cursor in the dialog box DS_CONTEXTHELP 2000h add a question mark to the title bar for help processing The following window styles and their respective values can also be used in this statement:- WS_TILED same as WS_OVERLAPPED 0h an overlapped window with a title bar and border WS_MAXIMIZEBOX 10000h has a maximizebox in the title bar WS_MINIMIZEBOX 20000h has a minimizebox in the title bar WS_THICKFRAME same as WS_SIZEBOX 40000h has a thick frame border for resizing WS_SYSMENU 80000h has a system menu in its title bar WS_HSCROLL 100000h has a horizontal scroll bar WS_VSCROLL 200000h has a vertical scroll bar WS_DLGFRAME 400000h creates a modal dialog box type of frame for the window which cannot have a title bar WS_BORDER 800000h has a thin-line border WS_CAPTION 0C00000h which is the same as WS_BORDER | WS_DLGFRAME and has a title bar WS_TILEDWINDOW same as WS_OVERLAPPEDWINDOW 0C80000h which is the same as WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | \ WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX an overlapped window combined with other styles WS_MAXIMIZE 1000000h created initially maximized WS_CLIPCHILDREN 2000000h a parent window can use this to exclude child window areas when drawing within the parent window WS_CLIPSIBLINGS 4000000h clips overlappping child windows out of the update region for the WM_PAINT message WS_DISABLED 8000000h initially created as disabled WS_VISIBLE 10000000h initially created as minimized WS_MINIMIZE 20000000h initially created as minimized WS_CHILD 40000000h a child window which cannot have a menu bar, and cannot be used with the WS_POPUP style WS_POPUP 80000000h a pop-up window which cannot be used with the WS_CHILD style WS_POPUPWINDOW 80880000h which is the same as WS_POPUP | WS_BORDER | WS_SYSMENU a pop-up window, used with WS_CAPTION to make the window menu visible
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
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
Defining statements give some further definition to each resource. There are three types of defining-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.
The syntax for these is the same:-
VERSION value CHARACTERISTICS value
Where,
value can be either:- a 32-bit number an expression which evaluates to a 32-bit number
The 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 some linkers.
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.
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.
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.
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).
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).
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.
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.
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).
Examples 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
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.
GoRC is Copyright © Jeremy Gordon 1997-2018 [MrDuck Software] - all rights reserved.
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.
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.