This document covers the following topics:
An image list control is a container of ordered images that can be associated with particular control types, such as list view and tree view controls. It allows images to be efficiently re-used by the control's items without the image being re-loaded from the disk each time. It also ensures that all images are compatible (e.g., are of the same size and color organization).
Image list controls are created, as usual, via the ADD action:
PROCESS GUI ACTION ADD WITH PARAMETERS HANDLE-VARIABLE = #IMGLST-1 TYPE = IMAGELIST PARENT = #DLG$WINDOW STYLE = 'LS' END-PARAMETERS GIVING *ERROR
An image list control may consist of up to two sets of images internally, one consisting
of large images (typically 32 by 32 pixels) and one consisting of small images (typically
16 by 16 pixels). Which of these (if any) is created internally depends on the image list
control's "Large Images (L)" and "Small Images
(S)"
STYLE flags. If neither of these flags are
specified, a single set of images is created, with an explicit image size as determined by
the image list control's ITEM-W and ITEM-H attribute values. If both of these are
zero, small images are assumed.
Images are added to an image list by creating an image control, based on the required image (bitmap or icon) file, as a child of the image list control:
PROCESS GUI ACTION ADD WITH PARAMETERS HANDLE-VARIABLE = #IMG-1 TYPE = IMAGE PARENT = #IMGLST-1 BITMAP-FILE-NAME = 'example.bmp' END-PARAMETERS GIVING *ERROR
Images are appended to the list by default, unless the SUCCESSOR attribute is used to insert them at
a specific position.
Image controls can be categorized into two types: single-image image controls and multi-image image controls.
Single-image image controls contribute a single image to each set of images stored by the parent image list control. That is, if the image list contains both large and small images, one of each is provided by the image control. Single-image image controls may be bitmaps or icons.
Multi-image image controls, as the name suggests, may contribute more than one image (in
each required size) to the parent image list control. Multi-image image controls must be
based on bitmap files, rather than icons, and are distinguishable from single-image image
controls in that their "Composite image (C)"
STYLE flag is set:
PROCESS GUI ACTION ADD WITH PARAMETERS HANDLE-VARIABLE = #IMG-1 TYPE = IMAGE PARENT = #IMGLST-1 STYLE = 'CsT' BITMAP-FILE-NAME = 'composite.bmp' END-PARAMETERS GIVING *ERROR
The number of images in the composite bitmap is automatically calculated from the size of the bitmap and the width and height of the images in the (smallest) set of images stored by the parent image list control. Thus, in the case where both large and small images are stored, the bitmap would typically be 16 pixels high, and (16 * N) pixels wide, where N is the number of images to be stored in the image control. Here is an example of a composite bitmap containing five images:
![]()
In the example provided in the preceding section, two other style flags were specified in addition to the "Composite image (C)" style: namely, the "Scaled (s)" and the "Transparent (T)" style flags. The first of these is absolutely necessary if the parent image list control contains multiple sets of images in different sizes. For example, if large images are also being used, the flag causes the composite image to be scaled internally first before being chopped up into its constituent images, as follows:
![]()
Note that if the "Scaled (s)" style flag were not specified, the composite bitmap would be extended in the background color, rather than being scaled, before being chopped up, as shown below:
![]()
This would result in the following five large images:
Needless to say, this is not normally what you want!
The "Transparent (T)" style flag indicates that the images
should be rendered transparently, such that all pixels in the bitmap's background color
are not drawn. The background color can be explicitly specified by setting the BACKGROUND-COLOUR-VALUE and/or BACKGROUND-COLOUR-NAME attributes for the
image control to the required value. Otherwise, if no color is specified (as in the
previous example), the color of the first (i.e., top-left) pixel in the bitmap is taken as
being the background color.
Of course, both the "Scaled (s)" and the "Transparent (T)" style flags can also be applied to non-composite images.
Apart from not being able to source multiple images (as described above), icons differ from bitmaps in two important ways. Firstly, a single icon (.ICO) file can contain multiple versions of the icons in different sizes. Thus when Natural requires the large image, and the source is an icon file, the large icon defined in the icon file is used, if present, in preference to synthesizing it from one of the other icons in the file by scaling. Similarly, when Natural requires the small image, and the source is an icon file, the small icon defined in the icon file is used, if present. In contrast, bitmap files do not contain multiple images, so if both large and small images are required for an image list, one of the two images (usually the large image) must by synthesized from the other as described in the previous section.
Secondly, icons typically contain a monochrome bitmap (known as the image mask) that
determines which pixels in the image are transparent (i.e., should not be drawn). Thus,
when Natural loads an image from an icon file, and the image control's BACKGROUND-COLOUR-NAME attribute is set to
DEFAULT (or is not specified), and the image control's
"Transparent (T)" style flag is specified without the
"Scaled (s)" style flag, Natural uses the icon's transparency
mask, instead of making the above-mentioned assumption that all pixels in the same color
as the first pixel are to be rendered transparently, as is the case for images loaded from
a bitmap file. If an explicit (i.e., non-default) background color is specified, all
pixels in this color are treated as transparent, regardless of whether an icon or bitmap
is being used. The icon's transparency mask is ignored here, as is also the case if the
icon is scaled.
Therefore, if both large and small images are needed, it may be preferable to use single-image image controls based on icon files containing both large and small representations of the image, rather than use a multi-image image control based on a single composite bitmap. The use of individual icon (.ICO) files has the advantage that the and large representations of the image (assuming that both are provided in the file) can have different levels of detail. The main disadvantage is that it normally takes longer to load the images from multiple icon files than it does to load them from a single composite bitmap file.
Before any images from the image list can be used by a control (such as the tree view or
list view control), the image list must be associated with the control. This association
is achieved by assigning the handle of the image list control to the host control's
IMAGE-LIST attribute. For example:
#LV-1.IMAGE-LIST := #IMGLST-1
Having set the image list, the image list control's images are now available for use by the control's items.
To use a particular image from the parent control's image list for a particular item (e.g. list view item or tree view item), the image to be used has to be specified in one of two ways:
By setting the item's IMAGE attribute to the handle of the
image control and (if necessary) the item's IMAGE-INDEX attribute to the
relative offset of the required image (starting from zero) within the image control.
If the image control only contains one image, it is not necessary to specify an image
index. The image specified must belong to the image list control assigned to the
item's container.
By setting the item's IMAGE-INDEX attribute to the ordinal of
the image within the image list (1=first image, 2=second image, and so on). The item's
IMAGE attribute must be either not
specified or set to the default value of NULL-HANDLE in this case.
In the first case (relative indexing), wrap-around is used on the index. Thus, if an image control has N images, an image index of 0 refers to the first image in the image control, an image index of (N - 1) refers to the last image, and an image index of N refers to the first image again, and so on. Thus, if the image control only contains one image, the relative image index (if specified at all) has no effect: due to wrap-around, the first (and only) image will always be taken.
In the second case (absolute indexing), no wrap-around is used on the image index, which must be in the range 1 through to the number of images in the image list (inclusive). If the specified value is not in this range, no image is displayed for the specified item.
Note that the IMAGE-INDEX attribute can also be applied
to an image control. In this case, the attribute is read-only, and returns the offset
(starting from zero) of the image control's first image within the parent image list
control.
One advantage of using relative indexing is that Natural keeps track the references to the specified image (both in the dialog editor and at run-time) and automatically propagates changes to the image control or to its position in the image list. In practice, absolute indexing is probably most useful in situations where an image list control with a single composite (i.e., multi-image) image control is used, and where the images are not modified at run-time.
There are situations where it is desirable to be able to offer several variations of an image. For example, the displayed image for an item representing a folder may need to be modified to indicated that the folder is active. Rather than providing an image of a folder and an image of an active folder, it may be more convenient to provide only the first of these images, and to indicate the active state via a second image containing only the "active" symbol, which is then superimposed on the first. Such an image is referred to as an overlay image, to distinguish it from the underlying base image.
Overlay images are contained within the same image list that is used to display the base
images, as determined via the host control's IMAGE-LIST attribute. They are
therefore the same size as the base images, but are always rendered transparently, to
allow the underlying image to show through.
To use an overlay image for an item, a value must be specified for the item's OVERLAY and/or OVERLAY-INDEX attributes. These attributes
are used analogously to the IMAGE and IMAGE-INDEX attributes (respectively) for
base images (see above).
For technical reasons, images intended for use as overlay images must be
"pre-registered". In Natural, this is done by setting the image list
control's "O" (Overlay) STYLE. However, if the overlay
controls are defined statically, this style is automatically set by the dialog editor. The
presence or absence of this style distinguishes base images from overlay images.
Consequently, the OVERLAY attribute (if specified) can only
refer to an image control with this style, whereas the IMAGE
attribute (if specified) can only refer to an image control without it. If absolute
indexing (see above) is being used, the IMAGE-INDEX can refer to an
overlay image (which is then "misused" as a base image). However, a
corresponding attempt to use the OVERLAY-INDEX attribute to refer
to a base image fails (no overlay image is drawn).
Windows sets a limit on the number of overlay images that may be defined for an image list. This limit is currently 15. Note that if any composite overlay image controls are used, each sub-image in the composite bitmap counts separately towards this quota.
As an example, suppose we create an image control based on a composite image containing the individual overlay images, as follows:
PROCESS GUI ACTION ADD WITH PARAMETERS HANDLE-VARIABLE = #IMG-2 TYPE = IMAGE PARENT = #IMGLST-1 STYLE = 'COs' BITMAP-FILE-NAME = 'overlays.bmp' END-PARAMETERS GIVING *ERROR
Then, we could create a list view item (say) using the second overlay image from the composite bitmap by executing the following code:
PROCESS GUI ACTION ADD WITH PARAMETERS TYPE = LISTVIEWITEM PARENT = #LV-1 STRING = 'Item with overlay' IMAGE = #IMG-1 IMAGE-INDEX = 3 OVERLAY = #IMG-2 OVERLAY-INDEX = 1 END-PARAMETERS GIVING *ERROR
In the above example, the list view item will use the fourth image from
COMPOSITE.BMP as its base image, and the second image from
OVERLAYS.BMP as the overlay image (relative image indexes are, as
already mentioned, zero-based). Note that the list view item is created anonymously (i.e.,
no explicit HANDLE-VARIABLE attribute value
specified).
Image controls may be modified even if they are currently in use. For example:
#IMG-1.BITMAP-FILE-NAME := 'new.bmp'
Natural keeps track of, and automatically updates and redraws, each item that explicitly (i.e., via relative indexing) references an image from the modified image control. However, if absolute indexing is used, the corresponding items are not updated, even if they are implicitly referring to an image within the modified image control.
Images may be removed from the image list by deleting the complete image control via the
DELETE action. For example:
PROCESS GUI ACTION DELETE WITH #IMG-1 GIVING *ERROR
All items that explicitly (i.e., via relative indexing) reference an image from the deleted image control are automatically updated and redrawn to show no image.
However, if absolute indexing is being used, no automatic updating occurs. For example, suppose an image list control contains three single-image image controls and that items exists that refer to all three images via absolute indexing. If the second image control is deleted, the items that used to refer to the second image would suddenly reference the third image and the items that used to refer to the third image would "fall off the end" and not reference anything. Furthermore, the controls containing the items would not automatically be redrawn to reflect the changes.
It is, of course, also possible to delete all images in the image list in one go, via the
DELETE-CHILDREN action:
PROCESS GUI ACTION DELETE-CHILDREN WITH #IMGLST-1 GIVING *ERROR
This is equivalent to deleting each image in the image list individually.
Note that it is not possible to delete individual images within a composite (i.e., multi-image) image control.
An image list control may be deleted when no longer required, even if it is in use. For example:
PROCESS GUI ACTION DELETE WITH #IMGLST-1 GIVING *ERROR
All controls using the image list control are updated accordingly, and their IMAGE-LIST attribute is automatically reset
to NULL-HANDLE.