For most programmers, the first encounter with GStrings (often, in fact, their first encounter with any sort of graphics mechanism) is with a program icon. Often this program icon consists of one or more GStrings, each of which contains a bitmap. These monikers are often set up using the
@visMoniker
keyword. This automatically stores the GString to a chunk. For an example of a GString stored this way, see the appSMMoniker GString in GString in Visual Monikers.
Code Display 23-3 GString in Visual Monikers
@start AppResource; @object GenApplicationClass AppIconApp = {
/* The visual moniker for this application (an icon) is created by selecting the * most appropriate moniker from the list below. Each moniker in this list is * suitable for a specific display type. The specific UI selects the moniker * according to the display type GEOS is running under. A text moniker is also * supplied if the specific UI desires a textual moniker. */
GI_visMoniker = list { AppIconTextMoniker, /* simple text moniker */ appLCMoniker, /* Large Color displays */ appLMMoniker, /* Large Monochrome displays */ appSCMoniker, /* Small Color displays */ appSMMoniker, /* Small Monochrome displays */ appLCGAMoniker, /* Large CGA displays */ appSCGAMoniker /* Small CGA displays */ } }
@visMoniker AppIconTextMoniker = "C AppIcon Sample Application"; @end AppResource
@start SAMPLEAPPICONAREASMMONIKERRESOURCE, data; @visMoniker appSMMoniker = { style = icon; /* Small monochrome icons use the standard size and 1 bit/pixel gray coloring. */ size = standard; color = gray1; aspectRatio = normal; cachedSize = 48, 30;
/* The following lines hold GString data: */ @gstring { /* GSFillBitmapAtCP: * This macro signals that we want to fill a bitmap. The next few * bytes should consist of information about the bitmap; the data * after that holds the bitmap data. The GString reader will know * when it's done reading the bitmap data based on the size stated * in the bitmap's info--it will thus know where to look for the * next command (in this case a GSEndString() macro. */ GSFillBitmapAtCP(186), /* Bitmap(): * This macro is used to write basic information about the bitmap * to the GString. In this case, that information consists of: * The bitmap is 48x30. It is compressed using PackBits. It is * monochrome. */ Bitmap (48, 30, 0, BMF_MONO), /* 0x3f, 0xff, 0xff, ...: * These numbers are the bitmap data itself. */ 0x3f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x80, 0x00, 0x60, 0x60, 0x00, 0x01, 0xc0, 0x00, 0x60, 0x60, 0x00, 0x03, 0xe0, 0x00, 0x60, 0x60, 0x00, 0x07, 0xf0, 0x00, 0x60, 0x60, 0x00, 0x03, 0xf8, 0x03, 0xfe, 0x60, 0x00, 0x01, 0xfc, 0x00, 0xf9, 0x60, 0x06, 0x04, 0xfe, 0x01, 0xfd, 0x60, 0x38, 0x06, 0x1f, 0x01, 0xfd, 0x60, 0x40, 0x03, 0x63, 0x81, 0x05, 0x60, 0x80, 0x01, 0xa3, 0xc1, 0x04, 0x60, 0x40, 0x00, 0xc3, 0x81, 0x04, 0x60, 0x38, 0x00, 0x6f, 0x01, 0x04, 0x60, 0x07, 0xfe, 0xf6, 0x00, 0x88, 0x60, 0x00, 0x01, 0xfc, 0x01, 0x8c, 0x60, 0x00, 0x03, 0xfe, 0x03, 0xde, 0x60, 0x00, 0x07, 0xf5, 0x07, 0x77, 0x60, 0x00, 0x03, 0xe2, 0x8f, 0xaf, 0x60, 0x00, 0x01, 0xc3, 0xdf, 0xdf, 0x60, 0x00, 0x00, 0x81, 0xff, 0xff, 0x60, 0x00, 0x00, 0x00, 0xff, 0xff, 0x60, 0x00, 0x00, 0x00, 0x7b, 0xff, 0x60, 0x00, 0x00, 0x00, 0x03, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, /* GSEndString(): * This macro lets the GString interpreter know we're done. */ GSEndString() } }
@end SAMPLEAPPICONAREASMMONIKERRESOURCE;
Notice that this example uses macros to set up the data for the GString. We could have just written the GString data as a series of numbers, as shown in GString Declared Without Macros, but the macros are usually easier to read. Each macro's name, you will notice, is taken from the corresponding graphics command name. Thus the
GSFillBitmap()
macro corresponds to the
GrFillBitmap()
routine. There are no GSGet...() macros; GStrings have no return values or conditional statements, and thus have no use for retrieving this sort of information.
Code Display 23-4 GString Declared Without Macros
const char byte myGString[] = { GR_SET_LINE_STYLE, /* First we set the line style. */ LS_DASHED, /* We want a dashed line. */ 0, /* Draw dashes starting with index 0 */
GR_DRAW_RECT_TO, /* Next we draw a rectangle from our current * position to... */ 0, 72, 0, 72, /* ...the point (72, 72). (We need the zeroes * because GStrings are arrays of bytes, but * we need a word to describe each * coordinate. */ GR_END_GSTRING }; /* myGString */
Just as all monikers are not GStrings, not all GStrings need be declared as monikers. See Statically Declared GString for an example of a statically declared GString taken from the Moniker sample application; here the declared GString is eventually used as a moniker, but could just as well have been passed to
GrDrawGString()
and drawn to an arbitrary graphics space.
Code Display 23-5 Statically Declared GString
static void _near SetPreDefinedGStringMoniker(void) { /* * A predefined graphics string that draws a * MONIKER_WIDTH by MONIKER_HEIGHT * light-blue rectangle at 0, 0. */ static const byte gstring[] = { GSSetAreaColorIndex(C_LIGHT_BLUE), GSFillRect(0, 0, MONIKER_WIDTH, MONIKER_HEIGHT), GSEndString() };
@call CycleMonikerTrigger::MSG_GEN_REPLACE_VIS_MONIKER( VUM_NOW, /* Update appearance immediately */ MONIKER_HEIGHT, MONIKER_WIDTH, /* Since source is a GString, we need to * pass the height and width of the * GString. */ sizeof(gstring), /* Pass the size of sourceGString. */ VMDT_GSTRING, /* Source is a gstring.... */ VMST_FPTR, /* ...referenced by a far pointer */ (dword) gstring); /* Pointer to gstring */ } /* End of SetPreDefinedGStringMoniker() */
For more examples of statically declared GStrings, see the Moniker, GSTest, and GSTest2 sample applications.