次の方法で共有


プロパティページのCOMオブジェクトの実装

プロパティシート拡張機能は、インプロセスサーバーとして実装されるCOMオブジェクトです。 プロパティシート拡張機能は、IShellExtInitインターフェイスとIShellPropSheetExtインターフェイスを実装する必要があります。 プロパティシート拡張機能は、クラスの表示指定子にプロパティシート拡張機能が登録されているクラスのオブジェクトのプロパティシートをユーザーが表示するときにインスタンス化されます。

IShellExtInitの実装

プロパティシート拡張COMオブジェクトがインスタンス化されると、IShellExtInit::Initializeメソッドが呼び出されます。 IShellExtInit :: Initialize は、プロパティシート拡張機能に、プロパティシートが適用するディレクトリオブジェクトに関連するデータを含むIDataObjectオブジェクトを提供します。

IDataObjectには、CFSTR_DSOBJECTNAMES形式のデータが含まれています。 CFSTR_DSOBJECTNAMESデータ形式は、DSOBJECTNAMES構造体を含むHGLOBALです。 DSOBJECTNAMES構造体には、プロパティシート拡張機能が適用するディレクトリオブジェクトデータが含まれています。

IDataObjectには、CFSTR_DS_DISPLAY_SPEC_OPTIONS形式のデータも含まれています。 CFSTR_DS_DISPLAY_SPEC_OPTIONSデータ形式は、DSDISPLAYSPECOPTIONS構造体を含むHGLOBALです。 DSDISPLAYSPECOPTIONSには、拡張機能で使用する構成データが含まれています。

IShellExtInit::InitializeからS_OK以外の値が返された場合、プロパティシートは表示されません。

IShellExtInit::Initialize メソッドのpidlFolderパラメーターとhkeyProgIDパラメーターは使用されません。

IDataObjectポインターは、IDataObjectの参照カウントをインクリメントすることによって、拡張機能によって保存できます。 このインターフェイスは、不要になったときに解放する必要があります。

IShellPropSheetExtの実装

IShellExtInit::Initialize が返された後、IShellPropSheetExt::AddPagesメソッドが呼び出されます。 プロパティシート拡張機能は、このメソッドの実行中にページを追加する必要があります。 プロパティページは、PROPSHEETPAGE構造体に入力し、この構造体をCreatePropertySheetPage関数に渡すことによって作成されます。 次に、lpfnAddPageパラメーターでIShellPropSheetExt::AddPagesに渡されたコールバック関数を呼び出すことによって、プロパティページをプロパティシートに追加します。

IShellPropSheetExt::AddPagesからS_OK以外の値が返された場合、プロパティシートは表示されません。

プロパティシート拡張機能がプロパティシートにページを追加する必要がない場合は、lpfnAddPageパラメーターでIShellPropSheetExt::AddPagesに渡されたコールバック関数を呼び出さないでください。

IShellPropSheetExt::ReplacePageメソッドは使用されません。

拡張オブジェクトをプロパティページに渡します

プロパティシート拡張オブジェクトは、プロパティページから独立しています。 多くの場合、プロパティページから拡張オブジェクトまたはその他のオブジェクトを使用できるようにすることをお勧めします。 これを行うには、PROPSHEETPAGE構造体のlParamメンバーをオブジェクトポインターに設定します。 プロパティページは、 WM_INITDIALOGメッセージを処理するときにこの値を取得できます。 プロパティページの場合、WM_INITDIALOGメッセージのlParamパラメーターはPROPSHEETPAGE構造体へのポインターです。 WM_INITDIALOG メッセージのlParamPROPSHEETPAGEポインターにキャストし、PROPSHEETPAGE構造体の lParam メンバーを取得することによって、オブジェクトポインターを取得します。

次C++のコード例は、オブジェクトをプロパティページに渡す方法を示しています。

case WM_INITDIALOG:
    {
        LPPROPSHEETPAGE pPage = (LPPROPSHEETPAGE)lParam;

        if(NULL != pPage)
        {
            CPropSheetExt *pPropSheetExt;
            pPropSheetExt = (CPropSheetExt*)pPage->lParam;

            if(pPropSheetExt)
            {
                return pPropSheetExt>OnInitDialog(wParam, lParam);
            }
        }
    }
    break;

IShellPropSheetExt::AddPagesが呼び出されると、プロパティシートはプロパティシートの拡張機能オブジェクトを解放し、二度と使用しないことに注意してください。 これは、プロパティページが表示される前に拡張オブジェクトが削除されることを意味します。 ページがオブジェクトポインターにアクセスしようとすると、メモリが解放され、ポインターが無効になります。 これを解決するには、ページが追加されたときに拡張オブジェクトの参照カウントをインクリメントし、プロパティページダイアログが破棄されたときにオブジェクトを解放します。 これにより、ページが初めて表示されるまでプロパティページダイアログボックスが作成されないため、別の問題が発生します。 ユーザーが拡張ページを選択しない場合、ページは作成されず、破棄されません。 これにより、拡張オブジェクトが解放されないため、メモリリークが発生します。 これを回避するには、プロパティページのコールバック関数を実装します。 これを行うには、PSP_USECALLBACKフラグを PROPSHEETPAGE構造体のdwFlagsメンバーに追加し、PROPSHEETPAGE構造体のpfnCallbackメンバーを実装されているPropSheetPageProc関数のアドレスに設定します。 PropSheetPageProc関数がPSPCB_RELEASE通知を受け取ると、PropSheetPageProcppspパラメーターには、PROPSHEETPAGE構造体へのポインターが含まれています。 PROPSHEETPAGE 構造体のlParamメンバーには、オブジェクトを解放するために使用できる拡張ポインターが含まれています。

次のC++コード例は、拡張機能オブジェクトを解放する方法を示しています。

UINT CALLBACK CPropSheetExt::PageCallbackProc(  HWND hWnd,
                                                UINT uMsg,
                                                LPPROPSHEETPAGE ppsp)
{
    switch(uMsg)
    {
    case PSPCB_CREATE:
        // Must return TRUE to enable the page to be created.
        return TRUE;

    case PSPCB_RELEASE:
        {
            /*
            Release the object. This is called even if the page dialog box was 
            never actually created.
            */
            CPropSheetExt *pPropSheetExt = (CPropSheetExt*)ppsp->lParam;

            if(pPropSheetExt)
            {
                pPropSheetExt->Release();
            }
        }
        break;
    }

    return FALSE;
}

通知オブジェクトの操作

プロパティシートの拡張機能ページは、拡張機能にとって不明なコンポーネントによって作成されたプロパティシート内に表示されるため、拡張機能ページとプロパティシート間のデータ転送を処理するには、"manager"を使用する必要があります。 この"manager"は、通知オブジェクトと呼ばれます。 通知オブジェクトは、個々のページとプロパティシートの間のモデレーターとして動作します。

プロパティシート拡張オブジェクトが初期化されると、拡張機能はADsPropCreateNotifyObjを呼び出して通知オブジェクトを作成し、IShellExtInit::Initializeから取得したIDataObjectとディレクトリオブジェクト名を渡す必要があります。 IDataObjectインターフェイスの参照カウントをインクリメントする必要はありません。これは、ADsPropCreateNotifyObj関数によって作成された通知オブジェクトによって行われるためです。 ADsPropCreateNotifyObjによって提供される通知オブジェクトハンドルは、後で使用するために保存する必要があります。 ADsPropCreateNotifyObjは、IShellExtInit::InitializeまたはIShellPropSheetExt::AddPages中に呼び出すことができます。 プロパティシート拡張機能がシャットダウンされると、WM_ADSPROP_NOTIFY_EXITメッセージを通知オブジェクトに送信する必要があります。 これにより、通知オブジェクトがそれ自体を破棄します。 これは、PropSheetPageProc関数がPSPCB_RELEASE通知を受信したときに最適です。

プロパティシート拡張機能は、ADsPropGetInitInfoを呼び出すことによって、CFSTR_DSOBJECTNAMESクリップボード形式で提供されるデータに加えて、データを取得できます。 ADsPropGetInitInfoを使用する利点の1つは、ディレクトリオブジェクトをプログラムで操作するために使用されるIDirectoryObjectオブジェクトを提供することです。

Note

ほとんどのCOMメソッドと関数とは異なり、ADsPropGetInitInfoIDirectoryObjectオブジェクトの参照カウントをインクリメントしません。 IDirectoryObjectは、参照カウントが最初に手動でインクリメントされない限り、解放しないでください。

 

プロパティページが最初に作成されたときに、拡張機能は、ページのウィンドウハンドルを使用してADsPropSetHwndを呼び出すことによって、ページを通知オブジェクトに登録する必要があります。

ADsPropCheckIfWritableは、プロパティシートの拡張機能がプロパティを書き込むことができるかどうかを判断するために使用できるユーティリティ関数です。

その他

プロパティページのハンドルは、ページダイアログボックスプロシージャに渡されます。 プロパティシートはプロパティページの直接の親であるため、プロパティシートのハンドルは、プロパティページハンドルを使用してGetParent関数を呼び出すことによって取得できます。

拡張機能ページの内容が変更された場合、拡張機能はPropSheet_Changedマクロを使用して、変更のプロパティシートに通知する必要があります。 プロパティシートでは、 [適用] ボタンが有効になります。

複数選択のプロパティシート

Windows Server 2003以降のオペレーティングシステムでは、Active Directory管理MMCスナップインは、複数のディレクトリオブジェクトのプロパティシート拡張をサポートしています。 これらのプロパティシートは、一度に複数の項目のプロパティを表示するときに表示されます。 単一選択のプロパティシート拡張と複数選択のプロパティシート拡張の主な違いは、IShellExtInit::InitializeCFSTR_DSOBJECTNAMESクリップボード形式によって提供されるDSOBJECTNAMES構造体に複数のDSOBJECT構造体が含まれることです。

通知オブジェクトが作成されると、複数選択のプロパティシート拡張は、拡張機能によって作成された名前ではなく、スナップインによって提供される一意の名前を渡す必要があります。 一意の名前を取得するには、IShellExtInit::Initializeから取得した IDataObjectからCFSTR_DS_MULTISELECTPROPPAGEクリップボード形式を要求します。 このデータは、一意の名前であるnullで終わるUnicode文字列を含むHGLOBALです。 この一意の名前は、通知オブジェクトを作成するためにADsPropCreateNotifyObj関数に渡されます。 プロパティシートCOMオブジェクトの実装のコード例CreateADsNotificationObject関数の例では、これを正しく行う方法を示しています。また、複数選択のプロパティシートをサポートしていないスナップインの以前のバージョンと互換性があります。

複数選択のプロパティシートの場合、システムはDSOBJECT配列の最初のオブジェクトにのみバインドされます。 このため、ADsPropGetInitInfoは、配列内の最初のオブジェクトに対してIDirectoryObject と書き込み可能な属性のみを提供します。 配列内の他のオブジェクトはバインドされません。

複数選択のプロパティシート拡張機能は、adminMultiselectPropertyPages属性の下に登録されます。

Windows Server 2003の新機能

次の機能は、Windows Server 2003の新機能です。

プロパティページでエラーが発生した場合は、適切なエラーデータを使用してADsPropSendErrorMessageを呼び出すことができます。 ADsPropSendErrorMessageは、すべてのエラーメッセージをキューに格納します。 これらのメッセージは、次にADsPropShowErrorDialogが呼び出されたときに表示されます。 ADsPropShowErrorDialogが返されると、キューに置かれたメッセージが削除されます。

Windows Server 2003では、ADsPropSetHwndWithTitle関数が導入されています。 この関数はADsPropSetHwndに似ていますが、ページタイトルが含まれています。 これにより、ADsPropShowErrorDialogによって表示されるエラーダイアログボックスが有効になり、ユーザーにより有用なデータが提供されます。 プロパティシート拡張機能でADsPropShowErrorDialog関数を使用する場合、拡張機能ではADsPropSetHwndではなくADsPropSetHwndWithTitleを使用する必要があります。

プロパティシートCOMオブジェクトを実装するためのコード例