![]()
Enumerating
Resources Included in
Visual DataFlex 8.2 and higher Applications
A Data Access Worldwide White Paper
by Vincent Oorsprong
July 2002
Last Edited: June 24, 2003
Overview
There are times when you need to find out if an image was included in the
program as a resource. When using an image, the Visual DataFlex virtual machine will automatically load the included
image resource if available. In case it is not included, the DataFlex search path will be used to provide the
image (only if it is found, of course). When it switches to the external source and the search for an
image file fails, the image will - in most cases - only not appear and cause no errors.
However, if you don't know the name of the image file, you cannot try to load it
to resolve the problem. This means that you cannot make a list of all included
image files. This paper will show you how one can find out from within the program if the
image file was included or not.
Methods to find out if the image was included
Try to load the image
Let us look at some lines of code from cImageList.pkg:
The Visual DataFlex 8 and higher product generates
.EXE programs.
Starting with version 8.2 it is possible to include image files (bitmaps and icons) and version resources in the compiled program.
Having images linked into the compiled program has the following advantages:
This method is used by, for example, the cImageList class. If you want to load an image with AddImage or AddTransparentImage, the system will first try to load the image from the
executable program file and, if it can't load it, it will try the standard Visual DataFlex search path.
You can use this same method to test if a certain (known by name) bitmap was included or not. Such a function could be:
Function IsBitmapIncluded String sBitmapName Returns Boolean
Boolean bIncluded
Handle hBitmap
Integer iVoid
Move (LoadImage (GetModuleHandle (0), sBitmapName, IMAGE_BITMAP, 0, 0, 0)) To hBitmap
If (hBitmap <> 0) Begin
Move True To bIncluded
Move (DeleteObject (hBitmap)) To iVoid
End
Function_Return bIncluded
End_Function // IsBitmapIncluded

Figure 1: IsBitmapIncluded function used in a view
If you want to test the above function and compile the same view as shown in
Figure 1,
download the attached source of the view, register it as an external component in the IDE in a workspace of your choice, and click the
Test Compile/Run button. The source code was created in Visual DataFlex 8.2 and can be used from that version and up.
^top
Use enumeration functions
The Windows API has some functions which we can use to enumerate the resources included in a module. The functions are:
|
|
The callback functions in our own DLL communicate with your Visual DataFlex program by sending newly defined Windows messages to a particular window handle.
To be able to let this all work, a new class, cEnumRscInfo, has been created. When an object of this class is activated (paged), the window handle assigned by the virtual machine is passed to the DLL using the RegisterVDFEnumResourcesWindow function. Only one object of this class is supported per program, but we never need more than one to enumerate our resources anyway.
The class has the following methods defined:
| Method name | Type | Public | Description |
| Construct_Object | P | No | Registers
the Windows messages WM_ENUMRESOURCENAMES and WM_ENUMRESOURCETYPES. These
are supposed to be new messages and the equal to the names registered by the
new DLL. These messages will be used to communicate. The message identifiers
are connected to the methods OnResourceTypesCallBack and OnResourceNamesCallBack. The class creates two child objects of the Array class to store the enumerated types and names. Their object IDs are stored in the properties phoResourceTypes and phoResourceNames. |
| OnResourceTypesCallBack | P | No | Will be called each time a resource type is found by the enumeration functions of the DLL and passed to the Visual DataFlex object of this class. Methods of this type (external_functions) are defined with two parameters, but only the first one is used in this case. The first parameter contains a pointer to a structure with information about the enumerated type. From this structure, only a pointer to the enumerated type will be used. While the other structure members could be used to do some checking, they are not used by the OnResourceTypesCallBack method. |
| OnResourceNamesCallBack | P | No | Will be called each time a resource name of a given type was found by the enumeration functions in the DLL and passed to the Visual DataFlex object of this class. Methods of this type (external_functions) are defined with two parameters but only the first one is used in this case. The first parameter contains a pointer to a structure with information about the enumerated name. From this structure only a pointer to the enumerated name will be used. While the other structure members could be used to do some checking, they are not used by the OnResourceNamesCallBack method. |
| DoAddResourceType | P | No | This method will be used by the OnResourceTypesCallBack method and stores the found type in the array child object that was created to store the resource types. The items of the object whose ID is stored in phoResourceTypes should be used to find out if the desired resource type was included or not. |
| DoAddResourceName | P | No | This method will be used by the OnResourceNamesCallBack method and stores the found name in the array child object that was created to store the resource names. The items of the object whose ID is stored in phoResourceNames should be used to find out if the desired resource name was included or not. |
| Page | P | No | Passes the window handle to the DLL. If the object is never PAGEd, the DLL does not have a window handle to communicate with and the request to enumerate the resource types and names will not work. |
| DoEnumResourceTypes | P | Yes | This method will load the EnumResourceInformation.dll to get a handle to DLL, which it needs for futher instructions. If the handle returned is zero, the enumeration request will not work. Inside the DLL the method with the name EnumResTypeProc is searched and this should be found, else the enumeration will not work. The next step is to delete all previous enumerated resource types from the internal array object. Finally, Windows will be instructed by sending the method EnumResourceTypes to start the enumeration. When the enumeration is ready, the method stops and other DataFlex functions/operations can take place. |
| DoEnumResourceNames | P | Yes | This
method will load the EnumResourceInformation.dll to get a handle to DLL,
which it needs for futher instructions. If the handle returned is zero, the
enumeration request will not work. Inside the DLL the method with the name EnumResNameProc
is searched and this should be found, else the enumeration will not work.
The next step is to delete all previous enumerated resource names from the
internal array object. Finally, Windows will be instructed by sending the
method EnumResourceNames to start the enumeration. When the enumeration is
ready, the method stops and other DataFlex functions/operations can take
place. The method takes one required parameter which should contain the type (one of the predefined RT_xxx ones) to be enumerated. Use only resource types that are present. |
| CopyPointerToDfString | F | No | Copies pointer to a DataFlex string variable. |
Figure 2: Results of RT_BITMAP resource name enumeration in a view
The above view (source code) works as follows:
The enumerated names are the same names as we specified in the .CFG file of the program, which is used by the Visual DataFlex linker. This may or may not
be the same name as the original file on disk. In fact, Figure 2 shows one name with the
.BMP extension and one without. The name without
was assigned a different name via the .CFG file than its original disk variant. The original name has been
removed.
When looking at icon resources, we see that icons are listed as RT_ICON and also as RT_GROUP_ICON.
Figure 3: Results of RT_ICON resource name enumeration in a view
Figure 4: Results of RT_GROUP_ICON resource name enumeration in a view
Note: As you can see, figures 2, 3 and 4 show all four resource types that are currently supported in our Visual DataFlex programs. Retrieving information about the version resource works differently and should be retrieved via the cVersionInfo class supplied with Visual DataFlex 8.2.
^top
Data Access
Worldwide
14000 SW 119 Ave
Miami, FL 33186
305-238-0012
Domestic Sales: 800-451-3539
Fax: 305-238-0017
email: sales@dataaccess.com
Newsgroup Server: news.dataaccess.com
Internet: http://www.dataaccess.com
Data Access Worldwide - Asia Pacific
Suite 5, 333 Wantirna Road, Wantirna VIC 3152 Australia
Phone: +61 3 9800 4233 f: +61 3 9800 4255
Sales: asiapacific@DataAccess.com
Support: support.asiapacific@DataAccess.com
Internet: http://www.DataAccess.com/AsiaPacific
Data Access Worldwide - Brasil
Av.Paulista, 1776 - 21st.Floor
São Paulo -SP - Brazil
CEP 01310-921
Phone: 5511-3262-2000
Fax 5511-3284-1579
Sales: info@dataaccess.com.br
Support: suporte@dataaccess.com.br
Internet: http://www.dataaccess.com.br
Data Access Worldwide - Europe
Lansinkesweg 4
7553 AE Hengelo
The Netherlands
Telephone: +31 (0)74 - 255 56 09
Fax: +31 (0)74 - 250 34 66
Sales: info@dataaccess.nl
Support: support@dataaccess.nl
Internet: http://www.dataaccess.nl
Data Access
Technical Support
800-451-3539 / 305-232-3142
email: support@dataaccess.com
Visit our Support Home page to see all of our Support options: http://www.dataaccess.com/support
Copyright Notice
This document is property of Data Access Corporation. With credit to Data
Access Corporation for its authorship, you are encouraged to reproduce
this information in any format either on paper or electronically, in
whole or in part. You may publish this paper as a stand alone document within
your own publications conditional on the maintenance of the intent,
context, and integrity of the material as it is presented here.
DataFlex
is a registered trademark of Data
Access Corporation.
Windows is a
registered trademark of Microsoft Corporation.
NO LIABILITY FOR CONSEQUENTIAL
DAMAGES
To the maximum extent permitted by applicable law, in no event shall Data Access
Corporation be liable for any special, incidental, indirect, or consequential
damages whatsoever (including, without limitation, damages for loss of business
profits, business interruption, loss of business information, or any other
pecuniary loss) arising out of the use of or inability to use any information
provided in this document, even if Data Access Corporation has been advised of
the possibility of such damages. Because some states and jurisdictions do not
allow the exclusion or limitation of liability for consequential or incidental
damages, the above limitation may not apply to you.