Intellisense: inspecting live objects

In this entry I talked about a performance improvement of FoxPro’s object handling.

I showed an example of object based programming:

oExcel=CREATEOBJECT("excel.application")

oExcel.

A live instance of Excel is created. When you type the “.”, intellisense shows the methods and properties of the Excel Application object.

Nick Parker asked in a comment how this works in Foxpro.

Ok, I've never worked with FoxPro, but in your example I can only assume you are late-binding to the COM object you are requesting. That said, I am surprised that you get intellisense, as you don't in VB6, only with early binding is this available (for VB6 that is). I'm assuming that under the covers you using the IUnknown pointer to request an ITypeInfo pointer to display specific information to the user? If this is the case, which makes it much more helpful for the programmer that doesn't read documentation I wonder why this wasn't implemented in VB6?

Nick is correct that in this instance, Foxpro is “late binding” to the requested COM object. This means Foxpro has no idea what the COM server is: the type information for that object is obtained dynamically to provide intellisense.

In fact, replace “excel” with “internetexplorer” and you get this:

oExcel=CREATEOBJECT("internetexplorer.application")

m.oexcel.Visible=1

m.oexcel.Navigate("www.msn.com")

You can use “Word.application”, “VisualFoxpro.application”, “Outlook.application”, etc. and get the intellisense for each of these

How does this work?

Nick is partially right that we can get an ITypeInfo interface from the object via its IDispatch interface. But many objects don’t implement IDispatch::GetTypeInfo

Another way to find the ITypeInfo is to search the registry for the “excel.application” ProgId. It points indirectly via a GUID to a registry entry with the full path to the server location. Foxpro tries to load that server as a typelibrary using LoadTypeLib. If that fails, then other files in that directory are loaded and searched for the GUID.

Although this seems like a long and laborious process, it is usually faster than the speed of user input.

If you use the Foxpro CreateObjectEx function, then the object is created dynamically as if it were late bound, but it’s called via early binding. Thus Dual interface objects can be called via either early or late binding in Foxpro. (See also GetInterface)

For late binding, the method or property name is converted to an ID via IDispatch::GetIDsOfNames and the parameters are packaged into a DISPPARAMS structure and passed to the IDispatch::Invoke method.

For early binding, the parameters are pushed directly onto the process stack and the method is called directly through the vtable. The ITypeInfo interface is used to know how to format the parameters and how to call the method. (Properties in COM are implemented as method calls: propertyset and propertyget.)

The above is showing intellisense for a live object. How does it work if you don’t have a live object?

You can trigger intellisense while not executing any commands via the AS clause of variable declarations.

PUBLIC oExcel as "excel.application"

oExcel=CREATEOBJECT("excel.application")

oExcel.

Additionally, you can easily create a Foxpro COM server (like “myapp.application”) and have it give the client intellisense and be called via early or late binding.

The above is a description of how VFP handles intellisense for COM objects. Handling intellisense for the VFP OOP language via table driven metadata is another topic.

45338