Module Dfextclm.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  : dfExtClM.pkg
    11// $File title : external class mixin support
    12// Notice      :
    13// $Author(s)  : John Tuohy
    14//
    15// $Rev History
    16//
    17// JJT  9/8/97    Revised
    18// JJT 7/25/97    File Created
    19//************************************************************************
    20
    21// This provides common mixin messages for hooking an external class
    22// to a VDF class. This assumes that this external class will be mixed into
    23// The main goal of this mixin is to sychronize the DataFlex focus event
    24// with the windows focus event.
    25// If is very important that a tool maker watches the focus change mechanism.
    26// It is very easy to create a control that looks like it is working but is
    27// An object takes the focus one of two ways: Either DataFlex gives it the
    28// focus (keyboard or send activate) or Windows gives it the focus (mouse).
    29// All of the internal DF classes makes sure that these two types of events
    30// are synchronized. When using external controls you must make sure that this
    31// is the case. Note that:
    32// 1. When DF sends activate to an object it may not give it the windows
    33//    focus. This one can usually be seen by testing with keyboard navigation.
    34//    Currently, we are augmenting Set Focus to make this work right.
    35// 2. When Windows gives the object the focus it may not tell DF about it.
    36//    You can not see this problem but you can test by getting the focus
    37//    property. If the focus is a different object than the object that
    38//    appears to have the focus, windows has given the object the focus
    39//    without telling DF. We use External_SetFocus (which is a notification
    40//    of a windows event) to check for this.
    41// 3. You want to make sure that DF sends the same focus change events when
    42//    an external object gets the focus or when it loses it. In particular,
    43//    you want to make sure that Notify_Focus_Change is sent to both objects
    44//    passing the appropriate Fg. This is very important. It insures that
    45//    OnSetFocus and onKillFocus are sent along with a number of other messages
    46//    which maintain status-help and default action buttons. This requires
    47//    careful checking to see what is sent and what is not and this must be
    48//    tested with both keyboard (DF side) and mouse (windows side) navigation.
    49//    Set Focus, External_SetFocus and External_KillFocus all had to be
    50//    messed with to get this right.
    51//
    52// Currently,
    53// 1. When the windows side takes the focus the DF side is not notified.
    54//    To make this work we sit on this message and send activate to the
    55//    DF side. We also need to send Notify_focus_Change (same needed
    56//    on a killFocus) because this is not getting sent.
    57//
    58// 2. There is a bug in the external class mechanism when used with
    59//    form objects. The DF Set_Focus message gets canceled. So we force
    60//    this through by sending a windows SetFocus. (This could change in
    61//    the future which could also affect #1's need to send notify
    62//    messages).
    63//
    64// 3. We hook into Page_object to force it to send PreInitializeWindow,
    65//    initializeWindow (both whose functionality must be provided) and
    66//    Shadow_display. Normally InitializeWindow is required to move
    67//    DF properties into the newly created windows control. PreIntializeWindow
    68//    is needed when windows styles must be set before creating the control.
    69//    Shadow_Display sends Enable_Window which normally requires not
    70//    additional code. Enable_Window  if provided to support shadowing of
    71//    objects.
    72//    NOTE: it is very important that developer uses object_Shadow_state
    73//    to disable entry to a window.  If you can not enter the object it should
    74//    be shadowed (disabled). Using a non-zero return to disable entry to an
    75//    enabled windows should be avoided.
    76//
    77// It is expected that the external control will want to hook into the
    78// following messages already created in this class:
    79//    External_SetFocus : Most likey assigned to WM_SetFocus
    80//    External_KillFocus: Most likely assign to WM_KillFocus
    81//
    82//
    83// expected usage:
    84//
    85//   Class MyFancyControl_Mixin is a Mixin
    86//      Import_Class_Protocol External_Class_Mixin
    87//      Procedure Define_MyFancyControl_Mixin
    88//            Set External_Class_Name '?????' To "?????"
    89//            Set External_Message ?????? To ?????
    90//            Set External_Message WM_SETFOCUS  To External_SetFocus
    91//            Set External_Message WM_KILLFOCUS To External_KillFocus
    92//            :
    93//      end_procedure
    94//      :
    95//      Procedure PreInitializeWindow
    96//          : called before control has been paged
    97//      End_procedure
    98//      :
    99//      Procedure InitializeWindow
   100//          : called after control has been paged
   101//      End_procedure
   102//   End_Class
   103//
   104//   Class dbMyFancyControl is a dbFormExternalControl
   105//      Import_Class_Protocol MyFancy_control_Mixin
   106//      Procedure Construct_Object
   107//          forward send construct_object
   108//          Send Define_MyFancyControl_Mixin
   109//          :
   110//        end_procedure
   111//        :
   112//    end_Class
   113//
   114Use VDFBase.pkg
   115
   116Class External_Class_Mixin is a Mixin
   117    { Visibility=Private }
   118    Procedure External_SetFocus
   119        integer iFail
   120        // if focus is already here then DF knows about the focus
   121        // change (it started it) and we need to do nothing. Else,
   122        // Windows started the focus change and we need to tell the
   123        // df side about it.
   124        if (Focus(desktop)<>self) Begin
   125           // this should not fail. If the object cannot be activated
   126           // then it should be disabled.
   127           get msg_Activate to iFail
   128           if not iFail ;
   129              Send Notify_Focus_Change true
   130        end
   131    End_Procedure
   132
   133    { Visibility=Private }
   134    Procedure External_KillFocus
   135        // this is not getting sent when the external control loses
   136        // the focus
   137        Send Notify_Focus_Change false
   138    End_Procedure
   139
   140    // Normally this is not used. This is called right before the
   141    // windows control is created. Can be used to set windows
   142    // styles.
   143    { Visibility=Private }
   144    Procedure PreInitializeWindow
   145    End_Procedure
   146
   147    // Normally this will get replaced (not augmented) by a mixin at
   148    // the same level.
   149    { Visibility=Private }
   150    Procedure InitializeWindow
   151    End_Procedure
   152
   153    { Visibility=Private }
   154    Procedure Page_Object Integer state
   155        Integer winhnd
   156        Get Window_Handle TO winhnd
   157        IF (state AND winhnd=0) Begin
   158           Send PreInitializeWindow // if init is required before creating control
   159           Forward Send Page_Object state
   160           Send InitializeWindow
   161           Send Shadow_Display
   162        End
   163        else ;
   164           Forward Send Page_Object state
   165    End_Procedure
   166
   167    // This could be augmented to do whatever is required to make
   168    // this control enable
   169    { Visibility=Private }
   170    Procedure Enable_Window integer iState
   171      integer hWnd
   172      Get Window_Handle to hWnd
   173      If hWnd ;
   174         Move (EnableWindow(hWnd,iState)) To hWnd
   175    End_procedure
   176
   177    { MethodType=Event Visibility=Private }
   178    Procedure Shadow_Display
   179      Send Enable_Window (Not(Object_Shadow_State(Self)))
   180    End_Procedure
   181
   182    // Currently form based classes cancel the set focus message if
   183    // there are no form_windows (which there will not be in an
   184    // external class). So we force windows to do the focus change. This
   185    // behavior may change in the future.
   186    //
   187    { Visibility=Private }
   188    procedure set Focus integer h1 integer h2
   189      integer rval
   190      Forward Set focus to h1 h2
   191      get window_handle to h1
   192      Move (SetFocus(h1)) to rval
   193      Send Notify_Focus_Change true
   194    end_procedure
   195
   196End_Class
   197