Class Hierarchy Changes
One of the goals for DataFlex 8.3 is to start the process of reorganizing the class hierarchy. Changes in the class hierarchy will lead to better (and easier) understanding of the class library, cleaner application code that is easier to debug, and set the basis for expanded capabilities.
In VDF 8.3, we have addressed what is probably the most significant design limitation in the class hierarchy. In all prior versions of DataFlex, the base class was based on UIObject, which was a rather complicated user interface class with many messages. This class was a poor choice when creating non-UI classes and objects. To complicate matters, this class could not be used for either sub-classing or instantiation, forcing developers to use even higher-level and more inappropriate classes for development.
We have now split the UIObject class and created a very simple, non-UI base class named cObject. All classes are derived from cObject. The UIObject class, now a subclass of cObject, has been renamed cUIObject. Some of the messages from UIObject were moved to cObject, while the rest remained in cUIObject. In addition, both of these classes can now be directly subclassed and instantiated.
While this class change represents a very low-level change in the runtime, we have designed this to be backward compatible with existing programs. Since all existing programs derive classes and objects from UIObject, this change should be completely compatible.
New Base Class: cObject
A new class, cObject, is created that can be used for subclassing and instantiation. It has the following interface:
Class cObject
Public Properties
Property Integer Child_CountProperty Integer Delegation_modeProperty Handle Object_IdProperty String Object_LabelProperty String NameProperty Handle ParentProperty Integer peNeighborhood
Public Methods
Procedure Construct_ObjectProcedure End_Construct_ObjectFunction Create Integer iClassId Returns HandleProcedure Destroy
Public Events
Procedure Destroy_Object
Private Properties
Property Integer ClassProperty Integer Base_Class
Private Methods
Procedure Init_InstanceFunction Object_Size Integer Arg1 Returns IntegerProcedure Set Location Integer iHeight Integer iWidth
Two other private methods exist in cObject: Set Focus_mode and Set Size. If either of these methods is sent to a cObject, the object will intentionally return an error. This was added for backward compatibility considerations. These are not messages you should ever send to a non-UI object, but the old class hierarchy might have required this. These errors are there to provide you with a warning that they should be removed. For the final release, we may decide to remove the error and do nothing (i.e., not delegate).
By default, the delegation_mode of cObject is delegate_to_parent, which means that your applications will work as they always did. However, when creating classes and objects based on cObject, you may decide to disable delegation by setting the property to no_delegation. If you have created a class or object that does not need automatic delegation (and you will find that this is often the case), setting delegation_mode to no_delegation creates a class that is much easier to debug. Messages that are not understood are reported as errors instead of delegating where they might be improperly understood. Even if delegation is turned off, you can always explicitly delegate a message by using the delegate command. This often makes your intention clearer.
Subclasses and objects may be created based on cObject using standard syntax. For example:
Class cMyInfoClass is a cObject
Procedure Construct_object
Forward send construct_object
Property string psMyInfo1
Property string psMyInfo2
End_Procedure
End_Class
Object oMyInfo is a cMyInfoClass
Set psMyInfo1 to "hi"
Set psMyInfo2 to "there"
End_object
Get Create U_cMyInfoClass to hoInfo
Set psMyInfo1 of hoInfo to "hi"
Set psMyInfo2 of hoInfo to "there"
Object oMyInfo is a cObject
Property String psMyInfo1 "hi"
Property String psMyInfo2 "there"
End_object
If you have existing non-UI classes, they are currently either based on Array or on a UI class (DFObject was often used). These classes will continue to work exactly as they did, and you do not need to make any changes. If you do choose to change these classes and make them subclasses of cObject, you can do this by:
- Change the class name to
cObject. - Search for UI messages in the class and remove them. Look for:
Set Focus_mode(this is the most likely method and it is no longer needed)Set SizeSet Location(leave this one alone – the Studio uses this andcObjectignores it)- If you are moving the class from
ArraytocObject, note that the defaultdelegation_modewill change.Arrayobjects neither delegate nor report errors.cObjectobjects delegate. Make sure you setdelegation_modeproperly.
Changes in cUIObject
cUIObject is now descended from cObject. All methods defined in the old UIObject reside in this class, with the exception of the methods that were moved to cObject. This class can now be used for instantiation and subclassing, although such use will probably be rare.
Objects that Now Derive from cObject
Now that we have a proper base object, we have changed the hierarchy of a number of our classes. Previously, these non-UI classes were based on UI superclasses (mostly dfObject). They are now placed where they belong.
StatusPanelStatusdbLogStatusAsciiLogColorDialogFontDialogPrintSetupDialogPrintDialogAbstractFileDialogHelpSystemcHtmlHelpcApplicationcCommandLinecImageListcIniFilecMapiHandlercRegistrycStatusPanecVersionInfocWorkSpacecToolBarButtoncBusinessProcessCrystalReportBaseData_setMixinReportErrorSystem
Class Name Changes
The following class names have been changed:
BaseClasstocUiObjectDesktoptocUIObjectdfDesktoptocDesktopdfPaneltodfBasePaneldfControltodfBaseControldfSessiontodfBaseSessiondfserialtodfBaseSerialHorzScrollBartodfBaseHorzScrollBarVertScrollBartodfBaseVertScrollBarSystemMenutodfBaseSystemMenuImageListtodfBaseImageListMessagetocUIObject_Data_settoBaseDataSet(note_Data_setis no longer defined)
The old names are still supported and defined as replacements. However, they will not be documented, and our package library no longer uses any of the old names. The exception to this is _data_set, which was private and is no longer defined.
Important: You are encouraged to no longer use the class names BaseClass, Desktop, and DFDesktop. These could only be used when using the “Procedure Xxxxx FOR cClassName” syntax. Actually, we discourage the use of the FOR syntax in general. Defining a method “for Desktop/BaseClass/cObject” is a very risky technique. Placing a method on the desktop (i.e., making it a method for the cDesktop object) should be done by using the new “DESKTOP” syntax, which is discussed in the Global/Desktop Methods section.