Partager via


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

  • Anonymous
    August 29, 2006
    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 *************

  • Anonymous
    October 20, 2006
    Here’s a blog post that I wrote a long time ago, but forgot to publish. Marco Cenzato commented on Why

  • Anonymous
    March 14, 2007
    Du musst ein Fachmann sein - wirklich guter Aufstellungsort, den du hast!

  • Anonymous
    April 10, 2007
    Luogo molto buon:) Buona fortuna!

  • Anonymous
    April 10, 2007
    pagine piuttosto informative, piacevoli =)

  • Anonymous
    April 13, 2007
    9 su 10! Ottenerlo! Siete buoni!

  • Anonymous
    April 14, 2007
    Stupore! ho una sensibilit molto buona circa il vostro luogo!!!!

  • Anonymous
    April 15, 2007
    E grande io ha trovato il vostro luogo! Le info importanti ottenute! ))

  • Anonymous
    April 11, 2008
         Good idea! P.S. A U realy girl?