前のトピック     次のトピック

第 27 章 C++ による VISIO アプリケーションのプログラミング

セクション 2   Visio 製品による C++ のサポート

Visio® のオブジェクトのオートメーション インターフェースは、\DVS\Libraries\C-CPP\Vao_incにある Visio.h に定義されています。このヘッダー ファイルでは、各 Visio オブジェクトの標準 OLE インターフェースが定義されています。C++ プログラムでオートメーションを使って Visio インスタンスを制御するには、作成するプロジェクトのソース ファイルに Visio.h をインクルードします。

また、Visio 2000 では、C++ を使った Visio アプリケーションのプログラミングを簡単にするために、ラップ クラス形式でサービスが提供されています。ラップ クラスは、インターフェース ポインタの取得と解放、文字列の処理などの特定の処理に関係するコードをカプセル化 (ラップ) します。これらのクラスの主な利点は、C++ のコンストラクタ、デストラクタ、および代入演算子を使って AddRefRelease への呼び出しを追跡できることです。また、これらのラップ クラスは、任意の引数または戻り値を自動的にラップ クラスにラップします。

\C-CPP フォルダには、プログラムで使用するファイルのほかに、ラップ クラスおよびイベント シンクの使い方を示すサンプル プロジェクトがあります。このフォルダにある Readme.txt には、このフォルダの内容に関する詳細と、サンプル プロジェクトの作成方法が示されています。実際のプログラムの開発を開始する前に、サンプル プロジェクトで学習しておくと役に立ちます。

このセクションの内容...

ラップ クラスの使用

ラップ クラスのインターフェース

Visio の Application オブジェクトの取得

Visio のメソッドの戻り値

Visio のメソッドに渡される引数

ラップ クラスの使用

ラップ クラスを使用するには、プロジェクトのソース ファイルに Visiwrap.h をインクルードします。このファイルは、Visio 製品の \DVS\Libraries\C-CPP\Vao_inc フォルダにあります。Visiwrap.h には Visio.h がインクルードされているため、ソース ファイルに Visio.h のインクルード文を追加する必要はありません。ラップ クラスは、次の命名規則に従います。

Visio のラップ クラスを使用するプログラムは、下の例のようなコードを含みます。サンプルの Generic.cpp から生成されたこのプログラムは、Sample.vst を基に新規の図面を作成し、2 つのマスタシェイプをドロップし、それを結合します。Visiwrap.h で定義されている関数 vaoGetObjectWrap は、Visio のインスタンスが実行されていればインスタンスを取得し、実行されているインスタンスがなければインスタンスを実行します。ここでは、エラー処理は省略しています。

この例ではまた、ヘルパ クラス VBstr および VVariant が使用されています。これらのクラスは Helpers.h で定義されています。

     HRESULT           hr = NOERROR;
     CvisioApplication app;
     CvisioDocuments   docs;
     CvisioDocument    doc;
     CvisioPages       pages;
     CvisioPage        page;
     CvisioShape       shape;
     CvisioShape       shape1;
     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 には Helpers.h がインクルードされているので、ラップ クラスを使用する場合は、ヘルパ クラスも使用できます。ヘルパ クラスの詳細については、Helpers.h のコメントを参照してください。

TOP へ

ラップ クラスのインターフェース

Visio.h ファイルでは、Visio によって公開されるオブジェクトが、標準的な OLE インターフェース宣言の構文で定義されています。Visiwrap.h で定義されているラップ クラスは、これらのインターフェースのメソッドを呼び出します。たとえば、Visiwrap.h 内の CVisioApplication ラップ クラスの宣言は、以下のようなコードで始まります。2 番目の VW_PUBLIC アクセス指定子の後に ActiveDocumentActivePage などのメソッドも宣言されています。

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);
...

Application オブジェクト インターフェース内の対応するメソッドは、Visio.h で、次のように宣言されています。

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;
     ...
};

Visio によって提供されるすべてのオブジェクトは、Visio.h の中で同じように宣言されています。この例では示していませんが、宣言内には、C または C++ ソース ファイルで Visio.h をインクルード可能にするためのさまざまなマクロがあります。

すべての Visio インターフェースは IDispatch インターフェースから派生するので、各 Visio インターフェースには以下のメソッドがあります。

これらのメソッドの後に以下のメソッドが続きます。

これらの標準的な OLE メソッドの詳細についは、OLE のマニュアルを参照してください。Visio の Application オブジェクトは、get_ActiveDocumentget_ActivePage などのほかのメソッドを公開します。これらのメソッドに対応する Microsoft Visual Basic プログラムのメソッドとプロパティは、このガイドのほかの章で説明されています。

メソッドの詳細については、Visio 製品付属のオンラインヘルプ「開発者用リファレンス」を参照してください。たとえば、前の例で宣言されている get_ActiveDocument メソッドの詳細については、「ActiveDocument」を検索してください。

TOP へ

Visio の Application オブジェクトの取得

ラップ クラスの使用のセクションで名前が出た Generic.cpp のサンプル プログラムは、次のようなコードで始まります。

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

このステートメントによって処理が開始されます。Visio インスタンスを使った処理を行う場合、Application オブジェクトが必要です。Application オブジェクトを取得するには、vaoGetObjectWrap を使用します。

vaoGetObjectWrap 関数は vaoGetObject 関数を呼び出します。vaoGetObject 関数は Ivisreg.h 内で宣言され、Ivisreg.cpp 内に実装されています。ラップ クラスを使用しない場合、vaoGetObject を直接呼び出します。vaoGetObject が行う処理については、ソース コードを参照してください。

Ivisreg.h で Visio インスタンスを操作するために定義されているサービスは、Visual Basic 用の Visreg.bas ファイルによって提供されるサービスと同じです。特に、これらのファイルは、新しい Visio インスタンスを作成したり、アクティブな Visio のインスタンスを表す Application オブジェクトを取得するための手段を提供します。

TOP へ

Visio のメソッドの戻り値

Visio.h で宣言されているすべてのメソッドは、メソッドが正常に実行されたかどうかを示す HRESULT を返します。Visio.h で宣言されているメソッドが返す HRESULT は、Visiwrap.h で定義されているラップ クラスの対応するメソッドによって渡されます。

メソッドが正常に実行された場合、NOERROR が返されます。通常、メソッドの結果 (HRESULT) を確認するには、SUCCEEDED (hResult) を使用します。サンプル プログラムでは、check_valid というマクロでメソッドの結果を確認しています。このマクロについては、後で説明します。

すべてのメソッドは HRESULT を戻しますが、そのうちの多くは別の値も返します。たとえば、CVisioApplication ラップ クラスの ActiveDocument メソッドは、Document オブジェクトへの参照を返します。慣例として、メソッドの出力値はそのメソッドの最後の引数に書き込まれます。たとえば、ActiveDocument メソッドの最後の引数には、CVisioDocument オブジェクトへの参照を指定します。すると、ActiveDocument メソッドは、この引数に Document オブジェクトへの参照を書き込んで返します。

オブジェクト参照の戻り値

多くのメソッドは出力値としてオブジェクト参照を返します。この値は実際には OLE インターフェース ポインタであり、他のインターフェース ポインタと同様に、不要になったら解放しなければなりません。

オブジェクト参照を返すメソッドが失敗した場合の出力値も、ラップ クラスを使用しているかどうかによって異なります。

メソッドが正常に実行された場合でも、出力値を確認しなければならない場合があります。たとえば、開いている図面がないときに ActiveDocument メソッドが呼び出された場合、ラップ クラスを使用しているかどうかにかかわらず、正常に実行されたことを示す HRESULT と NULL インターフェース ポインタが返されます。開いている図面がないのは正常であり、通常起り得る状態なので、エラーは発生しません。多くの Active* メソッドがこのように動作します。したがって、次の処理に移る前に、その出力値が NULL でないことを確認しておく必要があります。ただし、多くの Item メソッドおよび Add メソッドでは、正常に実行されたときには、NULL ではない参照値が常に返されます。

Generic.cpp で定義されている check_valid マクロは、出力値 (インターフェース ポインタ) と戻り値 (HRESULT) の両方をチェックします。check_valid を使用する関数では、CU ラベルで示される箇所に適切な後処理を記述する必要があります。

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

文字列の戻り値

文字列を返すメソッドもあります。たとえば、Shape オブジェクトの Name メソッド (CVisioShape オブジェクトの getNameIVShape オブジェクトの get_Name) がその一例です。Visio のメソッドで扱うすべての文字列引数は BSTR 型として宣言します。これは Microsoft Win32 プログラムでは 16 ビット (ワイド) 文字で構成されています。Visio エンジンは返される文字列にメモリを割り当てます。呼び出し側では、そのメモリを解放する必要があります。

Visiwrap.h で定義されているラップ クラスを使う場合は、文字列に割り当てられたメモリは自動的に解放されます。ラップ クラスを使用しない場合は、SysFreeString を呼び出して、Visio インスタンスから返された文字列を解放しなければなりません。

TOP へ

Visio メソッドに渡される引数

Visio メソッドに引数を渡す方法は簡単です。

オブジェクト ポインタ引数

メソッドの中には、オブジェクト ポインタを引数とするメソッドがあります。また、特定の Visio オブジェクトへのポインタを引数とするメソッドもあります。たとえば、Cell オブジェクトの GlueTo メソッドの引数には、別の Cell オブジェクトを参照するポインタを指定する必要があります。

オブジェクト ポインタを引数とするメソッドの中には、そのような制約のないものもあります。たとえば、Page オブジェクトの Drop メソッドには、図面ページにドロップするオブジェクトへの参照を引数として指定します。これは、ページにマスタシェイプをドロップする場合と図形をドロップする場合があり、どちらの場合にも対応できるようにするためです。

オブジェクト ポインタをメソッドに渡す最も簡単な方法は、適切なラップ クラスのオブジェクトへの参照を渡すことです。たとえば、GlueTo メソッドでは、CVisioCell オブジェクトの参照を引数として指定することができます。

Visio.h で定義されているインターフェースでは、対応するオブジェクト ポインタを、インターフェースと合わせて宣言します。たとえば Visio.h では GlueTo メソッドを IVCell インターフェースのへのポインタを引数とするメソッドとして宣言しています。Drop メソッドは、特定のオブジェクトによる制約がないので、Visio.h では IUnknown インターフェースを引数とするメソッドとして宣言されています。OLE では、これは Drop メソッドが任意のオブジェクトへの参照を引数として取ることを意味します。Drop メソッドは、渡されたオブジェクトを IDataObject インターフェースに照会して、何をドロップするかを判断します。Drop メソッドに渡すインターフェースは、Visio オブジェクトのインターフェースでなくてもかまいません。

文字列引数

Visio インスタンスに渡すすべての文字列は BSTR.型でなければなりません。Helpers.h で定義されているヘルパ クラス VBstr は、Visio インスタンスに文字列を渡す便利な方法です。VBstr は、文字列が作成されたときにメモリを割り当て、VBstr が廃棄されたときにメモリを解放します。VBstr を使用しない場合、必ず SysFreeString を呼び出して、文字列に割り当てたメモリを解放する必要があります。

たとえば、下のステートメントは、VBstr を使って CVisioShape オブジェクトの Cells メソッドにセル名を渡します。このステートメントでは、cell CVisioCell 型の変数です。

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

VARIANT 型引数

一部の Visio のメソッドでは、場合によって異なる型の引数を使用するものもあります。たとえば、Documents コレクションの Item メソッドに整数 5 を渡すと、コレクションの中の 5 番目の図面への参照が戻されます。また、同じメソッドに図面名の文字列を渡すと、その名前の図面への参照が戻されます (その図面が開いている場合)。

OLE では、そのような引数を渡すために、VARIANT 型というデータ構造体が定義されています。Helpers.h で定義されているヘルパ クラス VVariant は、VARIANT を Visio インスタンスに渡す便利な方法です。たとえば、次の 2 つのステートメントを比べてください。

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

最初のステートメントは、Pages コレクションの Item メソッドに整数値の 1 を渡しています。2 番目のステートメントは、Masters コレクションの Item メソッドに文字列 "Position" を渡しています。これらのステートメントの page および master はそれぞれ CVisioPage 型および CVisioMaster 型の変数です。

Top