Wiki Home

DODEFAULT Or NODEFAULT


Namespace: VB
The DODEFAULT() function and the NODEFAULT command sound like they affect the same thing, but that is misleading.

NODEFAULT - Cancels the native VFP behavior for this event.
DODEFAULT() - calls the method code in the parent class.

So, how are NODEFAULT and DODEFAULT related? They aren't. Therefore, you can mix and match them as you need.

They deal with 2 realms of VFP programming:
1) VFP event code (related to NODEFAULT): The native functionality of an event of a VFP baseclass. Example: it is what causes letters to appear in a textbox as the user hits keys on the keyboard. This event is implemented by C code. You may have taken it for granted that that should just happen, but nooo, VFP is dealing with the OS to get keyboard info, and if there is any, it is feverously calling the keypress event, which in turn is building a string that is linked to the .value property, moving the cursor, and updating the display. I suppose this is one of the traits of a high level language. Ok, so now we have a definition of VFP event. Calling DODEFAULT() in an object based on a base class causes the VFP event code to fire. If that method does not have a NODEFAULT statement, then the VFP event code fires twice.

2) Method code (related to DODEFAULT() ) : Written using VFP commands and functions that are part of a class's method. It is the code you can see when you open up an method in the editor, or you see it in the debugger's trace window when you step execution a line at a time. There are two things that can cause method code to be executed: 1)a call to it: myclass.mymethod() and 2) an Event occured that is linked to the method. Not all methods (even the VFP base class methods) have events linked to them; only the ones that say "event" next to them in the PEM window. And now we have a definition of Method code.

Now back to defaults.

NODEFAULT: The default is for VFP Event code to execute, regardless of any Method code that you put in the method, or even the method of a subclass. The NODEFAULT command will prevent the VFP Event code from executing. It will prevent the textbox from doing what I 'feel' it should normally do. Hmm, that's kind of vague, but I think that's as good as I can do. Hopefully, you have a 'feeling' as to what the NODEFAULT command does.

DODEFAULT(): another set of definitions: parent.yourcode, and child.yourcode - methods that both have Method code in them. The DODEFAULT function calls the method in the parentclass. Therefore, this function only applies when you have subclassed something. You could use it in the method of a baseclass, but it will should (see notes on this) have no effect. The default of a subclass is for the child.yourcode to to override the parent.yourcode. If you want the parent.yourcode to execute, you must call it with the dodefault() function. There is nothing magic about that call: think of parent.yourcode as a UDF named dodefault(). Just like any UDF, if you want it to execute, you have to call it.

A common misunderstanding:
Based on the similarity of the names, a common misunderstanding is that DODEFAULT() and NODEFAULT are opposites. It is true that if there is an empty method, VFP will automatically execute any code in the same method in ancestor classes, and that inserting a NODEFAULT statement into that previously empty method prevents that higher level code from executing unless you also place a DODEFAULT() call where it gets executed in the same method. HOWEVER, placing any other code (for example, just one * comment line) in that previously empty method would have the same effect. The difference is that the NODEFAULT statement would have an additional effect: the VFP Event code related to that method would also not get called.

This is because VFP Method code does not override the native VFP event... only the NODEFAULT statement prevents the native VFP event from being called.

Some confusion may have been caused by the Property sheet putting the word "Event" next to the methods that are fired by VFP events. They (Methods and Events) are two different things. The method is a hook into the event. The "Key Press method" gets called when a Key Press Event occurs. When you put code in the Key Press method, you are not replacing the Key Press Event code. Once the Key Press method (which may have moved down the class hierarchy by subclassing) is finished, control returns to the event; It will then execute its behavior unless a NODEFAULT has been issued in one of the hierarchy of Key Press Methods.

The confusion may also arise from the lack of documentation. The textbox.KeyPress docs read "Occurs when the user presses and releases a key.", but it does not say what will happen: text keys will add a letter to the control's .value, arrows can move the selection or cause focus to move to another control, and sometime the .Control Source gets updated.

Hope this helps. I would suggest subclassing a textbox, and putting bits of code in the Key Press method. Key Press is helpful for this discussion because it is very visual, and helps you 'see' when something is happening or not. -- ?CFK

I don't know about unlearning, but I always value an opporunity to learn more. It seems to me that you limited your discussion of dodefault() and nodefault to their use in relation to VFP Events, and your last comments bring that to a clearer focus. Certainly, nodefault is almost undocumented, both in the manuals and in a dangling reference in the Hackers Guide. I haven't needed, so far, to get too close to messing with VFP events, but when I do, I will be back here.

I have reworked my inital work. If it clears up the cause of misunderstanding, please remove the additional paragraphs. If it does not, please try to write a more clear description; maybe you will have better luck than I.

Look to NODEFAULT. I just described some useful behaviors of dodefault() after nodefault.

What VFP does when NODEFAULT used? Well, it just sets to true an internal flag to indicate that current event or method should not continue default processing. When event or method code finished, this flag is verified and used to skip the rest of default behavior. Default behavior also can run BEFORE event firing, this you cannot cancel. For example, all mouse events have default behavior before event firing, so changed parameters of event for dodefault() function will have no effect for mouse events.

Dodefault() causes running of the default code immediately if there are no parent class and there are no code in parent class(es) in all hierarchy for this event/method. Here is a danger for programmers that write class libraries: when parent class have no code, dodefault() will run VFP defaul behavior instead of calling of parent class method/event. This causes default behavior ro run 2 times. For example, for Key Press event in such case each character will be doubled in Text Box.

-- Vlad Grynchyshyn
One of the issues I have with VFP is that the behavior of controls isn't really documented. I have a 'feeling' about how a textbox works, but I sure can't find any documentation to refer to.
I like to call the default VFP behavior for an event 'intrinsic behavior.' For example, the intrinsic behavior of the textbox.lostfocus event is for the textbox to lose focus. A NODEFAULT command in text1.lostfocus method will cause text1 to not lose focus when it otherwise would. NODEFAULT in an event method will cause the parent class user code to not be executed, but then again so does any valid VFP command. The intrinsic behavior for an event by default occurs after any user code in that event method is executed. If you add user code to text1.lostfocus, it gets executed before text1 actually loses focus. You can use a combination of NODEFAULT and DODEFAULT() (or ::), to force intrinsic behavior to occur when you want it to.

In text1.lostfocus()

debugout thisform.activecontrol.name
nodefault
dodefault()
debugout thisform.activecontrol.name


The nodefault can be placed anywhere in the method, because the intrinsic behavior happens after all the user code. The 2nd debugout causes an error because text1 no longer has focus, and there is no activecontrol quite yet, as focus has not moved to the next control in the tab order. It can't because code is still executing in text1.lostfocus. I hope this clears things up some. I think it helps to clearly differentiate between intrinsic event behavior, and execution of inherited code. DODEFAULT() can be used to invoke either, where NODEFAULT suppresses intrinsic behavior, and affects inherited code to the degree that any VFP commmand does. There are indeed differences when using dodefault() with and without inherited parent class code. I like to use scope resolution, i.e., textbox::lostfocus, instead when I specifically want only the intrinsic behavior to occur, to eliminate confusion.

Jim Saunders

Your example for the definition of "intrinsic behaviour" still leaves a question in my mind - if the only intrinsic behaviour of Lost Focus is to cause the control to lose focus, by what means does the next control get focus? Personally I would attribute it to additional behaviour of Lost Focus but ideally the VFP documentation would tell us exactly (and for each event).--- Jim Nelson

I think of it as part of the form's "intrinsic behavior" or even the VFP event manager. An other example of mystery behavior is whatever causes an object to abort loading if its init() returns .f. I think of it as the "object manager." -- ?CFK

So, based on all of this, is the "rule of thumb" as follows?:
Don't put DODEFAULT() in a class that is based directly on a Foxpro Base Class in the base methods or events unless......
  • You want the Base Class intrinsic method/event to fire twice or -
  • You want to control when the Base Class method/event gets fired in which case you should use NODEFAULT at the end
  • If you are 2 sub-classes (levels) away from the Base Class, DODEFAULT() will NOT fire the Base Class intrinsic method/event twice even if there is no code in the first sub class AND -
  • You should ALWAYS include DODEFAULT beyond the first level to ensure Base Class intrinsic method/events DO fire.

  • Is the above correct or close to correct (I hope)? -- Randy Jean
    You can handle this in a consistent way. Just add a conditional test and fire nodefault. Using the textbox.keypress as an example, a baseclass instance would need a NODEFAULT, where a subclass instance would not.
    LPARAMETERS m.nKeyCode, m.nShiftAltCtrl
    IF EMPTY(THIS.ParentClass)
         NODEFAULT
    ENDIF
    RETURN DODEFAULT(m.nKeyCode, m.nShiftAltCtrl)
    
    -- Mike Yearwood
    Question: How do other OOP languages handle inheritance overrides? Is there something similar in Java or C++ that is less ambiguous? -- Randy Jean

    I believe C++ makes use of the scope resolution operator :: to handle calls up the hierarchy. VFP can make use of this as well. -- Larry Miller

    In Delphi ( Object Pascal ) (and C++, though I'm not so familiar with it) there is no difference between "intrinsic" method code and the method code of an ancestor class. Basically, the inherited code of an overridden method NEVER executes unless it is explicitly called (using the scope operator, "::" in Object Pascal or using the "inherited" keyword) in the descendant's method. For example:
    {ObjectPascal example of inheritance using this class hierarchy:
    
    • tButton
      • tButton2
        • tMyButton
    } . . . procedure tMyButton.click( sender:tObject ); begin if lSomething then inherited Click(sender) {calls tButton2.Click} else tButton::Click(sender); {calls tButton.Click} end;



    In C# a base class method is invoked manually via the base keyword and methods are non-virtual by default meaning that a method is only called when an object is casted to the particular type in which that method is defined or any subclass which doesn't override that method. Also in C# constructors have a special behavior when compared to regular methods in that by default a constructor in a subclass will invoke it's parent's default (parameterless) constructor if it exists otherwise an explicit call to one of the the base classes constructors is required on the subclass constructor. So in C# calling the base classes method is always something that must be done explicitly by using the base keyword unless within a constructor that has the special behavior described above.
    External Articles:
    There is an article by Jim Booth in the December 1999 issue, but it is locked for online subscribers only so I won't bother to put the link. Just go to the Fox Talk site. -- Randy Jean
    See also NODEFAULT
    Contributors Carl Karsten, CFK
    Category VFP Commands
    ( Topic last updated: 2010.06.17 10:33:02 PM )