IViewObjectEx
COM公式ドキュメント
IViewObject2 から派生した拡張インターフェースで、非矩形オブジェクトや透明オブジェクトに対する拡張されたちらつきのない描画、非矩形オブジェクトのヒットテスト、およびコントロールのサイズ変更をサポートします。
メソッド 5
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
要求された描画アスペクトを表す矩形を取得します。
| dwAspect | DWORD | in | 要求された描画アスペクト。 |
| pRect | RECTL* | out | 要求された描画アスペクトを表す矩形へのポインター。 |
戻り値
成功した場合、このメソッドは S_OK を返します。その他に返される可能性のある値には次のものがあります。
| 戻り値 | 説明 |
|---|---|
| このメソッドは指定されたアスペクトをサポートしていません。オブジェクトが要求されたアスペクトをサポートしていないか、アスペクトが矩形ではありません。 |
解説(Remarks)
このメソッドは、指定された描画アスペクトを表す矩形を返します。返される矩形は HIMETRIC 単位で、オブジェクトの原点からの相対位置です。返される矩形は描画アスペクトに応じて次のようになります。
| 描画アスペクト | 説明 |
|---|---|
| DVASPECT_CONTENT | オブジェクトはオブジェクト全体のバウンディング矩形を返す必要があります。左上隅はオブジェクトの原点にあり、サイズは IViewObject2::GetExtent が返す範囲(extent)と等しくなります。 |
| DVASPECT_OPAQUE |
矩形の不透明領域を持つオブジェクトは、その矩形を返す必要があります。それ以外のオブジェクトは失敗し、エラーコード DV_E_DVASPECT を返す必要があります。
矩形が返された場合、そのアスペクトに対して IViewObject::Draw を呼び出すことで完全に覆い隠されることが保証されます。コンテナーは、背面から前面への描画パスでオブジェクトの背後に他のオブジェクトを描画する前に、この矩形を使用してオブジェクトの不透明部分をクリップアウトする必要があります。非矩形の不透明領域を持つオブジェクトでこのメソッドが失敗した場合、コンテナーは背面から前面へのパスで DVASPECT_CONTENT アスペクトを使用してオブジェクト全体を描画する必要があります。 |
| DVASPECT_TRANSPARENT | オブジェクトは、すべての透明部分または不規則な部分を覆う矩形を返す必要があります。オブジェクトに透明部分や不規則な部分がない場合は、DV_E_ASPECT を返すことができます。コンテナーはこの矩形を使用して、あるオブジェクトの透明部分に重なる他のオブジェクトが存在するかどうかを判断できます。 |
オブジェクトの不透明性に関する情報と、サポートされる描画アスペクトを取得します。
| pdwStatus | DWORD* | out | ビューステータスへのポインター。この情報は VIEWSTATUS 列挙値の組み合わせとして返されます。 |
戻り値
成功した場合、このメソッドは S_OK を返します。
解説(Remarks)
描画処理を最適化するために、コンテナーはオブジェクトが不透明かどうか、および単色の背景を持つかどうかを判断できる必要があります。完全に不透明なオブジェクトによって全体が覆われているオブジェクトを再描画する必要はありません。スクロールなどの他の操作も、オブジェクトが不透明で単色の背景を持つ場合には大幅に最適化できます。
IViewObjectEx::GetViewStatus メソッドは、オブジェクトが完全に不透明かどうか(VIEWSTATUS_OPAQUE ビット)、およびその背景が単色かどうか(VIEWSTATUS_SOLIDBKGND ビット)を返します。この情報は時間とともに変化する可能性があります。オブジェクトはある時点では不透明であっても、後に、たとえば BackStyle プロパティの変更によって、全体的または部分的に透明になることがあります。オブジェクトが変化したときは、IAdviseSinkEx::OnViewStatusChange を使用してサイトに通知し、サイトがこの情報を高速アクセスのためにキャッシュできるようにする必要があります。
IViewObjectEx をサポートしないオブジェクトは、常に透明であるとみなされます。
IViewObjectEx::GetViewStatus メソッドは、どのアスペクトがサポートされているかを示すビットの組み合わせも返します。
特定の描画アスペクトがサポートされていない場合、描画アスペクトを入力パラメーターとして受け取るすべての IViewObjectEx メソッドは失敗し、E_INVALIDARG を返す必要があります。IViewObjectEx::GetViewStatus メソッドを使用すると、コンテナーはすべての描画アスペクトに関する情報を 1 回の高速な呼び出しで取得できます。通常、サポートされる描画アスペクトのセットは時間とともに変化すべきではありません。ただし、変化する場合には、オブジェクトは IAdviseSinkEx::OnViewStatusChange を使用してコンテナーに通知する必要があります。
どの描画アスペクトがサポートされているかは、オブジェクトが不透明か、部分的に透明か、完全に透明かとは独立しています。特に、DVASPECT_TRANSPARENT をサポートしない透明なオブジェクトは、背面から前面へのパスで DVASPECT_CONTENT を使用して正しく描画される必要があります。ただし、これはより多くのちらつきを生じさせる可能性があります。
ある点がオブジェクトの指定された描画アスペクト内にあるかどうかを示します。
| dwAspect | DWORD | in | 要求された描画アスペクト。 |
| pRectBounds | RECT* | in | 含んでいるウィンドウのクライアント座標におけるオブジェクトのバウンディング矩形。この矩形はコンテナーによって計算されて渡され、オブジェクトがヒット位置を意味のある形で解釈できるようにします。 |
| ptlLoc | POINT | in | 含んでいるウィンドウのクライアント座標におけるヒット位置。 |
| lCloseHint | INT | in | コンテナーが「近い」とみなす距離(HIMETRIC 単位)。この値はヒントであり、オブジェクトは独自の方法で解釈できます。オブジェクトはこのヒントを使用して出力解像度をおおまかに推測し、ヒットテスト実装の許容範囲(expansiveness)を選択することもできます。 |
| pHitResult | DWORD* | out | HITRESULT 列挙値として表される、ヒットに関する情報を返すためのポインター。 |
戻り値
成功した場合、このメソッドは S_OK を返します。その他に返される可能性のある値には次のものがあります。
| 戻り値 | 説明 |
|---|---|
| このメソッドは要求されたアスペクトに対して実装されていません。代わりに DVASPECT_CONTENT を使用してください。 |
解説(Remarks)
非矩形オブジェクトのヒット検出をサポートするには、コンテナーが、指定された位置がオブジェクトの描画アスペクトのいずれかの内側にあるかどうかをオブジェクトに問い合わせる信頼できる方法を必要とします。この機能は IViewObjectEx::QueryHitPoint によって提供されます。
返される可能性のある値には次のものがあります。
- 透明領域の外側
- ヒットとみなされるほど十分に近い(小さいオブジェクトや細いオブジェクトで使用されることがある)
- ヒット
IViewObjectEx::QueryHitPoint は、オブジェクトがサポートする任意の描画アスペクトに対して呼び出すことができます。要求された描画アスペクトに対してサポートされていない場合は失敗する必要があります。
透明なオブジェクトは、クリックがオブジェクト内のどこで正確に発生するかに応じて、ユーザーが透明なオブジェクトまたはその背後のオブジェクトのいずれかを選択できる複雑なヒット検出メカニズムを実装したい場合があります。 たとえば、十分に大きなテキストを表示している透明なテキストボックスでは、ユーザーが文字の間をクリックしたときに、背後のオブジェクト(たとえばビットマップ)を選択できるようにすることがあります。このため、 IViewObjectEx::QueryHitPoint が返す情報には、ヒットが不透明領域で発生したか透明領域で発生したかの指示が含まれます。
非矩形かつ透明なヒット検出の例として、背後にオブジェクト(以下の例では線)がある透明な円コントロールがあります。
:::image type="content" source="./images/a7c7fe0d-f171-4823-ba4c-b51cb90d8733.png" border="false" alt-text="対角線が引かれた円の図。円の内側と外側、および線の近くの領域についてのヒット検出値を示している。":::
表示されている値は円に対するヒットテストの結果です。灰色の領域はコントロールの一部ではありませんが、画像の周囲の「近い」とみなされる領域を示すためにここに表示されています。各オブジェクトは独自の「近い」の定義を実装しますが、コンテナーが提供するヒントによって支援されるため、画像を拡大または縮小するにつれて近さを調整できます。
上の図では、Hit、Close、Transparent とマークされた点は、Transparent とマークされたもの(ただし線に対しては close)を除いて、すべて円に対する強さの異なるヒットになります。これはヒットの強さの違いによる効果を示しています。円は transparent で応答し、線は close を主張し、transparent は close より弱いため、線がヒットを取得します。
実装者向けの注意事項
IViewObjectEx をサポートするオブジェクトは、少なくとも DVASPECT_CONTENT アスペクトに対してこのメソッドを実装する必要があります。オブジェクトは、このメソッドに応答して情報を返す以外の動作を行うべきではなく、副作用があってはなりません。矩形内のいずれかの点がオブジェクトの指定された描画アスペクト内にあるかどうかを示します。
| dwAspect | DWORD | in | 要求された描画アスペクト。 |
| pRectBounds | RECT* | in | 含んでいるウィンドウのクライアント座標におけるオブジェクトのバウンディング矩形。この矩形はコンテナーによって計算されて渡され、オブジェクトがヒット位置を意味のある形で解釈できるようにします。 |
| pRectLoc | RECT* | in | ヒットテスト矩形。オブジェクトの左上隅からの相対位置で、HIMETRIC 単位で指定されます。 |
| lCloseHint | INT | in | コンテナーが「近い」とみなす距離(HIMETRIC 単位)。この値はヒントであり、オブジェクトは独自の方法で解釈できます。オブジェクトはこのヒントを使用して出力解像度をおおまかに推測し、ヒットテスト実装の許容範囲(expansiveness)を選択することもできます。 |
| pHitResult | DWORD* | out | HITRESULT 列挙値として表される、ヒットに関する情報を返すためのポインター。 |
戻り値
成功した場合、このメソッドは S_OK を返します。その他に返される可能性のある値には次のものがあります。
| 戻り値 | 説明 |
|---|---|
| このメソッドは要求されたアスペクトに対して実装されていません。代わりに DVASPECT_CONTENT を使用してください。 |
解説(Remarks)
コンテナーは、あるオブジェクトが別のオブジェクトの指定された描画アスペクトに重なるかどうかをテストする必要がある場合があります。対象のアスペクトのリージョン、または少なくともバウンディング矩形を要求することで、オブジェクトが重なるかどうかを判断できます。ただし、これをより素早く行う方法は、IViewObjectEx::QueryHitRect を呼び出して、指定された矩形がオブジェクトの描画アスペクトのいずれかと交差するかどうかをオブジェクトに問い合わせることです。
実装者向けの注意事項
IViewObjectEx をサポートするオブジェクトは、少なくとも DVASPECT_CONTENT アスペクトに対してこのメソッドを実装する必要があります。オブジェクトは、このメソッドに応答して情報を返す以外の動作を行うべきではなく、副作用があってはなりません。座標が正確に変換されないなどの理由により、ある点がヒットかどうかにあいまいさがある場合、オブジェクトは矩形内のいずれかの点がオブジェクトへのヒットである可能性があるときは常に HITRESULT_HIT を返す必要があります。すなわち、実際にはレンダリングされていない点についてヒットを主張することは許容されますが、オブジェクトのレンダリングされた画像内にあるいずれの点についてもミスを主張することは決して正しくありません。ユーザーがオブジェクトのサイズを変更する際にオブジェクトが使用するための、コンテナーからのサイズ変更ヒントを提供します。
| dwAspect | DVASPECT | in | 要求された描画アスペクト。DVASPECT 列挙で定義される、次のいずれかの値を指定できます。 |
| lindex | INT | in | 描画操作で対象となるオブジェクトの部分を示します。その解釈は dwAspect パラメーターの値に応じて異なります。詳細については DVASPECT 列挙を参照してください。 |
| ptd | DVTARGETDEVICE* | in | オブジェクトのレンダリング先となるデバイスを記述するターゲットデバイス構造体へのポインター。NULL の場合、ビューは既定のターゲットデバイス(通常はディスプレイ)用にレンダリングされます。NULL 以外の値は hicTargetDev および hdcDraw と組み合わせて解釈されます。たとえば、hdcDraw がデバイスコンテキストとしてプリンターを指定している場合、ptd パラメーターはそのプリンターデバイスを記述する構造体を指します。hicTargetDev が有効な値であれば実際にデータが印刷される場合があり、hicTargetDev が NULL であれば印刷プレビューモードで表示される場合があります。 |
| hicTargetDev | HDC | in | ptd パラメーターで示されるターゲットデバイスの情報コンテキストを指定します。オブジェクトはこれを使用してデバイスメトリクスを抽出し、デバイスの機能をテストできます。ptd が NULL の場合、オブジェクトは hicTargetDev パラメーターの値を無視する必要があります。 |
| pExtentInfo | DVEXTENTINFO* | in | サイズ変更データを指定する DVEXTENTINFO 構造体へのポインター。 |
| pSizel | SIZE* | out | オブジェクトによって返されるサイズ変更データへのポインター。返されるサイズ変更データは、調整されなかった次元については -1 に設定されます。つまり、cx が -1 の場合は幅が調整されなかったことを、cy が -1 の場合は高さが調整されなかったことを意味します。サイズが調整されなかったことを示す E_FAIL が返された場合、pSizel は NULL になることがあります。 |
戻り値
成功した場合、このメソッドは S_OK を返します。その他に返される可能性のある値には次のものがあります。
| 戻り値 | 説明 |
|---|---|
| このメソッドは指定された dwAspect に対して実装されていないか、サイズが調整されませんでした。 | |
| このメソッドは実装されていませんでした。 |
解説(Remarks)
コントロールのサイズ変更には、大きく分けて 2 つのアプローチがあります。第 1 のアプローチはコントロール自身にサイズ変更の責任を持たせ、第 2 のアプローチはコンテナーにコントロールのサイズ変更の責任を持たせます。第 1 のアプローチはオートサイジング(autosizing)と呼ばれます。第 2 のアプローチには 2 つの方法があります。コンテンツサイジング(content sizing)とインテグラルサイジング(integral sizing)です。
IViewObjectEx::GetNaturalExtent メソッドはコンテンツサイジングとインテグラルサイジングの両方をサポートします。コンテンツサイジングでは、コンテナーが DVEXTENTINFO 構造体をオブジェクトに渡し、オブジェクトはそこに推奨サイズを返します。インテグラルサイジングでは、コンテナーが優先サイズを DVEXTENTINFO でオブジェクトに渡し、オブジェクトが実際にその高さを調整します。インテグラルサイジングは、ユーザーがデザインモードでラバーバンド操作により新しいサイズを指定するときに使用されます。
オートサイジングは通常、Label コントロールのようなオブジェクトで発生し、autosize プロパティが有効になっていて関連付けられたテキストが変更された場合にサイズが変更されます。オートサイジングはオブジェクトの状態に応じて異なる方法で処理されます。
オブジェクトが非アクティブな場合、次のことが行われます。
- オブジェクトが IOleClientSite::RequestNewObjectLayout を呼び出します。
- コンテナーが IOleObject::GetExtent を呼び出して新しい範囲(extent)を取得します。
- コンテナーが IOleObject::SetExtent を呼び出して新しい範囲を調整します。
- オブジェクトが IOleInPlaceSite::OnPosRectChange を呼び出して、サイズ変更が必要であることを指定します。
- コンテナーが IOleInPlaceObject::SetObjectRects を呼び出して新しいサイズを指定します。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IViewObjectEx "{3AF24292-0C96-11CE-A0CF-00AA00600AB8}" #usecom global IViewObjectEx IID_IViewObjectEx "{}" #comfunc global IViewObjectEx_GetRect 10 int,var #comfunc global IViewObjectEx_GetViewStatus 11 var #comfunc global IViewObjectEx_QueryHitPoint 12 int,var,int,int,var #comfunc global IViewObjectEx_QueryHitRect 13 int,var,var,int,var #comfunc global IViewObjectEx_GetNaturalExtent 14 int,int,var,sptr,var,var ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。#define global IID_IViewObjectEx "{3AF24292-0C96-11CE-A0CF-00AA00600AB8}" #usecom global IViewObjectEx IID_IViewObjectEx "{}" #comfunc global IViewObjectEx_GetRect 10 int,sptr #comfunc global IViewObjectEx_GetViewStatus 11 sptr #comfunc global IViewObjectEx_QueryHitPoint 12 int,sptr,int,int,sptr #comfunc global IViewObjectEx_QueryHitRect 13 int,sptr,sptr,int,sptr #comfunc global IViewObjectEx_GetNaturalExtent 14 int,int,sptr,sptr,sptr,sptr ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。