次の方法で共有


TN040: MFC/OLE In-Place サイズ変更とズーム

次のテクニカル ノートは、最初にオンライン ドキュメントに含まれてから更新されていません。 その結果、一部の手順やトピックが古くなっているか、正しくない可能性があります。 最新情報については、オンライン ドキュメント インデックスで関心のあるトピックを検索することをお勧めします。

このメモでは、インプレース編集に関連する問題と、サーバーで正しいズームとインプレース サイズ変更を実行する方法について説明します。 インプレース アクティブ化では、WYSIWYG の概念は、コンテナーとサーバーが相互に連携し、特に OLE 仕様をほとんど同じように解釈するという点でさらに 1 歩進みます。

インプレース ライセンス認証をサポートするコンテナーとサーバーの間で密接な相互作用があるため、エンド ユーザーからの多くの期待が維持される必要があります。

  • プレゼンテーション表示 ( COleServerItem::OnDraw オーバーライドで描画されるメタファイル) は、編集用に描画される場合とまったく同じになります (編集ツールが表示されない点を除く)。

  • コンテナーが拡大すると、サーバー ウィンドウも表示されます。

  • コンテナーとサーバーの両方に、同じメトリックを使用して編集するためのオブジェクトが表示されます。 つまり、ディスプレイ デバイスでのレンダリング時に、1 インチあたりの物理ピクセル数ではなく、1 インチあたりの 論理 ピクセル数に基づいてマッピング モードを使用します。

インプレース アクティブ化は埋め込み (リンクされていない) アイテムにのみ適用されるため、ズームは埋め込みオブジェクトにのみ適用されます。 COleServerDocCOleServerItemの両方で、ズームに使用される API が表示されます。 この二分法の理由は、リンクされたアイテムと埋め込みアイテムの両方に対して有効な関数のみが COleServerItem にあり(これにより、共通の実装を持つことができます)、埋め込みオブジェクトに対してのみ有効な関数が COleServerDoc クラスに配置されるためです(サーバーの観点からは、埋め込まれている ドキュメント です)。

ほとんどの負荷はサーバー実装者に課せられ、サーバーはコンテナーのズーム係数を認識し、必要に応じて編集インターフェイスを変更する必要があります。 ただし、コンテナーで使用されているズーム係数は、サーバーによってどのように決定されるか

MFC によるズームのサポート

現在のズーム係数は、 COleServerDoc::GetZoomFactorを呼び出すことによって決定できます。 ドキュメントがインプレース アクティブでない場合にこれを呼び出すと、常に 100% ズーム係数 (または 1:1 の比率) になります。 インプレース アクティブ中に呼び出すと、100%以外のものが返されることがあります。

正しくズームする例については、MFC OLE サンプル HIERSVR を参照してください。 HIERSVR でのズームは、テキストが表示され、テキストが一般に線形にスケーリングされないという事実によって複雑になります (ヒント、文字体裁規則、デザインの幅、高さはすべて問題を複雑にします)。 それでも、HIERSVR は、ズームを正しく実装するための妥当なリファレンスであり、MFC チュートリアル SCRIBBLE も含まれます (手順 7)。

COleServerDoc::GetZoomFactor は、コンテナーから、または COleServerItem クラスと COleServerDoc クラスの実装から使用できるさまざまなメトリックに基づいてズーム係数を決定します。 つまり、現在のズーム係数は次の式によって決まります。

Position Rectangle (PR) / Container Extent (CE)

位置四角形はコンテナーによって決定されます。 これは、 COleClientItem::OnGetItemPosition が呼び出されたときにインプレース アクティブ化中にサーバーに返され、コンテナーがサーバーの COleServerDoc::OnSetItemRects を呼び出したときに更新されます ( COleClientItem::SetItemRectsの呼び出しを使用)。

CONTAINER EXTENT は、計算が少し複雑になります。 コンテナーが (COleClientItem::SetExtent の呼び出しを使用して) COleServerItem::OnSetExtentを呼び出した場合、CONTAINER EXTENT はこの値を論理インチあたりのピクセル数に基づいてピクセルに変換します。 コンテナーが SetExtent を呼び出していない場合 (通常はそうです)、CONTAINER EXTENT は COleServerItem::OnGetExtentから返されるサイズです。 そのため、コンテナーが SetExtent を呼び出していない場合、フレームワークは、コンテナーが呼び出した場合、自然エクステントの 100% ( COleServerItem::GetExtentから返される値) で呼び出したと想定します。 別の方法として、フレームワークは、コンテナーが項目の 100% (それ以上、少なからず) を表示していることを前提としています。

COleServerItem::OnSetExtentCOleServerItem::OnGetExtentの名前は似ていますが、項目の同じ属性を操作しないことに注意してください。 OnSetExtent は、コンテナーに表示されているオブジェクトの量 (ズーム係数に関係なく) をサーバーに知らせるために呼び出され、 OnGetExtent はコンテナーによって呼び出され、オブジェクトの理想的なサイズが決定されます。

関連する各 API を見ると、より明確な画像を得ることができます。

COleServerItem::OnGetExtent

この関数は、アイテムの HIMETRIC 単位で "自然なサイズ" を返す必要があります。 "自然なサイズ" と考える最善の方法は、印刷時に表示されるサイズとして定義することです。 ここで返されるサイズは、特定の項目の内容に対して定数です (メタファイルと同じように、特定の項目に対して定数です)。 アイテムにズームを適用しても、このサイズは変更されません。 通常、コンテナーが OnSetExtent を呼び出すことによって項目に多かれ少なかれスペースを与える場合は変更されません。 変更の例としては、コンテナーによって送信された最後のエクステントに基づいてテキストをラップする "余白" 機能のない単純なテキスト エディターの場合があります。 サーバーが変更された場合、サーバーはシステム レジストリでOLEMISC_RECOMPOSEONRESIZE ビットを設定する必要があります (このオプションの詳細については、OLE SDK のドキュメントを参照してください)。

COleServerItem::OnSetExtent

この関数は、コンテナーにオブジェクトの "多かれ少なかれ" と表示されたときに呼び出されます。 ほとんどのコンテナーでは、これをまったく呼び出しません。 既定の実装では、コンテナーから受信した最後の値が 'm_sizeExtent' に格納されます。これは、前述の CONTAINER EXTENT 値を計算するときに COleServerDoc::GetZoomFactor で使用されます。

COleServerDoc::OnSetItemRects

この関数は、ドキュメントがインプレースアクティブな場合にのみ呼び出されます。 これは、コンテナーが項目の位置または項目に適用されたクリッピングを更新するときに呼び出されます。 上で説明したように、位置四角形は、ズーム係数の計算に分子を提供します。 サーバーは、 COleServerDoc::RequestPositionChangeを呼び出すことによって項目の位置の変更を要求できます。 コンテナーは、(COleServerItem::SetItemRects の呼び出しで) OnSetItemRectsを呼び出すことによって、この要求に応答する場合と応答しない場合があります。

COleServerDoc::OnDraw

COleServerItem::OnDrawのオーバーライドによって作成されたメタファイルは、現在のズーム係数に関係なく、まったく同じメタファイルを生成することを認識することが重要です。 コンテナーは、必要に応じてメタファイルをスケーリングします。 これは、ビューの OnDraw とサーバーアイテムの OnDrawの重要な違いです。 ビューはズームを処理し、項目は ズーム可能な メタファイルを作成し、適切なズームを行うためにコンテナーに残します。

サーバーが正しく動作することを保証する最善の方法は、ドキュメントがインプレースアクティブな場合に COleServerDoc::GetZoomFactor の実装を使用することです。

In-Place サイズ変更の MFC サポート

MFC は、OLE 2 仕様の説明に従って、インプレース サイズ変更インターフェイスを完全に実装します。 ユーザー インターフェイスは、 COleResizeBar クラス、カスタム メッセージ WM_SIZECHILD、および COleIPFrameWndでのこのメッセージの特別な処理によってサポートされます。

このメッセージの処理は、フレームワークによって提供される処理とは異なる場合があります。 前述のように、フレームワークはインプレースサイズの結果をコンテナーまで残します。サーバーはズーム係数の変更に応答します。 コンテナーが COleClientItem::OnChangeItemPosition の処理中に CONTAINER EXTENT と POSITION RECTANGLE の両方を設定して反応した場合 ( COleServerDoc::RequestPositionChangeの呼び出しの結果として呼び出されます)、インプレース サイズ変更により、編集ウィンドウに項目の "多かれ少なかれ" が表示されます。 COleClientItem::OnChangeItemPositionの処理中に POSITION RECTANGLE を設定するだけでコンテナーが反応すると、ズーム係数が変更され、項目が "拡大または縮小" と表示されます。

サーバーは、このネゴシエーション中に何が起こるかを (ある程度) 制御できます。 たとえば、スプレッドシートでは、アイテムのインプレース編集中にユーザーがウィンドウのサイズを変更するときに、表示するセルの数を増減できます。 ワード プロセッサでは、"ページの余白" を変更してウィンドウと同じにし、テキストを新しい余白にラップし直す場合があります。 サーバーは、サイズ変更の実行時に自然なエクステント ( COleServerItem::OnGetExtent から返されるサイズ) を変更することによってこれを実装します。 これにより、位置 RECTANGLE と CONTAINER EXTENT の両方が同じ量だけ変化し、同じズーム係数になりますが、表示領域が大きいか小さくなります。 さらに、ドキュメントの多かれ少なかれ、 OnDrawによって生成されたメタファイルに表示されます。 この場合、表示領域だけでなく、ユーザーがアイテムのサイズを変更すると、ドキュメント自体が変更されます。

カスタムサイズ変更を実装し、COleIPFrameWnd クラスのWM_SIZECHILD メッセージをオーバーライドすることで、COleResizeBarによって提供されるユーザー インターフェイスを引き続き利用できます。 WM_SIZECHILDの詳細については、 テクニカル ノート 24 を参照してください。

こちらも参照ください

番号別テクニカル ノート
カテゴリ別テクニカル ノート