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

CreateObject Misconception

Status
Not open for further replies.

csr

Programmer
Jul 20, 2000
507
I must have a misconception about CreateObject.

This code fails at the last line and I do not understand why ?

The error is ... OutputReport.scx does not exist !

I thought I had created a form object and was not calling that form. I guess not.

OutputReport = CREATEOBJECT("my_frm")
outputReport.caption = "Report Output"
OutputReport.AddObject("cmdVIEW", "my_cmd")
OutputReport.AddObject("cmdPRINT", "my_cmd")
DO FORM OutputReport

Don


 
Correction to that last line of my message ...

I thought I had created a form object and WAS calling that form. I guess not.



Don


 
Don,

OutputReport = CREATEOBJECT("my_frm")
outputReport.caption = "Report Output"
OutputReport.AddObject("cmdVIEW", "my_cmd")
OutputReport.AddObject("cmdPRINT", "my_cmd")
OutputReport.Show()

The CREATEOBJECT creates the form it is just hidden until you call the show method.
 
Don,

Your code is in fact trying to create the form twice.

You can use CREATEOBJECT() to create a form (or, more correctly, an instance of a form) based on a form class. It will return a reference to the form, which you can then store in a variable (OutputReport in your case).

Alternatively, you can use DO FORM to create an instance of the form. To do that, you need a form file, that is, an SCX file. In your case, there is no SCX called OutputReport, so the DO FORM will fail.

The solution is to use either CREATEOBJECT() or DO FORM, but not both. Also, given that the object created by CREATEOBJECT() is always initially invisible, you need to either set its Visible property .T. or call its Show method to make it visible.

Mike


Mike Lewis
Edinburgh, Scotland
 
Thanks for your help with this. It makes more sense now.

However, this exercise has led me to a solution that seems easier ...

I created a class (with all the buttons I need) and am not using simply ...

outputReport = createObject("my_frm_output_report_options")
outputReport.show()

The problem I now have is that I would like to send a result from this form to a parameter ... like in
do form xyz to nSomeParamter.

Is that possible with the CreateObject / Show method ?





Don


 
You can just create a property in the form class like "FormResult", and do something like:

Code:
outputReport = createObject("my_frm_output_report_options")
outputReport.show()
if outputReport.FormResult>1
  * whatever
endif

 
Don,

I think you mean that you want to return a result from the form. The usual way to do that is to use a RETURN command in the form's Unload. Then, call the form like this:

do form xyz to nSomeParamter

and nSomeParameter will acquire whatever value you return.

However, for this to work, the form has to be modal.

Mike


Mike Lewis
Edinburgh, Scotland
 
Mike ...

You are correct about what I wish to do. However, I wish to use the createObject() method ... not the DO FORM method.

wgcs ...

Your solution seems to make sense.
However, it brings up a question in my mind.

My form is modal. When I execute the SHOW() method my form "shows itself" and waits for me to make my selection.
Then (inside the form) I execute thisform.release()

I am wondering if the form is still available to find out what the value of outputReport.FormResult is after the form has been released.

And if it is ... how do I get the form out of memory entirely. I mention this because I am getting some messages about something still being in memory when I attempt to modify the base class for this form.





Don


 
You found the one gotcha... However, instead of using
THISFORM.Release() to get rid of the form, just use:
THISFORM.Hide()
(which, logically, is the opposite of using THISFORM.Show() to start showing the form)

To get rid of the form entirely, either just let the variable go out of scope that references the form, (outputReport), or explicitly release it when you're done with it:
RELEASE outputReport
 
from Mikelewis above:
You can use CREATEOBJECT() to create a form (or, more correctly, an instance of a form) based on a form class. It will return a reference to the form, which you can then store in a variable (OutputReport in your case).

Alternatively, you can use DO FORM to create an instance of the form. To do that, you need a form file, that is, an SCX file. In your case, there is no SCX called OutputReport, so the DO FORM will fail.

Light bulbs come on for me after reading this post, but they also raise more questions - Is there a way to take existing forms and convert them eaisly to code, and not store and distribute them?
 
One thing you can do is create the form visually in the Class Designer, based on the "Form" baseclass (or based on your own subclass of "Form") and save it in a VCX file,

Or you can write your form as code using the:
DEFINE CLASS myform AS Form
ENDDEFINE
syntax.

Or you can create your form using MODI FORM, then, while editing it, choose [ File -> Save As Class ] to save it into a VCX,

Or you can create your form however you like, get it into a VCX however you like, then load the VCX in the "Class Browser" and click the toolbar button "View Class Code" which will attempt to convert the VCX class into a DEFINE CLASS...ENDDEFINE definition. (I say "attempt" because it isn't always successful: it doesn't handle nested objects very well)
 
White605,

If you want to create a PRG file containing a DEFINE CLASS for an existing form, the easiest way is to open the form in the class browser, select "View Class Code" and save the resulting code in a PRG.

Mike


Mike Lewis
Edinburgh, Scotland
 
Don,

I'd go with Wgcs's suggestion. When you hide a form, it becomes, in effect, modeless. You can then access its properties and call its methods from the calling code.

So, create a form property to hold the value that you want to return (let's say you call it nRetVal). You can then do this:

DO FORM xyz
xyz.Show
* Do something with xyz.nretVal
xyz.Release

Give it a try.

Mike


Mike Lewis
Edinburgh, Scotland
 
This turned out to be highly informative. Thanks to all for your contribution.

the gist of what I finally ended up doing was this ...

Not a bad solution considering that the use of the private variable cMode is completely hidden within code in a library routine so I will not have to remember how it works.


function outputReport(cReportForm)
private cMode, outputReport
cMode = []
outputReport = createObject("my_form_outputreport")
outputReport.show() && this form modifies cMode
do case
case cMode = "PRINT"
report form (cReportForm) to print prompt noconsole
case cMode = "VIEW"
report form (cReportForm) preview noconsole
otherwise
endcase
return .t.


I may eventually (could be sooner rather than later) go back and do this over using the createObject / AddObject technique so I do not have to have the "my_form_outputreport" form prebuilt in a VCX file. But for now, this works fine. Thanks again.



Don


 
Don,

Looks like you've got a nice neat solution. The only suggestion I would make is that you make cMode a property of the form rather than a private variable. That way, the form won't be dependent on being called from that particular piece of code, and that would be a more OOP-like approach. On the other hand, the code you have written should also work fine, so go with it.

Mike


Mike Lewis
Edinburgh, Scotland
 
Mike ...

If I make (cMode) a property of the form then I am back
to ....

(Close form with HIDE rather than RELEASE)
cResult = outputReport.cMode
outputReport.release()

Correct ?





Don


 
Well, it is now more oop-like. [smile] I rebuilt it to incorporate those latest suggestions. It works just fine.
Thanks.


Don


 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top