### Converting Application Resources

Open Class Library provides tools to help you convert Windows, OS/2, and Motif resource files.

AIX does not support Windows and OS/2 Presentation Manager (PM) dialog templates. If you write portable applications, use canvases instead of dialog templates. The Hello World version 4 sample application shows you how to do this.

You define resources in a resource file. A resource file is a file that contains data that your application uses, such as text strings and icons. For example, you can define menus, menu items, strings, icons, bitmaps, accelerators, and help tables in the resource file. You also define the string ID, corresponding to each static string you use in a window in the resource file.

The resource compiler produces a binary version of the resources, which is then bound into the application's executable code or stored in a dynamic link library (DLL) for Intel or shared library for AIX.

A benefit of defining resources in a resource file is that you can make changes to resource definitions without affecting the application code itself.

You can also provide national language versions by storing the resources for each language in a separate resource file. You can then build your application as separate executable versions for each language (each with a different resource file bound to it) or as a single executable with a separate DLL or shared library for each language.

#### Defining Window Resources

Window resources are read-only data segments stored in an application's .exe file or in the dynamic link library's .dll file.

Predefined Open Class Library window resources include keyboard accelerator tables, icons, menus, and bitmaps.

Most window resources are stored in a format that is unique to each resource type. The system translates the formats, as necessary, for use in functions.

To access window resources, you must prepare a resource file (ASCII file with the extension .rc). Then the ASCII resource file and any bitmap and icon files must be compiled into a single binary file using the resource compiler. The binary resource file is bound to your application's .exe file or to a dynamic link library's .dll file.

#### Understanding Dialog Templates

A dialog template is a data structure that describes a dialog window and its control windows. Windows and PM uses the data in the dialog template to create the dialog window and control windows. An application can create a dialog template at run time, or it can use the system resource compiler to create a dialog-template resource.

Motif does not support dialog templates. If you write portable applications, use canvases instead of dialog templates. The Hello World 4 sample application shows you how to do this.

#### Accessing Bitmap and Icon Resources

To convert bitmap and icon resources between the Windows and OS/2 operating systems, use the IBMPCNV tool provided with the VisualAge C++ product.

The Motif resource compiler understands both OS/2 and Windows bitmap and icon formats.

The Open Class Library accesses bitmap and icon resources using an IResourceID (an unsigned long).

#### Adding Keyboard Accelerators

A keyboard accelerator is a keystroke or a series of combined keys that generate a command message for an application. Using a keyboard accelerator lets a user quickly access commands. It has the same effect as choosing a menu item.

Your application can load accelerators either statically or at runtime. The resource file is compiled and bound to the application. Then, the application frame window loads the accelerator table with the same resource ID, if found. The Open Class Library also provides IAccelerator, IAcceleratorKey, and IAcceleratorTable classes to add accelerators at runtime.

The following example shows how to define accelerators in a resource file:

    ACCELTABLE ID_MAIN
    {
        "I",  ID_ABOUT_ITEM, CONTROL, SHIFT, ALT
        "I",  ID_ADD_ITEM,   CONTROL, SHIFT
        "a",  ID_ASC-ITEM,   CONTROL
        "d",  ID_DESC_ITEM,  CONTROL
    }

When a user presses a key sequence of Ctrl+Shift+Alt+I, this causes an ID_ABOUT_ITEM event. A Ctrl+Shift+I key sequence causes an ID_ADD_ITEM command event. Notice that the more restrictive accelerator is coded first in the previous example.

Without accelerators, a user might generate commands by pressing the Alt or F10 keys for OS/2 and Windows, or the F10 key for Motif. These keys access the menu bar where you can use the Arrow keys to select the item, and then press the Enter key to choose the item. In contrast, accelerators let users generate commands with fewer keystrokes.

Although accelerators are usually used to generate existing commands as menu items, they also can send commands that have no menu-item equivalent.

#### Understanding Accelerator Tables

An accelerator table contains an array of accelerators.

Accelerator tables exist at two levels within the operating system: a single accelerator table for the system queue and individual accelerator tables for application windows.

Accelerators in the system queue apply to all applications. For example, the F1 key always generates a help message.

Having accelerators for individual application windows ensures that an application can define its own accelerators without interfering with other applications. An accelerator for an application window can override the accelerator in the system queue.

An application can modify both its own accelerator table and the system's accelerator table.

#### Converting Resource Files

The CONVRC tool on OS/2 and Windows converts resource (.rc) files between the two operating system formats. The IRCCNV tool on Motif converts a Windows resource file to the OS/2 format. Open Class Library uses the OS/2 format on the Motif operating system. There is no extension to invoke CONVRC under a build, it should be done manually or with a makefile.

To use the CONVRC on the Windows and OS/2 operating systems, use the following syntax in the VisualAge C++ command Line window:

    CONVRC -option input output

To convert from Windows to OS/2, you need to specify the following option:

    CONVRC -w input output

The current platform's resource files have a .rc file extension.

The following example shows the CONVRC command to use to convert an OS/2 PM resource file, myapp.rc, to a Windows resource file:

    CONVRC -o myapp.rcx myapp.rc

Note: | The IBM VisualAge C++ resource compiler uses extended menu support. To convert resource files to use native Windows menu support, use the option`-n`.

To use IRCCNV on Motif, use the following syntax:

    irccnv -option input output

Since Motif's resource compiler understands the OS/2 format, no conversion is needed for OS/2 resource files.

To convert Windows to OS/2 format on Motif, use the following:

    irccnv -o input output

#### Working with the Conversion Tool

The CONVRC and IRCCNV tools handle the following types of resources:

  accelerator table (ACCELTABLE)
  bitmap (BITMAP)
  extended menus (MENUEX)
  help tables (HELPTABLE)
  help subtable (HELPSUBTABLE)
  icon (ICON)
  menu (MENU)
  menu item (MENUITEM)
  pointers(POINTER) This is OS/2 only
  string table (STRINGTABLE)
  submenu (SUBMENU)

Also keep in mind the following:

- CONVRC and IRCCNV error checking do not flag the same errors as the resource compiler. For example, incomplete lines and missing commas produce erroneous output from IRCCNV but no error message. When you use these tools, check input files for errors using the resource compiler.
- IRCCNV processes only a single input file. For this reason, do not use wildcard (*) characters in the input file name.
- IRCCNV does not convert included files. Convert each included file individually.
- IRCCNV does not convert dialog templates as they are not a portable solution. Use the ICanvas class instead.
- IRCCNV does not change included headers.
- The accelerator table, menu, menu item, string table, and submenu definitions cannot span multiple lines:

      STRINGTABLE
      BEGIN
        STR_HELLO,
          "Hello World"
      END

#### Supporting Double-Byte Character Set and Multiple Languages

You can use one source file for your application code and then provide the double-byte character set (DBCS) and support multiple languages by using separate resource files for each of the languages you support. The Open Class Library approach includes either of the following:

- Use a single executable file with a separate .DLL for each language.
- Use separate executable files for each language (each with a separate resource file bound to it).

The following suggestions can assist you in creating DBCS-enabled applications:

- Use the canvas classes to build dialogs because you define message strings in resource files, you can translate them easily to another language without changing the source code.
- Use the IString class, which is DBCS-enabled and supports mixed strings that contain both the single-byte character set (SBCS) and DBCS characters. Objects of the IString class are essentially arrays of characters. The IString class provides functions to test the characters that make up the string. These functions help users determine whether a character is single byte or multiple byte, and whether it is a valid DBCS first byte.
- Use the IDBCSBuffer class, which ensures that the search functions do not inadvertently match the second byte of a DBCS character. The IDBCSBuffer class is derived from the IBuffer class, which holds the IString contents. The two bytes of a DBCS character will not be split.

  Use the following member functions in a DBCS-enabled application:

  Member Function | Returns True If...
  --- | ---
  isCharValid | The character at the given index is in the set of valid characters
  isDBCS1 | The byte at the given offset is the first byte of DBCS
  isPrevDBCS | The character preceding the one at the given offset is a DBCS character

- Specify one of the following data type styles when you create and manage the IEntryField and IComboBox classes:

  Data Type Styles | Allows the Following Input...
  --- | ---
  anyData | A mixture of SBCS and DBCS characters.
  dbcsData | DBCS-only data.
  mixedData | A mixture of SBCS and DBCS characters. Use this style if you plan to convert data to an EBCDIC code page.
  sbcsData | SBCS-only data.

- Specify the appDBCSStatus style when constructing an IFrameWindow to include a DBCS status area when the frame appears in a DBCS environment. The Open Class Library automatically shares DBCS status control between a parent and child frame window.

#### Using Bidirectional Language Support

After you develop your application you can port it to run on a bidirectional environment with a few code changes.

The IBidiSettings class contains the settings from the operating system and user for bidirectional (BIDI) language support. IBidiSettings allows you to query and change the BIDI attributes of an existing window. IBidiSettings also allows you to set the BIDI attributes of a presentation space. Most applications only need to use the following static functions:

- IBidiSettings::isBidiEnabled
- IBidiSettings::setApplicationDefaults

The Open Class Library has built-in BIDI support for reversing the positions of windows, primarily implemented in canvases, toolbars, and frame extensions. Other BIDI support in Open Class controls is implemented at the operating system level.

Additional functions are used if you need a mix of left-to-right (LTR) and right-to-left (RTL) looks and processing.

Application-level BIDI attributes used to set BIDI characteristics are used by top-level windows (windows parented to the desktop or created with no parent). Typically, these are primary frame windows. All other windows the inherit BIDI attributes of their parent window. Application-level attributes can be set using IBidiSettings::setApplicationDefaults or using the BIDIATTR environment variable and WinSetLangInfo for the OS/2 operating system.

Setting application-level BIDI attributes overrides BIDI Attributes set using Motif resources. Also, Motif does not support changing BIDI attributes of Windows after they have been created. To maintain a portable application, set the application-level BIDI attributes and modify them for individual windows using the IWindow::leftToRight and IWindow::rightToLeft styles.

##### Platform Specific Information

The Windows and OS/2 operating systems have similar BIDI support in that the controls manage themselves in a BIDI system. IWindow objectss are created (CreateWindowEx) with a style of WS_EX_RIGHT and WS_EX_RTLREADING, which are ignored unless the language is Arabic or Hebrew. Then things like the text appearing to the left of a radio button or scroll bars appearing on the right are all handled by the operating system. Menu support for Windows requires some additional code in the resource file that is unnecessary in OS/2.

Open Class Library has added support for process-level BIDI attributes with the addition of two public static functions to IBidiSettings:

    static IBidiSettings
      applicationDefaults    ( );
    static void
      setApplicationDefaults ( const IBidiSettings& applicationSettings );

We assign the process-level BIDI attributes to all frame windows we create on Windows and AIX (actually, any window that is parented to the desktop). We also emulate parent-child inheritance of BIDI attributes on Windows and AIX.

There is also a new public copy constructor, assignment operator, and equality operator, and protected default constructor to support the above functions.

The easiest way to pass an object to the set function is to call the query function (applicationDefaults) and then modify it by calling functions like IBidiSettings::setWindowLayout or setTextOrientation. On AIX, setting specific BIDI attributes for the application will override the setting of any corresponding BIDI resources (like XmNtextMode or XmNnssMode). The object returned by applicationDefaults does not reflect the setting of any BIDI resources. On Windows, the layout direction has changed to default to LTR to match OS/2 and AIX On OS/2, applicationDefaults reflect the setting of the BIDIATTR environment variable or process-level calls to WinSetLangInfo.

Note that these process-level values are used only when creating windows parented to the desktop. Other windows inherit at creation time the BIDI attributes of their parent window.

If you create a window yourself, you must control the BIDI attributes you give it. The Open Class Library allows some BIDI attributes to be specified at window creation time

The following are two new public styles added to IWindow:

    static const Style
      leftToRight,    // Gives the window an LTR direction.
      rightToLeft;     // Gives the window an RTL direction.

Both styles would be ignored on a non-BIDI system. Neither is a default style. If neither is specified, the window gets the direction indicated by the process-level BIDI attributes. To change any other BIDI attributes, you must call IBidiSettings::applyToApplication before creating the window. When calling applyToApplication you need to start synchronizing threads to be sure you do not accidentally create more windows than you intended with the special BIDI attributes.

PM-compatible controls on Windows are not be BIDI-enabled.

OS/2-specific information:

OS/2 is the most robust environment, from a BIDI standpoint. OS/2 has a notion of process-level BIDI attributes. By default, the application's layout direction (the most recognized BIDI attribute) is left-to-right (LTR), even on a BIDI machine. You can change this, and other BIDI attributes, by setting the BIDIATTR environment variable. You can also change process-level BIDI attributes dynamically by calling WinSetLangInfo. All top-level windows in an application (windows parented to the desktop) are created with the process-level BIDI attributes. When child windows are created, they inherit the BIDI attributes of their parent window. When you change the BIDI attributes of a window, you can optionally have those changes inherited by its child windows. This option is supported using IBidiSettings::apply.

The easiest way for an application to look right-to-left (RTL) is to set the BIDIATTR environment variable. OS/2 then assigns those process-level BIDI attributes to top-level windows, and their child windows subsequently inherit those attributes. If you do not have any special BIDI requirements (such as having a mix of LTR and RTL windows), you do not even need to use IBidiSettings, so no code changes are necessary in preparing an application written for an English audience to run on a Hebrew or Arabic system (other than standard translation). The Open Class Library BIDI support is designed to support both LTR and RTL applications on a BIDI machine, with little-to-no code changes required by the application.

OS/2 also supports the use of a BIDIPARAM keyword in dialog templates. You can use BIDIPARAM to assign BIDI attributes to a window/control. Use of BIDIPARAM probably overrides process-level BIDI attributes and the inheritance of BIDI attributes (I haven't played around with BIDIPARAM yet).

Windows-specific information:

Enabling a native Windows program for BIDI requires a lot of work, because Windows has no process-level BIDI attributes, and Windows does not have parent-child inheritance of BIDI attributes. As a result, a Windows programmer is responsible for creating all RTL windows with the BIDI styles WS_EX_RIGHT, WS_EX_RTLREADING, and/or WS_EX_LEFTSCROLLBAR. And contrary to the Windows doc, these styles are not entirely ignored on a non-BIDI system.

On Windows, we give all windows a RTL look on a BIDI machine. We do this by always adding WS_EX_RIGHT, WS_EX_RTLREADING, and WS_EX_LEFTSCROLLBAR to all windows we create when on a BIDI machine. This does not allow untranslated applications to easily keep an LTR look, and the behavior doesn't match OS/2.

AIX-specific information:

BIDI widget resources can be set when a widget is created and queried, but they cannot be changed after the widget is created (for example, with XtSetValues). Because of the limitation, IBidiSettings::apply does not work on AIX.

AIX also does not really have process-level BIDI attributes. However, it does support BIDI attributes as resources that you can set in an application resource file or in the .Xdefaults file. This capability allows you to control the BIDI attributes of a single window, or even of just about all windows in all applications (for example, you can place the line *layoutDirection: left_to_right in your .Xdefaults file to set this resource in all widgets that support it). AIX also does not have parent-child inheritance of BIDI attributes.

Resources

Hello World Version 4: Adding Dialogs and Push Buttons Creating Cross-Platform Applications

IAccelerator
IAccelTblHandle
IBidiAettings
IDBCSBuffer
IResourceID
IResourceLibrary
IString