A Dispatch Interface consists of a group of members deemed Methods and Properties. A Method is very similar to a normal function - it may take parameters and may return a result. A Property is more like a variable - it can hold a value or state.
A single Dispatch Interface can contain one or possibly hundreds of individual members.
PowerBASIC allows full access to Dispatch Interface members (Methods or Properties); however it is not possible to access a Property value directly. Rather, reading or writing a Property value has to be performed thorough the appropriate Interface Property member. This is similar to making a normal function call.
While this seems unusual compared with normal BASIC programming, it is actually an important principle of COM - only the Object itself can manipulate the data held within the Object's internal variables. This guarantees that the Object itself is wholly responsible for the movement of data in and out of the Object, providing an additional layer of security.
In addition to using the Property functions provided by the Interface, all return results and parameters passed from/to a Property (and a Method) must be performed using VARIANT variables.
Since Variants can be used to hold any type of data,
from bytes to string
arrays, they are the most convenient way to pass data between an application
and a COM Object. Additionally,
COM uses Unicode format for all
With these rules in mind, let's use some real code to demonstrate accessing Interface Methods and Properties exposed by Microsoft Word™.
The following code performs a number of steps. It starts off by attempting to reference an existing instance to Microsoft Word™ or starting a new instance if there is no existing one. Next, it counts the number of documents open in Word, adds a document, places some text in the document, saves the document, and finally, closes the document and Word itself.
The code uses early-binding, but the actual INTERFACE definitions are not shown due to their relatively large size. The #INCLUDE file used to compile this code was generated directly by the PowerBASIC COM Browser and saved as a .INC file. The code also uses the optional LET statement for the purposes of clarity, but this is not compulsory.
#COMPILE EXE
#INCLUDE "oword.inc"
FUNCTION PBMAIN()
DIM oWordApp AS WordApplication ' Application Interface
DIM oWordDoc AS WordDocument ' Document Interface
DIM oWordSel AS WordSelection ' Selection
DIM vBool AS VARIANT
DIM vText AS VARIANT
DIM vFile AS VARIANT
DIM vFileFmt AS VARIANT
DIM vVnt AS VARIANT
DIM sResult AS STRING
' Open an instance of MSWORD
LET oWordApp = WordApplication IN "Word.Application"
IF ISFALSE ISOBJECT(oWordApp) THEN _
LET oWordApp = NEW WordApplication IN "Word.Application"
' Could MSWORD be opened? If not, terminate this app
IF ISFALSE ISOBJECT(oWordApp) THEN EXIT FUNCTION
' Make MSWORD visible
LET vBool = 1
OBJECT LET oWordApp.Visible = vBool
' Get the current document count from the "documents collection"
LET vVnt = 0
OBJECT GET oWordApp.Documents.Count TO vVnt
sResult = "MSWORD has " + FORMAT$(VARIANT#(vVnt)) + _
" Files loaded!"
' Add a document to the "documents collection", and obtain a reference
' to the document Interface for the new document
LET vVnt = 0
OBJECT CALL oWordApp.Documents.Add TO vVnt
LET oWordDoc = vVnt
' Get the current document count from the "documents collection"
' This should be one value higher than before
LET vVnt = 0
OBJECT GET oWordApp.Documents.Count TO vVnt
sResult = "MSWORD has " + FORMAT$(VARIANT#(vVnt)) + _
" Files loaded!"
' Get the Interface to the correct selection of the document
OBJECT GET oWordApp.Selection TO vVnt
LET oWordSel = vVnt
' Enter some text into the document at the selection position
LET vText = "PowerBASIC controls Microsoft Word!"
OBJECT CALL oWordSel.TypeText(vText)
' Set a paragraph marker (end of paragraph)
OBJECT CALL oWordSel.TypeParagraph
' Another paragraph
LET vText = "COM client controls a COM server!"
OBJECT CALL oWordSel.TypeText(vText)
OBJECT CALL oWordSel.TypeParagraph
#IF %DEF(%PB_CC32)
PRINT "Press a key to continue the demo"
WAITKEY$
#ELSE
MSGBOX "Click to continue the demo", &H00002000& ' = %MB_TASKMODAL
#ENDIF
' Save the new document to disk
LET vFile = "Test.doc"
LET vFileFmt = %wdFormatDocument
OBJECT CALL oWordDoc.SaveAs(vFile, vFileFmt)
' Close the current document and then close MSWORD completely
OBJECT CALL oWordApp.ActiveWindow.Close
OBJECT CALL oWordApp.Quit
' Close all of the Interfaces
LET oWordSel = NOTHING
LET oWordDoc = NOTHING
LET oWordApp = NOTHING
END FUNCTION
As can be seen, this code performs minimal error testing or validation of the Interfaces returned. However, it still clearly shows some important concepts. For example, it clearly shows how the return result from several different Properties can return Interface references in the Variant TO variables. In these cases, the code assigns the references to object variables so that the returned Interfaces can be used with further OBJECT statements.
See Also