Type Library and Element Attributes

When we combine the data structures and elements stored in a type library and encapsulate those structures behind particular interfaces, we can refer to the library and each element in it as "objects." In doing so we raise the question of what sorts of properties these objects have.

The properties of a type library or an element are called attributes. The attributes that apply to the library and most of its elements are described in Table 3-2. Many of the attributes for elements are described through the bits in the Flags attribute.

Attribute

Description

Name

The descriptive name of the type library or element without spaces or punctuation, as in KoalaTypeLibrary, KoalaObject, or IKoala. Every element has a name.

Guid (or Uuid)

A programmatic identifier for the library or element. A library GUID is different from other CLSIDs or IIDs. A module cannot have a GUID; it is optional for a typedef; it is required for all other elements.

Version

The major and minor version of the library or element.

DocString

A short piece of text describing the purpose of the library or element.

HelpFileName

The name of a help file (no path) that contains further information about all the contents of the library. There is only one help file per library, so this attribute applies only to a library and not to individual elements.

HelpContext

The context ID inside HelpFileName, where specific information is found for library or element.

Lcid

A locale identifier, or locale, that describes the single national language used for all text strings in the type library and elements. A type library is intended to be written for a specific national language, with the exception that individual function arguments can be given a locale for the purpose of accommodating functions that might perform translations.

Flags

Bits specifying additional aspects about the library or element. Although there are many element flags, a library has only a few possibilities: no flags at all, hidden (not browsable through user interface), or restricted (controlled programmatically for security).


Table 3-2.

Attributes of a type library and its elements.

You can see that the HelpString, HelpFileName, and HelpContext attributes carry help information along with a type library, but not all of the help information. The idea is that a user can view any element in some sort of browser and quickly get a description of its purpose from the HelpString attribute. If the HelpFileName attribute is available, the browser would also provide a Help button that, when pressed, would launch WinHelp with the HelpContext value to show more information about the library or element.

The Lcid attribute deserves some more discussion. This is usually found only on a library, but it can appear on function arguments as well. As you might expect, a type library, like an owner's manual, will contain text in a specific written language, such as English, Russian, or Arabic. This language applies to everything in the library except specific function arguments. The intention is that you support multiple languages by providing multiple localized type libraries, each of which can coexist on the same machine and can share the same GUID. Registry entries differentiate these localizations.

The Lcid attribute is a value of the type LCID, for locale identifier, which was originally created by the Unicode Consortium. Such an identifier forms the basis for all localization or globalization or internationalization or whateveryouwanttocallittodayization not only of type information but of all other language-sensitive parts of the Win32 API. As part of supporting Unicode, the Win32 API took in the LCID as part of its National Language Support (NLS) API, and OLE uses that part of the operating system to handle its own language concerns.2

Simply said, an LCID, or "locale," as it's called for convenience, is nothing more than a 32-bit value whose lower 16 bits contain a "language identifier," or LANGID:

The Win32 macro MAKELCID will create one of these 32-bit values from a 16-bit LANGID through a bitwise OR with a 32-bit zero value. The LANGID itself contains a primary-language value and a sub-language value. The primary language (the lower 10 bits) identifies a generic category of languages, such as English, in which the sub-language (the upper 6 bits) identifies variations of the primary language such as American, British, Australian, Irish, New Zealand, and Canadian English:

A caution: it is very easy to mistakenly think of the primary and sub-language fields in a LANGID as being both 8 bits because that's how we intuitively think about bits. This can get you into a lot of trouble and confusion, so take a few well-invested moments to study the 10-bit/6-bit structure of this type.

Enough with the meditation. There are a number of macros to assist you in creating or decomposing a LANGID given values for the primary language and the sub-language:

MAKELANGID(primary, sub)

Creates a LANGID

PRIMARYLANGID(langID)

Extracts the primary language value

SUBLANGID(langID)

Extracts the sub-language value

LANGIDFROMLCID(lcid)

Chops off the upper 16 bits of lcid


The OLE and Win32 header files define constants of the form LANG_<primarylang> for all known primary languages as well as symbols of the form SUBLANG_<sublang> for all variations of the primary languages. So you can specify primary languages from Albanian to Catalan to Rhaeto-Romanic to Urdu,3 and sub-languages from Simplified Chinese to Brazilian Portuguese to Mexican or Modern Spanish. The header files have the most up-to-date list of language IDs, more current than any documentation.

Some of the more common LANGIDs you'll see are 0x0409 for American English (English primary language 9, American sub-language 1), 0x0009 for basic English, and 0x0000 for "neutral." The neutral language is generally the one used at the programming level and not the user interface level, and so it is typically English.

For the most part, you'll localize to primary languages, taking considerations about specific regions into account much less frequently. Specifying a sub-language is usually necessary only when you need to use words like "wrench," "semitrailer," and "cookie" in American English, which translate to "spanner," "lorry," and "biscuit" in British English.

This is not meant to be an exhaustive study of language and locale identifiers, just enough of one to make you aware of them and what they contain, because they apply to type information. Locales will come into play again when we talk about OLE Automation in Chapters 14 and 15. If you're interested in learning more about locales, please refer to the OLE and Win32 programmer's references as well as Developing International Software for Windows 95 and Windows NT, by Nadine Kano.

2 The NLS API is documented in the Win32 Programmer's Reference, volumes 2 and 5, particularly Appendix C of volume 2. (Note that the "String Manipulation and Unicode" chapter in volume 2 refers to Appendix C of volume 5, but this is incorrect: Appendix C is actually in volume 2.) These API functions allow you to retrieve the current user's locale identifier as well as locale-specific information.

3 OK OK so I picked the lesser-known languages from the list. (Urdu is actually last alphabetically.) Catalan is a Romance language used in Catalonia Valencia and the Balearic islands all eastern regions of Spain (around Barcelona) as well as Andorra the tiny country wedged between Spain and France. Rhaeto-Romanic is a Romance language of eastern Switzerland northeastern Italy and the adjacent parts of Austria. Urdu is an Indic language that is widely used in India and is an official literary language of Pakistan.