To Antonio: ReadVar()
-
- Posts: 56
- Joined: Mon Jul 03, 2006 2:34 am
To Antonio: ReadVar()
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
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
-
- Posts: 56
- Joined: Mon Jul 03, 2006 2:34 am
Re: To Antonio: ReadVar()
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.
--------------------------------------
------------------
...
...
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.
--------------------------------------
Re: To Antonio: ReadVar()
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
Are you talking about the substitute of oGet:VarGet(). Correct me if I am wrong. I could not understand the advantage
Regards
Anser
-
- Posts: 56
- Joined: Mon Jul 03, 2006 2:34 am
Re: To Antonio: ReadVar()
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
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
Re: To Antonio: ReadVar()
Dear Mr.Colin,
Thankyou for the information. Now I got it.
Regards
Anser
Thankyou for the information. Now I got it.
Regards
Anser
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Re: To Antonio: ReadVar()
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
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
- arpipeline
- Posts: 36
- Joined: Thu Oct 26, 2006 5:23 pm
- Location: United States
Re: To Antonio: ReadVar()
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
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
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Re: To Antonio: ReadVar()
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
> 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
- arpipeline
- Posts: 36
- Joined: Thu Oct 26, 2006 5:23 pm
- Location: United States
Re: To Antonio: ReadVar()
Antonio,
For TGet, TCheckBox, TRadMenu, TCheckBox, TMultiGet, I modified each control's #command statement (both New and Redefine statements) in FiveWin.ch like so:
In each Class, I modify the new and redfine Methods to accept the "Name" variable like so:
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:
The TRadMenu class is a bit different because you have to pass along the "Name" to TRadio like so:
Finally, in TControl's GotFocus Method I modify like so:
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
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]
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
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
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] ) )
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
Thanks
Re: To Antonio: ReadVar()
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,
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
Hakan ONEMLI
Harbour & VS 2019 & FWH 20.12
Re: To Antonio: ReadVar()
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,
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
Hakan ONEMLI
Harbour & VS 2019 & FWH 20.12