Module dbExtFrm.pkg

     1//************************************************************************
     2// Confidential Trade Secret.
     3// Copyright (c) 1997 Data Access Corporation, Miami Florida
     4// as an unpublished work.  All rights reserved.
     5// DataFlex is a registered trademark of Data Access Corporation.
     6//
     7//************************************************************************
     8//************************************************************************
     9//
    10// $File name  : dbExtFrm.pkg
    11// $File title : dbFormExternalControl
    12// Notice      :
    13// $Author(s)  : John Tuohy
    14//
    15// $Rev History
    16//
    17// 9/8/97    JJT - File created
    18//************************************************************************
    19
    20//This creates an class that can be used for creating single item data-entry
    21//classes based around a custom windows control(or any DLL). This class is used
    22//for sub-classing only. This contains all the "basic" behaviors required
    23//to create a DEO class. In a sub-class you must add the needed logic to
    24//talk to a custom control and the needed logic to coordinate the DF class and
    25//the windows control. Normally this is done as follows:
    26//
    27//1. Create a mixin class that contains all of the logic and interface to
    28//   support a custom control. Normally, this class will define an external
    29//   control (Set External_Class_Name 'DFTrackBar' To "msctls_trackbar32")
    30//   and map windows messages to DF messages (Set External_Message WM_HSCROLL
    31//   To Private_SliderNotification). Normally this mixin class will itself
    32//   contain a mixin class named External_Class_Mixin (DFExtClM.pkg) which
    33//   contains logic that will be common to all external control mixin classes.
    34//   In particular this creates two messages External_SetFocus and
    35//   External_KillFocus were created to handle focus changes events. Those
    36//   messages must be mapped to windows messages and will most likely be:
    37//        Set External_Message WM_SETFOCUS  To External_SetFocus
    38//        Set External_Message WM_KILLFOCUS To External_KillFocus
    39//
    40//2. When creating this mixin class you need to identify three message types:
    41//   A. The message(s) that is (are) sent when the control's data value is
    42//      changed. Whenever the windows control changes we want to notify the DF
    43//      side of this change so that Get Value is always up to date. This is very
    44//      important for DDs since they must be updated anytime a DEO's data value
    45//      changes. We will augment each of these messages and force it to send
    46//      the message ControlValueChanged. This will force the DF side to stay
    47//      synchronized with the control.
    48//   B. The message that gets the current data value of the windows control. This
    49//      is used to get this value and set the DF side's value accordingly.
    50//   C. The message that sets the current data value of the windows control. This is
    51//      used to set the control value to its DF value. Often B and C will be a
    52//      GET/SET message of the same name.
    53//
    54//   For the sake of example lets assume that messages A, B, and C were defined in
    55//   the mixin as:
    56//      A.  Procedure     onHeyControlChanged
    57//      B.  Function      MyCustomControlDataValue returns String
    58//      C.  Procedure Set MyCustomControlDataVale String sVal
    59//
    60//3. You will create your sub-class as follows:
    61//
    62//Class dbMyCustomFormClass is a dbFormExternalControl
    63//
    64//    import_class_protocol MyCustomControl_Mixin
    65//
    66//    Procedure Construct_Object
    67//       Forward Send Construct_Object
    68//       Send Define_MyCustomControl_Mixin
    69//    End_Procedure // Construct_Object
    70//
    71//    // we must identify all events that result in a changed
    72//    // value in the control and notify the DF side about this
    73//    // change. We notify DF by sending ControlValueChanged. If multiple
    74//    // events cause changes, multiple messages must be created all sending
    75//    // ControlValueChanged
    76//    Procedure OnHeyControlChanged
    77//        Send ControlValueChanged
    78//    End_Procedure
    79//
    80//    // The class expects a message named Set ControlValue. It is passed a string
    81//    // and should be used to change the value of the windows control. This
    82//    // is the message "C" from above.
    83//    Procedure Set ControlValue string sVal
    84//        Set MyCustomControlDataValue to sVal
    85//    End_Procedure
    86//
    87//    // The class expects a messsage named get controlValue. It will return
    88//    // the control's data value.
    89//    Function ControlValue Returns String
    90//        string sVal
    91//        Get MyCustomControlDataValue to sVal
    92//        Function_return sVal
    93//    End_Function
    94//
    95//End_Class
    96//
    97
    98
    99use dfentry.pkg
   100
   101
   102
   103Class dbFormExternalControl is a dbForm
   104
   105    Procedure Construct_Object
   106        Forward Send Construct_Object
   107        // This is used to prevent recursion. When a control notifies
   108        // DF that a value has changed, DF will attempt to notify the
   109        // control. We must stop that circularity
   110        
   111        Property integer Private.ControlChangingState false
   112
   113        // set true when making a local (externally triggered) change. This is
   114        // set when a Set Value of Set Local_Value change is made
   115        
   116        property integer LocalChangingState false
   117        Set Prompt_Button_Mode to PB_PromptOff  // add next revision
   118    End_Procedure // Construct_Object
   119
   120    //
   121    // When the DF side changes we must notify the control about the change.
   122    // If DD are in use we must use set Local_Value, if no DD we use set value
   123    //
   124    
   125    Procedure set Value integer iItem string sVal
   126        forward set value item iItem to sVal
   127        If (Extended_deo_State(self)=0 AND ;
   128            Private.ControlChangingState(self)=0 ) ;
   129                Send RefreshControl sVal
   130    End_Procedure
   131
   132    
   133    Procedure set Local_Value integer iItem string sVal
   134        forward set Local_value item iItem to sVal
   135        If not (Private.ControlChangingState(self)) ;
   136           send RefreshControl sval
   137    End_Procedure
   138
   139    // It is expected that the sub-class (or more likely another
   140    // mixin included with the sub-class will provide functionality
   141    // for these messages. This gets and sets the value of the actual
   142    // window control. These should only be used to synchronize the window
   143    // control and the DF side. Do not use for any other purpose.
   144    //
   145    
   146    Procedure Set ControlValue string sVal
   147    End_Procedure
   148
   149    
   150    Function ControlValue Returns String
   151    End_Function
   152
   153    // refresh control without triggering a DD changed condition.
   154    
   155    Procedure RefreshControl string sVal
   156        integer bOld
   157        Get LocalChangingState to bOld
   158        Set LocalChangingState to True
   159        set ControlValue to sval
   160        Set LocalChangingState to bOld
   161    End_Procedure
   162
   163    
   164    Procedure ControlValueChanged
   165        integer bOld
   166        String sval
   167        If (LocalChangingState(self)) Procedure_return
   168        Get Private.ControlChangingState to bOld
   169        Set Private.ControlChangingState to True
   170        Get ControlValue to sVal
   171        Set Changed_Value item 0 to sVal
   172        Set Private.ControlChangingState to bOld
   173    End_Procedure
   174
   175End_Class