Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Execute code before closing form
Message
From
30/03/2007 05:30:05
Hans-Otto Lochmann
Dr. Lochmann Consulting Gmbh
Frankfurt, Germany
 
 
To
29/03/2007 12:20:52
General information
Forum:
Visual FoxPro
Category:
Forms & Form designer
Miscellaneous
Thread ID:
01209324
Message ID:
01210264
Views:
35
>Hi everyone, and thanks for the over-whelming response!
>
>I had to suddenly get on the move, and I'm travelling at the moment.I will shortly digest and execute the different inputs given by you all, and get back with my feedback.
>
>Thanks again,
>
>With best regards,
>
>Steve

Hi Steve,

a final comment, though it will be a rather lengthy one.

Your initial question was:
"Before exiting a Visual FoxPro form, I need some code to execute, to update certain parameters through the command 'thisform.cmdUpdate.click'."
But unfortunately you did not explain, what kind of data you want to update/save and how you want to handle a situation, which might require user interaction (see my reply to Tamar's remark).

After also reading all of the comments, I have updated my "TestBed" (you will find it below) and I also add a class of an SDIChild form (also below), which has a structure, with which you could use to update "some parameters" in the calling parent form when closing the child form. This class was designed by putting together some proposals and hints found in the "Kilo-Fox" (Marcia Akins/Andy Kramek/Rick Schummer), among others in Chapter 13, "Miscellaneous Things".

Unfortunately the Fox Help is very cryptic in its comments about the various events and methods involved (see there). So in most cases, I am working on, I define a method called OnClose(), which takes the "closing code and which will be invoked only once, regardless whether the user decides to give the "closing instruction" by clicking on the Close/Exit CommandButton, by pressing the Enter Key if that Button has focus, by pressing the ESC key or by clicking on the CloseBox on top right of the form. Also by setting one property I can either put a question to the user like - "Do you really want to quit though you didn't finish your lunch?" (or whatever is appropriate) or refrain from that. The Child form class is self-explanatory. If you have any further questions pleae ask.

So - happy testing with your design decision.

Hans
** Closing Form Testbed **************************
oForm = Createobject('frmBase')
oForm.Show(1)

Define Class frmbase As Form

  Caption = "FormBase - Testbase for closing down"
  KeyPreview = .T.
  *-- Reflects the answer to the questions, whether the user wants to close the form.
  lReleaseApproved = .F.
  lRequestReleaseApproval = .T.
  Name = "frmbase"
  Width = 400
  Height = 250

  Add Object cmdexit As CommandButton With ;
    Top = 80, ;
    Left = 100, ;
    Width = 80, ;
    Height = 27, ;
    Caption = "E\<xit", ;
    Name = "cmdExit"

  Add Object cmdNoClick As CommandButton With ;
    Top = 80, ;
    Left = 250, ;
    Width = 80, ;
    Height = 27, ;
    Autosize = .T., ;
    Caption = "No Function", ;
    Name = "cmdNoClick"

  Add Object chkRequestReleaseApproval As Checkbox With ;
    Top = 200, ;
    Left = 70, ;
    Width = 200, ;
    Height = 27, ;
    Autosize = .T., ;
    Caption = "Request release approval", ;
    Name = "chkRequestReleaseApproval", ;
    ControlSource = 'thisform.lRequestReleaseApproval'

  Add Object cmdClearScreen As CommandButton With ;
    Top = 200, ;
    Left = 250, ;
    Width = 80, ;
    Height = 27, ;
    Autosize = .T., ;
    Caption = "Clear Screen", ;
    Name = "cmdClearScreen"

  Procedure Destroy
    Activate Screen
    ? 'frmbase.Destroy()'
    Thisform.cmdNoClick.SetFocus()
    Nodefault
  Endproc

  Procedure Init
    Activate Screen
    Clear
    ? 'frmbase.Init()'
    If !DoDefault()
      Return .F.
    Endif
    With Thisform
      .lReleaseApproved = .F.
      .AutoCenter = .T.
      .AutoCenter = .F.
    Endwith
  Endproc

  Procedure KeyPress
    Lparameters nKeyCode, nShiftAltCtrl
    Activate Screen
    ? 'frmbase.Keypress()'
    If nKeyCode = 27 And nShiftAltCtrl = 0
      Nodefault
      Thisform.Release
      Return
    Else
      DoDefault(nKeyCode, nShiftAltCtrl)
    Endif
  Endproc

  Procedure OnClose
    Activate Screen
    ? 'frmbase.Onclose()'
    Messagebox('Do some useful code here!')
  Endproc

  Procedure QueryUnload
    Activate Screen
    ? 'frmbase.Queryunload()'
    ? Iif(Thisform.ReleaseType = 0, "Variable released.",;
      Iif(Thisform.ReleaseType = 1, "Close menu command or close box.",;
      "Exit Visual FoxPro."))
    Local lnAnswer As Integer
    With This As Thisform
      If .lReleaseApproved = .F. And .lRequestReleaseApproval
        m.lnAnswer = Messagebox( ;
          'Would you really like to close down?', ;
          4+32+256+4096, .Caption)
        If m.lnAnswer = 6
          .lReleaseApproved = .T.
          .OnClose()
          *-- I do not know, whether this is really needed here.
          DoDefault()
        Else
          .lReleaseApproved = .F.
          *-- This is a MUST in order to prevent this method to call
          *-- the unload method.
          Nodefault
        Endif m.lnAnswer = 6
      Else
        DoDefault()
      Endif .lReleaseApproved = .F.
    Endwith
    Return
  Endproc

  Procedure Release
    Activate Screen
    ? 'frmbase.Release()'
    Local lnAnswer As Integer
    With This As Thisform
      If .lReleaseApproved = .F. And .lRequestReleaseApproval
        m.lnAnswer = Messagebox( ;
          'Would you really like to close down?', ;
          4+32+256+4096, .Caption)
        If m.lnAnswer = 6
          .lReleaseApproved = .T.
          .OnClose()
          *-- When this form has an object reference in a collection, and
          *-- this Release method is called, the object is removed from
          *-- the collection.
          DoDefault()
        Else
          .lReleaseApproved = .F.
          Nodefault
        Endif m.lnAnswer = 6
      Else
        DoDefault()
      Endif .lReleaseApproved = .F.
    Endwith
    Return
  Endproc

  Procedure Unload
    Activate Screen
    ? 'frmbase.Unload()'
    Nodefault
    *--- Do whatever needed at the very end like CLEAR EVENTS
    Release oForm
    DoDefault()
  Endproc

  Procedure cmdexit.Click
    Thisform.Release()
  Endproc

  Procedure cmdClearScreen.Click
    Activate Screen
    Clear
  Endproc

  Procedure chkRequestReleaseApproval.Click
    If This.Value = .T.
      This.Caption = "Request release approval"
    Else
      This.Caption = "No release approval"
    Endif This.Value = .T.
  Endproc

Enddefine
**************************************************
**************************************************
*-- SDI Child Form With The Same Data Session As the Parent
*--
*-- Class:        frmsdichildform (c:\dev\vfp\d\reuse\libraries\hlforms.vcx)
*-- ParentClass:  frmsdibase (c:\dev\vfp\d\reuse\libraries\hlforms.vcx)
*-- BaseClass:    form
*-- Time Stamp:   09/30/06 09:42:11 AM
*
DEFINE CLASS frmsdichildform AS frmsdibase


	DataSession = 1
	Top = 0
	Left = 0
	Height = 250
	Width = 400
	DoCreate = .T.
	Caption = "SDI Child Form With The Same Data Session As the Parent"
	*-- Set .T. if the Data Session of this form should be the same as the
         *-- Data Session of the calling form.
	lbindtoparentdatasession = .T.
	*-- If set .T. it will make the parent form invisible otherwise both.
         *-- Parent and Child will be visible. Applies only if called from a parent form.
	lmakeparentinvisible = .F.
	*-- Will be set .T. if NOT called from a parent form - will be set .F. if
         *-- called from a parent form.
	lclosewhendeactivated = .F.
	*-- Will be set .T. if called from a parent form - will be set .F. if NOT called
         *-- from a parent form.
	lclosewithcaller = .F.
	*-- Must be set .F. to prevent the user from changing the size of the form.
	lresizeable = .T.
	ocalledby = .NULL.
	nmaxnumberofconcurrentinstances = 1
	Name = "frmsdichildform"


	PROCEDURE Deactivate
		********************************************************************************
		*-- frmSDIChildForm.Deactivate()
		********************************************************************************

		If Thisform.lCloseWhenDeactivated = .T.
		  Thisform.Release
		Endif Thisform.lCloseWhenDeactivated ...
	ENDPROC


	PROCEDURE Load
		********************************************************************************
		*-- frmSDIChildForm.Load()
		********************************************************************************
		*-- This method provides for "connections" to the parent form.
		*-- (See Kilo-Fox, Chap. 13.4.2 for further details)
		********************************************************************************
		*--
		*-- Remarks:
		*--
		*-- As far as I understand it, there will be one member in the forms collection
		*-- of the objects _Screen. As far as I can see it, the names of these members
		*-- must be unique, otherwise VFP will get confused.
		*--
		*-- If you want to know more about it, study Kilo-Fox, Chap. 13, and the like.
		*--
		*-- As soon as the instantiation of a form (or form class) is started, obviously
		*-- a new member will have been added to the forms collection _screen.Forms().
		*-- This new member will be assigned the name of this form (thisform.name). If
		*-- the load method is started then this new ember exists already and carries
		*-- the name of this method.
		*--
		*-- So if we want to have only one instance of this form running, then we
		*-- should check the _screen.Forms() collection, whether there is a member
		*-- with has the the name thisform.name. If there is only one, then this is us
		*-- trying to create our first instance. If there are two members with "our"
		*-- name, then we should stop, because we have our instance already
		*--
		*-- If we want to have more than one instance of this form running, then we
		*-- should manipulate the name of each additional instance of this form in such
		*-- a way, that we easily can identify them. For instance, we could call the
		*-- second instance frmMyModalChild_2, the third instance frmMyModalChild_2 and
		*-- so on. Below we describe a way to do so assuming, that the first instance of
		*-- this class would be called frmMyModalChild, as usual.
		*--
		*-- By the way: The name of the newest form to instantiate seems always to be
		*-- the name of the member(1) of the forms collection. But (up to now) I did not
		*-- find any notes on that.
		********************************************************************************

		Local lnHowOften As Integer
		Local lnI As Integer
		Local lcNameBase As String

		With This As Thisform

		  *-----------------------------------------------------------------------------
		  *-- Check, whether there is an instance of this form active already.
		  *-----------------------------------------------------------------------------
		  m.lnHowOften = 0
		  *-- Find out, how often our name is found in the forms collection.
		  For m.lnI = 1 To _Screen.FormCount
		    If   At(Lower(This.Name),Lower(_Screen.Forms(m.lnI).Name)) > 0
		      m.lnHowOften = m.lnHowOften + 1
		      If m.lnHowOften > .nMaxNumberOfConcurrentInstances
		        *-- This is exactly one more of the number entries than we want to have.
		        *-- So we quit.
		        *_Screen.Forms(m.lnI).Show()
		        Return .F.
		      Endif m.lnHowOften < lnMaxNumberOfCo ...
		    Endif   At(Lower(This.Name),Lower(_S ...
		  Next m.lnI
		  *-- Build our name.
		  m.lcNameBase = This.Name
		  If m.lnHowOften > 1
		    This.Name = This.Name + '_' + Transform(m.lnHowOften)
		  Endif m.lnHowOften > 1

		  *-----------------------------------------------------------------------------
		  *-- If called by a parent form, get a reference to the parent form. If we are
		  *-- starting our next instance in the developer environment, then ActiveForm 
		  *-- will be our previous instance. We cannot take that instance as a "parent" 
		  *-- for obvious reasons.
		  *-----------------------------------------------------------------------------
		  If Type('_screen.ActiveForm') = 'O' And ;
		      At(Lower(m.lcNameBase), Lower(_Screen.ActiveForm.Name)) = 0
		    .oCalledBy = _Screen.ActiveForm
		  Else
		    .oCalledBy = .Null.
		  Endif Type('_screen.ActiveForm') = ' ...

		  *-----------------------------------------------------------------------------
		  *-- If we've been called by a parent form, then ...
		  *-----------------------------------------------------------------------------
		  If Not Isnull(.oCalledBy)

		    *---------------------------------------------------------------------------
		    *-- we bind OnRelease to the release event of the calling form and ...
		    *---------------------------------------------------------------------------
		    m.lnBindings = Bindevent(.oCalledBy,'Release',Thisform,'OnRelease')
		    .lCloseWithCaller = .T.
		    .lCloseWhenDeactivated = .F.

		    *---------------------------------------------------------------------------
		    *-- if requested, we set a reference to its datasession, so we can use its
		    *-- Data Environment (see Kilo-Fox, Chap. 13.3 for further details) and ...
		    *---------------------------------------------------------------------------
		    If .lBindToParentDataSession = .T.
		      .DataSessionId = .oCalledBy.DataSessionId
		    Endif .lBindToParentDataSession = .T ...

		    *-----------------------------------------------------------------------------
		    *-- if requested, we make the parent form invisible.
		    *-----------------------------------------------------------------------------
		    If .lMakeParentInvisible = .T.
		      .oCalledBy.Visible = .F.
		    Endif .lMakeParentInvisible = .T.

		  Else

		    *-----------------------------------------------------------------------------
		    *-- If we've not been called by a parent form, therefore ...
		    *-----------------------------------------------------------------------------
		    .lCloseWithCaller = .F.
		    .lCloseWhenDeactivated = .T.

		  Endif Pemstatus(Thisform,'oCalledBy',5 ...

		Endwith

		*-------------------------------------------------------------------------------
		*-- Use built-in functionality.
		*-------------------------------------------------------------------------------
		DoDefault()
	ENDPROC


	PROCEDURE Init
		********************************************************************************
		*-- frmSDIChildForm.Init()
		********************************************************************************

		*-------------------------------------------------------------------------------
		*-- The usual suspects.
		*-------------------------------------------------------------------------------
		If !DoDefault()
		  Return .F.
		Endif

		With This As Thisform

		  *-----------------------------------------------------------------------------
		  *-- If requested, inhibit any changes of the size.
		  *-----------------------------------------------------------------------------
		  If .lResizeable = .F.
		    .MinHeight=.Height
		    .MaxHeight=.Height
		    .MinWidth=.Width
		    .MaxWidth=.Width
		  Endif .lResizeable = .F.

		Endwith
	ENDPROC


	PROCEDURE Unload
		********************************************************************************
		*-- frmSDIChildForm.Unload()
		********************************************************************************
		*-- We undo a few things we did in the Load method.
		********************************************************************************

		With This As Thisform

		  *-----------------------------------------------------------------------------
		  *-- If we've been called by a parent form, then ...
		  *-----------------------------------------------------------------------------
		  IF  Not Isnull(.oCalledBy)
		    
		    *---------------------------------------------------------------------------
		    *-- we bind us to the release event of the calling form and ...
		    *---------------------------------------------------------------------------
		    m.lnBindings = Unbindevent(.oCalledBy,'Release',Thisform,'OnRelease')

		    *-----------------------------------------------------------------------------
		    *-- we make the parent form visible again and ...
		    *-----------------------------------------------------------------------------
		    If .lMakeParentInvisible = .T.
		      .oCalledBy.Visible = .T.
		    Endif .lMakeParentInvisible = .T.

		    *-----------------------------------------------------------------------------
		    *-- finally we cut the connection to the parent, so Thisform can be deleted.
		    *-----------------------------------------------------------------------------
		    .oCalledBy = .Null.

		  Else

		    *-----------------------------------------------------------------------------
		    *-- If we've not been called by a parent form, therefore ...
		    *-----------------------------------------------------------------------------
		    Dodefault() 

		  ENDIF  Not Isnull(.oCalledBy)

		Endwith

		*-------------------------------------------------------------------------------
		*-- Run built-in functionality.
		*-------------------------------------------------------------------------------
		DoDefault()
	ENDPROC


ENDDEFINE
*
*-- EndDefine: frmsdichildform
**************************************************
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform