Logo

Hacker’s Guide to Visual FoxPro
An irreverent look at how Visual FoxPro really works. Tells you the inside scoop on every command, function, property, event and method of Visual FoxPro.

Objects

This collection property gives you a handle to all the objects instantiated in an instance of VFP. It’s convenient for writing generic tools and especially useful for Automation servers. It also lets you look inside VFP’s container classes.

Usage

oObject = oContainer.Objects[ nIndex | cName ]

For the application-level collection, you can access Objects either through the _VFP system variable that references the current VFP session or through the Application Object. (Every control contains a property that points to the VFP instance that contains it.) Objects contains an element for each object that’s been created in the VFP session in question. So what’s an object in this context? Let’s start with the easy stuff. Anything you create with CREATEOBJECT() or NewObject() counts as an object. So does any form you run with DO FORM. Then, it gets more interesting. Browses count because, behind the scenes, a browse is really a grid. Opening the Class Designer adds a formset object to the collection—we’re not sure why it’s a formset rather than an object of the class you’re working on. Maybe it refers to the designer rather than the object being designed. Opening the Form Designer adds two objects to the collection: a data environment object and a formset object. Finally, opening the Report Designer or Label Designer adds only a data environment object to the collection, because there are no Report or Label objects.

You can manipulate at least some of the design-time objects that show up in the _VFP.Objects collection, but in VFP 6, we found it a dangerous game to play. We crashed or froze VFP more often in a couple of hours playing with the Objects collection than in weeks of doing other stuff. So far, in VFP 7, this collection seems a lot more stable.

All of VFP’s container classes have their own collections to let you see what’s inside. (For example, Form and Column both have Controls collections, while PageFrame has Pages.) However, they all also have an Objects collection, which makes it much easier to write generic code. In VFP 5 and VFP 6, only those containers that can contain objects of more than one type have an Objects collection in addition to their native collection. The objects that are limited to a single type of child (like OptionGroups, which are composed only of OptionButtons, or Grids, which are composed of Columns) have only their native collections.

Since we could already drill down into those objects with their native collections, why would we use Objects? Primarily for consistency. It keeps us from having to remember the name of the native collection (though that’s not a big deal, since it’s usually Controls). More importantly, though, Objects is a common collection in the Automation world. By including it, VFP makes things easier for programmers who want to talk to VFP but don’t know it that well.

The Objects collection has a Count Property that tells you how many objects are in the collection at the moment. Objects also has an Item method that allows you to iterate through the collection by number or name. This is redundant in VFP, where we can just specify the index directly on the Objects collection, but we suspect it’s a standard feature of COM objects like Objects.

In earlier versions, getting access to the Objects collection at runtime is flaky. As long as you're drilling down directly from the _VFP application object, all is well. But if you create an object reference to, say, a form, VFP can't see the Objects collection. That is,

? _VFP.Objects["frmMyForm"].Objects.Count 

tells you the number of controls on the form. But:

oForm = _VFP.Objects["frmMyForm"]
? oForm.Objects.Count

gives an error message. This bug is fixed in VFP 7.

Unfortunately, there's a nice new bug to replace it. When you use an object reference to drill down, and use the Item method to address the members of the collection, you get an error unless you got the object reference by drilling down from _VFP. That is, with a form running, this code works:

? _VFP.Objects["frmMyForm"].Objects.Item[1].Name

but this doesn't:

oForm = _SCREEN.ActiveForm
? oForm.Objects.Item[1].Name

And, assuming the form is called MyForm, neither does this:

? MyForm.Objects.Item[1].Name

We think this is a deeper manifestation of the earlier bug. Fortunately, you can work around it by using the shorthand notation:

? oForm.Objects[1].Name

But wait, there's more. IntelliSense mishandles the Objects collection. At the application level (that is, for _VFP.Objects), no IntelliSense is available—that is, no members pop up after you hit the period. Below that level, only Count is offered as a choice (except, sometimes, when Value appears instead). The Item method never shows up, and when you specify an index, IntelliSense doesn't offer you the members of the specified object.

Example

* Find out what objects exist.
FOR EACH oObj IN _VFP.Objects
   ? oObj.Name
ENDFOR

See Also

Application, Buttons, ButtonCount, Columns, ColumnCount, Controls, ControlCount, Count Property, CreateObject(), Forms, FormCount, NewObject(), Pages, PageCount, _VFP