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

Object Browser: View Class Code... USELESS!

Status
Not open for further replies.

CouponPages

Programmer
Feb 17, 2003
37
US
As a long time xBase developer, I must admit... I hate visual programming. I love the look, but I hate the output for one reason... it's not CODE, and I love to work with good old fashioned code.

Visual tools save some time, but I find I lose more time in hunting around the properties editor and looking for things like hidden attributes and all sorts of embedded things like datasessions, etc... For what it's worth, code is a lot easier for my old-school mind to work with. I can print it, browse through it, share it with people and even dictate it over the phone.

So, when I found out that the class browser allows us to load forms and click a simple "View Class Code" button to view the "Code" I was thrilled!... until I found out that the code it generates is USELESS!

Why do they bother with it? The code it produces cannot be run if it has any pageframes or a number of other common elements.

Does anyone know of another alternative to generating real honest to goodness code from forms or classes? It seems simple enough to write one... and if I find out there are none, I'll write one. I just bugs me that they include one, and it doesn't work.

While I'm on the subject, the late Tom Rettig once wrote a converter that could actually write class files from hard code (but it was for the older versions). Does anyone know of a newer version?
 
CouponPages

Welcome to the Visual FoxPro forum. Your first day here? Not a good start.

You will find that for most objects you use the code in the Class browser works. Some objects it will not (I would say about 20%), but if 80% works I would say it makes my job easier. Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
CouponPages

Sorry, I may have misunderstood your comment, my experience in using code from a browser is with the Class Browser and not the Object Browser. Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
Thanks for the reply, Mike, but I think the issue for me is that although it may be true that 80% will work, the remaining 20% renders it useless.

In fact if you use a PageFrame as a container, then 100% of your code will not work, because it adds every object to that container by using the ADD OBJECT command, which is not possible.

I know quite a few developers who use PageFrames to give quick access to multiple pages of data entry. As such, the fact that it spits out 99% of the code with lines like: "ADD OBJECT form1.pageframe1.page1.text1 AS textbox WITH ..." that are not possible. Therefore every element on the form is worthless. If you use a button or other element on one page with the same name on a second... don't get me started, the functions are declared identically with no connection to the page they were part of.

I've read the FAQ section, as have searched high and low before posting. While it may seem like the post was just my way of venting because the code it generates is not functional, the real point of my post is to ask if anyone knows of a code converter that DOES work.

So, since the FAQ has no mention of an alternative, and you are saying there is no alternative, then I guess the answer is to write it myself. But I sure hope there is at least one other member who may know of a newer generation of Rettig's code... or something, so I hope my post is not as useless as you said.

If the answer is still burried in the FAQ's, or in a prior post (which I searched)... Sorry for the interruption, but I hate re-writing something that already exists, so I thought there would be a few developers out there who may have experienced the same thing and were willing to help out.
 
In fact if you use a PageFrame as a container, then 100% of your code will not work, because it adds every object to that container by using the ADD OBJECT command, which is not possible.

I may be misunderatanding but if you copy the following into a program and run it, it runs. And this code is directly for the Class Browser.
Code:
PUBLIC oform1
oform1=NEWOBJECT("form1")
oform1.Show
RETURN
	**************************************************
*-- Form:         form1 (d:\production\form1.scx)
*-- ParentClass:  form
*-- BaseClass:    form
*-- Time Stamp:   02/17/03 11:47:05 AM
*
DEFINE CLASS form1 AS form


	DoCreate = .T.
	Caption = "Form1"
	Name = "Form1"


	ADD OBJECT pageframe1 AS pageframe WITH ;
		ErasePage = .T., ;
		PageCount = 2, ;
		Top = 12, ;
		Left = 36, ;
		Width = 289, ;
		Height = 197, ;
		Name = "Pageframe1", ;
		Page1.Caption = "Page1", ;
		Page1.Name = "Page1", ;
		Page2.Caption = "Page2", ;
		Page2.Name = "Page2"


ENDDEFINE
*
*-- EndDefine: form1
**************************************************
Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
Boy, talk about a tough first day... :)

Yes, you were correct... I messed up again... I posted the wrong title. I did mean the "Class Browser".

To set things straight:

The Class Browser cannot handle PageFrames, and messes up every object contained on it rendering the entire class code useless.

If you created a form with 2 pages in a pageframe, and placed a text box, a label, and a command button on each of the two pages you woulod get the following output:

PUBLIC oform1

oform1=NEWOBJECT("form1")
oform1.Show
RETURN


**************************************************
*-- Form: form1 (d:\dev\zlegal-2\dummy.scx)
*-- ParentClass: form
*-- BaseClass: form
*-- Time Stamp: 02/17/03 10:12:14 AM
*
DEFINE CLASS form1 AS form
DoCreate = .T.
Caption = "Form1"
Name = "Form1"
ADD OBJECT pageframe1 AS pageframe WITH ;
ErasePage = .T., ;
PageCount = 2, ;
Top = 24, ;
Left = 36, ;
Width = 241, ;
Height = 169, ;
Name = "Pageframe1", ;
Page1.Caption = "Page1", ;
Page1.Name = "Page1", ;
Page2.Caption = "Page2", ;
Page2.Name = "Page2"


ADD OBJECT form1.pageframe1.page1.text1 AS textbox WITH ;
Height = 23, ;
Left = 95, ;
Top = 56, ;
Width = 100, ;
Name = "Text1"

ADD OBJECT form1.pageframe1.page1.command1 AS commandbutton WITH ;
Top = 92, ;
Left = 95, ;
Height = 27, ;
Width = 84, ;
Caption = "Exit", ;
Name = "Command1"


ADD OBJECT form1.pageframe1.page1.label1 AS label WITH ;
AutoSize = .T., ;
Caption = "Page One", ;
Height = 17, ;
Left = 23, ;
Top = 32, ;
Width = 57, ;
Name = "Label1"


ADD OBJECT form1.pageframe1.page2.text1 AS textbox WITH ;
Height = 23, ;
Left = 103, ;
Top = 64, ;
Width = 100, ;
Name = "Text1"


ADD OBJECT form1.pageframe1.page2.command1 AS commandbutton WITH ;
Top = 100, ;
Left = 103, ;
Height = 27, ;
Width = 84, ;
Caption = "Exit", ;
Name = "Command1"


ADD OBJECT form1.pageframe1.page2.label1 AS label WITH ;
AutoSize = .T., ;
Caption = "Page Two", ;
Height = 17, ;
Left = 31, ;
Top = 40, ;
Width = 57, ;
Name = "Label1"


PROCEDURE command1.Click
thisform.Release
ENDPROC


PROCEDURE command1.Click
thisform.Release
ENDPROC


ENDDEFINE
*
*-- EndDefine: form1
**************************************************


The problem with the output:

1. Objects on pages cannot be declard using ADD OBJECT FormName.PageFrameName.PageName.ObjectName (as it did in the generated code), therefore every element is toast. The only way to programatically add elements to a pageframe is to declare each page as a class, then add that class to the pageframe.

2. Methods with the same name (on different pages) are not declared as such, so are also useless. The correct method is to include them within the individual page class as described in #1.

Since there is a way to do it programatically, it just surprises me that MS doesn't output code which works with PageFrames. Since most of my input forms contain a lot of fields, I use PageFrames often.
 
1. Objects on pages cannot be declard using ADD OBJECT FormName.PageFrameName.PageName.ObjectName (as it did in the generated code), therefore every element is toast. The only way to programatically add elements to a pageframe is to declare each page as a class, then add that class to the pageframe.

That is correct, but once again, most of the structure of the code is there, and know that the code produced by the Class Browser is only "pseudo-code" (That is how VFP reads the code) and knowing its limitations, it take a little time to modify the code to make it work as a program.
Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
Thanks again for your reply... and yes, your code will run, but try to put something... anything .. on one of the pages, like in my example... it won't work.

To place an item on a PageFrame such as yours programatically, you would need to define a class for each page, then add a new page of that class to the PageFrame1 container (at run time using pageframe1.addobject)
 
No, your post is quite unique of all the posts I've read...
Most people I know of who use the Visual Form Designer leave their forms visually designed, because that makes them easier to change in the future.

Personally, I dislike having two files hanging around for every form I create (the SCX/SCT pair), so I create ALL of my forms as classes, store them ALL in a class Library (VCX/VCT pair) and always instantiate them using CREATEOBJECT() (it's a little more complicated than that.. I use inheritance for the forms, and the inheritance is spread across three class libraries... the base form in a BASE.VCX/T, the inheritance for the framework in FRAMEWRK.VCX/T, and the final application forms in APP.VCX/T)

However, you're concern is valid for how you want to use it... I have not seen a good way to automatically generate code from a complex form definition.
 
To place an item on a PageFrame such as yours programatically, you would need to define a class for each page, then add a new page of that class to the PageFrame1 container (at run time using pageframe1.addobject)

Two lines of code? I guess it hardeous as a programmer to write some code every once in a while. ;-)

PUBLIC oform1
oform1=NEWOBJECT("form1")
oForm1.pageframe1.page1.addobject("Text1","textbox")
oForm1.pageframe1.page1.text1.visible = .t.

oform1.Show
RETURN
DEFINE CLASS form1 AS form
DoCreate = .T.
Caption = "Form1"
Name = "Form1"
ADD OBJECT pageframe1 AS pageframe WITH ;
ErasePage = .T., ;
PageCount = 2, ;
Top = 12, ;
Left = 36, ;
Width = 289, ;
Height = 197, ;
Name = "Pageframe1", ;
Page1.Caption = "Page1", ;
Page1.Name = "Page1", ;
Page2.Caption = "Page2", ;
Page2.Name = "Page2"
ENDDEFINE

Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
Hi Coupon,

I read your exchange with Mike Gagnon with interest. Let me add my welcome to you.

I have a sneaking sympathy with your point of view. I often long for a tool like Foxbase, that lets you just sit down and cut code, the way programmers were always meant to. I feel sure I used to develop apps much faster in those days, and with much less hassle.

The problem that you -- and many others -- are facing is not that the new visual tools are harder to use, but users' needs and expectations have grown so much.

The good news is that it is possible to write code in VFP the old way -- and your applications will be none the worse for it. You can happily ignore the visual class designer and form designer. You can write all your classes in code (using DEFINE CLASS) and put them in PRG file.

In fact, that approach has many advantages. You will overcome the problem of keeping all the code in one place, and you will never experience the hassles of corrupted class libraries or form files.

On the other hand, once you have got used to the visual tools, you might find that you prefer them, and won't then ever want to go back to hand-coding. It's largely a matter of personal attitudes and programming style.

So, please, do persevere with VFP. It is a great tool once you get over the initial shock.

Mike Lewis
Edinburgh, Scotland
 
I guess it's a volume thing. If you create a 10 page PageFrame, with 20 or more objects per page, it could take countless hours restructuring the output to make it actually run. Then if you visually tweak the original, you're stuck.

Since the output is not runable, I've been using it as a hard copy overview, and nothing more. It would feel so much better if it could be live code, and if Rettig's original reverse converter, I would be able to alter the code, and output it back to a class or form file.

I guess you may be wondering why anyone would want to go through all this effort to get code, when the form file will run fine as is? Well, like I said, having code is so much more flexible for me. I can search/replace with any utility and globally change tons of code in a fraction of the time with text based code than I could with visual tools.

I think Microsoft should either fix the output so it's runable, or rename it something like "Class Summary" or "Class Documenter". For what it's worth, it does a fine job of that. I can at least browse through classes and forms on paper, looking for hidden bugs, then hunt and peck later using the visual tools to make the changes.

Thanks again Mike
 
oForm1.pageframe1.page1.addobject("Text1","textbox")
oForm1.pageframe1.page1.text1.visible = .t.

Yes, Like I said, that's the only way to programatically add elements to a pageframe... at runtime. However, it would be a big mess trying to do an entire 10 page form using your two line approach. You wouldn't want to add each element like that. What I do is create a class of Pages, which contain all the textboxes, labels, etc, then just add the entire page using a similar method.

oForm1.pageframe1.addobject("NewPage1","MyPageClass1")
oForm1.pageframe1.addobject("NewPage2","MyPageClass2")
oForm1.pageframe1.addobject("NewPage3","MyPageClass3")

In this case, each page exists as it's own class, with all the objects already part of that class.

All Microsoft needs to do to fix their code output is to break the pages up into individual classes like I did, then add the classes to the pageframe. The fact that they make it say "add object form1.pageframe1.page1.myobject..." is a total mystery... it's not allowed.

You'd think by 7.0 they would've changed the output to use the correct syntax. Perhaps version 8 will? Has anyone tried it?
 
I guess you may be wondering why anyone would want to go through all this effort to get code, when the form file will run fine as is? Well, like I said, having code is so much more flexible for me. I can search/replace with any utility and globally change tons of code in a fraction of the time with text based code than I could with visual tools.

Recognizing that the visual designer is one-way, this is basically a major fork in the road: If you expect to be able to adjust the form in the Visual Designer, and regenerate, then the above mentioned capability to search-and-replace is useless.

However, there is a tool called GoFish ( that CAN search and replace right in the SCX/SCT's, VCX/VCT's, etc, and its changed DO apply to the code that was visually designed!

You're right, the reason it doesn't generate runnable code is because the MS VFP programmers got lazy.
 
BTW: For those who are wondering how you create the Page Class (because there is no visual tool to create an individual Page class), here's what I do:

1. Create a FORM class which contains everything you would've put on a Page.

2. From the Class Browser, generate the code and copy it into a PRG containing your library of classes.

3. Change the word "Form" to Page in the class definition:

DEFINE CLASS mypage AS form
--- becomes
DEFINE CLASS mypage AS Page

4. Set the PRG as a classlib.

5. Create your PageFrame with zero pages.

6. Add each Page class you created (originally as a form) using Form.PageFrame.Addobject
 
Just an update.

When I originally wrote this post in February, I had hoped that Microsoft would eventually enhance the Class Browser and/or the language for adding objects to individual pages in a pageframe in VFP 8.0.

No such luck. I just installed 8.0, created a form with a pageframe containing three pages, a textbox on the first two pages, and a simple commandbutton with a form release on the third page. It spits out the same invalid code as the prior versions.

Since I rely on pageframes for a large portion of my forms, I can't imagine why VFP still doesn't have a more direct method to programatically place objects on individual pages.

Thus far, the only method I have found that works is what I said in February, if you design visually, create a series of individual forms, change the class of each form from "form" to "page", then you can programatically add each page at runtime.

Once again visual purists may not understand the flexibility of keeping forms as PRGs rather then SCXs:

1. It gives me peace of mind in knowing I can see the entire form on paper and catch hidden problems embedded in the SCX. It simply takes way to long to review every method and property of a SCX form. You have to touch every element, then scroll down the properties box... it can take hours to see the whole thing.

2. I love the ability to search and replace through my code to make global changes such as field or variable names.

3. It also allows for flexible form changes at runtime. You could define several versions of the same individual page within the PRG, then add whichever page is appropriate at runtime, so the PageFrame becomes dynamic and individual pages can vary depending on the data. For example, for a client profile page, if the person is a company, additional tabs could be added to define the person's company information. For non-corporate clients, the same form could display an entirely different set of tabs where the user can describe family or home information instead.

Anyhow, I'm just venting. I love getting the newest version... I'd just love it more if they tackled some of the items on my own wishlist... I was happy to see one of my wishlist items in the new version, a maxlength property for ComboBoxes, which was a major annoyance in the prior versions.
 
I've been threatening to build a class that takes the
output of view-code and turn it into something truly
useful.

And yes, I've suffered through fixing all of the
problems that arise when viewcode tries to generate
anything that's more complicated than a form with basic
classes. You've probably noticed your data sessions are
missing also... :)


Someday...

It would probably be easier to create a better viewcode,
since it's easy enough to iterate over the properties and
methods of any visual class. Plus, it's known which objects
have to be added programmatically with caution.

Check back in about a hundred years and you may find it.

:)

Darrell


'We all must do the hard bits so when we get bit we know where to bite' :)
 
I use the class browser to convert my visual designed classes into code during the build process and then compile it to one fxp which is then used for the runtime version of my application (it makes my exe only 18 K).
And yes, you cannot create classes in code that are more than two levels deep. But that is just a design consideration....(and I do use pageframes and pages)...

HTH,


Weedz (Edward W.F. Veld)
My private project:Download the CrownBase source code !!
 
I just installed 8.0, created a form with a pageframe containing three pages, a textbox on the first two pages, and a simple commandbutton with a form release on the third page. It spits out the same invalid code as the prior versions. - couponPages

And yes, I've suffered through fixing all of the
problems that arise when viewcode tries to generate
anything that's more complicated than a form with basic
classes. You've probably noticed your data sessions are
missing also...
- darrell

However, VFP 8 introduces the BindEvent command, which can make this whole process easier....

You could either process the output of view code, or rewrite view code altogether, and change the invalid ADD OBJECT statements into calls in the Form's INIT event to THISFORM.PageFrame.Page.AddObject('ControlName','class')
Then, change the method names in the form to identify what they really refer to, ie: FUNCTION THISFORM_PageFrame_Page_ControlName
(If processing the View Code output, you'd have to rely on method order if there are name conflicts: I don't know if method order would be reliable, though)

THEN, you could use BindEvent() commands in the form's INIT event to bind these methods to the appropriate events in the class. You could also set the control's properties in INIT.

I'm not clear on whether you could bind to Methods of the contained controls that aren't Events (such as Move, Refresh, etc).
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top