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.

Session

Until this base class was added in VFP 6 Service Pack 3, the only way to create an object with its own private data session was to base it on Form, FormSet, or Toolbar. None of these choices are appealing for lightweight, non-visual objects such as COM servers.

Fortunately, we now have the Session base class. Its purpose in life is to create non-visual objects with private data sessions. A private data session is crucial to ensuring that an object won’t interfere with the data environment of other objects, even other instances of the same object. It also allows the object to have its own SET settings, at least for those scoped to a data session; see “Set” for a list of those. With the addition of this object, and a few other enhancements added in VFP 7, we are now easily able to produce “clean” COM objects competitive with those produced in any other product.

Session has only a few PEMs. Besides the ones shared by every class, including Name, Class, Init and Destroy, it also has DataSession and DataSessionID properties. Unlike forms, the default for DataSession is 2–Private DataSession, since that’s the whole point of this class; we can’t think of any reason why you’d change this. DataSessionID allows you to determine which data session the object created and lives in.

You may think Session is similar to Custom, another base class frequently used for creating non-visual objects, but in addition to private data sessions, they have two very important differences. First, Session is not a container, so it has no AddObject(), CREATEOBJECT(), or NewObject() methods. The only way to associate it with another object is by adding a property to contain a reference to the other object. The second difference is that you can create a subclass of Custom in the Class Designer. Not so with Session; like the other “half-classed” objects in VFP, including Column, Header, and Page, you can define an object based on Session only in a PRG.

The last issue isn’t as bad as it may sound. Microsoft added a lot of new capabilities to PRG-based classes in VFP 7, including finer control over the type library of COM servers, and a new Document View tool that makes navigating through a PRG a lot easier than before.

VFP 7 also added a couple of very important improvements to Session. First, all intrinsic PEMs are now hidden from the type library. Only those custom PEMs you add are exposed to the outside world. No more having to define every PEM as PROTECTED or tell your VB friends using your COM server to just ignore BaseClass, ClassLibrary, Comment, and other things they shouldn’t mess with. The second improvement is that EXCLUSIVE, TALK, and SAFETY are now all set to OFF by default, since those are the most likely settings you’d want in a COM object.

Property

Value

Meaning

DataSession

Numeric

Determines whether the object has its own private data session.

DataSessionID

Numeric

The data session being used by the object.

Example

DEFINE CLASS TableMaintenance AS SESSION OLEPUBLIC
  PROTECTED lErrorOccurred, cErrorMessage
  lErrorOccurred = .F.
  cErrorMessage  = ""

  PROCEDURE Reindex(TableName AS STRING) AS BOOLEAN ;
    HELPSTRING "Re-create the indexes for a table"
    LOCAL llReturn
    llReturn = .F.
    This.lErrorOccurred = .F.
    DO CASE
      CASE VARTYPE(TableName) <> "C" OR EMPTY(TableName)
        COMReturnError("TableMaintenance", ;
          "Table not specified")
      CASE NOT FILE(FORCEEXT(TableName, "DBF"))
        COMReturnError("TableMaintenance", TableName + ;
          " not found")
      OTHERWISE
        USE (TableName) EXCLUSIVE
        IF NOT This.lErrorOccurred
          REINDEX
        ENDIF
        USE
        llReturn = NOT This.lErrorOccurred
        IF NOT llReturn
          COMReturnError("TableMaintenance", This.cErrorMessage)
        ENDIF
    ENDCASE
    RETURN llReturn
  ENDPROC

  PROCEDURE Error(nError, cMethod, nLine)
    LOCAL laError[1]
    AERROR(laError)
    This.lErrorOccurred = .T.
    This.cErrorMessage  = laError[2]
  ENDPROC
ENDDEFINE

The example shows a simple table maintenance object. Since the TableMaintenance class is defined as OLEPUBLIC, it can be used as a COM server. The only PEM exposed is the Reindex method. The AS and HELPSTRING clauses provide information about this method and its parameters to the type library. (See “DEFINE CLASS” for details on those clauses.) To see how this works, create a project, add a PRG containing this code, and build a DLL. Then, instantiate the COM server into a variable and type the variable name followed by a period. VFP’s IntelliSense will show only Reindex in the list of PEMs and will display the help string defined in the class when you select it in the list. When you type “(“, you’ll see the parameter name and data type of the parameter and method. Is this cool or what?

See Also

Custom, DataSession, DataSessionID, Define Class, Form, FormSet, Set, Toolbar