Session E-AutoVisual FoxPro 7 Automation
|
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 |
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.
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.
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:
5. Click the OK button to save changes, then compile a new dll to apply the new descriptions to the Automation server.
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:
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.
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. |
You can also set multiple attribute flags for a single property or method:
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!
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:
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.
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.
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.
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.
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:
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:
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!
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.
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).
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.
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:
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:
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:
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.
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:
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.
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:
The new Foxruntime registry key identifier allows you to easily find all registered VFP Servers and easily identify the runtime they are using.
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
dFPUG c/o ISYS GmbH Frankfurter Str. 21 b
D-61476 Kronberg |
per Fax an: +49-6173-950903 oder per e-Mail an: |
© Texte, Grafiken und Inhalt: ISYS GmbH |