C Support in Visio

3 4

The Automation interfaces on Microsoft Visio objects are defined in Visio.h, which is in \Libraries\C-CPP\Vao.inc on the Developing Microsoft Visio Solutions CD. This file contains a standard COM interface definition for each Visio object. To control a Visio instance through Automation from a C++ program, include Visio.h in your project source files.

Microsoft Visio also provides services in the form of wrapper classes that simplify programming Visio using C++. A wrapper class is so called because it encapsulates, or "wraps" the code involved in certain tasks, such as getting and releasing interface pointers and working with strings. The basic benefit of using these classes is that they keep track of AddRef and Release calls for you, using C++ constructors, destructors, and assignment operators. When appropriate, these wrapper classes also automatically wrap any arguments or return values with a wrapper class.

In addition to the files you'll use in your programs, the C-CPP folder on the Developing Microsoft Visio Solutions CD contains sample projects that illustrate the use of wrapper classes and event sinks. The Readme.txt file in the C-CPP folder gives more details on its contents and instructions on how to build the sample projects. You might find it helpful to study these projects before developing your own programs.

Using the Wrapper Classes

To use the wrapper classes, include Visiwrap.h in your project source files. This file is provided with Visio in the \Libraries\C-CPP\Vao_inc folder on the Developing Microsoft Visio Solutions CD. If you include Visiwrap.h, you do not need to include Visio.h explicitly, because Visiwrap.h includes it for you. The wrapper classes observe the following conventions:

  • Wrapper class names use the CVisio prefix. For example, the wrapper class for a Page object is CVisioPage.
  • Properties are accessed through methods that use the get prefix to read the property or put to set the property. For example, the methods for the Name property are getName and putName. (In Visio.h, the corresponding methods include an underscore between the prefix and the method name: get_Name and put_Name.) To find out what these methods do, see the Name property in the Microsoft Visio Developer Reference (on the Help menu, click Developer Reference).

A program that uses the Visio wrapper classes might include a code fragment similar to the following example. This program, from the sample Generic.cpp, creates a new document based on Sample.vst, drops two masters, and connects them. The function vaoGetObjectWrap, defined in Visiwrap.h, gets the Visio instance if one is running and, if not, runs an instance. For conciseness, error handling has been omitted.

This example also uses the helper classes VBstr and VVariant, which are defined in Helpers.h.

  • VBstr A class that simplifies working with BSTR variables, which are used to pass strings through Automation.
  • VVariant A class that simplifies working with VARIANT variables, which are the Automation counterparts of C++ unions.
 HRESULT     hr= NOERROR; CVisioApplicationapp; CVisioDocuments   docs; CVisioDocument    doc; CVisioPagespages; CVisioPage  page; CVisioShapeshape; CVisioShapeshape1; CVisioMasters     masters; CVisioMaster      master; CVisioDocument    stencil; CVisioCell  cell; CVisioCell  cell1;       ...       if (VAO_SUCCESS != vaoGetObjectWrap(app))             //Error handling             goto CU;       ...       //Add a new document based on "sample.vst"        //and get the drawing page       hr= app.Documents(docs);       //VBstr is the helper class for type BSTR       hr= docs.Add(VBstr("sample.vst"), doc);       hr= doc.Pages(pages);       //VVariant is the helper class for type VARIANT       hr= pages.Item(VVariant(1L), page);       //Get the stencil and the first master to drop       hr= docs.Item(VVariant("sample.vss"), stencil);       hr= stencil.Masters(masters);       hr= masters.Item(VVariant("Executive"), master);       hr= page.Drop(master, 6.0, 6.0, shape);       //Get the second master and drop it       hr= masters.Item(VVariant("Position"), master);       hr= page.Drop(master, 3.0, 3.0, shape1);       //Connect the two shapes on the drawing page       hr= shape.Cells(VBstr("Connections.X4"), cell);       hr= shape1.Cells(VBstr("Controls.X1"), cell1);       hr= cell1.GlueTo(cell); ... } 

Visiwrap.h includes Helpers.h, so if you're using the wrapper classes, you can use the helper classes also. For details about the helper classes, see the comments in Helpers.h.

The Interfaces Behind the Wrappers

The Visio.h file defines the objects exposed by Visio in standard COM interface declaration syntax. The wrapper classes defined in Visiwrap.h call the methods of these interfaces. For example, the following code fragment shows the beginning of the CVisioApplication wrapper class declared in Visiwrap.h. Notice the method declarations of ActiveDocument, ActivePage, and so on following the second VW_PUBLIC access specifier.

 class FAR CVisioApplication : public CVisioUnknown { VW_PUBLIC:       CVisioApplication( ) : CVisioUnknown( ) { }       CVisioApplication(const CVisioApplication& other) : CVisioUnknown(other) { }       CVisioApplication(const IVApplication FAR * other, BOOL _             bAssumeResponsibility= FALSE)             : CVisioUnknown( ( LPUNKNOWN )other, bAssumeResponsibility ) { }       const CVisioApplication FAR & operator=( const CVisioApplication FAR &other )             { if ( &other != this )                   CopyIP( other.GetUnknown( ) );                   return *this; }       const CVisioApplication FAR & operator=( const IVApplication FAR * other )             { if ( ( LPUNKNOWN )other != GetUnknown( ) )                   CopyIP( ( LPUNKNOWN )other );                   return *this; }       virtual ~CVisioApplication( ) { }       IVApplication FAR * GetIP( ) const { return ( IVApplication FAR * ) _             GetUnknown( ); }       operator IVApplication FAR * ( ) { return ( IVApplication FAR * ) GetUnknown( ); } //CVisioApplication method declarations VW_PUBLIC:        HRESULT ActiveDocument(CVisioDocument FAR &rWrap);       HRESULT ActivePage(CVisioPage FAR &rWrap);       HRESULT ActiveWindow(CVisioWindow FAR &rWrap);       HRESULT Application(CVisioApplication FAR &rWrap);       HRESULT Documents(CVisioDocuments FAR &rWrap); ... 

The corresponding methods in the Application object interface are declared in Visio.h, as follows:

 IVApplication : public IDispatch {       public:       virtual /* [helpcontext][propget][id] */ HRESULT STDMETHODCALLTYPE _             get_ActiveDocument(              /* [retval][out] */ IVDocument __RPC_FAR *__RPC_FAR *lpdispRet) = 0;       virtual /* [helpcontext][propget][id] */ HRESULT STDMETHODCALLTYPE _             get_ActivePage(              /* [retval][out] */ IVPage __RPC_FAR *__RPC_FAR *lpdispRet) = 0;       virtual /* [helpcontext][propget][id] */ HRESULT STDMETHODCALLTYPE _             get_ActiveWindow(              /* [retval][out] */ IVWindow __RPC_FAR *__RPC_FAR *lpdispRet) = 0;       virtual /* [helpcontext][propget][id] */ HRESULT STDMETHODCALLTYPE _             get_Application(              /* [retval][out] */ IVApplication __RPC_FAR *__RPC_FAR *lpdispRet) = 0;       virtual /* [helpcontext][propget][id] */ HRESULT STDMETHODCALLTYPE _             get_Documents(              /* [retval][out] */ IVDocuments __RPC_FAR *__RPC_FAR *lpdispRet) = 0;       ...  }; 

Every object exposed by Visio has a similar declaration in Visio.h. Various macros in the declaration, which are not shown in this example, allow Visio.h to be included in either C or C++ source files.

Because every Visio interface derives from IDispatch, every Visio interface has the following methods:

  • QueryInterface
  • AddRef
  • Release (for IUnknown)

These methods are followed by:

  • GetTypeInfoCount
  • GetTypeInfo
  • GetIDsOfNames
  • Invoke (for IDispatch)

For details about these standard COM methods, see the Automation documentation in the Microsoft Platform Software Development Kit (SDK) on MSDN (msdn.microsoft.com). The Visio Application object exposes the remaining methods (get_ActiveDocument, get_ActivePage, and so forth). These methods correspond to the methods and properties described elsewhere in this guide for use with Microsoft Visual Basic programs.

To learn more about a method, see the Microsoft Visio Developer Reference (on the Help menu, click Developer Reference). For example, to find more about the get_ActiveDocument method declared in the previous example, search for "ActiveDocument."

Obtaining a Visio Application Object

The sample program in Generic.cpp, which is shown in the section Using the Wrapper Classes, begins with the following code:

 CvisioApplicationapp; if (VAO_SUCCESS != vaoGetObjectWrap(app))       //Error handling       goto CU; 

This pebble starts the avalanche. To do anything with a Visio instance, you need an Application object, which is what vaoGetObjectWrap gets.

The vaoGetObjectWrap function calls the vaoGetObject function, which is declared in Ivisreg.h and implemented in Ivisreg.cpp. If you're not using the wrapper classes, you can call vaoGetObject directly. Look at the source code to see what vaoGetObject actually does.

The services defined in Ivisreg.h for working with a Visio instance are equivalent to those provided by the Visreg.bas file, which is supplied for use with Visual Basic. In particular, these files provide the necessary means to launch a new Visio instance or establish an Application object for the active Visio instance.

Values Returned by Visio Methods

Every method declared in Visio.h is specified to return an HRESULT that indicates whether the method executed successfully. The HRESULT returned by a method declared in Visio.h is passed along by the equivalent method of the corresponding wrapper class defined in Visiwrap.h.

If a method succeeds, it returns NOERROR. A common practice is to check a method's result by using SUCCEEDED(hResult). The sample program includes a macro called check_valid to check the result of the method. This macro is shown later in this section. Many methods also produce an output value that is independent of the HRESULT returned by every method. For example, the ActiveDocument method of the CVisioApplication wrapper class produces a reference to a Document object. By convention, a method's output value is written to the method's last argument. Thus the last argument passed to ActiveDocument is a reference to a CVisioDocument object, where the method can write a reference to the Document object.

To learn more about Visio methods, see the Microsoft Visio Developer Reference (on the Help menu, click Developer Reference).

Object reference return values

Many methods return an object reference as their output value. This value is really a COM interface pointer, which, like any interface pointer, must eventually be released.

  • If you're using wrapper classes, the value returned is an object of another wrapper class—such as the CVisioDocument previously mentioned—in which the interface pointer is packaged. When the object goes out of scope, the Visio interface pointer it holds is automatically released.
  • If you're not using wrapper classes, the interface pointer is held directly by your program, which must explicitly release the pointer at the appropriate time.

If a method that returns an object reference fails, the output value again depends on whether you're using wrapper classes.

  • If you're using wrapper classes, you'll still get an object of the appropriate wrapper class, but the interface pointer held by the object is NULL. Calling the IsSet function on that object will return FALSE.
  • If you're not using wrapper classes, the interface pointer is NULL, so you can simply check for that.

Even if the method succeeds, you might still need to check the output parameter. For example, if ActiveDocument is called when no documents are open, it returns an HRESULT of success and a NULL interface pointer (wrapped or not). The reasoning here is that an error did not occur—having no documents open is a perfectly valid state for which the caller should account. The various Active* methods behave in this manner, and you should verify that their output values are not NULL before proceeding. The various Item and Add methods, however, always return a non-NULL reference if they succeed.

The check_valid macro, defined in Generic.cpp, checks both possibilities. A function using check_valid must provide a CU label where it performs cleanup tasks.

 #define check_valid(hr, obj)  \ if(!SUCCEEDED(hr) || !((obj).IsSet()))    \ goto CU; 

String return values

Several methods return a string to the caller. The Shape object's Name property (getName of CVisioShape or get_Name of IVShape) is an example. All strings passed to or returned by Visio methods are of type BSTR, which consists of 16-bit (wide) characters in Microsoft Win32 programs. The Visio engine allocates the memory for the strings it returns, and the caller is responsible for freeing the memory.

The wrapper classes, defined in Visiwrap.h, take care of freeing memory for strings. If you do not use the wrapper classes, however, make sure that you call SysFreeString to free any string returned by a Visio instance.

Arguments Passed to Visio Methods

Passing arguments to Visio methods is straightforward:

  • Integer arguments are declared as short or long, depending on whether they are 2-byte or 4-byte values.
  • Floating-point arguments are declared as double.
  • Boolean values are passed as short integers or as VARIANT_BOOL.
  • Arguments that are object pointers, such as BSTR or VARIANT, merit further discussion.

Object pointer arguments

Some methods take object pointers, and some require a pointer to a specific type of Visio object. The Cell object's GlueTo method, for example, takes an argument that must refer to another Cell object.

Other methods that take object pointers are more lenient. For example, the Page object's Drop method takes a reference to the object to be dropped, because you might want to drop a master or a shape on a page.

The simplest way to pass an object pointer to a method is to pass a reference to an object of the appropriate wrapper class; for example, pass a reference to a CVisioCell object as an argument to the GlueTo method.

The interfaces defined in Visio.h declare object pointers as the corresponding interfaces. For example, Visio.h declares GlueTo as taking a pointer to an IVCell interface. Because the Drop method is not restricted to a particular object, Visio.h declares Drop to take an IUnknown interface, which means Drop takes a reference to any object. Internally, the Drop method determines what to drop by querying the object passed to it for an IDataObject interface. The interface you pass to Drop does not necessarily have to be an interface on a Visio object.

String arguments

Any string passed to a Visio instance must be of type BSTR. The helper class VBstr, defined in Helpers.h, is a convenient way to pass strings to Visio instances. VBstr allocates memory for the string when it is created and frees the memory when the VBstr is destroyed. If you don't use VBstr, make sure that you call SysFreeString to free the memory you have allocated for strings.

For example, the following statement uses a VBstr to pass a cell name to the Cells method of a CVisioShape object. In this statement, cell is a variable of type CVisioCell :

 hr = shape.Cells(VBstr("Connections.X4"), cell); 

VARIANT arguments

Some Visio methods take arguments that aren't constrained to a single type. For example, if you pass an integer 5 to the Item method of a Documents collection, it returns a reference to the fifth document in the collection. If you pass a string that is a document name to the same method, however, it returns a reference to a document of that name (assuming that the document is open).

COM defines a data structure known as a VARIANT for passing such arguments. The helper class, VVariant defined in Helpers.h, is a convenient way of passing a VARIANT to a Visio instance. For example, compare the following two statements:

 hr = pages.Item(VVariant(1L), page); hr = masters.Item(VVariant("Position"), master); 

The first statement passes 1 (an integer) to the Item method of a Pages collection. The second statement passes "Position" (a string) to the Item method of a Masters collection. In these statements, page and master are variables of type CVisioPage and CVisioMaster, respectively.



Developing Microsoft Visio Solutions 2001
Developing Microsoft Visio Solutions (Pro-Documentation)
ISBN: 0735613532
EAN: 2147483647
Year: 2004
Pages: 180

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net