Images and Imagelists
The images used in menus, toolbars, and status bars are all managed by an imagelist within the cCJCommandBarSystem object. The internal mechanism for supporting images is:
- Images are added to the image list and assigned an imagelist Id.
- Images from the imagelist are bound to a menu, toolbar, or status bar item by that imagelist Id.
It is a goal of the menu classes to hide most of the complexity of managing this two-step process without having to deal with defining Ids and dealing with imagelists. At the class level, images are added to an item by setting the psImage property. Setting this property adds the image to the imagelist, assigns it an imagelist Id, and assigns this Id to the item. This provides a mechanism for statically assigning an image to an item. This mechanism is visually modeled in the Studio’s menu designer. A mechanism also exists for dynamically assigning images to an item.
Image Capabilities
A variety of image sizes and styles can be assigned to the imagelist and displayed by the command bar system. Bitmap (.bmp) and Icon (.ico) files are supported. A variety of image color depths can be used. Images of different sizes may also be defined. These may all be intermixed in the imagelist.
Images will be scaled to fit the required size. It is best to test this scaling to determine if the results are satisfactory for your needs.
When you have an icon file containing multiple icons, Codejock seems to always use the first icon in the file and scales it. This means the best thing to do with icon files is to make sure you only have one icon per file, that being the one you intend to display. If you want to change sizes from 16x16 to 32x32, then you will need two files and change the psImage property of the appropriate menu items to point to the new filename. If this needs to be done dynamically, you can use the piIconId property.
Codejock uses a mask color to automatically shade images to represent their different states (e.g., disabled, selected, pressed). With icon files, this data is stored in the icon file. With bitmap files, it does this by using the image’s upper left corner as the mask color. This automatic handling of image states works well, and it means that a single image (psImage) can be used to represent all of the image states. When special needs arise, you may assign special images for each of the image states (psImage, psImageDisabled, psImageHot, psImageChecked, psImagePressed).
Also note that the cCJCommandBarSystem’s pbIconsWithShadow property can be used to perform shading in images when they are selected. By default, this is enabled. With these built-in capabilities, you can get very good imaging using a single default image.
Alpha-blend icons are 32-bit icons that use the extra 8 bits to provide percentage transparency data (i.e., 256 different percentage levels of transparency). These are not supported on all Windows platforms. Alpha-blend icons are supported in the Windows API since Windows XP. While Codejock supports displaying alpha-blend icons, we found that the automatic disable logic does not look good with alpha-blend. The solution to this problem is to provide a set of dedicated disabled images for each menu item and set the psImageDisabled property of each menu item accordingly. This gives you complete control over the shaded appearance of each Menu Item. It also doubles the number of icons that you need to supply for each operation. An alternate solution is to not use alpha-blend images.
The icons shipped in DataFlex are 24-bit color depth icons. This provides images that look good and work well with all Windows platforms.
When an application is run, the images may be loaded from files or they may be loaded from a resource file that is embedded in your exe file. If an image exists in the resource file, it will be found there first. The file names of images can and usually will be relative file names. If images are stored in the workspace or library bitmap directory, they will be found at design time and at runtime.
Image Size
Codejock supports two image sizes, large and small, for toolbar images. You may select the size by setting the cCJCommandBarSystem property pbLargeIcons (the default is false – small images). Initially, large images are 32x32 and small images are 16x16. The sizes can be changed using ComSetIconSize. The size of popup menu images defaults to 16x16. This may be changed by using ComSetPopupIconSize.
This example sets small images to 24x24, large images to 48x48, and popup images to 24x24.
Procedure OnCreateCommandBars
Handle hoOptions
Get OptionsObject to hoOptions
Forward Send OnCreateCommandBars
Send ComSetIconSize of hoOptions False 24 24
Send ComSetIconSize of hoOptions True 48 48
Send ComSetPopupIconSize of hoOptions 24 24
End_Procedure
When image sizes are changed, the images are scaled. This scaling may not provide satisfactory results. In such a case, you will wish to provide properly sized images. This can be done at design time using psImage or dynamically using piIconId.
Dynamic Image Assignment
The psImage property and its variants (e.g., psImageDisabled) are design-time properties. When the command bar system is paged and all of the COM objects are created, the value of psImage is assigned to the COM item object. After that assignment, changing psImage will not change the image.
Images may be changed dynamically by setting the piIconId property. The value of this piIconId must be set to the Id of the image that was set when it was added to the imagelist using the AddImage function.
Adding Images to the Imagelist
If you are dynamically changing images with piIconId, you need to add the image to the imagelist. Images are added to the command bar system’s imagelist using the AddImage message. This message must be sent after the command bar system object has been paged (i.e., after the COM object has been created), usually within the OnCreateCommandBars event.
AddImage is passed three parameters - the image’s file name, an image id, and the image state. Each image in the command bar system's imagelist is identified by a numeric ID. When images are added using psImage, these Ids are assigned automatically.
If you are adding images to the imagelist manually, you will probably need to define and assign your own Ids constants. The only restriction placed on these IDs is that we suggest they fall in the range of 1 to 4999.
This sample shows how image IDs are defined and how they are added to an imagelist.
// First you must assign IDs for the images
Define idImgSave for 100
Define idImgDelete for 101
Define idImgClear for 102
// next you add the images within OnCreateCommandBars
Procedure OnCreateCommandBars
Integer iId
Forward Send OnCreateCommandBars
Get AddImage "ActionSave.ico" idImgSave xtpImageNormal to iId
Get AddImage "ActionDelete.ico" idImgDelete xtpImageNormal to iId
Get AddImage "ActionClear.ico" idImgClear xtpImageNormal to iId
End_Procedure
If you need to assign additional images for the various image states (disabled, hot, etc.), this would be done as follows:
Procedure OnCreateCommandBars
Integer iId
Forward Send OnCreateCommandBars
Get AddImage "ActionSave.ico" idImgSave xtpImageNormal to iId
Get AddImage "ActionSaveDis.ico" idImgSave xtpImageDisabled to iId
Get AddImage "ActionSaveHot.ico" idImgSave xtpImageHot to iId
Get AddImage "ActionDelete.ico" idImgDelete xtpImageNormal to iId
Get AddImage "ActionDeleteDis.ico" idImgDelete xtpImageDisabled to iId
Get AddImage "ActionDeleteHot.ico" idImgDelete xtpImageHot to iId
Get AddImage "ActionClear.ico" idImgClear xtpImageNormal to iId
Get AddImage "ActionClearDis.ico" idImgClear xtpImageDisabled to iId
Get AddImage "ActionClearHot.ico" idImgClear xtpImageHot to iId
End_Procedure
If you pass zero as the image Id, the AddImage message will assign an Id for you and return its value. This is probably not all that useful when manually adding images to the imagelist as you will need to use the Id elsewhere in your program. If the image is not found, the Id returned is zero. This could be used for error checking (but is not in the above samples).
Changing Menu and Toolbar Images Dynamically
You can change an image dynamically by setting the cCJMenuItem’s piIconId property to any image Id in your imagelist. Initially, piIconId is zero, which instructs the object to use the image defined by psImage (and its variants). If you change it to a different Id, that change will be immediately reflected. If you reset piIconId back to 0, the image defined by psImage will be redisplayed.
This example will show how this can be used. Clicking on the toolbar item will change the caption and toolbar. This is not particularly useful, but it shows how images may be changed dynamically.
Object oFlip is a cCJMenuItem
Set psCaption to "Add"
Set psImage to "ActionSave.ico"
Set peControlStyle to xtpButtonIconAndCaption
// when pressed change the text and change the icon.
Procedure OnExecute Variant vCommandBarControl
String sCap
Get psCaption to sCap
If (sCap = "Add") Begin
Set psCaption to "Del"
Set piIconId to idImgDelete
End
Else Begin
Set psCaption to "Add"
// setting this to 0 makes it use the psImage.
Set piIconId to 0
End
End_Procedure
End_Object
This example shows how to set all images using piIconId. An additional button has been added that rotates these images within the toolbar (again not particularly useful, but hopefully instructive).
// first define the constants
Define ID_First for 200
Define ID_Previous for 201
Define ID_Next for 202
Define ID_Last for 203
// within the cCJCommandBars object add the images to the imagelist
Procedure OnCreateCommandBars
Integer iId
Forward Send OnCreateCommandBars
Get AddImage "ActionFirst.ico" ID_First xtpImageNormal to iId
Get AddImage "ActionPrevious.ico" ID_Previous xtpImageNormal to iId
Get AddImage "ActionNext.ico" ID_Next xtpImageNormal to iId
Get AddImage "ActionLast.ico" ID_Last xtpImageNormal to iId
End_Procedure
// Create a toolbar with images from imagelist
Object oTest is a cCJToolbar
Set psTitle to "test"
Object oFirst is a cCJMenuItem
Set piIconId to ID_First
End_Object
Object oPrevious is a cCJMenuItem
Set piIconId to ID_Previous
End_Object
Object oNext is a cCJMenuItem
Set piIconId to ID_Next
End_Object
Object oLast is a cCJMenuItem
Set piIconId to ID_Last
End_Object
// special button that changes the images by rotating
// them one to the left.
Object oRotate is a cCJMenuItem
Set psCaption to "Rotate"
Procedure OnExecute Variant vCommandBarControl
Integer iFirst iPrev iNext iLast
Get piIconId of oFirst to iFirst
Get piIconId of oPrevious to iPrev
Get piIconId of oNext to iNext
Get piIconId of oLast to iLast
// rotate all images one to the left
Set piIconId of oFirst to iPrev
Set piIconId of oPrevious to iNext
Set piIconId of oNext to iLast
Set piIconId of oLast to iFirst
End_Procedure
End_Object
End_Object
Changing Statusbar Pane Images Dynamically
Statusbar panes use the same interface for statically adding images (psImage) and changing images dynamically (piIconId). Unlike cCJMenuItem objects, resetting piIconId to 0 in status bar panes clears the current image.
This sample changes the text and the icon in a status bar pane by clicking on it. This assumes that the images have already been added to the imagelist.
Object oStatusPane3 is a cCJStatusBarPane
Property Boolean pbSave True
Set piIconId to idImgSave
Set psText to "Save"
Procedure OnClick
Boolean bSave
// toggle the property
Get pbSave to bSave
Move (not(bSave)) to bSave
Set pbSave to bSave
// adjust the text and the image
If bSave Begin
Set psText to "Save"
Set piIconId to idImgSave
End
Else Begin
Set psText to "Delete"
Set piIconId to idImgDelete
End
// this forces the pane to readjust its size to fit the text
Set piWidth to 0
End_Procedure
End_Object