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 SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

how to pass value to first form? 5

Status
Not open for further replies.

Mandy_crw

Programmer
Jul 23, 2020
578
0
16
PH
I have first form that has text1, text11 and text12, as textboxes. In text1 i have keypress(F3) that calls another form(form2) which has computations. My question is how would i pass a computed value from form2 back to text11 and text12 to form1? I hope i have explain it well.... thanks....
 
Not 100% sure what you mean, but in the close code for form2 you might test for the visibility of
the form1 element and drop the details in directly:


Code:
if type("form1.text11") = "O"
  form1.text11.value = thisform.text11.value
endif

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

There is no place like G28 X0 Y0 Z0
 
To always be able to address objects of form1 from within form2, you could pass in form1 into form2, when defining a parameter in init that receives it.

Form2 init should have LPARAMETER toCallform and stor loCallform in some property of form2, for example you add a form property "oCAllform".

Then the init code of form2 can be
Code:
LPARAMETER toCallform
This.oCallform = toCallform

Code within form2 can then do what Griff suggests, for example in this way:
Code:
This.oCallform.Text11.VALUE ='abc'
This.oCallform.Text12.VALUE='xyz'

This way you can do that at any moment with any intermediate result, too.

The call of form2 must pass in form1, that could be done like that:
Code:
DO form2 WITH thisform

There's a catch as this makes form2 depend on getting the correct reference of a form with text11 and text12. Not only have those textboxes to exist, they have to be the right textboxes to pass back those results. You're mixing the context and violate the self contained nature code should have.

Remeber you can always "pass back" something just by storing data into a record that is displayed somewhere else. Changing that DBF record then changes everywhere that specific record is displayed no matter in which form and no matter how the textboxes are named, that's something to always prefer to hardcoding forms to know of each others controls. It's causing a dependency you don't oversee in the long run.

Chriss
 
If I've understand this right, Form2 would have to be modal (WindowType = 2). You would call Form2 (for example from the Keypress of the textbox) with a TO clause:

Code:
DO FORM Form2 WITH <whatever parameters you want to pass> [b]TO SomeVariable[/b]

Immediately after executing that command, SomeVariable will contain the value that Form2 passes back.

In the Unload event of Form2, issue a RETURN command to specify the value you want to pass back.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Also, I'm not sure about your "keypress (F3)". Do you mean you have [tt]ON KEY LABEL F3 DO FORM ...?[/tt] for calling Form2? If so, that is not ideal, for several reasons. In this case, the most important reason is that the user can press F3 at any time, including when Form1 is not active. Doing that would either cause Form2 to pop up at the wrong time, or - more likely - cause a runtime error because VFP can't find the values that you want to pass.

Better to provide a button for calling Form2 instead of the keypress. You will still be able to pass parameters, and you will still be able to use the value that Form2 returns in the same way as before.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike,

it's right, we don't know the exact details, but what Mandy say is:
Mandy said:
In text1 i have keypress(F3) that calls another form(form2)

Well, there is a keypress even in any textbox you can program, and I expect that to be the case, so Manys keypress code may act when the nKeyCode, nShiftAltCtrl parameters of the Keypress event point out a) the textbox text1 has focus and b) F3 was the last key pressed.

I'm not sure myself, it would help to get descriptions that are less vague.

Chriss
 
Chris, I see what you mean.

So the textbox would have a KeyPress event. If nKeyCode = -2 (the code for unshifted F3), it would call the form, otherwise the key would be processed normally (no NODEFULT). That would clearly be better than ON KEY LABEL, but I think a button next to the textbox would be more obvious to the user. But of course Mandy can judge that for herself.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
True, and you could offer such a button and still react to F3 the same way.

Chriss
 
Hi griff, Chriss and Mike... thank you for your answers... i tried doing all the answers you have given, sorry that i cant still get it.... but to further explain... i have a form(main) that has a button that when click will open another form1... (modal) then from that form1 I have tetxt1, text11 and text12 as textboxes. In my text1 (form1) i have a keypress(F3) that when press, another form(2) modal will appear, in the form(2) it has a button that when click it includes computations.... I need to bring the results of the computations from form2 to form1 and should be put particularly in text11 and text12 of the form1. I hope i have explain it well... pardon me... i hope you would still help me... Thanks and God bless....
 
Mandy,

I think Chris & Mike's advice is exactly what you need. But it seems to me your last post asked the same question. Let me try a step-by-step approach in a differ5ent way, which might help.

1. To trigger the appearance of form2 from form1, do it with
DO Form2 TO myResult

2. In form2's Init, add a property THISFORM.AddProperty('ReturnValue','') (Or any other name)

3. Do your computations in Form2 (modal). Assign the result of these computations to the property you created (ReturnValue).

4. In form2's Unload: RETURN THISFORM.ReturnVal;ue.

5. In Form1, assign m.myResult to Text11 and Text12.

HTH

Steve
 
Mand, thanks for describing your situation in more detail. ne detail is still not very clear:

i have a keypress(F3) that when press, another form(2) modal will appear
Did you program code iunto a keypress event that does start form2 or did you program ON KEY LABEL F3?

The suggestions I made would still work very well, too. Given you have modal forms Steve's alternative solution can also work, as you can return values from modal forms in their Unload event code, that's what VFPs help also describes here:
help said:
To return a value to the TO VarName clause in the DO FORM command, use the RETURN command in the Unload event. For more information, see DO FORM Command.

That refers to what Steve said in point 1 of his instructions to [tt]DO Form2 TO myResult[/tt]

The help describes that in the help topic of DO FORM
help said:
TO VarName

Specifies a variable to hold a value returned from the form. If the variable doesn't exist, Visual FoxPro automatically creates it. Use the RETURN command in the Unload event procedure of the form to specify the return value. If you do not include a return value, the default value of true (.T.) is returned. If you use TO, the WindowType property of the form must be set to 1 (Modal). If the form Init event procedure returns .F., preventing the form from being instantiated, the Unload event procedure will not return a value to VarName.

As your form2 is modal, this works, but it has one disadvantage, the unload event has to run - as an event - not just by calling it, so what you can't do in your button of form2 doing calculations you then set form2.returnvalue <and call form2.unload, the unloiad has to happen, which means form2 has to be released to trigger this return mechanism. So the DO form2 ... TO Varname and RETURN value from form2.Unload is a mecahnism that only works when form2 is modal and you close it, as the modal state means you get back to the DO FORM line of the calling form. form2 also then does not set form1s textboxes 11 and 12 to whatever you need, form1 has to do that from the variable Varname or in Steves instructions the myResult variable. Which also means you can only return 1 value and to return two values for text11 andtext12, you need to put them both into one return value you can split.

So Steve's instructios work, but are limited to working only when form2 closes and make it harder to return two values. You can return an object that has two properties, you could return an array, you could return a string that has valuefortext11 + semicolon + valuefortext12, but if the types of them are numeric wouldn't work that simple. You see, it's complicated, too.

I wonder what step you didn't manage to do in the solution first proposed by Griff, and in more detail by me. I try to explain it in the multiple steps you need to do:

The idea as Griff sketched it that form2 knows how to address form1.text11 and form1.text12. Well, Griffs's checking whether type('form1.text11')='O' and he expects form1 to be a valid object reference. That's likely not the case. The way to be able to addess a form and its controls in code that is not inside that form is to have a reference, whcih first needs to be passed from form1 to form2 in the moment form1 calls form2, so that's where this begins:

1. form2 has to have the ability to receive an object reference to form1 in its init, so the form2 init event has to have this code:
Code:
LPARAMETERS toFormWithText11andtext12
Thisform.Addproperty('oFormWithText11andtext12',toFormWithText11andtext12)
2. form1 has to make the call to form2 like this:
Code:
DO Form2 [i]With Thisform[/i]
Instead of just DO FORM2.
So point2 has to be done in the keypress, that will fail if you mean an ON KEY LABEL f3, because then "THISFORM" won't be a valid form object reference. That's why it's so important we know what you mean by keypress. If you don't mean the keypress event of a text1 box in form1, than you're discombobulating us and yourself, too. I hope not.

These two parts of the changes already establish that form2 knows form1 and can act on it, for example it can do what you want and set the text11 and text12 texboxes.

Now the third change you need is within the "button that when click it includes computations". Thjat is part of form2, so it can access the property oFormWithText11andtext12 the init of form2 created and set to the passsed in reference. So in that calculation butt you can add to your code:
Code:
*... do calculations
Thisform.oFormWithText11andtext12.text11.value = calculationresult1
Thisform.oFormWithText11andtext12.text12.value = calculationresult2
Thisform.oFormWithText11andtext12.refresh()

Where you better know than us what to put in as calculationresult1 and calculationresult2.

But that's it. Now form2 could even do this multiple times during the calculations. For example if calculations are done in a scan..endscan loop you could update the text11 and text12 values multiple times, you don't have to, but you could.

In my previoius decription I said
myself said:
for example you add a form property "oCAllform"
This time I used Steve's idea of uaing Addproperty instead, but it would actually be better to add a property to the form when editing it - at design time - because that also means you already have it, also while you write code that uses it intellisense could help ou refer to it.

It's simple to add a property to a class or form when you modify it, that's why I didn't tell that in detail, when you edit form2 you have the menu "Form" and the first menu item of that is "New Property" to define a form property that can be used, as here to store a received value. And you have to store a received parameter in init, because after init all init parameters you don't store away anywhere are released and forgotton, but you need the form reference to form1 later in the calculatio button.

Mandy, just one more thing that you should never do, is just ssaying "i cant still get it". You also don't need to be sorry about that, it's not shameful you don't understand something we said to do, but undersstnad one thing: I wrote a long post with multiple sections, then please descibe what of it you don't get. It's also not helpful you star posts when you couldn't do what was recommended to you, as you mark something as a solution to future readers and you should not do this just by believing anything posted is surely right, but only after something actually helped you as non expert to get your problem solved. It's not just a marker for what you have read, either, it's a signal you give to other forum readers and it shouldn't be done just with assuming it will eventually help, it's feedback after it actually did help and you're not there yet, very obviously.

Chriss
 
I gave another even simpler solution when I said
myself said:
you can always "pass back" something just by storing data into a record that is displayed somewhere else

You use DBFs all the time, don't you? So you can use a dbf and a record within it that you display in form1 by setting text11 and text12 controlsources to fields of a DBF and in form2 you can set the fields to the results. That's then displayed by the controlsource mechanism. So there is no need to actually RETURN soemthing or set text11 and text12 values from form2, you just store the result into the DBF that's used as controlsource of the textboxes of form1.

That mechanism is always the most natural way of communcation between forms, even between different applications and different computers, because as many participants anywhere with access to the DBF can open that same DBF, position to the same record and display the same field and that'll "communicate" between all participants without any explicit object X referring to another object Y and doing something to it, all participants of that just look at the same fields of a DBF.

You do this all the time you use a DBF, even if you usually only have one participant displaying that data. But the moment you write a form that many users on many workstations use, the common data they see is also just a simple example of how values are seen on multiple forms, even on multiple computers.

Chriss
 
Hello,

maybe like this, from memory, not tested :

Code:
*in form1 keypress
*I would prefer formvariables instead of objects, see below.

local ohandle , oback
ohandle = createobject("empty")
addprop(ohandle,"v1",thisform.text1.value)
addprop(ohandle,"v2",thisform.text2.value)
addprop(ohandle,"v3",thisform.text3.value)
addprop(ohandle,"retv","OK")

do form form 2 with ohandle to oback && just for clarification
if !empty(oback.retv)
 thisform.text1.value = oback.v1
 ...
endif 

in form2.init
Lparam oh
thisform.whatever.value = oh.v1

in form2.unload
local oret
oret = createobject("empty")
addprop(oret,"v1",thisform.whatever.value) && thisform is form 2 here
addprop(oret,"v2",thisform.text2.value)
addprop(oret,"v3",thisform.text3.value)
addprop(oret,"retv","OK")

or :
* add from property oret1 in form1
* add from property oret2 in form2

in form1.keypress
* could be done in init, then no addprop, just set values
thisform.oret1 = createobject("empty")  
addprop(thisform.oret1,"v1",thisform.text1.value)
addprop(thisform.oret1,"v2",thisform.text2.value)
addprop(thisform.oret1,"v3",thisform.text3.value)
addprop(thisform.oret1,"retv","OK")

do form form2 with thisform.oret1 to oback && just for clarification , could be "to thisform.oret1"

if !empty(oback.retv)
 thisform.oret1 = oback.v1
 thisform.text1.value = thisform.oret1.v1 
 ...
endif 

in form2.init
Lparam oh && = form1.oret1
thisform.oret2= oh
thisform.whatever.value = thisform.oret2.v1

in OK button
thisform.oret2.v1 = thisform.whatever.value
thisform.oret2.v2 = thisform.whatever2.value
thisform.oret2.v3 = thisform.whatever3.value
Thisform.oret2.retv = "OK"

and in cancel
Thisform.oret2.retv = ""

and in unload
return thisform.oret2

Regards
tom

 
Last not least something about code understanding, Mandy.

Let's start with functions, like your form that should pass back the result of calculations, even 2 results here, a function is the most basic construct that does a calculation and return a result, it does not include interactions, usually, and it also returns the result as last step when returning ad finishing.

You write the code of a function into a PRG like AddTax.prg with code
Code:
Lparameters Value
#Define Tax 10
Return VALUE*(1+TAX/100)

And you call this function and receive the result with either
Code:
ValueWithTAX = AddTax(Value)
or with
Code:
Do AddTax With Value To ValueWithTax

The latter way of calling a function is imitated in the TO clause of the DO FORM command.
So let's see how this looks when instead of this AddTax.prg you design a form AddTax.scx. To still use the same kind of code to get a result back you can write
Code:
Do FORM AddTax.scx With Value To ValueWithTax
Looks quite similar to the PRG call in the second variation, doesn't it? That's designed intentionally that way.

Not any form can act as a function, though. It has to be modal, as it is in your case, if it wouldn't have been, you could have made it modal, though. That's not the major point. the modality is necessary because you can only use the return value in further code, so the DO FORM line of code has to wait for the result to come back and that's the case when the called form is modal. What is a more important point in that regard is there has to be some defined point where the form actually returns its result. And the VFP developers decided to do that in the last event that runs when a form closes, the Unload event. That's a natural place for returning a result like a function does, because a function also ends at that point it returns the calculated value. That's why the decision has been made to use Unload for returning to the DO FORM call.

And that's how you can remember why it's Unload and so how to program such a form. Not only that you have to put the RETURN result into the Unload event of the form that acts as a function with potential interactions with a user - for example to pick one of multiple tax rates from a combobox. not only that, it should be "clear as mud" that you have to close the form to get to the point where this "function" form ends and returns its result in Unload as last action it does, just like a function.

If you want to have more options like returning something before closing the form, to have multiple results or let the user try different things and adjust to the right result as wanted. For example imagine the form "function" is like that of a gas pedal and you present a slider that the user can slide up/down and have feedback while the slider is used and not just once when the form is closed again, until the feedback is as the user likes it and then closes the form. That's doable both with the simple mechanism of storing values into a DBF multplpe participants also share and look into or the mechanism of passing in what the function form should be able to influence.

Chriss

Sorry, one thing was misleading here: The syntax to call a PRG and specify the variable which should receive the result with a TO clause is not available in the DO command, it's only part of the DO FORM command, but you may just imagine this to exist, it just illustrates the similarity of that mechanism to a function returning a result and doing so at the end of its execution.
 
Mandy,
To summarize (and avoid confusion), there are MANY approaches to do what you want to achieve. Here are some:

1. Return a value from DO FORM Xx TO Yy (parse if several values)
2. Put the return in a dbf accesssible to other forms (olr other apps as Chris mentioned)
3. Put the return in an accessible object you create.
4. Create an accesible property in the first form.

I've used most of them. They all work. I'm sure there are more I haven't thought of.

Just a suggestion: Go with the one you understand best after rereading the above posts. Then come back with [hopefully] specific questions.

Steve
 
Indeed, there's no reason to do all that's been suggested, look at what seems doable to you and if you have questions for details, don't hold back and let that be the reason you don't even begin with trying a suggestion.

Since you specifically asked to set text11 and text12 values, the first answer of Griff also was already about the most complicated aspect of being able to address form1 from form2, it's not natural and easy to do, a form, and in principle anything in programming is and should be self contained, doing something in another object is not normal, therefore you also have no simple to use feature for that and need to progam this from both sides.

Chriss
 
Oh... my... im just so thank ful to everyone.... Steve, Griff, Tomk3, Mike and Chriss.... You are all wonderfull and generous.... i cant thank you enough for always helping me.... I would have to read it all carefully as steve said... I need to understand everything...

In my keypress(F3) i already have idnam as one of the parameters to be passed to form2 so that it will be put in the textbox1 of form2,
DO FORM forms WITH idnam

but i still need another two variables from form2 to be put in the form(1) which are text11 and text12. Thanks everyone....God bless


 
Mandy,

1. you still don't answer whether you programmed a keypress event or ON KEY LABEL F3. Or do you even have a menu item with F3 as its assigned hotkey starting form2? You're still not making this clear by repeatedly talking about "a keypress", "my keypress". If you define what happens when a user presses F3 with ON KEY LABEL you couldn't use the solution that requires to pass in THISFORM (the reference to form1) to form2.

2. When your form call already has a parameter you can still add a 2nd, 3rd,.... as many as you need, so you can still use any solution requiring to pass in something else than idnam. Is it really that, what's holding you back?

I don't see a problem with what you describe, you could still use any of the recommended ways of solving this.

Chriss
 
Let me ask about those textboxes text11 and text12 on form1: Are their controlsources properties set to something?
I hope you know how to see that, if not: Open up form1 in the form editor, then start the properties window and pick text11 at the top to see its properties list, then text12.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top