22 November 2010

ImageList Ocx Part 2

In the introduction to the GFA-BASIC 32 ImageList Ocx (1) the emphasis was placed on the creation of the image list common control, which – as we saw - is delayed to the moment the first picture is added to the control. All images have the same size. The size is determined by the first picture's height and width, or the size values set using the .ImageWidth and .ImageHeight properties of the ImageList Ocx.  The .ColorFormat property specifies how the pictures are added and whether or not a mask is generated. The color for the mask is  specified using the .MaskColor property.

After the creation
Once the underlying image list common control is created, the .ColorFormat, .ImageWidth and .ImageHeight properties fail to accept a new value. These properties raise the E_FAIL COM error. This is also demonstrated when you use the 'ImageList Data' dialog box to add images to an ImageList Ocx. The upper left controls contain the options to create the image list common control. You may specify the required size and color format. The default settings are zero for both the size properties, and the 0 (device dependent/mask included) ColorFormat property.
After adding an image these control are disabled, because ImageList_Create() has been invoked using the settings from these controls.  
Using masks in GFA-BASIC 32 is a bit confusing because its setting is the opposite of Windows API.

Masks in GFA-BASIC 32
By default GFA-BASIC 32 creates a mask for each and every picture you add to the ImageList control. Whether or not the mask is added to the underlying image list common control is determined by the .ColorFormat property value.
In contrast with the API specifications, GFA-BASIC 32 uses a reversed setting for the mask option. The flags argument in the ImageList_Create() function specifies the mask using the ILC_MASK bit value. In GFA-BASIC 32 you don't explicitly specify  a mask by setting bit 1 to 1; in GFA-BASIC the .ColorFormat value must hold a zero value in bit 1.

.ColorFormat = 0    '(default) create mask
.ColorFormat |= 1   ' no mask

Just before creating the image list common control GFA-BASIC inverts the first bit and includes it in the flags parameter passed to the ImageList_Create() function.
However, when you explicitly exclude a mask (by setting .ColorFormat |= 1) GFA-BASIC 32 will continue to create masks. However, when picture and the mask are added they are simply ignored by the image list common control.
Note Excluding a mask will result in loss of data when you add an icon to the image list. Therefore GFA-BASIC 32 uses a mask at all times.

Purpose of UseMaskColor and MaskColor Properties
When you add an icon into the list, GFA-BASIC uses its internal mask. If a bitmap or a metafile is added, a mask is created in memory. When .UseMaskColor == 0 the mask is simply a black monochrome bitmap of the same size, all pixel bits are set to zero. However, when you set .UseMaskColor to a nonzero value, the pixels in the image that have the same color value as the .MaskColor setting have a corresponding white color in the monochrome mask bitmap. This opens up the possibility to draw the image transparently. How the image is drawn later depends on more factors than the availability of a mask bitmap only, however.
You can change both UseMaskColor and the MaskColor properties before adding the next image to the list. That way you can have GFA-BASIC generate the correct mask for the image to add. (Each image might have a different transparency color.) 
UseMaskColor and MaskColor are a per image setting when adding a Picture to the list.

The BackColor Property
The only property we didn't discuss so far. The .BackColor property isn't used in the creation of the image list common control and it isn't used in the addition of images to the list. The .BackColor property setting is used when we want to get something out of the image list control. It is used in drawing operations and when a Picture object is retrieved.
The .BackColor is used in the ListImage.Draw method. The .Draw method is simply a wrapper around the ImageList_Draw(himl, i, hdc, x, y, fStyle) API, which draws an imagelist item in the specified device context. The fStyle parameter is used to set the drawing style and only when fStyle = ILD_NORMAL (0) the image is drawn using the background color. You can experiment with this, it speaks for itself.
Note The .BackColor value is passed to the underlying common control using ImageList_SetBkColor() API. 

The .BackColor setting is also used when the ImageList control is used with other controls (that can't be bound to the ImageList control). You can assign the ListImage.Picture object of the ListImage item to the .Picture property of another control. For example, the following code assigns the Picture object of the first ListImage object in a ListImages collection to the Picture property of a newly created StatusBar panel:

Dim pn As Panel
Set pn = sb.Panels.Add() ' Add a new Panel object.
Set pn.Picture = im1.ListImages(1).Picture 

However, how is this Picture created? That is , how are single Pictures  extracted from the image list control? Can this be done by invoking some ImageList_Xxx() API function? The answer is no, the Picture property is a GFA-BASIC 32 specific implementation which uses the .BackColor setting.

The Picture property With .Picture (Get-property) GFA-BASIC allows to create a new bitmap from the image list (and its mask). It creates always a 24 bits DIB memory bitmap to draw the image using ImageList_Draw(). The size of the DIB is ImageWidth x ImageHeight and the background is cleared using the color from .BackColor setting. Then, GFA-BASIC uses the ImageList_Draw() API to draw the specified image using the API background color for the image list (which is also set with .BackColor property!). The net result is a bitmap with a background color .BackColor.
Since the .Picture property returns a 24 bit DIB only, possibly transparent, the new obtained image form the ImageList Ocx might be quite different from what first was added. The .Picture property only returns device independent bitmaps or icons. Any jpg and metafile images are converted to a DIB.  

When you require a transparent image for some other control that accepts an icon use the .ExtractIcon property instead. This will return a real Windows icon resource which is transparent by default.

No comments:

Post a Comment