Skip to content

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_Count
  • Property Integer Delegation_mode
  • Property Handle Object_Id
  • Property String Object_Label
  • Property String Name
  • Property Handle Parent
  • Property Integer peNeighborhood

Public Methods

  • Procedure Construct_Object
  • Procedure End_Construct_Object
  • Function Create Integer iClassId Returns Handle
  • Procedure Destroy

Public Events

  • Procedure Destroy_Object

Private Properties

  • Property Integer Class
  • Property Integer Base_Class

Private Methods

  • Procedure Init_Instance
  • Function Object_Size Integer Arg1 Returns Integer
  • Procedure 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:

  1. Change the class name to cObject.
  2. Search for UI messages in the class and remove them. Look for:
  3. Set Focus_mode (this is the most likely method and it is no longer needed)
  4. Set Size
  5. Set Location (leave this one alone – the Studio uses this and cObject ignores it)
  6. If you are moving the class from Array to cObject, note that the default delegation_mode will change. Array objects neither delegate nor report errors. cObject objects delegate. Make sure you set delegation_mode properly.

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.

  • StatusPanel
  • StatusdbLog
  • StatusAsciiLog
  • ColorDialog
  • FontDialog
  • PrintSetupDialog
  • PrintDialog
  • AbstractFileDialog
  • HelpSystem
  • cHtmlHelp
  • cApplication
  • cCommandLine
  • cImageList
  • cIniFile
  • cMapiHandler
  • cRegistry
  • cStatusPane
  • cVersionInfo
  • cWorkSpace
  • cToolBarButton
  • cBusinessProcess
  • CrystalReport
  • BaseData_set
  • Mixin
  • Report
  • ErrorSystem

Class Name Changes

The following class names have been changed:

  • BaseClass to cUiObject
  • Desktop to cUIObject
  • dfDesktop to cDesktop
  • dfPanel to dfBasePanel
  • dfControl to dfBaseControl
  • dfSession to dfBaseSession
  • dfserial to dfBaseSerial
  • HorzScrollBar to dfBaseHorzScrollBar
  • VertScrollBar to dfBaseVertScrollBar
  • SystemMenu to dfBaseSystemMenu
  • ImageList to dfBaseImageList
  • Message to cUIObject
  • _Data_set to BaseDataSet (note _Data_set is 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.