Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

DODEFAULT() / NODEFAULT: Default events & methods for controls 3

Status
Not open for further replies.

Rajesh Karunakaran

Programmer
Sep 29, 2016
545
MU
Hi Team!

We have DODEFAULT() and NODEFAULT in VFP. Even though I know upto an extend the affect of these, I am finding it difficult to assume what is the default event/method for a given control. For example, I have read somewhere that for a Texbox control the default event is to feed the typed keys into the keyboard buffer.

Now, how do we know what is the default event/method for any given control and any of its event/method?
Is there any list for this available somewhere.

Thanks in advance.
Rajesh

 
Sorry, but that points out having the wrong idea about DODEFAULT()/NODEFAULT. No matter what you already understand about it, but there is no single default method of a control you call from anywhere with DODEFAULT() or suppress from anywhere with NODEFAULT, that points out you have established the idea from only ever seeing this in the context of a few events of classes like KeyPress() of a TextBox.

DODEFAULT() and NODEFAULT are acting about the same method or event they are called in, just in parent or base class level, so this isn't about recursive self calls nor about calling one specific default method. Maybe try to remember having seen NODEFAULT in other contexts of the TextBox, too, like using it in InteractiveChange() or GotFocus(). That then suppresses those events base behavior, not KeyPRess.

Let's start with NODEAULT, as that is only controlling the base class behavior of this method or event. The base class behavior surely also is code, but C++ and not VFP language code, you never see it but, of course, just as one example, a KeyPress event does handle keyboard input and changes the control value even without your help with any of your code just from the C++ code Microsoft did for the TextBox. With NODEFAULT you can suppress that behavior, ie putting just NODEFAULT in Keypress of a TextBox would render that TextBox to a read-only control.

NODEFAULT only suppresses base class code, not your code. NODEFAULT never plays a role in suppressing user-defined code, even if you use the base class TextBox on a form NODEAULT is not becoming self-referential.

DODEFAULT() is concerned with the next level parent class code and that parent class level is the base class level when you put a base class TextBox control on a form. In general, it's not calling the base TextBox behavior, when you have designed your own control based on the Textbox, DODEFAULT() merely executes what you defined in your own class, which in turn could call DODEFAULT() to call the base class or NODEFAULT to suppress it. I'm sure you'll find an example of that posted by me if you use the search of this forum.


But to see what this means for the simple case of a base class Texboxt on a form, we can try any combination and order of execution of NODEFAULT and DODEFAULT() and see what they do:
Code:
LPARAMETERS nKeyCode, nShiftAltCtrl

This is what you see in KeyPress method in the class code editor when you do nothing to it. The empty event means just running base behavior. So running a TextBox with no code in KeyPress the TextBox acts normal, you don't influence it at all.

Code:
LPARAMETERS nKeyCode, nShiftAltCtrl
NODEFAULT

As already said this causes the TextBox to act read-only. Almost. You can copy a text into the clipboard and act on the TextBox with CTRL+V, pasting the text into it. That global Windows keyboard shortcut is not processed by the Keypress, you don't get a KeyPress event. It's just a side note, as this is not about NODEFAULT and DODEFAULT() at all, but obviously, it could puzzle you when you'd like to intercept that from happening.

Another thing to note is that the base TextBox.Keypress() behavior is not executed before your KeyPress() code. Otherwise, your NO DEFAULT could never work and hinder this base behavior.

Code:
LPARAMETERS nKeyCode, nShiftAltCtrl
NODEFAULT
DODEFAULT(nKeyCode, nShiftAltCtrl)
-OR-
Code:
LPARAMETERS nKeyCode, nShiftAltCtrl
DODEFAULT(nKeyCode, nShiftAltCtrl)
NODEFAULT

In both cases, you get back to the normal TextBox behavior and it doesn't matter if you first state you want to suppress base class behavior and then execute it yourself anyway or first execute it yourself and then suppress it. As already said the default behavior is not yet run and NODEFAULT suppresses it from running. The first variant doing NODEFAULT illustrates, that the suppressing doesn't mean a total lock of this event where DODEFAULT() of the base behavior would also do nothing, the default behavior can still always be called, no matter if NODEFAULT already was executed or will be executed.

And the last code variant is
Code:
LPARAMETERS nKeyCode, nShiftAltCtrl
DODEFAULT(nKeyCode, nShiftAltCtrl)

DODEFAULT() means you explicitly call the base behavior here, as the parent of the Textbox object on the form is the Textbox base class. So that base behavior now runs twice that way because you don't suppress the standard call of it after your code already ran, so you get all keyboard input twice.

And to conclude about the Keypress example; You can override only some cases of nKeyCode, nShiftAltCtrl by executing NODEFAULT in an IF statement, it only acts as suppressor when executed.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Hi Rajesh,

Olaf has given you a very complete and accurate answer. If I may just add a few words to summarise ....

Use DODEFAULT() when you are writing code in subclasses. As an example, suppose you have a class with some code in its Init event. You then subclass that class, and write some new code in the subclass's Init event. The subclass's code will override the Init of the parent. The code in the parent will not be executed. That's the correct behaviour.

If that's not what you want, place DODEFAULT() in the code of the subclass. At the point at which VFP encounters that command, it will execute the code in the parent, in much the same way as a subroutine call. And that's about all there is to it.

NODEFAULT is quite different. This is used when you want to prevent an event from performing whatever action that event normally performs. It is only used in a limited number of cases. The usual example is the Keypress() event. Normally, when you press a key, that key is passed to the active control. So, if the control is a textbox, the textbox will receive the keypress and add the relevant character to its value.

NODEFAULT overrides that behaviour. Say you want the user to be able to enter the current date into the textbox by pressing the letter D. In the Keypress event, you test for the letter D, and if it is present, you insert the date into the value of the textbox. What you don't want is for the letter D also to appear in the texbox. Issuing NODEFAULT will achieve that.

I hope this will help with your understanding.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Olaf,
As usual, you have given a complete package of information on this! Great! Thank you so much.

Hi Mike,
I really like and appreciate your 'skill' of answering in a simple and straight to the point manner!
Thank you so much!

Rajesh
 
Now, another query.

I have a class 'MyClass' containing the base textbox control with custom properties, say like background color control on 'GotFocus' & 'LostFocus' methods.

Suppose I use this textbox in a form. In its 'GotFocus' method, I have given

Code:
MyClass::GotFocus
*------------------*
this.FontBold = .t.

So, my query is, what is the difference if I say 'DODEFAULT()' instead of 'MyClass::GotFocus' ?
(apologies, if this an idiotic question after going through all your detailed answers)

Rajesh
 
It's not an idiotic question. On the contrary.

The short answer is that there is almost no difference. [tt]MyClass::GotFocus[/tt] was the original way of doing it. In VFP 5.0, Microsoft introduced [tt]DODEFAULT()[/tt] as an alternative. Essentially it does the same thing.

The main benefit of DEFAULT() is that it allows you to pass parameters up the parent class and to receive a reply.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
In your scenario, there is no difference, but it*s good you mention this, it's the last detail puzzle piece.

Only using Dodefault() or not you either execute inherited code or override the behaviour when not calling it.

If that was your only way of calling parent class code, you couldn't do, what sometimes can be helpful: Skip one level and call the code of a specific class of the hierarchy. Besides, :: doesn't limit you to call the same method.

Code:
oChild = CreateObject("mychild")
oChild.dosomething()


Define Class mychild as myparent
   Procedure dosomething()
       ? 'dosomething child level'
       mybase::dosomething()
       mybase::dosomethingelse()
   EndProc 
EndDefine 

Define Class myparent as mybase
   Procedure dosomething()
       ? 'dosomething parent level'
   EndProc 

   Procedure dosomethingelse()
       *
   EndProc 
EndDefine 

Define Class mybase as Custom
   Procedure dosomething()
       ? 'dosomething base level'
   EndProc 

   Procedure dosomethingelse()
       ? 'dosomethingelse base level'
   EndProc 
EndDefine

Bye, Olaf.

Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top