View RSS Feed

Development Team Blog

Loading Values in a ComboForm

Rate this Entry
The ComboForm class is part of the Visual DataFlex product since it was introduced in 1996. The control is also called a drop-down box and combines a single value entry control with a list of options. By setting the property Entry_State to false you turn the control into a select only list, users can rotate through the values with a arrow-down/arrow-up keys and open the list by clicking on the arrow on the right. Usually the list is static and does not extend during the program run.

If the ComboForm is not connected to a ValidationTable, a DescriptionValidationTable, a FileValidationTable or a CodeValidationTable you will load the data in a method named Combo_Fill_List. For example:

Code:
Object oGenderForm is a ComboForm
    Set Location to 35 50
    Set Size to 13 153
    Set Label to "Gender:"
    Set Label_Col_Offset to 2
    Set Label_Justification_Mode to JMode_Right
    Set Combo_Sort_State to False
    Set peAnchors to anTopLeftRight
    Set Entry_State to False
    Set Color to clBtnFace

    Procedure Combo_Fill_List
        Send Combo_Add_Item "Unknown"
        Send Combo_Add_Item "Male"
        Send Combo_Add_Item "Female"
    End_Procedure
End_Object
The above code loads the three words in the list of values and the first one of the list will be the default. In the program from which I took this code I do not allow the users to change information but I allow the control to take the focus. Therefore I color the control as it is shown when it is disabled (clBtnFace).

As you can see it is very easy to create a ComboForm with values. The code above however has one disadvantage when looked at with an object oriented mindset; Because it is technically not possible in an object oriented language to add new behavior to an object (add a method, a property) the Visual DataFlex compiler makes a sub-class from the ComboForm class, adds our procedure Combo_Fill_List to that class and base the object on that dynamically sub-classed class. The class of this control is not longer ComboForm but it is something else (say ComboForm'1). Not really a problem until you need a dozen of these objects all with a similar list of data items. In that case we wouldn't make use of the powers offered by good object orientated programming. If the data was 100% the same you would more quickly decide to sub-class manually and base the objects yourself on the self made sub-class.

I was faced with this problem in one of my projects and I also wanted to reduce the number of source code lines in the module. Therefore I created sub-class that makes it all easier and more object oriented. With the following code I made a sub-classed ComboForm that loads the data from a property instead of in a method. This way we can have a dozen objects without that every object has its own Combo_Fill_List method.
Code:
Class cComboForm is a Comboform
    Procedure Construct_Object
        Forward Send Construct_Object

        Set Size to 13 153
        Set peAnchors to anTopLeftRight
        Set Label_Col_Offset to 2
        Set Label_Justification_Mode to JMode_Right
        Set Entry_State to False
        Set Color to clBtnFace
        
        Property String psValues
        Property String psUnknownValue "Unknown"
        Property String psDelimiter ';'
        Property Boolean pbUnknownFirst False
    End_Procedure
    
    Procedure Combo_Fill_List
        String sValues sDelimiter
        Integer iPos        
        Boolean bUnknownFirst
        
        Get pbUnknownFirst to bUnknownFirst
        If (bUnknownFirst) Begin
            Get psUnknownValue to sValues
            If (sValues <> "") Begin
                Send Combo_Add_Item sValues
            End                    
        End
        
        Get psValues to sValues
        Get psDelimiter to sDelimiter
        While (sValues <> "")
            Move (Pos (sDelimiter, sValues)) to iPos
            If (iPos > 0) Begin
                Send Combo_Add_Item (Left (sValues, iPos - 1))
                Move (Right (sValues, Length (sValues) - iPos)) to sValues
            End
            Else Begin
                Send Combo_Add_Item sValues
                Move "" to sValues
            End
        Loop

        If (not (bUnknownFirst)) Begin
            Get psUnknownValue to sValues
            If (sValues <> "") Begin
                Send Combo_Add_Item sValues
            End
        End
    End_Procedure
End_Class
An example of an object based on this class is:
Code:
Object oGenderForm is a cComboForm
    Set Combo_Sort_State to False
    Set Location to 35 50
    Set Label to "Gender:"
    Set psValues to "Male;Female"
End_Object
You can see that the code is much more clean at object level. It makes much more use true object orientation. The values in the psValues property are separated by a semi-colon which is configurable via the psDelimiter property. The value of "Unknown" can be changed via the property psUnknownValue which defaults to "Unknown". You can even indicate if you want that "Unknown" value at the top of the bottom of the list of options. I needed it on the bottom but you might want to do the opposite.

Comments