プロパティ ページの追加 (ATL チュートリアル、パート 6)
Note
ATL OLE DB プロバイダー ウィザードは、Visual Studio 2019 以降では使用できません。
プロパティ ページは個別の COM オブジェクトとして実装されるため、必要に応じて共有することができます。 この手順では、次のタスクを行ってプロパティ ページをコントロールに追加します。
プロパティ ページのリソースを作成する
コードを追加してプロパティ ページを作成および管理する
プロパティ ページをコントロールに追加する
プロパティ ページのリソースを作成する
プロパティ ページをコントロールに追加するには、ATL プロパティ ページ テンプレートを使用します。
プロパティ ページを追加するには
ソリューション エクスプローラーで
Polygon
を右クリックします。ショートカット メニューの [追加]>[新しい項目] をクリックします。
テンプレートの一覧で [ATL]>[ATL プロパティ ページ] を選択し、[追加] をクリックします。
ATL プロパティ ページ ウィザードが表示されたら、短い名前として「PolyProp」と入力します。
[文字列] をクリックして [文字列] ページを開き、タイトルとして「&Polygon」と入力します。
プロパティ ページのタイトルは、そのページのタブに表示される文字列です。 ドキュメント文字列は、プロパティ フレームのステータス行またはツール ヒントに表示される説明です。 標準のプロパティ フレームでは現在この文字列が使用されないため、既定の内容のままにすることができる点に注意してください。 現時点ではヘルプ ファイルを生成しないので、そのテキスト ボックス内のエントリを削除します。
[完了] をクリックすると、プロパティ ページ オブジェクトが作成されます。
次の 3 つのファイルが作成されます。
ファイル | 説明 |
---|---|
PolyProp.h | プロパティ ページを実装する C++クラス CPolyProp が含まれています。 |
PolyProp.cpp | PolyProp.h ファイルが含まれています。 |
PolyProp.rgs | プロパティ ページ オブジェクトを登録するレジストリ スクリプトです。 |
次のコード変更も行われます。
新しいプロパティ ページが Polygon.cpp のオブジェクト エントリ マップに追加されます。
PolyProp
クラスが Polygon.idl ファイルに追加されます。新しいレジストリ スクリプト ファイル PolyProp.rgs がプロジェクトのリソースに追加されます。
ダイアログ ボックスのテンプレートがプロパティ ページのプロジェクトのリソースに追加されます。
指定したプロパティの文字列がリソース文字列テーブルに追加されます。
次に、プロパティ ページに表示するフィールドを追加します。
プロパティ ページにフィールドを追加するには
ソリューション エクスプローラーで Polygon.rc リソース ファイルをダブルクリックします。 これにより、リソース ビューが開きます。
リソース ビューで
Dialog
ノードを展開し、IDD_POLYPROP
をダブルクリックします。 表示されるダイアログ ボックスは空白で、コントロールを挿入する場所を示すラベルだけが表示されていることに注意してください。そのラベルを選択して
Sides:
に変更します。これには、[プロパティ] ウィンドウ内の [キャプション] のテキストを変更します。テキストのサイズに合わせてラベル ボックスのサイズを変更します。
ツールボックスからラベルの右側に編集コントロールをドラッグします。
最後に、[プロパティ] ウィンドウを使用して編集コントロールの ID を
IDC_SIDES
に変更します。
これで、プロパティ ページのリソースを作成するプロセスが完了します。
コードを追加してプロパティ ページを作成および管理する
プロパティ ページのリソースを作成したので、実装コードを記述する必要があります。
まず、CPolyProp
クラスを有効にして、[適用] ボタンが押されたときのオブジェクトの側面の数を設定します。
Apply 関数を変更して側面の数を設定するには
PolyProp.h の
Apply
関数を次のコードに置き換えます。STDMETHOD(Apply)(void) { USES_CONVERSION; ATLTRACE(_T("CPolyProp::Apply\n")); for (UINT i = 0; i < m_nObjects; i++) { CComQIPtr<IPolyCtl, &IID_IPolyCtl> pPoly(m_ppUnk[i]); short nSides = (short)GetDlgItemInt(IDC_SIDES); if FAILED(pPoly->put_Sides(nSides)) { CComPtr<IErrorInfo> pError; CComBSTR strError; GetErrorInfo(0, &pError); pError->GetDescription(&strError); MessageBox(OLE2T(strError), _T("Error"), MB_ICONEXCLAMATION); return E_FAIL; } } m_bDirty = FALSE; return S_OK; }
プロパティ ページには同時に複数のクライアントをアタッチできるため、Apply
関数は繰り返し実行し、編集ボックスから取得した値を持つ各クライアントに対して put_Sides
を呼び出します。 ここで使用している CComQIPtr クラスは、各オブジェクトに対して QueryInterface
を実行し、(m_ppUnk
配列に格納されている) IUnknown
インターフェイスから IPolyCtl
インターフェイスを取得します。
このコードは、この段階で Sides
プロパティの設定が実際に行われたかどうかをチェックします。 失敗していた場合、コードはメッセージ ボックスを表示して、IErrorInfo
インターフェイスからのエラーの詳細を表示します。 通常、コンテナーはまずオブジェクトに ISupportErrorInfo
インターフェイスを要求して InterfaceSupportsErrorInfo
を呼び出し、そのオブジェクトでエラー情報の設定がサポートされているかどうかを確認します。 このタスクは省略できます。
CComPtr によって参照カウントが自動的に処理されるため、インターフェイスで Release
を呼び出す必要がありません。 CComBSTR
では BSTR の処理が行われるため、最後に SysFreeString
の呼び出しを実行する必要がありません。 また、さまざまな文字列変換クラスのいずれかを使用して、BSTR を必要に応じて変換することができます (これが、関数の先頭に USES_CONVERSION マクロがある理由です)。
さらに、プロパティ ページのダーティー フラグを設定し、[適用] ボタンを有効にする必要があることを示す必要があります。 これは、ユーザーが [側面] 編集ボックスの値を変更したときに発生します。
[適用] ボタンを処理するには
クラス ビューで
CPolyProp
を右クリックし、ショートカット メニューの [プロパティ] をクリックします。[プロパティ] ウィンドウの [イベント] アイコンをクリックします。
イベント一覧で
IDC_SIDES
ノードを展開します。EN_CHANGE
を選択し、右側のドロップダウン メニューで <[追加] > [OnEnChangeSides] をクリックします。OnEnChangeSides
ハンドラーの宣言が Polyprop.h に、ハンドラーの実装が Polyprop.cpp に追加されます。
次に、ハンドラーを変更します。
OnEnChangeSides メソッドを変更するには
Polyprop.cpp の次のコードを
OnEnChangeSides
メソッドに追加します (ウィザードによって配置されているコードはすべて削除します)。LRESULT CPolyProp::OnEnChangeSides(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { SetDirty(TRUE); return 0; }
IDC_SIDES
コントロールの EN_CHANGE
の通知とともに WM_COMMAND
メッセージが送信されるときに、OnEnChangeSides
が呼び出されます。 その後 OnEnChangeSides
は SetDirty
を呼び出して TRUE を渡し、プロパティ ページがダーティになり、[適用] ボタンを有効にする必要があることを示します。
プロパティ ページをコントロールに追加する
プロジェクトには複数のコントロールがある可能性があるため、ATL プロパティ ページのテンプレートやウィザードによって、コントロールにプロパティ ページが自動的に追加されることはありません。 コントロールのプロパティ マップにエントリを追加する必要があります。
プロパティ ページを追加するには
PolyCtl.h を開き、次の行をプロパティ マップに追加します。
PROP_ENTRY_TYPE("Sides", 1, CLSID_PolyProp, VT_INT) PROP_PAGE(CLSID_PolyProp)
コントロールのプロパティ マップは次のようになります。
BEGIN_PROP_MAP(CPolyCtl)
PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
#ifndef _WIN32_WCE
PROP_ENTRY_TYPE("FillColor", DISPID_FILLCOLOR, CLSID_StockColorPage, VT_UI4)
#endif
PROP_ENTRY_TYPE("Sides", 1, CLSID_PolyProp, VT_INT)
PROP_PAGE(CLSID_PolyProp)
// Example entries
// PROP_ENTRY("Property Description", dispid, clsid)
// PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()
プロパティ ページの CLSID を使用して PROP_PAGE
マクロを追加する方法もありますが、上記のように PROP_ENTRY
マクロを使用すると、コントロールの保存時に Sides
プロパティの値も保存されます。
このマクロへの 3 つのパラメーターは、プロパティの説明、プロパティの DISPID、そのプロパティを持つプロパティ ページの CLSID です。 これが役に立つのは、たとえば Visual Basic にコントロールを読み込み、設計時に側面の数を設定する場合です。 側面の数を保存すると、Visual Basic プロジェクトを再読み込みするときに側面の数が復元されるからです。
コントロールのビルドとテスト
次は、このコントロールをビルドし、ActiveX コントロール テスト コンテナーに挿入します。 テスト コンテナーの [編集] メニューで、[PolyCtl クラス オブジェクト] をクリックします。 プロパティ ページが開き、追加した情報が表示されます。
[適用] ボタンは最初は無効になっています。 [側面] ボックスで値の入力を開始すると、[適用] ボタンが有効になります。 値の入力が完了したら、[適用] ボタンをクリックします。 コントロールの表示が変化して、[適用] ボタンが再び無効になります。 無効な値を入力してみてください。 メッセージ ボックスが開き、put_Sides
関数で設定したエラーの説明が表示されます。
次は、コントロールを Web ページに配置します。