Chapter.23

リンクコンテナ(1)

2007/7/8
 ・サンプルソースのリンクオブジェクトに対してOleSetContainedObjectを呼び出していた問題を修正。

1.オブジェクトへのリンク

OLE(Object Linking And Embedding)の頭文字の1つであるリンクは、オブジェクトの埋め込みと同等、場合によってはそれ以上に重要な機能です。が、必要となる機能が多岐に渡るため、今までは解説を飛ばしてきました。この章からしばらくは、リンクとリンクに必要な機能について解説していきます。

リンクとはその名の通り、オブジェクトへの参照を保持することであり埋め込みオブジェクトとは以下の点が異なります。
 ・構造化ストレージファイルには、ファイルのパス等のオブジェクトの位置に関する情報とオブジェクトのイメージのみが保存される。
 ・ファイル全体ではなくファイルの一部をリンクすることが可能である。(埋め込みは構造化ストレージ単位)
 ・インプレースアクティベーションは不可能。
上記3点はそれぞれ密接に関連しています。ファイル全体を埋め込まないのでファイルの一部をリンクすることが可能であり、ファイルの一部をインプレース編集する機能をサーバに実装するのはコストが大きすぎるため、インプレースアクティベーションは不可能としています。実際のところリンクしたファイルを編集する場合、そのファイル専用のアプリケーションで編集するのが最も効率が良いと思われます。


2.基本的なリンクコンテナの実装

基本的なリンクコンテナの実装について述べます。前章までに解説した基本的な埋め込みコンテナにわずかなコードを追加すればリンクコンテナとしての実装が完了するため、先にサンプルを提示することにします。

VB.NETサンプルソース:chap23.vb.lzh (41KB 2007/7/8)
C#サンプルソース:chap23.cs.lzh (40KB 2007/7/8)

前章のサンプルからどのように改造してリンクコンテナを実装したかを解説していきます。

OleUIInsertObject
OLEUIINSERTOBJECTに設定するフラグを変更しています。具体的には、前章ではリンクを禁じるために指定していたIOF_DISABLELINKを削除しました。この結果、下図のようにリンクチェックボックスが追加されたダイアログが表示されるようになっています。
オブジェクトの挿入ダイアログ - ファイルからリンク
また、ダイアログが制御を返した時にインプロセスハンドラを起動するためIOF_CREATELINKOBJECTを追加しました。この章の時点では、リンクオブジェクトはOleUIInsertObjectダイアログでのみ作成できます。

IOleClientSite.GetMoniker
リンクを扱う上で重要となってくるのがモニカです。リンクオブジェクト(より正確にはインプロセスハンドラ)は、構造化ストレージファイルにリンクしたファイルの位置を保存しますが、この時リンクしたファイルのパスは絶対パスと相対パスの両方の形式で格納されます。そして、(インプロセスハンドラが)相対パスを作成するためには、ドキュメントの絶対パスが必要となります。インプロセスハンドラにドキュメントのパスを供給するため、コンテナはIOleClientSite.GetMonikerメソッドを実装し、コンテナ側のモニカ(ドキュメントを指すファイルモニカ)を返さなければなりません。

IOleObject.SetMoniker
ファイルに名前を付けて保存した場合、ドキュメントのパスが変わりリンクオブジェクトとの相対パスがずれてしまいます。リンクオブジェクトの相対パスを更新するため、ファイルのパスを変更した場合、IOleObject.SetMonikerを呼び出してドキュメントの変更後のパスを通知しなければなりません。

IOleLink
(標準の)インプロセスハンドラが実装するインターフェースです。コンテナはIOleLinkインターフェースのメソッドを直接呼び出す必要はほとんどありません。今回はオブジェクトがリンクオブジェクトか埋め込みオブジェクトかを判断するのに使用しています。オブジェクトサーバがIOleLinkインターフェースを直接実装している場合、常にリンクオブジェクトとして動作することになってしまいますが、基本的にオブジェクトサーバがIOleLinkインターフェースを実装していることはありません。

その他
OLEの仕様では、リンクオブジェクトと埋め込みオブジェクトを見た目で区別できるようにするため、周囲を破線と実線で描き分けることが推奨されています。今回はオブジェクトの周囲を目立たせるため、この対応は行っていません。代わりにドラッグによる移動時に描き分けています。


3.まとめ

解説を始めたばかりですので、今回の実装程度ではリンクの利点を挙げることはできません。リンクしたファイルを更新しても、ドキュメント上のリンクオブジェクトには全く反映されません。これは構造化ストレージに保存されているオブジェクトのイメージを更新できないためです。埋め込みオブジェクトもインプレースアクティベーションできないので、レベルの低さで互角と言ったところでしょうか・・・。ファイルのサイズでは圧倒的にリンクした方が小さいですが・・・。

とりあえず、リンクコンテナは埋め込みコンテナをちょっと拡張したものであるという認識が出来るようになっていれば、この章の目的はまずまず達成していると言えるのはないでしょうか。


前へ 次へ
OLE on .NET Frameworkへ
総合トップへ

サンプルで使用しているキーワード
CreateFileMoniker IAdviseSink IOleClientSite IOleObject IOleLink IPersistStorage IRootStorage IStorage IStream IViewObject2 OleDraw OleLoad OleSave OleSetContainedObject OLEUIINSERTOBJECT OleUIInsertObject StgCreateDocfile StgOpenStorage System.ComponentModel.IComponent System.Runtime.InteropServices.UCOMIMoniker