![]()
Microsoft Common Controls via FlexCOM 2 - part 1
A
Data Access Worldwide White Paper
by Vincent Oorsprong
August 12, 2003
Last Edited: January 23, 2004
This white paper is the first one in a series that was written to demonstrate the usage of FlexCOM2. To learn more about COM and Visual DataFlex a hands on training is available, contact your local Data Access representative. To demonstrate the usage of COM via FlexCOM, a connection to the Microsoft Windows Common Controls ActiveX library was made. The library contains a number of controls such as ListView, ImageList, ImageCombo, TabStrip, ToolBar, Treeview, ProgressBar, StatusBar, Slider, Animation, DateTimePicker, MonthView, FlatScrollBar, UpDown, CoolBar. In this white paper, we will concentrate on the ImageCombo control. Once you have read this white paper, you should have all the knowledge to implement it yourself.
Important! The ActiveX library used in this White Paper (mscomctl.OCX file) is installed with Microsoft Visual Basic 6.0. According to the information in the Microsoft Knowledge Base Article - 194784 (INFO: Controls Shipped in Visual Basic 6.0), which can be read in full at http://support.microsoft.com/default.aspx?scid=kb;en-us;194784, you will need to have at least the Learning Edition of that product installed in order to be able to use the controls from that OCX file.
Contents
The ImageCombo control is a ComboForm which has a list of selectable options, just like any other ComboForm, but in addition each list item has an image in front of the item and the data can be indented so that a tree can be shown. This makes the control in fact a combination of a Treeview and a ComboForm, where the ComboForm is already a combination of a List and a Form control. Below you will see how you can build the control and what special actions you have to be aware of.
First off, let's state that you may not have a need for this control. The usage is not very common in a database application like you are used to building with Visual DataFlex. Using ComboForms in a data entry application is quite limited by the static nature of a ComboForm. For Visual DataFlex programs we advise the use of a more dynamic way to select a record; the selection list (lookup).
Results
The above picture shows the end result of the steps outlined in this white
paper. It includes the following components:
One ImageCombo
Three Forms
One Checkbox
One Array (non-visible)
One ImageList (non-visible)
The ImageCombo is the control on the left that displays the treeview of Visual DataFlex sample workspaces. This control is one of the ActiveX controls imported into Visual DataFlex when you follow the steps described in the next section.
The three Form controls to the right are used to display the information about a workspace and will be updated while browsing through the workspaces in the ImageCombo control.
The checkbox at the bottom, labeled "Lock the image Combo Control", is a toggle that has comparable results to the Entry_State property in the Visual DataFlex ComboForm and dbComboForm classes. The Entry_State property in these classes enables or disables entering information in the form part of the ComboForm. So, if Entry_State is False, you cannot enter new information; you can only select from existing values. The best default is to not allow entering new information, because you need to have a way to add the new information to the list part as well. That issue is more complex and outside the scope of this white paper.
The two non-visible controls -- an Array and an ImageList -- play important roll when using the ImageCombo (read more details in the next sections).
Steps to Create the View Shown Above
Follow the document and you should be able to create the view as shown in the results section.
Import the ActiveX control
The first action to complete is importing the ActiveX control into the Visual
DataFlex Studio.
This is done via the "Import ActiveX Control..." option, which can be found on the
Tools pulldown menu. The following dialog will be shown:
The ImageCombo control is part of the Microsoft Windows Common Control 6.0 OCX library listed. While it is possible to remove some classes from the list of classes found, it is better to let FlexCOM generate code for all of them because:
Note: It is recommended that you generate the package (and the Studio
subclass files) in the workspace
subdirectories instead of the global area. When copying a workspace to a
different computer, globally generated and registered classes tend to be
forgotten quite easily by developers, and this would provide the application
from compiling on the new computer.
The next step is to design the view and place the controls we need on it. At
design time, the view should look like
this:
Now you can see the two non-visible controls displayed -- the view has two more controls than the five controls shown in the first picture.
Make sure you create all the objects from the correct class and name them as listed below:
| Class / Type | Name |
| Array | oWorkspaces |
| cComImageList | oImageList |
| cComImageCombo | oImageCombo |
| Form | oWorkspaceNameForm |
| Form | oWorkspaceDescriptionForm |
| Form | oWorkspacePathForm |
| Checkbox | oLockedCheckbox |
Note that the ImageList object is not a standard Visual DataFlex cImageList object, but instead derived from the cComImageList class (from the same ActiveX library that the ImageCombo comes from). We need the ImageList object to load pictures from disk to display in the list portion of the ImageCombo control.
The ImageList Object
Since the images are a very important part of the ImageCombo control (it is even
in the name), we will
focus on this class first.
The cComImageList class can load images, like the standard VDF cImageList class, and store the information about the images for retrieval by another control. We cannot use the standard cImageList class because an object of this class does not have the iDispatch interface ID required by COM. Other differences between the COM variant and the standard cImageList control are:
The ImageList object visible in picture 3 is derived from the cComImageList class and can be dragged from Studio's Controls Palette to your view. Before we can load images to the object, we need to code an aggregated object in Code Explorer.
The images of the cComImageList are loaded via a COM method (ComLoadPicture) in an object of the class cComListImages. If you ever want to address individual images you need to create an object of the cComListImage class. Since there is no need in this whitepaper to address the individual images we do not need an object of this class. The cComListImages and cComListImage are aggregated objects and thus will the COM interface be automatically created by the outer object. If we need to address one of the aggregated objects we need to create a DataFlex object, query the outer object for the COM dispatch id (there is no standard message/property so you need to examine documentation and/or class methods) and set the pvComObject property of the DataFlex object to this value.
Creating the Visual DataFlex counter part of the aggregated objects as children of their parent is not needed. The COM part has no idea how we handle it from Visual DataFlex. Nested creation may give a better overview of the nested structure in COM. But since the peNeighborhood property of the COM objects is set to nhPrivate you will find out that nesting of the Visual DataFlex objects will make addressing the objects more difficult. Instead of using just the object name you need to code the path to the object. For this whitepaper we address the aggregated object of the class cComListImages from within the cComImageList object and therefore the best place to add the following code is inside the oImageList object:
// This object is used to store the images in the
image list
// it is a child object of cComImageList.
Object oListImages Is A cComListImages
End_Object // oListImages
The images must be loaded after the COM object has been instantiated. This means via the OnCreate event. Keeping procedures and functions small will make the programs easier to read and therefore we load the images in a method called DoLoadImages. In that method we set the properties that describe the size of the images in the OnCreate event. So we will add this code at the same location (oImageList object):
// This method will be used to initialize the
image list. Properties of a
// COM control cannot be set before a Dispatch ID is retrieved.
// We set the size of each image to 16x16 pixels
// We set the transparent color to clFuchsia (in this control ALL bitmaps
// do need to have the same transparency color)
Procedure OnCreate
Forward Send OnCreate
Set ComImageHeight To 16
Set ComImageWidth To 16
Set ComMaskColor To clFuchsia
Send DoLoadImages
End_Procedure // OnCreate
The classes cComImageList and cComListImages do not have a function to load a graphic from disk so we need the FlexCOM method ComLoadPicture to load the pictures. This FlexCOM method first checks if the picture is embedded as resource in our compiled Visual DataFlex program and loads from there. If the picture is not embedded, the method will search the path in the runtime attribute DF_OPEN_PATH.. The method will return, on success, a dispatch ID to the loaded image. The result will be placed in a variable of the Variant data type, called vPicture in our program. The picture is loaded in the COM object via the ComAdd method, a member of the cComListImages class. If you want to address the just loaded picture, you can use the vListImage dispatch ID.
Add the following code to the cComImageList object below the green line:
// This method will first retrieve the dispatch ID for the child object that is used
// to store the images. When this is not 0, we will assign it to the child object. Then, we
// use the FlexCOM 2.0 message ComLoadPicture to load an image. This method respects the
// DF_OPEN_PATH attribute and also checks the include bitmap and icon resources in the Visual
// DataFlex EXE file. ComAdd seems not to support, like the Visual DataFlex cImageList,
// loading of multiple images at the same time cutting them in pieces by the height and the
// width.
Procedure DoLoadImages
Variant vListImages vListImage vPicture
Integer hoListImages
Move oListImages To hoListImages
Move (NullComObject ()) To vListImages
Get ComListImages To vListImages
If (Not (IsNullComObject (vListImages))) Begin
Set pvComObject Of hoListImages To vListImages
Move (NullComObject ()) To vPicture
Get ComLoadPicture "WorkspaceGroup.Bmp" To vPicture
If (Not (IsNullComObject (vPicture))) Begin
Get ComAdd Of hoListImages Nothing Nothing vPicture To vListImage
End
Else Begin
Error DFERR_OPERATOR "Cannot load WorkspaceGroup.Bmp"
End
Move (NullComObject ()) To vPicture
Get ComLoadPicture "Workspace.Bmp" To vPicture
If (Not (IsNullComObject (vPicture))) Begin
Get ComAdd Of hoListImages Nothing Nothing vPicture To vListImage
End
Else Begin
Error DFERR_OPERATOR "Cannot load Workspace.Bmp"
End
End
End_Procedure // DoLoadImages
The above code initializes the variant variables that will contain the iDispatch IDs. Always do this when there is the possibility for the call to a COM method to fail. If you do not do this and the call fails, the variant will have its initial status. Since that is not the same as an iDispatch ID, the compare with IsNullComObject would fail with an error telling you that you have done an invalid data type conversion.
As mentioned, if the ComLoadPicture is successful, the vPicture variant variable contains a handle that we can use with the ComAdd method defined in the cComListImages class. That method takes 3 parameters and the first 2 are optional.
The first parameter can be used to insert the image at a specific location in the image list and, if omitted (we pass Nothing to indicate this), will add the image to the end of the list.
The second argument makes it possible to give the image a unique string identifier (key). You can search on this keyvalue if you need. If you start using it, you need to pass a unique value or you will receive an error while loading. Because this unique string identifier also applies to the later described cComImageCombo, it is important that you know about this and also about the fact that it needs to be a string and may not start with a number (undocumented but generating an error).
The Pictures
The two pictures mentioned above can be found - combined into one - in the
bitmaps directory of your Visual DataFlex development set. You need to open the
bitmap file with a tool like paint and store each of the pictures as individual
files in the bitmaps directory of your workspace. Store the blue "W"
as WorkspaceGroup.Bmp and the red "W" as Workspace.Bmp.
The Array Object
An array object is used in this example to store the enumerated
information from the workspaces.ini file. This way we do not need to retrieve the
data over and over again from the INI file. For each ImageCombo item, we will store 3 items in the
array. Therefore, add the following method to the array object (which you
created by dragging the Array control from the Studio's control palette)
below the green line.
// This method stores the workspace key (e.g. "DAW.Sample Applications.Order.ws"), the
// Description (read from the .WS file) and the path to the .WS file. Each 3 items of the
// array are seen as one element. The method returns the item number of the first value
Function AddWorkSpaceInfo String sFullWorkspaceKey String sDescription String sPath Returns Integer
Integer iWorkspaceId
Get Item_Count To iWorkspaceId
Set Array_Value Item iWorkspaceId To sFullWorkspaceKey
Set Array_Value Item (iWorkspaceId + 1) To sDescription
Set Array_Value Item (iWorkspaceId + 2) To sPath
Function_Return iWorkspaceId
End_Function // AddWorkSpaceInfo
The Form
Objects
The color of the Form objects will give the user the idea that the controls
have their Enabled_State set to false. However, if you set the Enabled_State to false,
the objects will refuse getting the focus, and we don't want this -- we
need to give them the focus in order to enable the select and copy functions of these objects.
So, we need to set the Forms' colors to clBtnFace and their Entry_State to false. Using this combination of property settings, the user cannot enter a value in the Form object while selecting and copying the information is still possible.
To set the Forms' colors to clBtnFace, use the Properties panel and change the Color property. After that, we need to set the Entry_State to false. To do this, add the following code to each of the Form objects below the green line:
// Do not allow the user to enter text. We use this property instead
// of Enabled_State to make it possible to scroll through the data and
// select a value to copy. Note that the color of the control is set
// to the usual color for disabled controls.
Set Entry_State Item 0 To False
The Entry_State needs the item parameter otherwise it will not disable data entry.
The Checkbox Object
The checkbox is a regular Visual DataFlex Checkbox object, but when checked, it will try to
change a property of the cComImageCombo control that can best be compared with
the Visual DataFlex Entry_State property. Because we want to use the
cComImageCombo for selecting a workspace and do not want the user to enter new
information, the default will be "locked". The property ComLocked
can only be executed if the COM portion of the oImageCombo object has been
created, hence the checking for the validity of the vImageCombo variant
contents.
We will represent this by setting the Checked_State property of the Checkbox object. So, add the following code to the Checkbox object below the green line:
// To reflect the default of the "locked" property we set in the activating
// method of oImageCombo via the checked_state. At this moment we cannot
// query the COM control because it is not yet instantiated.
Set Checked_State To True
// When the user clicks the checkbox, the "locked" property of the
// combo will be set to true/false.
Procedure OnChange
Boolean bChecked
Integer hoImageCombo
Variant vImageCombo
Get Checked_State To bChecked
Move oImageCombo To hoImageCombo
Get pvComObject Of hoImageCombo To vImageCombo
If (Not (IsNullComObject (vImageCombo))) Begin
Set ComLocked Of hoImageCombo To bChecked
End
End_Procedure // OnChange
Note: Since the method OnChange is automatically added to a checkbox object when you create one with drag and drop from the controls palette, it is easy to forget to add the code to set the default appearance of the checkbox object to match with the setting done in OnCreate of the ImageCombo object.
The ImageCombo Object
Finally, the ImageCombo object. For those readers that jump directly to this
description part, the above code contains important information as well.
The cComImageCombo object has an aggregated object which can be derived from the cComComboItems class. The object contains the methods to address each individual combo item, both for accessing existing items and for adding new items. The individual items are addressed via a different aggregated object of the cComComboItem class. So add the following code to the cComImageCombo object below the green line:
// The ComboForm has a child object with the
combo items. This
// object is used to add combo items.
Object oComboItems Is A cComComboItems
End_Object // oComboItems
// The combo items object has a child object to individually
// address the combo items. In this sample this object is used to retrieve
// the key value to display the workspace information.
Object oComboItem Is A cComComboItem
End_Object // oComboItem
The pvComObject property of the oComboItems object will be set in the procedure DoFillWithData described below. The pvComObject to "talk" to individual combo items will be set each time we do address the comboitem, for example, in the method OnComClick.
The OnCreate Event
Usually, you set runtime properties and load data (see the cComImageList class
above) in the OnCreate event. However, if you do this with the cComImageCombo
object you will never see data in the list portion of the control. As far as I can see, this is a
failure in the control, since no error is given when loading data in the
OnCreate event. Instead of OnCreate, we use the Activating event,
which is sent -- like OnCreate, only once, but on a later moment in time (when the object is activated for
the first time). Add the
following code to the cComImageCombo object under the object listed above:
// When this control is activated, we will make the control not accept any
// user entered data ("locked" property) and we will read in the data.
Procedure Activating
Forward Send Activating
Set ComLocked To True
Send DoFillWithData
End_Procedure // Activating
Filling the Object with Data
As written earlier in this paper, the data shown in this example are the
workspaces from the central file named workspaces.ini. This is done because the
grouping feature of workspaces makes it an ideal example for using the ImageCombo
control in
the Visual DataFlex environment.
The routine in this example to load the data is called, as you can see in the Activating event, DoFillWithData. The code below should be added to the cComImageCombo object before the Activating method:
// This method reads the file workspaces.ini (usually this file is found in the BIN directory)
// into an object instantiated from cIniFile. All the sections of the INI file (the information
// between the square brackets) are stored, via ReadSections, in an array object. After this
// enumeration all the items of the array are sorted. This is done to make sure that the
// workspaces with the same path are listed in the same order (we can say that
is true when the
// path is equal to the last path we have a path value we do not have to store).
For each
// workspace, the description and the path to the .WS file is retrieved. This information is
// stored in the oWorkspaces array. The paths part of the each workspace is stored via the
// DoAddWorkspacePath method and the name of the workspace is stored here. Each workspace
// gets a unique ID (the item number of the oWorkspaces array) and this is used to fill
// the key property of the combo item. This property does not like numeric values and
thus,
// we place the constant string "WS" in front of it. Furthermore, the key property must have
// a unique value or be empty. So a value for the groups like "GROUP" is not ok.
Procedure DoFillWithData
String sWorkspace sFileName sWorkspacePath
String sPreviousWorkspacePath sFullWorkspaceKey
String sDescription sPath sWorkspaceId
Integer hoIniFile hoArray hoComboItems iWorkspaceId
Integer iItem iItems iSeparatorPos iIndentCount hoWorkspaces
Variant vComboItems vComboItem vImageList
Move oComboItems To hoComboItems
Move oWorkspaces To hoWorkspaces
Get ComComboItems To vComboItems
If (Not (IsNullComObject (vComboItems))) Begin
Set pvComObject Of hoComboItems To vComboItems
Get pvComObject Of oImageList To vImageList
Set ComImageList To vImageList
Get Create U_cIniFile To hoIniFile
Get Create U_Array To hoArray
Move "Workspaces.Ini" To sFileName
Get_File_Path sFileName To sFileName
If (sFileName <> "") Begin
Set psFileName Of hoIniFile To sFileName
Send ReadSections Of hoIniFile hoArray
End
Send ComClear Of hoComboItems
Send Delete_Data Of hoWorkspaces
Send Sort_Items Of hoArray
Move (Item_Count (hoArray) - 1) To iItems
For iItem From 0 To iItems
Get String_Value Of hoArray Item iItem To sWorkspace
Get ReadString Of hoIniFile sWorkspace "Description" "" To sDescription
Get ReadString Of hoIniFile sWorkspace "Path" "" To sPath
Move sWorkspace To sFullWorkspaceKey
Get LastSeparatorPos sWorkspace To iSeparatorPos
If (iSeparatorPos > 0) Begin
Move (Left (sWorkspace, iSeparatorPos)) To sWorkspacePath
If (sWorkspacePath <> sPreviousWorkspacePath) Begin
Move sWorkspacePath To sPreviousWorkspacePath
Send DoAddWorkspacePath sWorkspacePath hoComboItems
End
Move (Right (sWorkspace, Length (sWorkspace) - iSeparatorPos)) To sWorkspace
Get WorkspaceLevels sWorkspacePath To iIndentCount
End
Else Begin
Move 0 To iIndentCount
End
Get AddWorkSpaceInfo Of hoWorkspaces sFullWorkspaceKey sDescription sPath To iWorkspaceId
Move ("WS" - String (iWorkspaceId)) To sWorkspaceId
Get ComAdd Of hoComboItems Nothing sWorkspaceId sWorkspace 2 2 iIndentCount To vComboItem
Loop
Send Destroy Of hoIniFile
Send Destroy Of hoArray
End
End_Procedure // DoFillWithData
Let us examine the above code. The first 2 MOVE lines retrieve the object ID of the aggregated oComboItems object and the array object that we use to store the workspace data.
In the next step, we dynamically create an object of the cIniFile class and an object of the Array class using the Create method. The cIniFile object is used to open and enumerate the workspace names found in the workspace.ini file. If we examine the workspaces.ini file, we will see data like:
[DAW.Examples.Windows.Big]
Description=Big Sample Application
Path=c:\program files\visual dataflex 9.1\Examples\Windows\Big\Programs\
[DAW.Examples.Windows.Contact]
Description=Contacts Sample Application
Path=c:\program files\visual dataflex 9.1\Examples\Windows\Contact\Programs\
The above shows 2 sections from the workspaces.ini file. Each section can have a number of values. The number of values is always 2: the workspace description and the path to the .WS file. The enumerated workspace sections from the INI file are stored in the array object whose ID is passed to the ReadSections function call. After reading all the section names, we will sort the values so that all workspaces with equal portions are put together.
The sorting and erasing of existing data from the COM control will be followed by the loop that gets the section names one by one and reads the information values (description and path). In order to determine the correct number of indents for the list portion of the cImageCombo object, we determine the position of the last dot in the workspace name. This is done in the following function (add it to the cComImageCombo object, right before DoFillWithData method):
// This method searches for the last separator in the passed string. In workspace
// keys this is a dot (as in "DAW.Sample Applications.Order"). This method will
// be called to split the string into substrings.
Function LastSeparatorPos String sWorkspace Returns Integer
Integer iLength
Move (Length (sWorkspace)) To iLength
While (iLength > 0)
If (Mid (sWorkspace, 1, iLength) = ".") Begin
Function_Return iLength
End
Decrement iLength
End
Function_Return 0
End_Function // LastSeparatorPos
Since all workspace names are sorted, the information in the array object should look something like:
DAW.Examples.Advanced Components.COMSamples
DAW.Examples.Advanced Components.DataDefinition
DAW.Examples.Advanced Components.INetTransfer
DAW.Examples.Advanced Components.MAPI
DAW.Examples.Advanced Components.OrgTreeView
DAW.Examples.Advanced Components.XML-Sample
DAW.Examples.Advanced Components.Embedded SQL
DAW.Examples.Web.WebAppSample91
DAW.Examples.Windows.Big
DAW.Examples.Windows.Contact
DAW.Examples.Windows.Order
DAW.Examples.Windows.Wine
DAW.Utilities.CodeMnt
DAW.Utilities.VDFOEMAnsi
The shared part of each value shown above is the portion to the left of the last dot. As soon as anything in this portion changes the workspace is part of another grouping and the number of dots inside the workspacepath need to be counted again. This information must be added to the cComComboItems (oComboItems) object. The number of dots is counted via the function call WorkspaceLevels. The code of this function is (add this one also to the cComImageCombo object right after the LastSeparatorPos method):
// This method counts the number of dots in the string. This
// way we know how many levels there are.
Function WorkspaceLevels String sWorkspacePath Returns Integer
Integer iLength iPos iLevels
Move (Length (sWorkspacePath)) To iLength
For iPos From 1 To iLength
If (Mid (sWorkspacePath, 1, iPos) = ".") Begin
Increment iLevels
End
Loop
Function_Return iLevels
End_Function // WorkspaceLevels
// This method will add each part of the workspace path. The key property of the
// comboitem has no value for us so we pass a nothing. The imagelist contains
two
// pictures and we use image number 1 for the path part.
Procedure DoAddWorkspacePath String sWorkspacePath Integer hoComboItems
Integer iIndentCount iSeparatorPos
String sWorkspace
Variant vComboItem
Move 0 To iIndentCount
While (sWorkspacePath <> "")
Move (Pos (".", sWorkspacePath)) To iSeparatorPos
If (iSeparatorPos > 0) Begin
Move (Left (sWorkspacePath, iSeparatorPos - 1)) To sWorkspace
Move (Right (sWorkspacePath, Length (sWorkspacePath) - iSeparatorPos)) To sWorkspacePath
End
Else Begin
Move "" To sWorkspace
Move "" To sWorkspacePath
End
If (sWorkspace <> "") Begin
Get ComAdd Of hoComboItems Nothing Nothing sWorkspace 1 1 iIndentCount To vComboItem
Increment iIndentCount
End
End
End_Procedure // DoAddWorkspacePath
The information of each workspace is added to the oWorkspaces object via the AddWorkspaceInfo method. This method returns the item number in the array where the data starts. This item number is coded into a key value for the combo item by appending this number to the constant string "WS". This is done because the COM object does not allow us to use a number as key value -- the value of the key is used to find the workspace information when we point at an item.
The ComAdd function call finally adds the data to the COM object. The first parameter tells the COM object whether it should insert the data rather than append the data. If no value is specified, as in our code, the data is appended. If you want to insert it, you need to specify here where you want to do the insert. The 2 parameters passed to ComAdd are used to tell which image from the image list needs to be used for the value. The first tells the COM object which image to use for normal display and the second tells it what image to use when the user cursor is sitting on the item.
Now that we have loaded the COM object with data, the user needs to start using it. When the user opens the list and browses through the items or when the list is closed and the arrow up/down keys are pressed, the COM object notifies us about this event by sending the OnComClick message. So our OnComClick method (add it to the cComImageCombo object right after the Activating method) will be:
// When the user selects a combo item with the mouse or the keyboard this
// event occurs. In this method we find out if the user select a workspace
// or one of the branches. This is done via the value retrieved from the
// Key property. When there is a value, we will get the number out of this
// value. The control does not allow to store a number as key, it has to be
// a string. The keys are WS<nnn> (just an enumerated number). The combo
// items that are used to store the branches do not have a key and are empty.
Procedure OnComClick
Variant vComboItem
Integer iWorkspaceInfoId hoWorkspaces
String sWorkspaceInfoId sWorkspaceName sWorkspaceDescription sWorkspacePath
Get ComSelectedItem To vComboItem
If (Not (IsNullComObject (vComboItem))) Begin
Set pvComObject Of oComboItem To vComboItem
Get ComKey Of oComboItem To sWorkspaceInfoId
If (sWorkspaceInfoId <> "") Begin
Move (Right (sWorkspaceInfoId, Length (sWorkspaceInfoId) - 2)) To iWorkspaceInfoId
If (iWorkspaceInfoId >= 0) Begin
Move oWorkspaces To hoWorkspaces
Get String_Value Of hoWorkspaces Item iWorkspaceInfoId To sWorkspaceName
Get String_Value Of hoWorkspaces Item (iWorkspaceInfoId + 1) To sWorkspaceDescription
Get String_Value Of hoWorkspaces Item (iWorkspaceInfoId + 2) To sWorkspacePath
Set Value Of oWorkspaceNameForm To sWorkspaceName
Set Value Of oWorkspaceDescriptionForm To sWorkspaceDescription
Set Value Of oWorkspacePathForm To sWorkspacePath
End
End
Else Begin
Set Value Of oWorkspaceNameForm To ""
Set Value Of oWorkspaceDescriptionForm To ""
Set Value Of oWorkspacePathForm To ""
End
End
End_Procedure // OnComClick
The code starts with the retrieval of the selected item. The returned value is not a number but an iDispatch ID, which we will assign to the oComboItem object. After that assignment we can get information from the item.
We have stored the workspace key name, the description and path in an array object and we keep track of the starting item by the value in the Key property of the oComboItem object. The ComKey function call returns something like "WS1" or "WS99" and we need to strip off the "WS" part. We do this by taking the right part of the key minus 2 characters (the length of "WS"). The result should be the item number to read from. If so, we will get the data from the array object and display it in the 3 Form objects.
Final Steps
Now that we have created all the objects and inserted the code shown in this
paper, we can compile the sample and see if it all works.
The source code for the view is not available for download, this will make you go through all the steps at least once and it should help you learn how to implement a control like ImageCombo. The next white paper in this series will be about another Microsoft Windows common control.
Credits
Special thanks to my colleagues Dennis Piccioni and Marcia Ferreira for proof
reading and making sure you can succesfully implement this control.
Contacting Data Access Worldwide
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.au
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
Data Access Technical Knowledge
Base
http://www.dataaccess.com/kbase
Many answers to technical problems can be found online in the Data Access Technical Knowledge Base. Here, you can access the
same live data that Data Access Worldwide technical support and development staff use to
enter and track technical articles.
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.
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.