To Antonio: ReadVar()

Post Reply
Colin Wisbey
Posts: 56
Joined: Mon Jul 03, 2006 2:34 am

To Antonio: ReadVar()

Post by Colin Wisbey »

I suggest a better approach to determing READVAR() is by using :oGet:Name by making the following simple changes to FHW source:

1. In FIVEWIN.CH:

#xcommand REDEFINE GET [ <oGet> VAR ] <uVar> ;
[ ID <nId> ] ;
[ <dlg: OF, WINDOW, DIALOG> <oDlg> ] ;
[ <help:HELPID, HELP ID> <nHelpId> ] ;
[ VALID <ValidFunc> ] ;
[ <pict: PICT, PICTURE> <cPict> ] ;
[ <color:COLOR,COLORS> <nClrFore> [,<nClrBack>] ] ;
[ FONT <oFont> ] ;
[ CURSOR <oCursor> ] ;
[ MESSAGE <cMsg> ] ;
[ <update: UPDATE> ] ;
[ WHEN <uWhen> ] ;
[ ON CHANGE <uChange> ] ;
[ <readonly: READONLY, NO MODIFY> ] ;
[ <spin: SPINNER> [ON UP <SpnUp>] [ON DOWN <SpnDn>] [MIN <Min>] [MAX <Max>] ] ;
=> ;
[ <oGet> := ] TGet():ReDefine( <nId>, bSETGET(<uVar>), <oDlg>,;
<nHelpId>, <cPict>, <{ValidFunc}>, <nClrFore>, <nClrBack>,;
<oFont>, <oCursor>, <cMsg>, <.update.>, <{uWhen}>,;
[ \{|nKey,nFlags,Self| <uChange> \}], <.readonly.>,;
<.spin.>, <{SpnUp}>, <{SpnDn}>, <{Min}>, <{Max}>, <"uVar">) // added <"uVar"> to this line


// Do same for @ ... SAY ... GET ...
-------------------

2. In TGET.PRG:

(i)
METHOD ReDefine( nId, bSetGet, oWnd, nHelpId, cPict, bValid,;
nClrFore, nClrBack, oFont, oCursor, cMsg,;
lUpdate, bWhen, bChanged, lReadOnly,;
lSpinner, bUp, bDown, bMin, bMax, uVarNam) CONSTRUCTOR // added uVarNam

(ii)
METHOD ReDefine( nId, bSetGet, oWnd, nHelpId, cPict, bValid, nClrFore,;
nClrBack, oFont, oCursor, cMsg, lUpdate, bWhen, bChanged,;
lReadOnly, lSpinner, bUp, bDown, bMin, bMax,;
uVarNam ) CLASS TGet // added uVarNam

....
....
DEFAULT oWnd := GetWndDefault(),;
nClrFore := GetSysColor( COLOR_WINDOWTEXT ),;
nClrBack := GetSysColor( COLOR_WINDOW ),;
lUpdate := .f., lReadOnly := .f., lSpinner := .f.,;
uVarNam := SPAC(4) //added uVarNam
...
...
::oGet = GetNew( 20, 20, bSetGet, uVarNam, cPict ) // inserted uVarNam (which is how Clipper did it anyway)
...

// Do same for METHOD NEW
--------------------------

With these simple changes to FWH source, the app can get the equivalent of READVAR() by

oMyGetObj:oGet: Name

I made the above changes to my own copies of FWH source when I first switched from DOS Clipper to FW many years ago and it's always seemed to work fine.

Colin
Colin Wisbey
Posts: 56
Joined: Mon Jul 03, 2006 2:34 am

Re: To Antonio: ReadVar()

Post by Colin Wisbey »

Here's a template example of possible usage:
------------------
...
...
REDEFINE GET oMYGet1 VAR CustNo ID 101 OF oDlg UPDATE VALID {|oGet|GENERALUDF(oGet)}
REDEFINE GET oMyGet2 VAR PostCode ID 102 OF oDlg UPDATE VALID {|oGet|GENERALUDF(oGet)}
REDEFINE GET oMyGet3 VAR ProductNo ID 103 OF oDlg UPDATE VALID {|oGet|GENERALUDF(oGet)}
...
...
------------------------

FUNCTION GENERALUDF(oGet)

LOCAL cVarNam := UPPER(oGet:oGet:Name)

IF "CUSTNO" $ cVarNam
<do something specific to CUSTNO>
ELSEIF "POSTCODE" $ cVarNam
<do something specific to POSTCODE >
ELSEIF "PRODUCTNO" $ cVarNam
<do something specific to PRODUCTNO>
ENDI

<do some additional stuff common to all cases>

RETU .T.
--------------------------------------
User avatar
anserkk
Posts: 1280
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India

Re: To Antonio: ReadVar()

Post by anserkk »

Dear Mr.Colin
Are you talking about the substitute of oGet:VarGet(). Correct me if I am wrong. I could not understand the advantage

Regards

Anser
Colin Wisbey
Posts: 56
Joined: Mon Jul 03, 2006 2:34 am

Re: To Antonio: ReadVar()

Post by Colin Wisbey »

Hi Anser

No. oGet:VarGet returns the contents of the get. (e.g. "Smith")
oGet:Name returns the name of the GET's variable (e.g. "Surname").

My suggested changes to FWH code are no big deal and there are usually other approaches that can be used. It's just that I've recently read some posts discussing READVAR() / oGet:Name and, for some types of needs of some people, my approach might be a bit simpler than others I've seen (depending on why such person might want to know the name of the current GET variable and/or what they intend to do with the result).

Colin
User avatar
anserkk
Posts: 1280
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India

Re: To Antonio: ReadVar()

Post by anserkk »

Dear Mr.Colin,

Thankyou for the information. Now I got it.

Regards

Anser
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: To Antonio: ReadVar()

Post by Antonio Linares »

Colin,

A very good, simple and effective solution. Many thanks! :-)

We have already implemented it for FWH 9.01, with some modifications:

1. Please notice that since ... GET ... ACTION ... implementation, the preprocessor adds these two extra params:

... , [\{|self| <uAction> \}], <cBmpName>, <"uVar"> )

so we have added <"uVar"> after them. The same applies for supplied params to Method New() and Redefine()

2. We have named the new param as cVarName

3. We don't default initialize it to Space( 4 ). We see no reason for it, as we were using nil before with no problems. We appreciate your comments about this. thanks
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
arpipeline
Posts: 36
Joined: Thu Oct 26, 2006 5:23 pm
Location: United States

Re: To Antonio: ReadVar()

Post by arpipeline »

Antonio,

I have run across this issue in my code way back in the day using Clipper and migrating to FiveWin. I solved it the exact same way, except I took it a step further. In every control that can "touch" a database field directly, CHECKBOX, RADIO, RADMENU, MGET, TGET, COMBO, I've implemented the same thing -- <"uVar"> -- in the #command statements. This also means that I have to watch for changes in each new FW release and modify one or more souce files.

I use ReadVar to direct calculation rountines inside our application. We have many forms that "GET" the same field name over and over, some are radio buttons, checkboxes, comboboxes and memo fields. It's a document based system and many of the documents repeat the same fields. Rather than code an ON CHANGE clause or VALID with hard coded calculation routine specific to each field, I trap the uVar name via ReadVar in a central calculation and route control to the appropriate calculation function. This allows me to make code changes more efficiently, and in one location, and it works for all appropriate controls, not just a TGet.

I would hope that you see merit in modifying fivewin.ch and the 6 or so classes to expose <"uVar"> to all controls that may accept a DB field or a mem field of the same type. Maybe I am wrong, but there must some other way to get the "name" of the variable in focus and not just it's value. If so, let me know that that method is.

Thanks
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: To Antonio: ReadVar()

Post by Antonio Linares »

ARoss,

> I've implemented the same thing -- <"uVar"> -- in the #command statements

If you are so kind to publish here your changes, then we can implement them for next FWH build so there is no further need for you to modify those files in every FWH build, thanks :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
arpipeline
Posts: 36
Joined: Thu Oct 26, 2006 5:23 pm
Location: United States

Re: To Antonio: ReadVar()

Post by arpipeline »

Antonio,

For TGet, TCheckBox, TRadMenu, TCheckBox, TMultiGet, I modified each control's #command statement (both New and Redefine statements) in FiveWin.ch like so:

Code: Select all

// This is for Radio Buttons

#xcommand @ <nRow>, <nCol> RADIO [ <oRadMenu> VAR ] <nVar> ;
             [ <prm: PROMPT, ITEMS> <cItems,...> ] ;
             [ <of: OF, WINDOW, DIALOG> <oWnd> ] ;
             [ <help:HELPID, HELP ID> <nHelpId,...> ] ;
             [ <change: ON CLICK, ON CHANGE> <uChange> ] ;
             [ COLOR <nClrFore> [,<nClrBack>] ] ;
             [ MESSAGE <cMsg> ] ;
             [ <update: UPDATE> ] ;
             [ WHEN <uWhen> ] ;
             [ SIZE <nWidth>, <nHeight> ] ;
             [ VALID <uValid> ] ;
             [ <lDesign: DESIGN> ] ;
             [ <lLook3d: 3D, _3D> ] ;
             [ <lPixel: PIXEL> ] ;
       => ;
          [ <oRadMenu> := ] TRadMenu():New( <nRow>, <nCol>, {<cItems>},;
             bSETGET(<nVar>), <oWnd>, [{<nHelpId>}], <{uChange}>,;
             <nClrFore>, <nClrBack>, <cMsg>, <.update.>, <{uWhen}>,;
             <nWidth>, <nHeight>, <{uValid}>, <.lDesign.>, <.lLook3d.>,;
             <.lPixel.>, [color=#FF0000]<"nVar"> )  // <-nVar Passed to TRadio[/color]
In each Class, I modify the new and redfine Methods to accept the "Name" variable like so:

Code: Select all

   METHOD New( nRow, nCol, acItems, bSetGet, oWnd, aHelpIds, bChange,;
               nClrText, nClrPane, cMsg, lUpdate, bWhen, nWidth, nHeight,;
               bValid, lDesign, l3D, lPixel, [color=#FF0000]cVarName[/color] ) CONSTRUCTOR

METHOD New( nRow, nCol, acItems, bSetGet, oWnd, aHelpIds, bChange,;
            nClrText, nClrPane, cMsg, lUpdate, bWhen, nWidth, nHeight,;
            bValid, lDesign, l3D, lPixel, [color=#FF0000]cVarName[/color] ) CLASS TRadMenu

   METHOD Redefine( bSetGet, oWnd, aHelpIds, aRadioIDs, bChange,;
                    nClrText, nClrPane, cMsg, lUpdate, bWhen,;
                    bValid, [color=#FF0000]cVarName[/color] ) CONSTRUCTOR

METHOD Redefine( bSetGet, oWnd, aHelpIds, anItemsIDs, bChange, nClrText,;
                 nClrPane, cMsg, lUpdate, bWhen, bValid, [color=#FF0000]cVarName[/color] )  CLASS TRadMenu
 
This is the same way you modified TGet.

I then assign the cVarName data element (inherited from TControl) in the New and Redefine Methods of each control type:

Code: Select all

// Somewhere in both the New and Redefine Method of each control class add:
::cVarName  = cVarName
 
The TRadMenu class is a bit different because you have to pass along the "Name" to TRadio like so:

Code: Select all

   // TRadMenu New Method
   for n = 1 to Len( acItems )
      #ifndef __XPP__
      AAdd( ::aItems, TRadio():New( nRow + ( ( n - 1) * nStep ) , nCol, acItems[ n ],;
            n == 1,;                // First element is group
            n == Eval( bSetGet ),;  // Is Checked ?
            n, oWnd, Self, aHelpIds[ n ], nClrText, nClrPane, cMsg, lUpdate, bWhen,;
            nWidth, nHeight, bValid, lDesign, lPixel, [color=#FF0000]cVarName[/color] ) )
      #else
      AAdd( ::aItems, TRadio():New():_New( nRow + ( (n - 1 ) * nStep ), nCol, acItems[ n ],;
            n == 1,;                // First element is group
            n == Eval( bSetGet ),;  // Is Checked ?
            n, oWnd, Self, aHelpIds[ n ], nClrText, nClrPane, cMsg, lUpdate, bWhen,;
            nWidth, nHeight, bValid, lDesign, lPixel, [color=#FF0000]cVarName[/color] ) ) 
      #endif
   next
   
   // from TRadMenu Redefine Method
   for n = 1 to Len( anItemsIDs )
       AAdd( ::aItems, TRadio():ReDefine( anItemsIDs[ n ], ;
                               n == Eval( bSetGet ),;  // Is Checked ?
                               n,;
                               oWnd, Self, aHelpIds[ n ], nClrText, nClrPane,;
                               cMsg, lUpdate, bWhen, bValid, [color=#FF0000]cVarName[/color] ) )

 
Finally, in TControl's GotFocus Method I modify like so:

Code: Select all

METHOD GotFocus( hCtlLost ) CLASS TControl

   ::lFocused       = .t.
   ::oWnd:nResult   = Self  // old code pending to be oCtlFocus
   ::oWnd:oCtlFocus = Self
   ::oWnd:hCtlFocus = ::hWnd
   ::SetMsg( ::cMsg )

   [color=#FF0000]ReadVar( ::cVarName )[/color]

   if ::lDrag
      ::ShowDots()
   endif

   if ::bGotFocus != nil
      return Eval( ::bGotFocus, Self, hCtlLost )
   endif

return nil
The cool thing you can do is expose the field names in your program using ::bGotFocus in TControl to show the field name in the main window's Message Bar or wherever you want. I do this to help our integrators know what DB field names are where in the application. That way, they don't always have to refer to a data dictionary or documentation if the are writing custom reports or other add ons.

Thanks
Horizon
Posts: 997
Joined: Fri May 23, 2008 1:33 pm

Re: To Antonio: ReadVar()

Post by Horizon »

Hi,

There is a cVarName in TGet. But I could not show it. I use unchanged fwh classes and fivewin.ch.

How Can I show variable name of TGet, TCombobox, Tcheckbox (all input controls)?

Thanks,
Regards,

Hakan ONEMLI

Harbour & VS 2019 & FWH 20.12
Horizon
Posts: 997
Joined: Fri May 23, 2008 1:33 pm

Re: To Antonio: ReadVar()

Post by Horizon »

Hi,

I can show variables name in TGet as described at first message. using oGet:oGet:Name. But I could not get other controls.

What does the cVarName for?

Thanks,
Regards,

Hakan ONEMLI

Harbour & VS 2019 & FWH 20.12
Post Reply