ON CHANGE in tGet

ON CHANGE in tGet

Postby TimStone » Wed Jul 25, 2007 12:32 am

Maybe old age is getting me.

I thought the ON CHANGE activated when the total value of a get was modified, not for each character entered. I realize a VALID tests the total value, but I want to run a function only if the total value changes, not everytime the field is displayed.

Currently, ON CHANGE will activate with every keystroke, as demonstrated in the following example. Is this a correct behavior ?

// Test On Change in get
#INCLUDE "fivewin.CH"

PROCEDURE main

LOCAL oDlg
LOCAL oTestGet := SPACE(10)

DEFINE DIALOG oDlg SIZE 500, 300

@ 3, 10 GET oTestGet PICTURE "@!" ON CHANGE ( MsgAlert( "Changed" ) )

ACTIVATE DIALOG oDlg

RETURN NIL
Tim Stone
http://www.MasterLinkSoftware.com
http://www.autoshopwriter.com
timstone@masterlinksoftware.com
Using: FWH 23.10 with Harbour 3.2.0 / Microsoft Visual Studio Community 2022-24 32/64 bit
User avatar
TimStone
 
Posts: 2944
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA

Postby James Bott » Wed Jul 25, 2007 12:58 am

Tim,

Yes, that is the correct behavior for bChange. It is used to do special processing while the data is being input. You can use it for custom pictures, etc.

As you said, use the VALID clause. To use bValid just store the "before" value in a var and then test it with the after value in bValid. bValid won't be eval'd unless the user enters the field. If you are using a database, you can check the get var against the field contents to see if it has been changed instead of creating a "before" var.

James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

VALID

Postby TimStone » Wed Jul 25, 2007 1:09 am

James,

Using tData, I'm editing oDbf:var1 for example, and if I now change the content in the dialog, how can I validate against the original database unless I store a new var on loading the record ?

Tim

ie>

REDEFINE GET oGt1 VAR oDbf:var1 ID 201 OF oDlg ;
VALID testvalue( )

Where testvalue( ) only executes if the originally saved value of oDbf:var1 is changed in this control ?

I know I can read the value at load and store it to a variable that executes if there is a change, but I wanted to avoid the extra code if I can read the data ....
Tim Stone
http://www.MasterLinkSoftware.com
http://www.autoshopwriter.com
timstone@masterlinksoftware.com
Using: FWH 23.10 with Harbour 3.2.0 / Microsoft Visual Studio Community 2022-24 32/64 bit
User avatar
TimStone
 
Posts: 2944
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA

Postby James Bott » Wed Jul 25, 2007 1:43 am

Tim,

>Using tData, I'm editing oDbf:var1 for example, and if I now change the content in the dialog, how can I validate against the original database unless I store a new var on loading the record ?

Try this:

REDEFINE GET oGt1 VAR oDbf:var1 ID 201 OF oDlg ;
VALID if( oDbf:var1 <> (oDbf:cAlias)->var1, msgInfo( "Changed"),)

The upside is that you don't have any extra code, the downside is that this requires a disc read. But it will only do a disc read if the user enters the field.

Another approach is to create a subclass of TData or TCustomer or whatever you are using, and add another buffer array. In the load() method copy the data to this array also. Then you can test every field against the original without another disk read and without any more code (the same code is reused everywhere your database class is used).

Code: Select all  Expand view  RUN
class TXData from TData
   data aOriginal init {}
   method load
endclass

method load()
   super:load()
   acopy(::aBuffer, ::aOriginal)
return nil


[Note: I always recommend using a subclass of TData for each application, even if it starts out empty. Then you use this class in your app. When you later want to add a generic feature to the database class, you can just add it to this one subclass, and the entire application will inherit it without any other code changes.]

James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Valid / On Change

Postby TimStone » Wed Jul 25, 2007 4:33 pm

Thanks.
Tim Stone
http://www.MasterLinkSoftware.com
http://www.autoshopwriter.com
timstone@masterlinksoftware.com
Using: FWH 23.10 with Harbour 3.2.0 / Microsoft Visual Studio Community 2022-24 32/64 bit
User avatar
TimStone
 
Posts: 2944
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA

Postby James Bott » Thu Jul 26, 2007 11:05 am

Tim,

There was something nagging me in the back of mind about this topic and it finally came to me.

In the old Clipper Get there was a var oGet:original which contained the original data. Unfortunately, in xHarbour this isn't working--it always returns nil. Too bad.

However, there is a simple workaround and that is to use oGet:cargo. It does require that you force this to be loaded in your code, but by doing this you can avoid an extra disk read or using an extra var. Below is a working sample.

Regards,
James


Code: Select all  Expand view  RUN
#include "fivewin.ch"

function main()
   local oDlg,oGet,oGet2,cVar:="Test     ",cVar2:="xxx       "

   define dialog oDlg

   @ 1,1 get oGet var cVar of oDlg ;
      valid if( oGet:cargo <> oGet:varGet(), (msgInfo("Changed"),.t.), (msgInfo("Not changed"),.t.) );

      oGet:cargo:= oGet:varGet()

   @ 2,1 get oGet2 var cVar2 of oDlg

   activate dialog oDlg centered

return nil
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Postby Enrico Maria Giordano » Thu Jul 26, 2007 12:19 pm

Did you try

Code: Select all  Expand view  RUN
oGet:oGet:Original


?

EMG
User avatar
Enrico Maria Giordano
 
Posts: 8716
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Postby James Bott » Thu Jul 26, 2007 12:58 pm

Enrico,

>Did you try

>oGet:oGet:Original

Yes, that is what I was referring to. It has never worked in Harbour or xHarbour as far as I know.

James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Postby Enrico Maria Giordano » Thu Jul 26, 2007 1:17 pm

Works fine for me:

Code: Select all  Expand view  RUN
#include "Fivewin.ch"


FUNCTION MAIN()

    LOCAL oDlg

    LOCAL oGet, cVar := PADR( "Test", 20 )

    DEFINE DIALOG oDlg

    @ 1, 1 GET oGet VAR cVar

    oGet:bLostFocus = { || MsgInfo( oGet:oGet:Original ) }

    @ 3, 1 BUTTON "&Close";
           ACTION oDlg:End()

    ACTIVATE DIALOG oDlg;
             CENTER

    RETURN NIL


EMG
User avatar
Enrico Maria Giordano
 
Posts: 8716
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Postby James Bott » Thu Jul 26, 2007 2:34 pm

Enrico,

Hmm, that does seem to work, but this doesn't. It returns nil.

James

Code: Select all  Expand view  RUN
#include "Fivewin.ch"

FUNCTION MAIN()

    LOCAL oDlg

    LOCAL oGet, cVar := PADR( "Test", 20 )

    DEFINE DIALOG oDlg

    @ 1, 1 GET oGet VAR cVar valid (msgInfo( oGet:oGet:original ),.t.)

   // oGet:bLostFocus = { || MsgInfo( oGet:oGet:Original ) }

    @ 3, 1 BUTTON "&Close";
           ACTION oDlg:End()

    ACTIVATE DIALOG oDlg;
             CENTER

    RETURN NIL
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Postby Enrico Maria Giordano » Thu Jul 26, 2007 2:44 pm

Please remember that "Get:Original is meaningful only while the GET has input focus".

EMG
User avatar
Enrico Maria Giordano
 
Posts: 8716
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Postby James Bott » Thu Jul 26, 2007 4:11 pm

Enrico,

>Please remember that "Get:Original is meaningful only while the GET has input focus".

Are you saying that it doesn't have input focus when bValid is executed? I would think it has to have.

James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Continuing

Postby TimStone » Thu Jul 26, 2007 4:39 pm

For the purpose of discussion, I would suppose this modification would work:

#include "Fivewin.ch"

FUNCTION MAIN()

LOCAL oDlg

LOCAL oGet, cVar := PADR( "Test", 20 )

DEFINE DIALOG oDlg

@ 1, 1 GET oGet VAR cVar valid (IIF( cVar <> oGet:oGet:origianl, msgInfo( "Data changed"), ), .t. )

// oGet:bLostFocus = { || MsgInfo( oGet:oGet:Original ) }

@ 3, 1 BUTTON "&Close";
ACTION oDlg:End()

ACTIVATE DIALOG oDlg;
CENTER

RETURN NIL
Tim Stone
http://www.MasterLinkSoftware.com
http://www.autoshopwriter.com
timstone@masterlinksoftware.com
Using: FWH 23.10 with Harbour 3.2.0 / Microsoft Visual Studio Community 2022-24 32/64 bit
User avatar
TimStone
 
Posts: 2944
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA

Postby James Bott » Thu Jul 26, 2007 4:51 pm

Tim,

>For the purpose of discussion, I would suppose this modification would work:

No, from a VALID oGet:oGet:original returns nil. It does return the proper value from bLostFocus. This seems to be a bug to me.

James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Postby Enrico Maria Giordano » Thu Jul 26, 2007 6:28 pm

James Bott wrote:Are you saying that it doesn't have input focus when bValid is executed?


Yes. Just check oGet:oGet:HasFocus. It is .T. in bLostFocus and .F. in bValid.

EMG
User avatar
Enrico Maria Giordano
 
Posts: 8716
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Next

Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 61 guests