ResourceImage Class

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.

Requires:

The ResourceImage class requires the class definition file ooDialog.cls:

::requires "ooDialog.cls"

Methods:

Instances of the ResourceImage class implement the methods listed in the following table:

Table 25-4. Name Instance Methods

Method......description
new (Class method)new
getImagegetImage
getImagesgetImages
handlehandle
isNullisNull
releaserelease
systemErrorCodesystemErrorCode

new (Class method)

>>--new(--fileName--+--------+--)--------------------------><
                    +-,-dlg--+

Instantiates a new resource image that represents the module specified by fileName.

Details

Sets the .SystemErrorCode variable.

Raises syntax errors when incorrect arguments are detected.

Arguments:

The arguments are:

fileName

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.

dlg

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.

Return value:

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.

Example:

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

>>--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.

Details

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.

Arguments:

The arguments are:

id

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.

type

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_BITMAPIMAGE_ICON
IMAGE_CURSOR 

The default is IMAGE_BITMAP

size

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.

flags

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_DEFAULTCOLORLR_CREATEDIBSECTION
LR_DEFAULTSIZELR_LOADFROMFILE
LR_LOADMAP3DCOLORSLR_LOADTRANSPARENT
LR_MONOCHROMELR_SHARED
LR_VGACOLOR 

The default is LR_SHARED.

Return value:

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.

Example:

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

>>--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.

Details

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.

Arguments:

The arguments are:

ids

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.

type

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_BITMAPIMAGE_ICON
IMAGE_CURSOR 

The default is IMAGE_BITMAP.

size

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.

flags

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_DEFAULTCOLORLR_CREATEDIBSECTION
LR_DEFAULTSIZELR_LOADFROMFILE
LR_LOADMAP3DCOLORSLR_LOADTRANSPARENT
LR_MONOCHROMELR_SHARED
LR_VGACOLOR 

The default is LR_SHARED.

Return value:

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.

Example:

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

>>--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.

Details

Raises a syntax error if the resource image is null.

Sets the .SystemErrorCode variable.

Arguments:

There are no arguments.

Return value:

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.

Example:

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

>>--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.

Arguments:

There are no arguments.

Return value:

The return is the handle for the module the resource image represents.

Example:

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

>>--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.

Arguments:

There are no arguments.

Return value:

Returns .true if the object is null, otherwise .false.

Example:

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

>>--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.

Arguments:

This method does not take any arguments.

Return value:

The return is a system error code, which will usually be 0, no error.

Example:

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])
        ...