contents   index   previous   next



Obtaining an interface to a running Automation server

 

In many cases rather than create a new object in your application you may want to control an object that is already running or has been created by another application. Automation servers that allow this type of access register their running objects with OLE to indicate that the objects are loaded in memory. f90VB provides function GetActiveOleObject that can check the OLE’s table of running objects for a specific Automation server. If the server is loaded, GetActiveOleObject returns a pointer to its IDispatch interface. This process is illustrated in Example 6.2. The program implements a simple search/replace utility that can be used to change the text of the active document in Word. Obviously, attempting to run this utility when you don’t have an open Word document wouldn’t make any sense, so instead of creating a new instance of Word the example requests an interface to the Word instance that is currently running.

 

 

 

 

 

Example 6.2

 

program Example62

 

!Example shows how to use f90VB to automate Word

!Copyright (C) 1999-2000, Canaima Software, Inc.

!Illustrates:

!   - Creating an new object

!   - Getting an interface to an active object

!   - Setting/retrieving property values

!   - Executing object methods

!  - Passing optional arguments to a method   

 

use f90VBDefs

use f90VBBStrings

use f90VBVariants

use f90VBAutomation

implicit none

 

!Variants containing main objects

type(VARIANT)::Word, Document, SelObj

!Variants used to stored temporal objects and collections

type(VARIANT)::VarTmp

 

integer(HRESULT_KIND)::iRet

character(len=255)::TmpStr

type(VARIANT)::WrdToFind,WrdReplace

type(EXCEPINFO)::EInfo

 

!Initialize Ole

iRet = OleInitialize()

 

!If Word is already running, then get an interface

!to the running instance. Otherwise exit with 

!an error message

Word = GetActiveOleObject('Word.Application',iRet)

if (iRet.ne.S_OK) goto 900

 

!Get a reference to the active document. If there

!is no active document, exit with an error message

Document=PropertyGet(Word,'ActiveDocument', EInfo=EInfo, iRet=iRet)

if (iRet.ne.S_OK) goto 1000

 

!read the words to find and replace

print *,'Enter the word to replace:'

read(*,*) TmpStr

WrdToFind = VariantCreate(VT_BSTR,trim(TmpStr))

print *,'Enter the word to use as replacement:'

read(*,*) TmpStr

WrdReplace = VariantCreate(VT_BSTR,trim(TmpStr))

 

!Get a find/replace object for the whole document

SelObj = PropertyGet(Document,'Content.Find', EInfo=EInfo, iRet=iRet)

if (iRet.ne.S_OK) goto 1000

 

!Set the text to find

call PropertyPut(SelObj,'Text',WrdToFind, EInfo=EInfo,iRet=iRet)

if (iRet.ne.S_OK) goto 1000

 

!Set the text to use as replacement

call PropertyPut(SelObj,'Replacement.Text',WrdReplace, &

                 EInfo=EInfo, iRet=iRet)

if (iRet.ne.S_OK) goto 1000

 

!Execute the find/replace for all occurrences of the word to replace

!(i.e. pass the value 2 in argument 11 of the method

VarTmp = ExecMethod(SelObj,'Execute',EmptyParam(),EmptyParam(), &

                    EmptyParam(),EmptyParam(),EmptyParam(),EmptyParam(), &

                    EmptyParam(),EmptyParam(),EmptyParam(),EmptyParam(), &

                    VariantCreate(VT_INT,2),EInfo=EInfo,iRet=iRet)

if (iRet.ne.S_OK) goto 1000

 

!We are done

goto 2000

 

 

900  continue

 

     print *,'You must have an instance of Word for Windows'

     print *,'running for this example to work'

    

1000 continue

 

     print *, 'The following Errors were detected:'

     print *, 'HRESULT:',iRet

     call StrCopy(EInfo%bstrDescription,TmpStr)

     print *,TmpStr

 

2000 continue

 

!clear variants containing BStrings

call VariantClear(WrdToFind)

call VariantClear(WrdReplace)

call ExceptionClear(Einfo)

!release references to objects

call Release(SelObj)

call Release(Document)

call Release(Word)

 

!Uninitialize Ole

call OLEUninitialize()

 

stop

end

 

 

As you have probably noticed, there are many new things in this example that we have not explained yet. Don’t worry, we’ll go through them in the following sections. At this point, what is important is that you see how function GetActiveOleObject was used, instead of CreateOleObject.

 

The other point worth mentioning is that this is the first time we use function PropertyGet. This function requests the value of an object’s property. It works in a similar way to PropertyPut. The first argument is the variant containing the object reference, the second argument is the name of the property. If this is an indexed property, then you can pass the index(es) as the third, forth, etc. arguments. Property values are always returned as variants. Properties can be normal numbers, but many objects also return other objects as properties. This is explained in more detail in the section that discusses collections and object hierarchies.

 

Obtaining information about errors and exceptions