Resource Images represent modules that contain resources. These modules are binary executable files, which on Windows are for all practical purposes .exe and .dll files. Before an application can use a resource in a module, the resource must be loaded from the module into memory. Once in memory, the application needs a handle to the specific resource in order to work with it.
The ResourceImage class contains methods and function to assist in the loading of resources into memory and obtaining handles to the desired resources. ooDialog has always had, limited, access to resources in modules through the ResDialog class. The ResourceImage class expands that access, both improving it and making the access avaiable in any ooDialog program, with or without ResDialog objects. The class supports the loading of, and obtaining handles to, resources from any binary executable file.
The class provides the release() method to free up system resources if a module containing the resources is no longer needed. The general remarks concerning freeing the .Image class are applicable here. The release() method will ignore requests to release the module when it is known absoulutely that the module should not be released, such as in the case the module is the oodialog.dll. In other cases only the programmer can know if the module should or shouldn't be released. In those cases, the ResourceImage class will do as requested. As with the images that the .Image class represents, the system resources used by the module the ResourceImage class represents will be automatically cleaned up when the interpreter process ends. The comments about why would a programmer want to release resources in the .Image class remarks are equally apropos here.
Note: The ResourceImage class is new in ooDialog as of ooRexx version 4.0.0. Its first implementation supports image resources and provides the basic framework upon which to expand in the future.
The ResourceImage class requires the class definition file ooDialog.cls:
::requires "ooDialog.cls"
Instances of the ResourceImage class implement the methods listed in the following table:
>>--new(--fileName--+--------+--)--------------------------><
+-,-dlg--+Instantiates a new resource image that represents the module specified by fileName.
Sets the .SystemErrorCode variable.
Raises syntax errors when incorrect arguments are detected.
The arguments are:
Specifies the file name of the module containing resources that the ooDialog program wants to access. If the module is in the path, (or the current directory,) the file name alone is sufficent. The operating system will search the path for the file as it normally does when a program is executed. If the module is not in the path then a full, or relative, file name is required.
The second optional dlg argument is a dialog object in the current program. It specifies that the module containing the resources that the ooDialog program wants to acess is one of the modules already avalable to the program. That is, either the oodialog.dll module, or the module used for a ResDialog.
To specify the oodialog.dll module, the file name must be oodialog.dll and the dialog object can be any instantiated dialog in the current program.
To specify the module used with a ResDialog, the dialog object must be the instantiated ResDialog dialog object.
Returns a new ResourceImage object. This object may be null if an error occurred. Use the isNull() method to check for this. Both the .SystemErrorCode or the systemErrorCode() method should contain an error code if the object is null.
This example instantiates a resource image using the oodialog.dll module and uses it to load the generally available icon resources from that module. The icons are then displayed in a list-view control.
::method initDialog
expose list
list = self~getListControl(IDC_LV_IMAGES)
ids = .array~new()
ids[1] = self~constDir[IDI_DLG_OODIALOG]
ids[2] = self~constDir[IDI_DLG_APPICON]
ids[3] = self~constDir[IDI_DLG_APPICON2]
ids[4] = self~constDir[IDI_DLG_OOREXX]
SM_CXICON = 11
SM_CYICON = 12
size = .Size~new(.DlgUtil~getSystemMetrics(SM_CXICON), .DlgUtil~getSystemMetrics(SM_CYICON))
oodModule = .ResourceImage~new("oodialog.dll", self)
icons = oodModule~getImages(ids, .Image~toID(IMAGE_ICON), size)
flags = .DlgUtil~or(.Image~toID(ILC_COLOR24), .Image~toID(ILC_MASK))
imageList = .ImageList~create(size, flags, 4, 0)
imageList~addImages(icons)
list~setImageList(imageList, .Image~toID(LVSIL_NORMAL))
names = .array~new()
names[1] = "IDI_DLG_OODIALOG"
names[2] = "IDI_DLG_APPICON"
names[3] = "IDI_DLG_APPICON2"
names[4] = "IDI_DLG_OOREXX"
do i = 1 to ids~items
list~add(names[i] '('ids[i]')', i - 1)
end
>>--getImage(--id--+--------+--+--------+--+---------+--)-----><
+-,-type-+ +-,-size-+ +-,-flags-+Loads the specified image resource in the module and returns a new .Image object.
Note: LoadImage() is the underlying Windows API used here. This method is very similar to the getImage() method of the .Image class. The documentation for that method may provide additional insight.
Raises a syntax error if the resource image is null.
Sets the .SystemErrorCode variable.
Raises syntax errors when incorrect arguments are detected.
Provides an interface to the Win32 API: LoadImage(). Use the MSDN library documentation to get more information on the arguments to this method.
The arguments are:
The resource id of the image in the module.
Note: At this time symbolic IDs are not supported for this argument. That restriction may be lifted in a furture version of ooDialog.
Specifies the type of the image: bitmap, icon, or cursor. You can use .Image~toID() to get the correct numeric value for one of the following symbols:
| IMAGE_BITMAP | IMAGE_ICON |
| IMAGE_CURSOR |
The default is IMAGE_BITMAP
A .Size object that specifies the size of the image. The default is a size of 0x0. Under most circumstances this indicates that the actual size of the image should be used. However, the MSDN library documentation for LoadImage() should be consulted for other meanings.
The load resource flags for the LoadImage() API. The flags are one or more of the following symbols. You can use .Image~toID() to get the correct numeric value for any of the following symbols. The or method of the .DlgUtil class can be used to combine more than one of the symbols if needed.
| LR_DEFAULTCOLOR | LR_CREATEDIBSECTION |
| LR_DEFAULTSIZE | LR_LOADFROMFILE |
| LR_LOADMAP3DCOLORS | LR_LOADTRANSPARENT |
| LR_MONOCHROME | LR_SHARED |
| LR_VGACOLOR |
The default is LR_SHARED.
This method returns an .Image object that represents the specified image resource in the module. The image may be null if an error occurred, for instance if no image resource was found.
This example uses a ResDialog with a static control that displays a bitmap image. The image for the static control is obtained from the resource-only DLL used by the ResDialog.
::class SimpleDialog subclass ResDialog inherit AdvancedControls MessageExtensions
...
::method initDialog
...
resources = .ResourceImage~new("simpleImage.dll", self)
image = resources~getImage(self~constDir[ID_BMP_IMAGE1])
...
picture = self~getStaticControl(IDC_BMP_PICTURE)
oldImage = picture~setImage(image)
>>--getImages(--ids,--+--------+--+--------+--+---------+--)-----><
+-,-type-+ +-,-size-+ +-,-flags-+Loads a number of image resources from the module. An array of resource IDs is used to specify which image resources. All the image resources must have the same characteristics. That is they must all be the same type and use the same flags. If the type is bitmap, and the flags include LR_DEFAULTSIZE, and the size is 0 x 0, then the size of the image will be the actual resource size. Otherwise, all the images also need to be the same size.
Note: LoadImage() is the underlying Windows API used here. This method is very similar to the fromIDs() method of the .Image class. The documentation for that method can provide additional information.
Raises a syntax error if the resource image is null.
Sets the .SystemErrorCode variable.
Raises syntax errors when incorrect arguments are detected.
Provides an interface to the Win32 API: LoadImage(). You can use the MSDN library documentation to get more information on the interaction between the flags, size, and type arguments.
The arguments are:
An array of the resource IDs of the image resources in the module. The array can contain any number of IDs, but it can not be sparse. That is, each index of the array must contain a number. If an incorrect item is detected in the array, then a syntax error is raised and no images are returned.
If there is an error with an individual image resource, then the index in the array for that image is left empty. One way to check for this type of error is to compare the number of items in the returned array with the number of items in ID array.
Specifies the type of the image: bitmap, icon, or cursor. You can use .Image~toID() to get the correct numeric value for one of the following symbols:
| IMAGE_BITMAP | IMAGE_ICON |
| IMAGE_CURSOR |
The default is IMAGE_BITMAP.
A .Size object that specifies the size of the image. The default is a size of 0x0. Under most circumstances this indicates that the actual size of the image should be used. However, the MSDN library documentation should be consulted for other meanings.
The load resource flags for the LoadImage() API. The flags are one or more of the following symbols. You can use .Image~toID() to get the correct numeric value for any of the following symbols. The or method of the .DlgUtil class can be used to combine more than one of the symbols if needed.
| LR_DEFAULTCOLOR | LR_CREATEDIBSECTION |
| LR_DEFAULTSIZE | LR_LOADFROMFILE |
| LR_LOADMAP3DCOLORS | LR_LOADTRANSPARENT |
| LR_MONOCHROME | LR_SHARED |
| LR_VGACOLOR |
The default is LR_SHARED.
The return will be an array of .Image objects, one for each resource ID specified in the ids array, if there is no error. If there is an error loading the image of any specified ID, the corresponding index in the returned array will be empty.
If there is an error, both the .SystemErrorCode and the systemErrorCode attribute of this resource image will be set (to the same code.) It is conceivable that an error could occur where the system does not set an error code, but unlikely.
The following is a complete working dialog. Four bitmap images are used. Each time the user clicks the next button, the next image is displayed.
An array is constructed containing the resource IDs of the 4 images. A new resource image object is instantiated from the images.dll module. The getImages() method is then used to get an array of 4 .Image objects, using the array of resource IDs.
/* Simple Dialog to display some images */
dlg = .SimpleDialog~new( , 'simpleImage.h')
if dlg~initCode = 0 then do
dlg~createCenter(200, 247, "Simple Image Viewer", "", , "MS Shell Dlg 2", 8)
dlg~Execute("SHOWTOP", 14)
end
dlg~Deinstall
return 0
-- End of entry point.
::requires "oodWin32.cls"
::class SimpleDialog subclass UserDialog inherit AdvancedControls MessageExtensions
::method defineDialog
self~addStatic(IDC_BMP_PICTURE, 10, 10, 20, 17, "BITMAP REALSIZEIMAGE")
self~addStatic(IDC_ST_DESCRIPTION, 14, 190, 176, 20, "TEXT LEFT", "Description")
self~addButton(IDC_PB_NEXT, 10, 223, 50, 14, "Next", onNext)
self~addButton(IDOK, 140, 223, 50, 14, "Ok", ok, "DEFAULT")
::method initDialog
expose picture images description descriptions nextImage
ids = .array~new
ids[ 1] = self~constDir[ID_BMP_IMAGE1]
ids[ 2] = self~constDir[ID_BMP_IMAGE2]
ids[ 3] = self~constDir[ID_BMP_IMAGE3]
ids[ 4] = self~constDir[ID_BMP_IMAGE4]
descriptions = .array~new
descriptions[1] = "Conrad, King of the Hill"
descriptions[2] = "Berk, Squint Eye"
descriptions[3] = "Cienna, Deer in the Headlights"
descriptions[4] = "Vail, The Flower Child"
picture = self~getStaticControl(IDC_BMP_PICTURE)
description = self~getStaticControl(IDC_ST_DESCRIPTION)
self~connectButton(IDC_PB_NEXT, onNext)
nextImage = 1
module = .ResourceImage~new("images.dll")
images = module~getImages(ids)
self~onNext
::method onNext
expose picture description images descriptions nextImage
if nextImage > images~items then nextImage = 1
picture~setImage(images[nextImage])
description~setText(descriptions[nextImage])
nextImage += 1
>>--release----------------------------------------------------><
Releases the resource module so that the operating system can reclaim the system resources. After the resource image has been released it can no longer be used. The programmer should not release the resource image while resources loaded from the module are still in use.
If the resource image represents the oodialog.dll module, or the module used for a ResDialog, then the resource image should never be released. The release() method will ignore release requests in those sitautions.
Raises a syntax error if the resource image is null.
Sets the .SystemErrorCode variable.
There are no arguments.
This method return the system error code, which will be zero if there is no error, and non-zero if there is an error. The .SystemErrorCode is also set to this value.
In this example, the images for an image list are loaded from a resource module. The resource module is no longer needed after the image list is created. Since an image list makes a copy of the images added to it, once the image list has all the images added to it, the resource image can be released.
::method getImages private
use strict arg resourceIDs, size, ilFlags
imageList = .ImageList~create(size, ilFlags, 20, 10);
module = .ResourceImage~new("zooImages.dll")
images = module~getImages(resourceIDs)
imageList~addImages(images)
do i = 1 to images~items
images[i]~release
end
module~release
return imageList
>>--handle----------------------------------------------------><
Returns the Windows system handle for the resource module. It is an error to invoke this method if the resource image is null, or after the resource image has been released.
At this time, the handle is only useful for display.
There are no arguments.
The return is the handle for the module the resource image represents.
This example ...
::method showHandles
oodMod = .ResourceImage~new("oodialog.dll", self)
resMod = .ResourceImage~new("simpleImage.dll", self)
say 'The oodialog.dll module handle is: ' oodMod~handle
say 'The resource module for this ResDialog is:' resMod~handle
/* The output, for a ResDialog, might be:
The oodialog.dll module handle is: 0x009E0000
The resource module for this ResDialog is: 0x00AF0000
*/
>>--isNull----------------------------------------------------><
Determines if the resource image is valid. isNull() will always return .true after the resource image has been released. It will also return .true if there was an error instantiating a new resource image object.
There are no arguments.
Returns .true if the object is null, otherwise .false.
It is a good idea to check that a new resource image object is valid before using it.
::method initDialog
...
resourceModule = .ResourceImage~new("simpleImage.dll", self)
if \ resourceModule~isNull the do
image = resources~getImage(self~constDir[ID_BMP_IMAGE1])
else do
-- Some error handling here.
end
>>--systemErrorCode----------------------------------------------------><
When a method for a resource image is invoked that sets the .SystemErrorCode, the systemErrorCode attribute of the resource image object is also set. This can be useful if the programmer wants to check for an error code at some point when it is possible that .SystemErrorCode has been reset.
This method can always be invoked, even if the resource image is null. It is very similar to the systemErrorCode() method of the .Image class and the documentation for that method is generally applicable here.
This method does not take any arguments.
The return is a system error code, which will usually be 0, no error.
This example uses the systemErrorCode attribute to get more information on a possbile error, rather than the .SystemErrorCode.
::method initDialog
...
mod = .ResourceImage~new("simpleImage.dll", self)
if mod~isNull the do
self~writeToLog("Error with resource module simpleImage.dll")
self~writeToLog(" RC: " mod~systemErrorCode)
self~writeToLog(" msg:" SysGetErrorText(mod~systemErrorCode)
return
end
image = resources~getImage(self~constDir[ID_BMP_IMAGE1])
...