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{ ClassType=Abstract }
   102{ HelpTopic=dbFormExternalControl }
   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        { Visibility=Private }
   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        { Visibility=Private }
   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    { MethodType=Property  NoDoc=True }
   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    { Visibility=Private MethodType=Property }
   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    { Visibility=Private MethodType=Property }
   146    Procedure Set ControlValue string sVal
   147    End_Procedure
   148
   149    { MethodType=Property Visibility=Private }
   150    Function ControlValue Returns String
   151    End_Function
   152
   153    // refresh control without triggering a DD changed condition.
   154    { Visibility=Private }
   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    { Visibility=Private }
   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
   176