プロパティ ウィンドウのフィールドとインターフェイス
[プロパティ] ウィンドウにどのような情報を表示するかを決定する選択のモデルは、IDE 内でフォーカスのあるウィンドウに基づいています。 すべてのウィンドウと、選択されたウィンドウ内のオブジェクトでは、その選択コンテキスト オブジェクトをグローバル選択コンテキストにプッシュできます。 環境では、あるウィンドウにフォーカスがあるときに、そのウィンドウ フレームの値でグローバル選択コンテキストを更新します。 フォーカスが変更されると、選択コンテキストも変更されます。
IDE での選択の追跡
IDE によって所有されるウィンドウ フレームまたはサイトには、STrackSelection という名前のサービスがあります。 次の手順は、ユーザーがフォーカスを別の開いているウィンドウに変更するか、またはソリューション エクスプローラーで別のプロジェクト項目を選択することによって発生する選択の変更が、[プロパティ] ウィンドウに表示される内容を変更するためにどのように実装されるかを示しています。
選択されたウィンドウに配置されている VSPackage によって作成されたオブジェクトが、QueryService を呼び出して STrackSelection で ITrackSelection を呼び出すようにします。
選択されたウィンドウによって提供される選択コンテナーによって、独自の ISelectionContainer オブジェクトが作成されます。 選択が変更されると、VSPackage は OnSelectChange を呼び出して、環境内のすべてのリスナー ([プロパティ] ウィンドウを含む) にその変更を通知します。 また、新しい選択に関連した階層と項目に関する情報へのアクセスも提供します。
OnSelectChange を呼び出し、
VSHPROPID_BrowseObject
パラメーターで選択された階層項目を渡すと、ISelectionContainer オブジェクトが設定されます。要求された項目の __VSHPROPID.VSHPROPID_BrowseObject に対して IDispatch インターフェイスから派生したオブジェクトが返されると、環境では、それを ISelectionContainer にラップします (次の手順を参照)。 この呼び出しが失敗した場合、環境では
IVsHierarchy::GetProperty
への 2 番目の呼び出しを行い、それを 1 つまたは複数の階層項目によって提供される選択コンテナー __VSHPROPID.VSHPROPID_SelContainer に渡します。プロジェクト VSPackage では ISelectionContainer を作成しません。それを実装している、環境によって提供されるウィンドウ VSPackage (ソリューション エクスプローラーなど) が、代わりに ISelectionContainer を構築するためです。
環境では、ISelectionContainer のメソッドを呼び出して、[プロパティ] ウィンドウに入力するための
IDispatch
インターフェイスに基づいたオブジェクトを取得します。[プロパティ] ウィンドウ内の値が変更されると、VSPackage では、その変更を要素の値に報告するために
IVsTrackSelectionEx::OnElementValueChangeEx
とIVsTrackSelectionEx::OnSelectionChangeEx
を実装します。 その後、環境では IVsUIShell または IConnectionPointContainer を呼び出して [プロパティ] ウィンドウに表示される情報をプロパティ値と同期された状態に維持します。 詳細については、「プロパティ ウィンドウでのプロパティ値の更新」を参照してください。ある項目に関連したプロパティを表示するためにソリューション エクスプローラーでその別のプロジェクト項目を選択することに加えて、[プロパティ] ウィンドウで使用可能なドロップダウン リストを使用して、フォームまたはドキュメント ウィンドウ内から別のオブジェクトを選択することもできます。 詳細については、「プロパティ ウィンドウのオブジェクト一覧」を参照してください。
情報が [プロパティ] ウィンドウ グリッドに表示される方法をアルファベット順からカテゴリ別に変更できるほか、可能な場合は、[プロパティ] ウィンドウの適切なボタンをクリックすることによって、選択されたオブジェクトのプロパティ ページを開くこともできます。 詳細については、「プロパティ ウィンドウのボタン」および「プロパティ ページ」を参照してください。
最後に、[プロパティ] ウィンドウの下部には、[プロパティ] ウィンドウ グリッドで選択されたフィールドの説明も表示されています。 詳細については、「プロパティ ウィンドウからのフィールドの説明の取得」を参照してください。
[プロパティ] ウィンドウでプロパティ値を更新
[プロパティ] ウィンドウをプロパティ値の変更と同期するには、2 つの方法があります。 1 番目の方法は、IVsUIShell インターフェイスを呼び出すことです。このインターフェイスは、環境によって用意されているツール ウィンドウやドキュメント ウィンドウのアクセスや作成を含む、基本的なウィンドウ操作機能へのアクセスを提供します。 次の手順は、この同期プロセスを説明したものです。
IVsUIShell を使ってプロパティ値を更新する
IVsUIShell インターフェイスを使ってプロパティ値を更新するには
VSPackage、プロジェクト、エディターがツール ウィンドウまたはドキュメント ウィンドウを作成したり列挙したりする必要が生じた時点で、IVsUIShell を (SVsUIShell サービスを通じて) 呼び出します。
RefreshPropertyBrowser を実装することにより、IConnectionPointContainer を実装したり OnChanged イベントを起動したりすることなく、[プロパティ] ウィンドウをプロジェクト (または、[プロパティ] ウィンドウによって参照されている他の任意の選択されたオブジェクト) のプロパティ変更と同期された状態に維持します。
IVsHierarchy のメソッド AdviseHierarchyEvents および UnadviseHierarchyEvents を実装します。この 2 つのメソッドは、それぞれ、階層イベントのクライアント通知を設定および無効化します。これにより、階層で IConnectionPointContainer を実装する必要がなくなります。
IConnection を使ってプロパティ値を更新する
[プロパティ] ウィンドウとプロパティ値の変更を同期する 2 番目の方法は、接続可能なオブジェクトに IConnection
を実装することにより、発信インターフェイスの存在を示すことです。 プロパティ名をローカライズする場合は、オブジェクトを ICustomTypeDescriptor から派生させます。 ICustomTypeDescriptor の実装では、実装から返すプロパティ記述子を変更し、プロパティの名前を変更できます。 説明をローカライズするには、DescriptionAttribute から派生させた属性を作成し、Description プロパティをオーバーライドします。
IConnection インターフェイスを実装する際の考慮事項
IConnection
は、IEnumConnectionPoints インターフェイスを持つ列挙子サブオブジェクトへのアクセスを提供します。 また、すべての接続ポイント サブオブジェクトへのアクセスも提供し、それぞれは IConnectionPoint インターフェイスを実装します。すべての参照オブジェクトは、IPropertyNotifySink イベントを実装する必要があります。 [プロパティ] ウィンドウは、
IConnection
を通してイベントを設定することをお勧めします。接続ポイントは、Advise の実装で許容される接続数 (1 つまたは複数) を制御します。 インターフェイスを 1 つのみ許容する接続ポイントでは、EnumConnections メソッドから E_NOTIMPL を返すことができます。
クライアントは、
IConnection
インターフェイスを呼び出すことにより、IEnumConnectionPoints インターフェイスを持つ列挙子サブオブジェクトへのアクセスを取得できます。 その後、IEnumConnectionPoints インターフェイスを呼び出すと、各発信インターフェイス ID (IID) の接続ポイントを列挙することができます。また、
IConnection
を呼び出すことにより、各発信 IID への IConnectionPoint インターフェイスを持つ接続ポイント サブオブジェクトへのアクセスを取得することもできます。 クライアントは、IConnectionPoint インターフェイス経由で、接続可能なオブジェクトとそのクライアント独自の同期によるアドバイザリ ループを開始または終了します。クライアントはまた、IConnectionPoint インターフェイスを呼び出して、認識している接続を列挙するための IEnumConnections インターフェイスを含む列挙子オブジェクトを取得することもできます。
[プロパティ] ウィンドウからのフィールドの説明の取得
[プロパティ] ウィンドウの下部にある説明領域に、選択したプロパティ フィールドに関連する情報が表示されます。 既定では、この機能は有効になっています。 説明フィールドを非表示にするには、 [プロパティ] ウィンドウを右クリックし、 [説明]をクリックします。 これにより、メニュー ウィンドウの [説明] タイトルの横のチェック マークが削除されます。 同じ手順を行って [説明] の表示をオンに戻すことにより、フィールドを再度表示できます。
説明フィールド内の情報は ITypeInfo から取得されます。 それぞれのメソッド、インターフェイス、コクラスなどには、タイプ ライブラリのローカライズされていない helpstring
属性を適用できます。 [プロパティ] ウィンドウでは、GetDocumentation から文字列を取得します。
ローカライズされたヘルプ文字列を指定するには
タイプ ライブラリ (
helpstringdll
) のライブラリ ステートメントにtypelib
属性を追加します。Note
この手順は、タイプ ライブラリがオブジェクト ライブラリ (.olb) ファイルにある場合は省略可能です。
文字列の
helpstringcontext
属性を指定します。helpstring
属性を指定することもできます。これらの属性は、実際の.chm ファイルのヘルプ トピックに含まれる
helpfile
属性とhelpcontext
属性とは異なります。強調表示されているプロパティ名に対して表示される説明情報を取得するために、[プロパティ] ウィンドウでは、選択されているプロパティの GetDocumentation2 を呼び出し、出力文字列のための目的の
lcid
属性を指定します。 内部的には、ITypeInfo2 はhelpstringdll
属性で指定された .dll ファイルを検索し、指定されたコンテキストとlcid
属性を使ってその .dll ファイル上にDLLGetDocumentation
を呼び出します。DLLGetDocumentation
の署名と実装は次のとおりです。
STDAPI DLLGetDocumentation
(
ITypeLib * /* ptlib */,
ITypeInfo * /* ptinfo */,
LCID /* lcid */,
DWORD dwCtx,
BSTR * pbstrHelpString
);
DLLGetDocumentation
関数はDLL の .def ファイルで定義されているエクスポートである必要があります。
内部的には、実際には DLL である .olb ファイルが作成されます。 この DLL には、1 つのリソース、タイプ ライブラリ (.tlb) ファイル、および 1 つのエクスポートされた DLLGetDocumentation
関数が含まれます。
.olb ファイルの場合は、 helpstringdll
属性は.tlb ファイル自体を含む同じファイルであるため省略可能です。
したがって、 [説明] ウィンドウに表示する文字列を取得するために最低限必要な操作は、タイプ ライブラリに helpstring
属性を指定することです。 これらの文字列をローカライズする場合は、 helpstringdll
(省略可能) 属性と helpstringcontext
(必須) 属性を指定し、 DLLGetDocumentation
を実装する必要があります
idl の helpstringcontext
属性と DLLGetDocumentation
によって取得したローカライズされた情報を取得する場合は、実装する必要のある追加のインターフェイスはありません。
別の方法でプロパティのローカライズされた名前と説明の取得には、GetLocalizedPropertyInfo を実装します。 このメソッドの実装に関する詳細については、「 Properties Window Fields and Interfaces」を参照してください。