Session E-Auto

Visual FoxPro 7 Automation
Server Enhancements

Kevin McNeish
Oak Leaf Enterprises, Inc.


Contents

Visual FoxPro has been positioned by Microsoft as a great choice for building middle-tier business components. Is this good news or bad news? If you’re building one or two tier monolithic applications you may not know for sure—you’re probably putting the majority of your application logic within methods of the user interface. So, if you use another tool to build the user interface (i.e. Visual Basic, Active Server Pages) you may not see a place for Visual FoxPro.

However, if you’re building three-tier applications—whether they are true three-tier applications or simply partitioned logically into user interface, business logic and data components—you understand that positioning Visual FoxPro in the middle tier is great news for Visual FoxPro. This is because in a three-tier architecture, the majority of your application logic is placed in middle tier components.

With this in mind, the Fox team has made great strides in keeping Visual FoxPro up to date with the latest middle tier technologies introduced with COM+. Some of the biggest changes in Visual FoxPro 7 involve enhancements for creating more robust Automation servers.

 Setting up the Example Source Files

To set up the example source files for this session, I recommend creating a directory named “VFP7COM” off the root directory of your C: drive and copying all the files to this directory. If you choose to place the files in a different directory, do the following after copying the files to the chosen directory:

    1. From within Visual FoxPro, CD to the chosen directory
    2. In the Command Window, enter: MODI COMM BindEvnt.prg
    3. Locate the string “SourceDB=C:\VFP7COM\TESTDATA.DBC”
    4. Change the string to the name of the drive/directory in which you have copied the source files.
    5. Close BindEvnt.prg and save changes

Whenever this document refers to the C:\VFP7COM directory, simply refer to your chosen drive/directory instead.

The source files can all be accessed through the COMTest and COMTest2 projects. The majority of example code can be found in the COMTest project. The code that demonstrates “event binding” is found in the COMTest2 project.

Understanding Automation Server Type Libraries

Once you have created an Automation Server, how will developers using Active Server Pages, Visual Basic, C++, etc. know how to use it? A server’s type library defines all of the public classes and their properties, events and methods that are available in the Automation server.

To see an example of an Automation Server’s type library you can examine the type library of any Microsoft Office product. For this example, view the Microsoft Word type library using Visual FoxPro 7’s new Object Browser:

    1. From the Tools menu, select Object Browser
    2. Click on the Open Type Library button (located in the upper left corner of the Object Browser).
    3. In the Object Browser’s “Open” dialog, click the Browse button
    4. In the “Open” dialog’s Files of Type combo box, select “*.olb”.
    5. Use the Open dialog to navigate to and select the MSWORD9.OLB file (By default, it’s located in the C:\Program Files\Microsoft Office\Office directory).
    6. Click the OK button to return to the Object Browser’s “Open” dialog. The MS Word type library appears under the “Selected Type Library Files” node.
    7. Click the OK button to return to the Object Browser.

To view MS Word’s classes and their associated properties, events and methods, click on the “+” sign to open the Word node, then click on the “+” sign next to open the Classes node. Click on a class in the left pane of the Object Browser, then open the Interfaces, Methods and Properties node in the left pane to check out the PEMs.

Visual FoxPro 7 Type Libraries

When you build an Automation server in Visual FoxPro, in addition to building your dll or exe server, it also “auto-magically” builds a type library for you. To see this for yourself:

    1. From within Visual FoxPro 7, CD to the C:\VFP7COM directory
    2. In the Command Window, enter: MODI PROJ COMTest
    3. Click the Build button on the Project Manager and in the Build Options dialog, select Multi-threaded COM server (dll), Recompile All Files, and Display Errors
    4. Click the OK button to build the COM server dll.
    5. In the Save As dialog, click the Save button to select the default COMTest.dll server name.

If you look in the C:\VFP7COM directory, you will see three new files:

  • Comtest.dll (the new COM Server)
  • Comtest.tlb (the type library file)
  • Comtest.vbr (the Windows Registry file)

To view the contents of comtest.tlb, open VFP7’s Object Browser and open ComTest.tlb.

Method and Property Visibility

The only classes that appear in the type library are those that have been marked as OLE Public. The only properties and methods that appear are those that have been marked as public. However, most Visual FoxPro classes that you use to create your OLE Public classes contain properties, events and methods that you do not want to appear in the type library.

For example, if you use VFP’s custom class to create your OLE Public classes, there are properties such as BaseClass, Class and ClassLibrary and methods such as ReadExpression, ReadMethod and SaveAsClass that make no sense to expose in a type library. By setting this properties and methods to HIDDEN, you can prevent them from being listed in an Automation server’s type library.

  Textfeld: Note: 	In Visual FoxPro 7, if you base an OLE Public class on the Session class, the compiler will not place any of the intrinsic (built-in) PEMs in the type library.

Weak Typing vs. Strong Typing

Visual FoxPro 7 (as was true in previous version of Visual FoxPro) has weak typing. The positive side of this is that weak typing allows you to store a value of any TYPE into a variable. Despite the virtues that may be listed for weak typing, it’s not a good thing when it comes to type libraries. Weak typing does not allow you to specify the TYPE of parameters, class properties or the return value of methods. There are many clients using Automation servers that are strongly typed (such as Visual Basic). These clients need to know the correct type information of classes in your automation server.

In Visual FoxPro 6, all properties, parameters and method return values are listed in the type library as “variant”. Visual FoxPro 7 addresses this problem. It supports strong typing by means of the new AS clause in the DEFINE CLASS command. As shown below, the AS clause is used to specify that the parameter passed to the GetCreditLimit method is an integer. It is also used to specify that the return value of the GetCreditLimit method is “Currency”.

    DEFINE CLASS Client AS Custom OLEPUBLIC
       FUNCTION GetCreditLimit(ClientID AS Integer) AS Currency ;
          LOCAL  lyCreditLimit
          RETURN lyCreditLimit
       ENDFUNC
    ENDDEFINE

If you look at the Client class’s GetCreditLimit method in an object browser, you’ll see the following:

 

Although the AS clause allows the proper TYPE to be specified in the type library, Visual FoxPro does not enforce strong typing at compile time or run time. It is only used for type libraries and IntelliSense.

Mapping Visual FoxPro Data Types

The following table shows how Visual FoxPro data types map to Type Libraries and IntelliSense (Thanks to Randy Brown at Microsoft).

VFP Defined Type 

Type Library Conversion * 

Intellisense ** 

BinaryMemo 

VARIANT 

-- 

Boolean

VARIANT_BOOL

Logical 

Byte

unsigned char

Number

Character

VARIANT

--

Currency

CURRENCY

Currency

Date

DATE

Date

DateTim

DATE

Date

Decimal

wchar_t

Number

Double

double

Number

Float

VARIANT

--

Integer

long

Number

Logical

VARIANT_BOO

Logical

Long

long

Number

Memo

VARIANT

--

Number

double

Number

Object

IDispatch*

Object

Short 

long

Number

Single

single

Number

String

BSTR

String

Variant

VARIANT

--

Void

void

VOID

*what appears in actual type library
** what appears in VFP Intellisense (quick info parameter tips)

Specifying a VOID Return Value

As the last item in the above table shows and as demonstrated below, you can also specify that a method returns a value of VOID.

    DEFINE CLASS Order AS abizobj OLEPUBLIC
       FUNCTION Cancel(OrderNum AS Integer) AS VOID
       ENDFUNC
    ENDDEFINE

This is strictly for use in the type library. For example, the above Cancel method still returns .T. by default. The ability to specify a method returns VOID in a type library is important for COM+ Queued components that do not allow methods to have a specified return value. In addition, Web Service generators like the SOAP toolkit generate XML by reading the type library. Different tags are used for methods that return VOID.

Specifying Class and Method Descriptions

Another extremely important part of the type library is the descriptions specified for the classes and their properties, events and methods. To specify the description for an OLE Public class:


  1. Open the Automation Server project (e.g. ComTest.pjx)

 

  1. From the Project menu, select Project Info…
  1. In the Project Information dialog, select the Servers tab. In the Server classes list box there is a list of all classes that have been marked as OLE Public (you need to compile an Automation Server before the OLE Public classes appear in this list).


  1. Click on each server class and enter the class description in the Description text box. By default, VFP 7 enters the name of the server.class in this box, but you can override the default with a more user-friendly description.

5.       Click the OK button to save changes, then compile a new dll to apply the new descriptions to the Automation server.

Specifying Method Descriptions

In Visual FoxPro 7 you can specify the description for a class method by using the HELPSTRING argument in the class definition as shown below:

    DEFINE CLASS Order AS abizobj OLEPUBLIC
       FUNCTION Cancel(OrderNum AS Integer) AS VOID ;
        HELPSTRING "Cancels the specified order"
    ENDFUNC

Using COMATTRIB to Specify Property and Method Attributes

The previous sections showed how to specify types for parameters and method return values as well as descriptions for classes and methods—but how is this accomplished for class properties? The answer is Visual FoxPro 7’s new COMATTRIB functionality.

In a manner similar to Visual FoxPro 6’s access and assign methods, you can specify attributes for a class’s properties and methods by creating a new property with the same name but with a _commattrib suffix. For example, the Client class shown below has a property named GrossSales. A second GrossSales_comattrib property is defined for the purpose of setting the GrossSales property’s attributes—in this case read only.

    #DEFINE COMATTRIB_READONLY 0x100000
    DEFINE CLASS Client AS Custom OLEPUBLIC
       GrossSales = .00
       GrossSales_comattrib = COMATTRIB_READONLY
    ENDDEFINE

The following table lists valid flags that can be set for properties and methods using COMATTRIB:

#DEFINE

Value

Description

COMATTRIB_RESTRICTED

0x1

The property/method should not be accessible from macro languages. This flag is intended for system-level variables or variables that you do not want type browsers to display.

his means that macro-oriented programmers should not be allowed to access this member. These members are usually treated as _HIDDEN by tools such as Visual Basic, with the main difference being that code cannot bind to those members.

COMATTRIB_HIDDEN

0x40

The property/method should not be displayed to the user in a browser, although it exists and is bindable.

This means that the property should never be shown in object browsers, property browsers and so on. This attribute is useful for removing items from an object model. Code can bind to the member, but the user will never know that the member exists.

COMATTRIB_NONBROWSABLE

0x400

The property/method appears in an object browser, but not in a properties browser.

This means that the property should not be displayed in a properties browser. It is used in circumstance in which an error would occur if the property were shown in a properties browser.

The following table lists valid flags that can be set for properties only using COMATTRIB:

#DEFINE

Value

Description

COMATTRIB_READONLY

0x100000

The property is read-only. Assignment to the property is not allowed.

COMATTRIB_WRITEONLY

0x200000

The property is write-only.

  Textfeld: Note:	COMATTRIB “attributes” are only used for generating type library information. They are inaccessible from within Visual FoxPro. If you try to access them from Visual FoxPro code, you will get an error informing you that the property is not found. This truly makes a property with a _COMATTRIB suffix an attribute rather than a property.

 

You can also set multiple attribute flags for a single property or method:

    DEFINE CLASS AttribTest2 AS abizobj OLEPUBLIC
       
         MyProperty = ""
         MyProperty_comattrib = COMATTRIB_WRITEONLY + COMATTRIB_RESTRICTED
        
         MyMethod_comattrib = COMATTRIB_RESTRICTED + COMATTRIB_HIDDEN
         FUNCTION MyMethod AS VOID
         ENDFUNC
       
    ENDDEFINE

Read-Only and Write-Only Attributes

In Visual FoxPro 6 you can create individual properties that you can read from or write to. In the COM world, a single Visual FoxPro property translates into two methods (PropertyGet for read access and PropertyPut for write access) that are specified in the type library.

In Visual FoxPro 6 there is no way to create read-only or write-only properties. However, certain technologies such as COM+ Queued Components do not allow a COM server to be marked as “Queueable” if there are any properties on the server that have read access. In Visual FoxPro 7, the COMATTRIB functionality gets around this limitation by allowing you to specify that properties are write-only.

If you specify both the read-only and write-only for a property, it’s the same as not specifying either attribute since both PropertyGet and PropertyPut are generated. In addition, if you specify read-only or write-only attributes for a method, the attribute is ignored. Remember that read-only and write-only attributes apply to properties only!

  Textfeld: Note:	Read-only and write-only attributes only work properly with early binding clients—they cannot write to a read-only property and cannot read from a write-only property. However, late binding clients (such as Visual FoxPro using IDispatch) can still write to a read-only property and read from a write-only property.

Setting Property Attributes with COMATTRIB Arrays

All attributes of methods (flags, description, capitalization and type) can be set by arguments of the DEFINE CLASS command. However, to set the attributes of a property, you must use a COMATTRIB array:


    DEFINE CLASS Invoice AS aBizObj OLEPUBLIC
           Subtotal = .00
         DIMENSION Subtotal_COMATTRIB[4]
         Subtotal_COMATTRIB[1] = 0x100000       && Attributes
         Subtotal_COMATTRIB[2] = "Invoice Subtotal"      && Description
         Subtotal_COMATTRIB[3] = "Subtotal"        && Capitalization
         Subtotal_COMATTRIB[4] = "Currency"        && Type
      ENDDEFINE

The first row of the COMATTRIB array specifies the attribute flags for the property. If there are no special attributes you wish to assign, simply set the value of the first row to zero (0).

The second row of the COMATTRIB array specifies the description of the property. This is equivalent to the HELPSTRING argument used to specify the description of a method in a class definition.

The third row of the COMATTRIB array specifies the proper capitalization of the property.

The fourth row of the COMATTRIB array specifies the TYPE of the property or method.

Textfeld: Note:	If you leave the value of a row empty or .F., Visual FoxPro sets the default value. For example, the Type would be set to “Variant”.


Implementing Interfaces

Visual FoxPro 7 now supports the ability to implement interfaces. This functionality is critical for supporting COM+ Services such as COM+ Events. What does it mean to implement an interface?

Visual FoxPro 6 supports something called “implementation inheritance”. This means that a subclass inherits the properties, events and methods of its parent class as well as the code (the implementation) contained within the parent’s methods. As shown in the UML diagram to the right, the Manager, SalesRep and Contractor classes inherit the Work, GetGrossPay, GetHourlyRate, etc. methods and any code contained within these methods, from the Employee parent class

 

Unlike Visual FoxPro, COM does not support implementation inheritance. You cannot subclass a COM Employee class and inherit the code contained within its methods. What COM does support is interfaces. In the COM world, an interface is a set of related methods that define a particular type of behavior. An interface is the only way that a client can communicate with a COM component.

As shown in the UML diagram to the right, you can create an Employee interface that contains the Work, GetGrossPay, GetHourlyRate, etc. methods that together define the behavior of an Employee. The Manager, SalesRep and Contractor classes can implement this Employee interface.

 

In addition, a single COM component can support any number of interfaces. In many cases the client may not even know all of the interfaces that a component supports! The UML diagram to the right shows the Person class implementing both the Employee and the Parent (as in father, mother) interface—a person can be both an employee and a parent.

Reusability Through Polymorphism

So, if you’re not “inheriting” any code, what does the implementation of interfaces buy you? Polymorphism—the ability to treat different objects in the same manner! If two components support the same interface, the client can use the same code to manipulate either component. Using the above example, any place your application code expects to use an Employee, you can use a Manager, SalesRep or Contractor component.

The Unchanging COM Interface

Once you have published a COM interface, it cannot change or you will break all the client applications that are using your COM objects. When you release new versions of your components, rather than changing an existing interface, you create a new interface and add it to your component. This allows existing applications to continue functioning while still allowing newer applications to take advantage of enhancements to your components.

IUnknown—Getting to Know Your Blind Date

Since a COM object can implement any number of interfaces, how can clients determine which interfaces a COM object supports? The answer to this question is the IUnknown interface. The COM standard dictates that all COM interfaces must inherit from the IUnknown interface.

The IUnknown interface contains a method named QueryInterface that allows your application to query a component at run time to determine if it supports a particular interface. If the component does not support the specified interface, QueryInterface returns an error code. The client can then ask if the component supports another interface, or it can simply release the component.

 
Interfaces in Visual FoxPro COM Servers

Visual FoxPro hides much of the complexity inherent in creating COM Servers. When you build a COM server, Visual FoxPro automatically creates a default interface for each of your OLE Public classes. This interface is given the same name as your class plus an “I” prefix.

For example, as shown at the right, if you create an OLE Public class named Client, when you build your server, Visual FoxPro creates an interface named IClient.

In Visual FoxPro 7 the DEFINE CLASS command allows you to specify that an OLE Public class implements additional interfaces. This allows clients to call QueryInterface on our VFP7 components and make calls against these implemented interfaces. For example:


    DEFINE CLASS Person AS KBizObj OLEPUBLIC
         IMPLEMENTS Employee IN "COMTest.Employee"
         IMPLEMENTS Parent IN "COMTest.Parent"
    ...

In this example, the Employee and Parent interfaces have been defined in the COMTest automation server. When implementing an interface, you must supply a default implementation for each method in the implemented interface. You must also create a corresponding Get and Put method for each property in the interface.

Since multiple interfaces can be implemented in a single class it opens up the possibility that the interfaces you are implementing have methods with the same name. To avoid this conflict, you must specify the name of the interface as a prefix to the method or property you are implementing. In the following example, the Person class implements the Employee and Parent interfaces. When defining a default implementation for each property and method, the name of the interface is used as a prefix:

 

    DEFINE CLASS Person AS KBizObj OLEPUBLIC
         IMPLEMENTS Employee IN "COMTest.Employee"
         IMPLEMENTS Parent IN "COMTest.Parent"
        
         HIDDEN PROCEDURE Employee_Get_ID
         ENDPROC
         HIDDEN PROCEDURE Employee_Put_ID(ID AS Integer)
         ENDPROC
         HIDDEN PROCEDURE Employee_Get_FullName
         ENDPROC
         HIDDEN PROCEDURE Employee_Put_FullName(FullName AS String)
         ENDPROC
         HIDDEN PROCEDURE Employee_Get_Salary
         ENDPROC
         HIDDEN PROCEDURE Employee_Put_Salary(Salary AS Currency)
         ENDPROC
         HIDDEN PROCEDURE Employee_Get_HoursWorked
         ENDPROC
         HIDDEN PROCEDURE Employee_Put_HoursWorked(HoursWorked AS Number)
         ENDPROC
         HIDDEN PROCEDURE Employee_Get_numDeps
         ENDPROC
         HIDDEN PROCEDURE Employee_Put_numDeps(numDeps AS Integer)
         ENDPROC
       
         *--- Implement Employee interface methods ---*
         HIDDEN PROCEDURE Employee_GetGrossPay AS Currency
             RETURN This.GetHourlyRate() * This.GetHoursWorked()
         ENDPROC
         HIDDEN PROCEDURE Employee_GetHourlyRate AS Currency
             RETURN This.Employee_Get_Salary()/40
         ENDPROC
         HIDDEN PROCEDURE Employee_GetHoursWorked AS Number
             RETURN This.HoursWorked
         ENDPROC
         HIDDEN PROCEDURE Employee_BeginPayPeriod AS VOID
             This.HoursWorked = 0
         ENDPROC
         HIDDEN PROCEDURE Employee_Work(numHours AS Integer) AS VOID
             This.HoursWorked = This.HoursWorked + numHours
         ENDPROC
         HIDDEN PROCEDURE Employee_GetNumDependents AS Integer
             RETURN This.numDependents
         ENDPROC
         HIDDEN PROCEDURE Employee_SetNumDependents(NumDependents AS Integer) AS VOID
             This.numDependents = numDependents
         ENDPROC
         HIDDEN PROCEDURE Employee_GetName AS String
             RETURN This.Employee_Get_Fullname()
         ENDPROC
         HIDDEN PROCEDURE Employee_GetSalary AS Currency
             RETURN This.Salary
         ENDPROC
        
         *--- Implement Parent interface methods ---*
         HIDDEN PROCEDURE Parent_Scold(ChildName AS String) AS VOID
         ENDPROC
         HIDDEN PROCEDURE Parent_Play(Game AS Integer) AS VOID
         ENDPROC
         HIDDEN PROCEDURE Parent_ReadBedTimeStory(BookTitle AS String) AS VOID
         ENDPROC
      
    ENDDEFINE

This looks like a lot of work! However as shown below, Visual FoxPro 7’s Object Browser makes this an easy task. If you drag an interface from the Object Browser onto a prg file or the Command Window, VFP7 automatically generates all of the IMPLEMENTS code for you!

 

Early Binding with GETINTERFACE()

As mentioned earlier, a client can use the QueryInterface method to determine if a COM object implements a particular interface. However, late-binding clients (such as Visual FoxPro 6) cannot use QueryInterface to natively access an interface. So how do late-binding clients access COM components? It’s by means of the IDispatch interface created by the Visual Basic group at Microsoft. The IDispatch interface enables high-level languages to access COM services (show in Object Browser). The downside of using IDispatch is that it’s slower than using early-binding. In addition, some COM interfaces are simply not accessible via IDispatch.

Enter VFP7’s GETINTERFACE() command! GETINTERFACE allows Visual FoxPro clients to access COM interfaces by means of early binding! GETINTERFACE performs a QueryInterface on a COM object to see if it supports a specified interface. If it does, GETINTERFACE returns it as a Visual FoxPro object.

Syntax

GETINTERFACE(oObject [, cIID | cInterface [, cTypelib | c])

Returns: Object (interface) reference

 

Arguments

    oObject                 COM object reference. It can be either early or late binding object.

    cIID                        The Interface ID GUID of the specified CLSID / when creating early binding instance

    cInterface            the interface name

    cTypeLib              Name of type library

    c                Name of to lookup type library

 

Remarks

  •  If no second parameter is passed, the object returned is an early binding (non IDispatch) object reference of the object passed.

  •   If a second parameter is passed, the object returned is that of specified interface.

  • If a native VFP object reference (or any non COM one) is passed, an error will occur.

  • If early binding object is passed as first parameter, a second parameter must be passed, otherwise an error will occur.

  • You can pass "IDispatch" as the cInterface parameter to convert object back to late binding.

  •  The 3rd parameter is needed if the interface isn't found in the typelib of the object. You can specify a different typelib (e.g., in the case of a Fox server doing an IMPLEMENTS).

COM Event Binding

There are two main types of COM interfaces—Incoming and Outgoing. Incoming interfaces consist of properties and methods that are accessed by clients. The term “incoming” is used because this type of interface allows objects to receive incoming messages from their clients.

However, when building COM applications there are times when you need a COM object to send messages to a client when something has happened. This requires an “outgoing” interface that consists of events exposed by a class. It also requires the ability to connect objects.

VFP7’s EventHandler()

In Visual FoxPro 6, VFPCOM.dll introduced the BindEvents() command that provided the ability to bind a Visual FoxPro client object to the outgoing interface of a COM Server. In Visual FoxPro 7, this capability has been brought directly into the product in the form of the EVENTHANDLER command.

The EVENTHANDLER command syntax is:

    EVENTHANDLER(oCOMObject, oVFPObject [,lUnbind])

The first parameter contains a reference to the COM object whose events you want to bind. The second parameter contains a reference to the Visual FoxPro “event sink” object. This object must implement the events interface of the COM object to which it is bound.

For example, if you want to bind a VFP object to an ADO RecordSet’s events, you need to include the following code in the object’s class definition:

    DEFINE CLASS ADOEventSink AS Custom
     
    IMPLEMENTS RecordsetEvents IN "adodb.recordset"
     
    PROCEDURE Recordsetevents_WillChangeField(cFields AS Number @, Fields AS VARIANT @, adStatus AS VARIANT @, pRecordset AS VARIANT @) AS VARIANT
     
    PROCEDURE Recordsetevents_FieldChangeComplete(cFields AS Number @, Fields AS VARIANT @, pError AS VARIANT @, adStatus AS VARIANT @, pRecordset AS VARIANT @) AS VARIANT
     
    PROCEDURE Recordsetevents_WillChangeRecord(adReason AS VARIANT @, cRecords AS Number @, adStatus AS VARIANT @, pRecordset AS VARIANT @) AS VARIANT
     
    PROCEDURE Recordsetevents_RecordChangeComplete(adReason AS VARIANT @, cRecords AS Number @, pError AS VARIANT @, adStatus AS VARIANT @, pRecordset AS VARIANT @) AS VARIANT
     
    PROCEDURE Recordsetevents_WillChangeRecordset(adReason AS VARIANT @, adStatus AS VARIANT @, pRecordset AS VARIANT @) AS VARIANT
     
    PROCEDURE Recordsetevents_RecordsetChangeComplete(adReason AS VARIANT @, pError AS VARIANT @, adStatus AS VARIANT @, pRecordset AS VARIANT @) AS VARIANT
     
    PROCEDURE Recordsetevents_WillMove(adReason AS VARIANT @, adStatus AS VARIANT @, pRecordset AS VARIANT @) AS VARIANT
     
    PROCEDURE Recordsetevents_MoveComplete(adReason AS VARIANT @, pError AS VARIANT @, adStatus AS VARIANT @, pRecordset AS VARIANT @) AS VARIANT
     
    PROCEDURE Recordsetevents_EndOfRecordset(fMoreData AS LOGICAL @, adStatus AS VARIANT @, pRecordset AS VARIANT @) AS VARIANT
     
    PROCEDURE Recordsetevents_FetchProgress(Progress AS Number @, MaxProgress AS Number @, adStatus AS VARIANT @, pRecordset AS VARIANT @) AS VARIANT
     
    PROCEDURE Recordsetevents_FetchComplete(pError AS VARIANT @, adStatus AS VARIANT @, pRecordset AS VARIANT @) AS VARIANT
     
    ENDDEFINE

Again, VFP7’s Object Browser easily creates the implementation code for you. Just drag and drop the desired interface onto a prg file and VFP7 does the rest.

Here are some additional features of event binding:

  • Multiple COM objects can be bound to a single VFP event sink object.
  • A single COM object can be bound to multiple VFP objects 
  •  Event handling is automatically unbound when either object is released.

VFP7 and Outgoing Interfaces

Although Visual FoxPro supports incoming interfaces, since it does not support the ability to raise events, it does not support outgoing interfaces. This means that you cannot directly bind a client object to a Visual FoxPro COM component.  Although this may seem like a serious limitation, the ability to support COM+ Events mitigates this problem.

COM+ Loosely Coupled Events

One of the greatest benefits of VFP7’s ability to implement interfaces is that Visual FoxPro COM components can participate in COM+ Events.

COM+ Events is a COM+ service that allows components (Publishers) to send notifications to other components (Subscribers).  COM+ Events provide asynchronous communication between components. Publishers and Subscribers do not have to be active at the same time. Based on this premise, COM+ Events are also referred to as “Loosely Coupled Events”.

To implement COM+ Events you need the following:

  • An Event class that contains one or more Event interfaces
  • A Publisher that fires an event by calling a method on one of the Event class’ interfaces
  • A Subscriber that implements one or more of the Event interfaces in the Event class.

As you can see, COM+ Events rely on the ability of components to implement interfaces. Since this ability has been added to Visual FoxPro 7, it makes Visual FoxPro a player in the COM+ arena.

For more information on Visual FoxPro 7 and COM+ Events, check out the samples that the Fox team has provided with the latest release.

Miscellaneous Automation Server Enhancements

Passing Parameters by Reference

By default, strong typed parameters are passed by value.You can specify that a strong typed parameter is passed by reference by including an “@” after the type information. For example:


    DEFINE CLASS Math AS Custom OLEPUBLIC
       FUNCTION IncrementValue(Value AS Integer @) ;
        HELPSTRING "Increments the value passed by reference"
           Value = Value + 1
       ENDFUNC
    ENDDEFINE

New Foxruntime Registry Key Identifier

The new Foxruntime registry key identifier allows you to easily find all registered VFP Servers and easily identify the runtime they are using.

 

 

 


SYS(2336) Support for “Critical Section”

The new SYS(2336) command provides access to the EnterCriticalSection and LeaveCriticalSection Windows API calls from multithreaded servers.

SYS(2336 [,nAction)]

NAction Value

Description

Not specified

Returns the current refcount

1

Calls EnterCriticalSection

2

Calls LeaveCriticalSection

3

Calls LeaveCrticialSection as many times as necessary to reduce refcount to zero, thereby freeing the critical section

For more information on EnterCriticalSection and LeaveCriticalSection API calls, check out the following:

http://msdn.microsoft.com/isapi/msdnlib.idc?theURL=/library/sdkdoc/winbase/synchro_3xym.htm

 

vorheriger Vortrag D-OUT

zur Übersicht der Gruppe COM

nächster Vortrag D-OLE

 

dFPUG c/o ISYS GmbH

Frankfurter Str. 21 b

 

D-61476 Kronberg

per Fax an:

+49-6173-950903

oder per e-Mail an:

konferenz@dfpug.de

© Texte, Grafiken und Inhalt: ISYS GmbH