[ Next ] [ Previous ] Chapter 12
[ Contents ]  [ Chapter 11: Window Messages and Queues ] [ Chapter 13: Dialog Boxes ]

Resources

Although resources such as CPU rime and memory in the traditional sense are viewed as "things" that need so be shared, the term has a different meaning in a GUI environment. In a Presentation Manager environment resources are viewed as items that are necessary for the user interface of an application but nor part of the application code itself.
So, why does this book contain a chapter dedicated to resources if they aren't code-related? The operative phrase in the preceding paragraph is "necessary for the user interface." Resources are not something that can be done without. Instead, programmers will spend a large amount of time on "developing" resources, since they define the look of the resulting application (though not its operation).
This chapter discusses the following types of resources, what they are, and how they are used within an application: pointers, icons, bitmaps, string tables, accelerator tables, and application defined resources. Help tables, dialog boxes, and menus are also resources that are discussed briefly. with cross-references to chapters on these topics provided. Fonts, which are the other resource type defined, will not be discussed because their use requires a detailed look as the Graphics Programming Interface (GPI), which It a hock in itself.

More About Resources, I Would Know

In an orchestra, there are the musicians, the conductor, and the seating arrangement,  which allows the conductor to know exactly where everything can be found. In this chapter, we will look the analogous  parts in a PM application: The resources are the actual user interface items that are used by the application - pointers, menus, and so on; as in an orchestra, without the resources themselves, the rest is pointless. The application coordinates the use of the resources to get a meaningful result: is wouldn't make sense, for example, to show an "Open" dialog when the user requested that the document should be printed. The resource file is where the compiler is instructed which resources the application will use; these resources, as we will show, are  appended to the executable in a separate area (called resource segments ), which are analogous to the seats in the orchestra section.

Table 12.1 shows the types of resources, defined by OS/2, that we look at this chapter
 

Table 12.1 Resource Types.
Resource Description
Pointer Pointer or icon data
Bitmap  Bitmap data
String table Table of strings
Accelerator table Table of "shortcut" keys
Menu Menu description
Dialog Dialog description
Font Font description
Help table Table of frame windows and dialogs for which online help is to be provided
Help subtable Table of windows within a frame window or dialog for which online help is to be provided
User data Data in an application-specific format

All resources are defined using resource identifiers, numeric constants that, together with the type of the resource being referenced, uniquely identify each resource in an application. A resource is said to be loaded when an application needs to use it for the first time; this loading of the resource results in a handle that the application uses when it calls a Presentation Manager function.

Resource Files

But before we can look at the resources themselves, we must first look at the place in which they are specified and the compiler used to append them to the executable. The resource file usually has a main file with the extension .RC, and this file usually includes one or more dialog definition files with the extension .DLG. The resource file can include C header files using the #include keyword and also can include comments according to the C++ standard (i.e., using "/*" and "*/" or using "//"). Where a construct requires a BEGIN and END keywords, the symbols "{" and "}" also may be used.
Dialog files are included in a funny manner: The main file uses the keyword DLGINCLUDE to specify that dialog file is to be included.
DLGINCLUDE  resid filename
resid specifies the resource identifier of the file (!) and filename is the name of the file to be included. The original intent was that each dialog definition would go in a separate file and all of the files would be included by the main file.
Gotcha!

Because the original purpose of the dialog file is as described, each DLGINCLUDE statement must have a unique resource identifier. It is not necessary, however, to limit each dialog file to having a single dialog box definition.

As if that weren't enough trouble, each dialog file also must use the RCINCLUDE statement to specify what the main file is to which it is being attached. This is to allow the dialog file to access the symbolic definitions (i.e., #defines )
As was said, dialog files are included in is funny manner, and the logic is rather illogical. This process was not followed in every PM sample presented in this book; instead, all of the dialog definitions were moved from the dialog files into the main file to eliminate the confusion of resource identifiers for files.

Using the Resource Compiler

Now that a resource file is defined, it needs to be compiled into a .RES file. This is accomplished using the resource compiler (RC.EXE). The compiler comes with the base operating system and can be found in the \OS2 directory. It also comes with the Programmer's Toolkit, Visual Age C++  and Watcom compilers. It supports the command-line options listed in Table 12.2.
Table. 12.2 Resource Compiler Switches
Option  Description
 -d defname 
-Ddefname
Preprocessor define - Defines a macro and optionally a value
 -i Include file path - specifies a path to include when searching files
 -r  Create .res file - Do not attach the compiled .RES file to the .EXE or .DLL
-p Pack - 386 resources will not cross 64K boundaries
-x[1|2]  Exepack - Compress resources, using method 1 or 2
 -cc cc Country code
 -cp cp | lb,tb,... DBCS codepage or lead/trail byte info.
 -n  Don't show logo
-w2  Suppress warnings
-?
-h
Access Help

To compile a resource file, MYAPP.RC, to a .RES file without attaching MYAPP.RES to MYAPPS.EXE, compressing resources, and using "." as a directory to search, the following code would be entered:

RC -R  -X1  -I.  MYAPP.RC

Pointers and Icons

Pointers and icons are defined and accessed in the same manner. This isn't coincidence; with the exception of the first two bytes in the file containing the actual data, the two are identical. Both resources are defined in the resource file in the following manner:
POINTER resid filename
resid is the resource identifier of the pointer or icon, and filename is the name of the file containing the pointer or icon data. These files are created using the "icon editor" utility (ICONEDIT.EXE), which is provided by OS/2 and also can be found as part of the Programmer's Toolkit. For help on using the icon editor, programmers should refer to the online documentation.
In a program, both are loaded using the WinLoadPointer function.
HPOINTER APIENTRY WinLoadPointer(HWND hwndDesktop,
                                 HMODULE hmod,
                                 ULONG idres);
hwndDesktop is the desktop window handle, for which HWND_DESKTOP can he specified. hmDll  is the handle to a DLL that was loaded with DosLoadModule or WinLoadLibrary to which the resource is attached. If the resources are appended to the executable, then NULLHANDLE should he used for this parameter. ulId is the resource identifier of the pointer or icon to he loaded. This function returns a handle to the pointer or icon that was loaded, which is used in subsequent functions that act upon pointers or icons.

Once a pointer or icon is loaded, it can be drawn in a window with WinDrawPointer  function.

BOOL     APIENTRY WinDrawPointer(HPS hpsWnd,
                                 LONG lX,
                                 LONG lY,
                                 HPOINTER hpPointer,
                                 ULONG ulFlags);
hpsWnd is a handle to the presentation space in which the pointer or icon is to be drawn. lX and lY specify the position within the presentation space where the pointer or icon is to be drawn. hpPointer specifies the handle of the pointer or icon that is to  be drawn. ulFlags specifies how the pointer or icon is to be drawn, and is one of the constants listed in Table 12.3.
Table 12.3 Values for ulFlags
Constant Description
DP_NORMAL  Draw the pointer or icon in the "normal" manner.
DP_HALFTONED  Draw the pointer or icon in a halftone manner.
DP_INVERTED Draw the pointer or icon in color-inverted state.
DP_MINI   0x0004  /*   Feature:85493  */ (???)

This function returns a flag indicating success or failure.
The WinDrawPointer function is useful for drawing an icon in a window, but it cannot be used to set the mouse pointer to anything. To accomplish this, we instead need the WinSetPointer function.

BOOL     APIENTRY WinSetPointer(HWND hwndDesktop,
                                HPOINTER hptrNew);
hwndDesktop  is the handle to the desktop; again, the HWND_DESKTOP constant for this can be specified. hptrNew is the handle to the pointer to which one wishes the mouse pointer to change. This function also returns a flag indicating success or failure.
Gotcha!

Just because the mouse is set to a specified pointer doesn't mean that something else cannot set it to something else. In fact. WinDefWindowProc will set the pointer to the arrow pointer within its processing for the WM_MOUSEMOVE message. Typically, the application would intercept the WM_MOUSEMOVE message and call WinSetPointer at that point to change the mouse pointer and not call WinDefWindowProc.

In addition to any user-drawn pointers or icons, Presentation Manager defines a number of "system pointers": the arrow pointer, the waiting pointer, and some icons that have been discussed come from here. These pointers and icons can be accessed or reloaded using the WinQuerySysPointer function.

HPOINTER APIENTRY WinQuerySysPointer(HWND hwndDesktop,
                                     LONG lptr,
                                     BOOL bLoad);
hwndDesktop is the desktop handle (HWND_DESKTOP). lPtr specifies which system pointer or icon one wishes to access or load. It is one of the constants found in Table 12.4.
 
 
Table 12.4 System Pointers
Constant  Description
SPTR_APPICON  Default icon for a PM application
SPTR_ARROW  Arrow pointer
SPTR_FILE  File icon
SPTR_FOLDER  Folder icon
SPTR_ICONERROR  Error icon
SPTR_ICONINFORMATION  Information icon
SPTR_ICONQUESTION  Query icon
SPTR_ICONWARNING  Warning icon
SPTR_ILLEGAL Illegal action icon
SPTR_MOVE Move icon
SPTR_MULTFILE Multiple object icon
SPTR_PROGRAM  Executable object icon
SPTR_SIZE  Sizing pointer
SPTR_SIZENESW  Sizing pointer from upper right to lower left
SPTR_SIZENWSE  Sizing pointer from upper left to lower right
SPTR_SIZENS  Vertical sizing pointer
SPTR_SIZEWE  Horizontal sizing pointer
SPTR_SIZETEXT Text "I-beam" pointer
SPTR_WAIT Waiting pointer

bLoad specifies whether the handle to the pointer that the system loaded during its initialization should be returned or whether the pointer should be loaded again and a new handle returned. To make modifications to the pointer for use within your application, bLoad should be specified TRUE. This function returns a handle to the specified pointer or to a copy of the specified pointer, depending on the value of bLoad.

Pointers and icons that were loaded explicitly by an application are destroyed using the WinDestroyPointer function.

BOOL     APIENTRY WinDestroyPointer(HPOINTER hpPointer);
hpPointer specifies the handle of the pointer or icon to be destroyed. This function returns a flag indicating  success or failure.

Bitmaps

Bitmaps are similar to their cousins, pointers and icons. However, pointers and icons are of a fixed size, defined by Presentation Manager and cannot be any bigger or smaller. Bitmaps do not have this restriction;they do not have a "transparency" color, though, which is something that pointers and icons do have. Bitmaps in general have many uses - no blanket statement describes their usual purpose in an application.

The manner in which a bitmap is specified within a resource file is like that of the pointer and icon.

BITMAP resid filename
This causes the bitmap file with the specified name, filename, to be included in the resource tables and be assigned the specified resource id, resid.
Bitmaps are loaded with the GpiLoadBitmap function.
HBITMAP  APIENTRY GpiLoadBitmap(HPS hpsWnd,
                                HMODULE hmDll,
                                ULONG idBitmap,
                                LONG lWidth,
                                LONG lHeight);
hpsWnd is a handle to the presentation space that is used to load the bitmap; this parameter is complex and will not be discussed. hmDll is a handle to a DLL that contains the resources, if this is the case. Again, if the resource is appended to the executable, NULLHANDLE should be specified. idBitmap is the resource identifier of the bitmap to be loaded. lWidth and lHeight are the width and height to which the bitmap should be stretched, if this is desired. Specifying 0 for  both of these parameters specifies that the bitmap should be kept at its original size. This function returns a handle to the bitmap loaded.
Drawing a bitmap is accomplished in one of many ways. We will look at the simplest of these, which is to use the WinDrawBitmap function. Like WinDrawPointer, this will draw a bitmap into a presentation space that is associated with a window.
BOOL  APIENTRY WinDrawBitmap(HPS hpsWnd,
                             HBITMAP hbmBitmap,
                             PRECTL prclSrc,
                             PPOINTL pptlDst,
                             LONG clrFore,
                             LONG clrBack,
                             ULONG ulFlags);
hpsWnd is, again, a handle to a presentation space in which the bitmap will be drawn. hbmBitmap is a handle to the bitmap to be drawn. prclSrc points to a RECTL structure that defines the portion of the bitmap to be drawn. If NULLHANDLE is specified, the entire bitmap is drawn. pptlDst specifies the point corresponding to where the lower left corner of the bitmap is to be in the presentation space.
clrFore  and clrBack are the foreground and background colors and are used for monochrome bitmaps only.  ulFlags specifies how the bitmap is to be drawn and can be one of the constants depicted in Table 12.5
 
Table 12.5 Values for  ulFlags
Constant Description
DBM_NORMAL Draw the bitmap in  a "normal" fashion.
DBM_INVERT Draw the bitmap in a color-inverted state.
DBM_HALFTONE Draw the bitmap in a halftone manner.
DBM_STRETCH Draw the bitmap stretched to fit prclSrc.
DBM_IMAGEATTRS Draw the (monochrome) bitmap using the current foreground and background colors of the presentation space. clrFore and clrBack are ignored if this is specified.

This function returns a flag indicating its success or failure.

We've used the word "monochrome" twice, so it is helpful to be able to determine what the parameters are that were used to create the bitmap. This is done with the GpiQueryBitmapInfoHeader function

BOOL    APIENTRY GpiQueryBitmapInfoHeader(HBITMAP hbmBitmap,
                                          PBITMAPINFOHEADER2 pbmpData);
hbmBitmap is a handle to the bitmap in which the programmer is interested. pbmpData points to a very interesting structure - BITMAPINFOHEADER2.

typedef struct _BITMAPINFOHEADER2        /* bmp2  */
{
   ULONG  cbFix;            /* Length of structure                    */
   ULONG  cx;               /* Bit-map width in pels                  */
   ULONG  cy;               /* Bit-map height in pels                 */
   USHORT cPlanes;          /* Number of bit planes                   */
   USHORT cBitCount;        /* Number of bits per pel within a plane  */
   ULONG  ulCompression;    /* Compression scheme used to store the bitmap */
   ULONG  cbImage;          /* Length of bit-map storage data in bytes*/
   ULONG  cxResolution;     /* x resolution of target device          */
   ULONG  cyResolution;     /* y resolution of target device          */
   ULONG  cclrUsed;         /* Number of color indices used           */
   ULONG  cclrImportant;    /* Number of important color indices      */
   USHORT usUnits;          /* Units of measure                       */
   USHORT usReserved;       /* Reserved                               */
   USHORT usRecording;      /* Recording algorithm                    */
   USHORT usRendering;      /* Halftoning algorithm                   */
   ULONG  cSize1;           /* Size value 1                           */
   ULONG  cSize2;           /* Size value 2                           */
   ULONG  ulColorEncoding;  /* Color encoding                         */
   ULONG  ulIdentifier;     /* Reserved for application use           */
} BITMAPINFOHEADER2;
typedef BITMAPINFOHEADER2 *PBITMAPINFOHEADER2;

The GpiQueryBitmapInfoHeader  function returns a flag indicating success or failure of the function..
In  OS/2 versions l.x. this structure was called BITMAPINFOHEADER and contained only the first five fields. In the current structure, PM developers have enabled programmers to have much more control over the creation of a bitmap (or, in this situation, much mow information about a bitmap). However, they also realized that programmers probably still will use only the first five fields. So,  the Gpi requires only that programmers initialize all fields up to the last one they are interested in and that they specify the number of bytes initialized in the cbFix field; and if the parameters of an existing bitmap are being queried, only cbFix needs to be initialized to specify how many bytes need to be returned. Thus, if cbFix  has the value 16. only the first five fields (sizeof(cbFix) + sizeof(cx) + sizeof(cy) + sizeof(cPlanes) + sizeof(cBitCount) = 16) would be provided, but any value that makes sense, up to the size of the structure, can be specified. Before GpiQueryBitmapInfoHeader is called, cbFix should be initialized to specify bow much information should be returned.
 
 
Gotcha!
Initializing cbFix to the proper value is a must when calling the GpiQueryBitmapInfoHeader function, or unpredictable information will be returned.

cx and cy specify the width and height of the bitmap. cPlanes specifies the number of color planes used by the bitmap; while OS/2 supports multiplane bitmaps, the APIs to draw bitmaps support only single-plane bitmaps. cBitCount specifies the number of bits it takes to represent one pel in the bitmap and can have a value 1, 2, 4, 8, or 24; if the value is 1, it is a monochrome bitmap, since it can base only 21 colors. ulCompression specifies the compression scheme used to compress the bitmap in memory and can be one of the values listed in Table 12.7.
 
Table 12.7 Values for  ulCompression
Constant  Description
BCA_UNCOMP  Uncompressed
BCA_HUFFMAN1D  Huffman encoding scheme
BCA_RLE4  Run-length encoding for 4 bit-per-pel (BPP) bitmaps
BCA_RLE8  Run-length encoding for 8 BPP bitmaps
BCA_RLE24  Run-length encoding for 24 BPP bitmaps

cbImage specifies how much memory is needed to store the bitmap data. cxResolution and cyResolution specify  the resolution of the device for which the bitmap was intended to be displayed upon. This does not  prohibit the bitmap from being displayed on another display type; it merely indicates the display type for which the bitmap was drawn. cclrUsed, cclrImportant, ulRecording, ulRendering, cSizel, cSize2,  and ulColorEncoding all  specify additional data as described in structure's comments and are beyond the scope of this text.

Bitmaps are destroyed using the GpiDeleteBitmap function.

BOOL     APIENTRY GpiDeleteBitmap(HBITMAP hbmBitmap);
hbmBitmap specifies the handle to the bitmap to be deleted. This function returns a flag indicating the success or failure of the function.

String tables.

String tables are very simple in concept and implementation. They age lookup tables where the application provides the resource identifier of a string  and Presentation Manager provides the corresponding text that was defined in the resource file. The purpose of a string table is to allow easy translation of an application to other languages, providing all of the "user-readable" text is placed into a string table. "User-readable" in  this sense means text that the user sees; window class names would not be included in this group, but messages would be.

Unlike all other resources, string tables do not have a resource identifier explicitly assigned to them by the programmer. Instead, the resource compiler breaks up the string table into groups of 16 strings and automatically assigns an identifier to each 16- string group. A string table has the following form in a resource file.

STRINGTABLE
{  resid1,   "string1"
    rasid2,   "string2"'
    rasid3,   "string3"'
}
As was stated earlier and is now obvious, a string table is simply that - a table of strings. Each string has a unique identifier associated with it, which is specified on the call to WinLoadString which loads a string from the string table.
LONG    APIENTRY WinLoadString(HAB habAnchor,
                               HMODULE hmDll,
                               ULONG ulId,
                               LONG lSzBuffer,
                               PCSZ  pchBuffer);
habAnchor  is the handle to the anchor block of the calling thread. hmDll is the handle to the  DLL where the string table resides, or NULLHANDLE if it resides in the executable's resource tables. ulId is the identifier of the string to be loaded. lSzBuffer specifies  the size of the buffer pointed to by pchBuffer. This function returns  the number of characters loaded from the string table, up to a maximum of  lSzBuffer - 1.

That's all there is to it!

Accelerators

Accelerators are "shortcut" keys that accelerate the rate at which a user is able to complete certain tasks within an application. The accelerator table defines a translation from a keystroke, modified by the Alt, Ctrl, or Shift keys if specified, to a numeric identifier that is sent to the application via the WM_COMMAND message.
The accelerator table has the following form.
ACCELTABLE resid
{
  key, cmd_id, type  [, modifiers ]
  key, cmd_id, type  [, modifiers ]
  key, cmd_id, type  [, modifiers ]
}
resid is the resource identifier for the accelerator table, key is the base key for the accelerator and can be a VK_ constant (e.g. VK_F1) or a character in quotes. cmd_id is the numeric identifier to be sent as  SHORT1FROMMP(mpParm1) in the WM_COMMAND message. type is the type of character and must be CHAR or VIRTUALKEY. modifiers are optional and can be one or more of those listed in Table 12.8,  separated by commas.
Table 12.8 Values for modifiers
Modifier Description
CONTROL  Ctrl key must be pressed.
ALT  Alt key must be pressed.
SHIFT Shift key must be pressed.
Gotcha!
If a character (instead of a virtual key) is specified (or an accelerator, it is case-sensitive, so two entries must he provided to cover both possibilities of the shift key stale (unless each case should have different meanings, of course).
If the sole modifier of a character accelerator is the control key, the CONTROL modifier  may be be omitted and the key prefixed with a caret symbol, "^"., Also, keys that are not virtual  keys must be specified in quotes.
ACCELTABLE RES_CLIENT
{  "^O", MI_OPEN
   "^o", MI_OPEN
}
Accelerator tables usually are associated with standard windows through the use of it FCF_ACCELTABLE  frame control flag. However, an accelerator table can be loaded explicitly with WinLoadAccelTable function.
HACCEL APIENTRY WinLoadAccelTable(HAB habAnchor,
                                  HMODULE hmDll
                                  ULONG idAccelTable);
habAnchor is the handle to the anchor block of the calling thread. hmDll is the handle to the DLI if the accelerator table resides there, or  to NULLHANDLE if is in the executable's resource tables. idAccelTable is the resource identifier of the accelerator table. This function returns a handle to the loaded accelerator table.
After an accelerator table is loaded, is can be made active with the WinSetAccelTable function.
BOOL   APIENTRY WinSetAccelTable(HAB habAnchor,
                                 HACCEL haAccel,
                                 HWND hwndFrame);
habAnchor  is the handle to the anchor block of the calling thread. haAccel  is the handle to the accelerator table o be made active. hwndFrame is the handle to the frame window to which the accelerator table attached. This function returns a flag indicating success or failure.

For each message queue, there are certain "standard" accelerators that are defined, such as Alt+F4 to close a frame window. These are called "queue accelerators," since they are in effect for the entire message queue and are independent of the active window. If hwndFrame in the call to WinSetAccelTable  is NULLHANDLE, the accelerator table replaces the queue accelerator table.
Accelerator tables are destroyed with the WinDestroyAccelTable function.

BOOL   APIENTRY WinDestroyAccelTable(HACCEL haAccel);
This function destroys the accelerator table whose handle is specified in haAccel and returns a flag indicating success or failure.
 

Dialog Boxes

Dialog boxes are complicated beasts, but their use is simplified greatly through the use of the "dialog box" editor DLGEDIT.EXE (as well as through the use of resource editor URE named IRE in VisualAge C++ 4) A dialog box is described in a resource file using the dialog template. This template consists of three parts: The nice thing is that the dialog box editor will create the template for the programmer; all he or she needs to do is build the dialog box using its WYSIWYG interface. When the work is saved in the dialog box editor, a dialog file (.DLG) is generated, containing the dialog templates corresponding to the dialog boxes that the programmer designed.
However, it is nice to know how to make minor adjustments manually, so let us look briefly at the format of  of the dialog template.
DLGTEMPLATE resid
{
  DIALOG "title text", resid, x, y, cx, cy, style, flags
  [CTLDATA controldata]
  [PRESPARAM presparam]
  {  CONTROL "text", id, x, y, cx, cy, class, style
      [CTLDATA controldata]
      [PRESPARAM presparam]
   }
}
Gotcha!
The resid on the DLGTEMPLATE and DIALOG statements must match, or the dialog will fail to load. Why the same constant must be specified twice is beyond our understanding.

x,y, cx, and cy are the coordinates of the lower left corner and the size of the dialog or window, respectively. style is one or more style flags;  since a dialog is really nothing more than a subclassed frame window, it can use the FS_ constants in addition to the WS_ constants. The child windows (CONTROL statement) can use the WS_. constants as well as the constants specific to their window class. class can be a WC_ constant or an application-defined class-registered prior to the loading of the dialog with WinRegisterClass - in double quotes.

The control data (CTLDATA statement) is used to initialize the dialog or the child window, as will be shown in later chapters. The presentation parameters (PRESPARAM statement) define the appearance, such as the font used, the foreground and background colors, and so on. See Chapter 9 for more information on setting presentation parameters.
It should be noted that the coordinates and size of the dialog and the child windows are based on a different coordinate system; the units are dialog units, which are based on the average character width of the system font for the resolution of the display. The concept-went-awry is that dialog units are supposed to be "display independent," meaning that the dialog will occupy the same amount of physical space on different resolutions; however, most monitors (in 1995) do not report their pel densities properly, so this rarely works. WinMapDlgPoints  can be used to convert between dialog units and pels.

BOOL    APIENTRY WinMapDlgPoints(HWND hwndDlg,
                                 PPOINTL pptlPoints,
                                 ULONG ulNumPoints,
                                 BOOL bCalcWindowCoords);
hwndDlg is the handle to the dialog window. pptlPoints points to one or more POINTL structures to convert. ulNumPoints specifies how many structures pptlPoints points to. bCalcWindowCoords  is TRUE if the programmer wants to convert to window coordinates from dialog coordinates or FALSE if the opposite is desired.

Menus

Menus are a familiar user-interface component to anyone who has used a Macintosh,  Windows, OS/2 or some other GUI. Their definition in a resource file is also quite simple, for there are only three different parts: the main "MENU" keyword, submenu definitions, and menu item definitions.
MENU resid 
{
    SUBMENU "Text", submenu_id  [,styles]
    {
  MENUITEM "Text", menuitem_id  [,attributes]
        MENUITEM "Text", menuitem_id  [,attributes]

     }

}
resid is the resource identifier of the menu, submenu_id and menuitem_id are unique identifiers of the submenus and menu items, respectively. They are used when communicating with the menu via the MM_ messages, styles are one or more MIS_ constants that affect the entire submenu. attributes  are one or more MI_A constants that affect a specific menu item. Both styles and  attributes optional.
See Chapter 14 for more information on using menus.

Help Tables

Help tables are used to provide a linkage between the application's child windows (including menu items, which are child windows in an odd way) and the help panels which are defined by a help developer. As you will see in Chapter 29, there are two parts to this linkage: the HELPTABLE and the various HELPSUBTABLES. See that chapter for information on the resource file syntax and how online help is provided by an application.

Application-defined Data

Application-defined data is the general case for all resources. In facts all of the APIs discussed in this chapter for loading resources follow these instructions in the bowels of the Presentation Manager code. The OS/2 kernel provides two APIs for resource management that are used to load and unload a specific resource - DosGetResource  and DosFreeResource .
APIRET APIENTRY  DosGetResource(HMODULE hmDll,
                                ULONG ulType,
                                ULONG ulId,
                                PPVOID ppvData);

APIRET APIENTRY  DosFreeResource(PVOID pvData);

hmDll is the handle to the DLL where the resource resides, or is NULLHANDLE if it is found in the executable's resource tables. uIType is an RT_ constant that specifies the type of the resource.
Table 12.9 Resource Type Constants
Constant Description
RT_POINTER Pointer data
RT_BITMAP Bitmap data
RT_MENU Menu template
RT_DIALOG Dialog template
RT_STRING String table
RT_FONTDIR Font directory
RT_FONT Font data
RT_ACCELTABLE Accelerator table
RT_RCDATA Binary data
RT_MESSAGE Error message
RT_DLGINCLUDE File name for the DLGINCLUDE statement
RT_HELPTABLE Help table for Help Manager
RT_HELPSUBTABLE Help subtable for Help Manager

ulId is the resource identifier to be loaded. ppvData is a pointer to a pointer that is initialized by OS/2 to point to the beginning of the resource data. This pointer is specified on the call to DosFreeResource to return the memory consumed to the system, since OS/2 allocates the memory for the programmer when DosGetResource is called.
In the resource file, application-defined data must reside in a separate file and is included via the RESOURCE keyword.

RESOURCE type resid filename
type and resid correspond to their definitions as described earlier, and filename is the name of the file where the resource data resides. It should be noted  that application-defined resources must have a value for type of 256 or greater.
[ Next ] [ Previous ] Chapter 12
[Contents ]  [ Chapter 11: Window Messages and Queues ] [ Chapter 13: Dialog Boxes ]