Why doesn’t my form close?


If you run the code below, you’ll get an error message. The grid height is being set to 19, which is too small for a vertical scrollbar. Dismiss the message and try to close the form. If you hit Ctrl-F4 or click on the close box, the close box gets dim, but the form doesn’t close.  If you CLEAR ALL in the command window, the form is released.


 


If you change the 19 to 39 so it is a valid height, the form can close.


Why?


 


To figure out the answer, I used the VS debugger to trace through the VFP internal code that closes the form. When an object is asked to be released, VFP tries to see if the object can close. If there are any member objects on the form, each one must have a reference count of one. If there is any member object that has an outstanding reference, then the form says that it cannot close. As you can imagine, this process is recursive.


 


For example, change it to 39 for the non-error case, run the form and get an outstanding reference to the form by typing NewVar=oForm.spin1. This creates a new variable called NewVar which references the spinner. Now the form cannot close as in the error case. Set NewVar to 0, and the form disappears.


 


Internally, for a routine that handles for example, a spinner keypress event, VFP will increment the refcount on the spinner, call the code to handle the event, then decrement the refcount. This protects VFP from user code that releases the object in the event.


 


There was some code that was incrementing the refcount, encountering the error, and the error caused that code’s matching refcount decrement to be bypassed. This code was processing CanLoseFocus, which was storing the spinner value to the grid height, which caused the error.


 


The fix is simple: don’t bypass the decrement if an error occurs.


 


 


 


Thanks to Fabio Lunardon for this bug report.


 


PUBLIC oform


 


oForm = NEWOBJECT(“form1”)


oForm.Show


KEYBOARD ’19{TAB}’      PLAIN


 


DEFINE CLASS form1 AS form


      ADD OBJECT grid1 AS grid


     


      ADD OBJECT spin1 AS spinner WITH ;


            format = ‘K’,;


            Left = 108, ;


            Top = 96, ;


            ControlSource = “thisform.grid1.height”


 


ENDDEFINE


 

Comments (9)

  1. Marco Cenzato says:

    Here is another case; what do you think: is related?

    ************* cut here *************

    ** Comment the define and rerun the program

    #Define USE_BINDEVENT

    Activate Screen

    Clear

    Local oForm

    oForm = NewObject(‘MyForm’)

    If Vartype(oForm) == ‘O’

    ? "A form was created: this is not the expected behaviour"

    oForm.Show(1)

    Else

    ? "No form was created: this is the expected behaviour"

    EndIf

    Define Class MyForm As Form

    Autocenter = .T.

    #Ifdef USE_BINDEVENT

    Procedure Load

    BindEvent(This, ‘Init’, This, ‘InitCompleted’, 1)

    EndProc

    Procedure InitCompleted

    ? ‘InitCompleted fired’

    EndProc

    #EndIf

    Procedure Init

    Return .F.

    EndProc

    EndDefine

    ************* cut here *************

  2. Here’s a blog post that I wrote a long time ago, but forgot to publish. Marco Cenzato commented on Why

  3. ... says:

    Du musst ein Fachmann sein – wirklich guter Aufstellungsort, den du hast!

  4. ... says:

    Luogo molto buon:) Buona fortuna!

  5. ... says:

    pagine piuttosto informative, piacevoli =)

  6. ... says:

    9 su 10! Ottenerlo! Siete buoni!

  7. ... says:

    Stupore! ho una sensibilit molto buona circa il vostro luogo!!!!

  8. ... says:

    E grande io ha trovato il vostro luogo! Le info importanti ottenute! ))

  9. Memmorium says:

         Good idea!

    P.S. A U realy girl?