Implémentation de l’objet COM de la page de propriétés

Une extension de feuille de propriétés est un objet COM implémenté en tant que serveur in-proc. L’extension de la feuille de propriétés doit implémenter les interfaces IShellExtInit et IShellPropSheetExt . Une extension de feuille de propriétés est instanciée lorsque l’utilisateur affiche la feuille de propriétés d’un objet d’une classe pour laquelle l’extension de la feuille de propriétés a été inscrite dans le spécificateur d’affichage de la classe.

Implémentation de IShellExtInit

Après l’instanciation de l’objet COM de l’extension de feuille de propriétés, la méthode IShellExtInit :: Initialize est appelée. IShellExtInit :: Initialize fournit l’extension de la feuille de propriétés avec un objet IDataObject qui contient des données relatives à l’objet d’annuaire que la feuille de propriétés applique.

IDataObject contient des données au format CFSTR _ DSOBJECTNAMES . Le format de données CFSTR _ DSOBJECTNAMES est un HGLOBAL qui contient une structure DSOBJECTNAMES . La structure DSOBJECTNAMES contient des données d’objet d’annuaire que l’extension de feuille de propriétés applique.

IDataObject contient également des données au format CFSTR _ DS _ Display _ spec _ options . Le format de données CFSTR _ DS _ Display _ spec _ options est un HGLOBAL qui contient une structure DSDISPLAYSPECOPTIONS . Le DSDISPLAYSPECOPTIONS contient des données de configuration utilisables par l’extension.

Si une valeur autre que S _ OK est retournée à partir de IShellExtInit :: Initialize, la feuille de propriétés n’est pas affichée.

Les paramètres pidlFolder et hkeyProgID de la méthode IShellExtInit :: Initialize ne sont pas utilisés.

Le pointeur IDataObject peut être enregistré par l’extension en incrémentant le décompte de références de l' IDataObject. Cette interface doit être libérée lorsque vous n’en avez plus besoin.

Implémentation de IShellPropSheetExt

Après que IShellExtInit :: Initialize retourne, la méthode IShellPropSheetExt :: AddPages est appelée. L’extension de la feuille de propriétés doit ajouter la ou les pages pendant cette méthode. Une page de propriétés est créée en remplissant une structure PROPSHEETPAGE , puis en passant cette structure à la fonction CreatePropertySheetPage . La page de propriétés est ensuite ajoutée à la feuille de propriétés en appelant la fonction de rappel transmise à IShellPropSheetExt :: AddPages dans le paramètre lpfnAddPage .

Si une valeur autre que S _ OK est retournée à partir de IShellPropSheetExt :: AddPages, la feuille de propriétés n’est pas affichée.

Si l’extension de la feuille de propriétés n’est pas requise pour ajouter des pages à la feuille de propriétés, elle ne doit pas appeler la fonction de rappel transmise à IShellPropSheetExt :: AddPages dans le paramètre lpfnAddPage .

La méthode IShellPropSheetExt :: ReplacePage n’est pas utilisée.

Passage de l’objet d’extension à la page de propriétés

L’objet d’extension de la feuille de propriétés est indépendant de la page de propriétés. Dans de nombreux cas, il est préférable d’être en mesure d’utiliser l’objet d’extension, ou un autre objet, à partir de la page de propriétés. Pour ce faire, définissez le membre lParam de la structure PROPSHEETPAGE sur le pointeur d’objet. La page de propriétés peut ensuite récupérer cette valeur lors du traitement du message WM _ INITDIALOG . Pour une page de propriétés, le paramètre lParam du message WM _ INITDIALOG est un pointeur vers la structure PROPSHEETPAGE . Récupérez le pointeur d’objet en castant le lParam du message WM _ INITDIALOG en pointeur PROPSHEETPAGE , puis en récupérant le membre lParam de la structure PROPSHEETPAGE .

L’exemple de code C++ suivant montre comment passer un objet à une page de propriétés.

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

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

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

Sachez qu’après l’appel de IShellPropSheetExt :: AddPages , la feuille de propriétés libère l’objet d’extension de la feuille de propriétés et ne l’utilise jamais. Cela signifie que l’objet d’extension est supprimé avant l’affichage de la page de propriétés. Lorsque la page tente d’accéder au pointeur d’objet, la mémoire est libérée et le pointeur n’est pas valide. Pour corriger cela, incrémentez le décompte de références pour l’objet d’extension lorsque la page est ajoutée, puis libérez l’objet lorsque la boîte de dialogue de la page de propriétés est détruite. Cela crée un autre problème, car la boîte de dialogue page de propriétés n’est pas créée tant que la page n’est pas affichée pour la première fois. Si l’utilisateur ne sélectionne jamais la page d’extension, la page n’est jamais créée ni détruite. Cela a pour effet que l’objet d’extension n’est jamais libéré, ce qui entraîne une fuite de mémoire. Pour éviter cela, implémentez une fonction de rappel de page de propriétés. Pour ce faire, ajoutez l' indicateur PSP _ USECALLBACK au membre DwFlags de la structure PROPSHEETPAGE et définissez le membre pfnCallback de la structure PROPSHEETPAGE sur l’adresse de la fonction PropSheetPageProc implémentée. Lorsque la fonction PropSheetPageProc reçoit la notification de _ publication PSPCB , le paramètre PPSP de l' PropSheetPageProc contient un pointeur vers la structure PROPSHEETPAGE . Le membre lParam de la structure PROPSHEETPAGE contient le pointeur d’extension qui peut être utilisé pour libérer l’objet.

L’exemple de code C++ suivant montre comment libérer un objet d’extension.

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;
}

Utilisation de l’objet de notification

Étant donné que les pages de l’extension de la feuille de propriétés sont affichées dans une feuille de propriétés créée par un composant inconnu de l’extension, il est nécessaire d’utiliser un « gestionnaire » pour gérer le transfert de données entre les pages d’extension et la feuille de propriétés. Ce « gestionnaire » est appelé « objet de notification ». L’objet de notification agit comme un modérateur entre les pages individuelles et la feuille de propriétés.

Lorsque l’objet d’extension de la feuille de propriétés est initialisé, l’extension doit créer un objet de notification en appelant ADsPropCreateNotifyObj, en transmettant l' IDataObject obtenu à partir de IShellExtInit :: Initialize et le nom d’objet d’annuaire. Il n’est pas nécessaire d’incrémenter le décompte de références de l’interface IDataObject , car l’objet de notification créé par la fonction ADsPropCreateNotifyObj effectue cette opération. Le descripteur d’objet de notification fourni par ADsPropCreateNotifyObj doit être enregistré pour une utilisation ultérieure. ADsPropCreateNotifyObj peut être appelé lors de IShellExtInit :: Initialize ou IShellPropSheetExt :: AddPages. Lorsque l’extension de la feuille de propriétés est arrêtée, elle doit envoyer un message de _ _ _ sortie de notification WM ADSPROP à l’objet de notification. L’objet de notification se détruit alors lui-même. Cela s’effectue de façon optimale lorsque la fonction PropSheetPageProc reçoit la notification de _ publication PSPCB .

L’extension de la feuille de propriétés peut obtenir des données en plus de celles fournies par le format de presse-papiers CFSTR _ DSOBJECTNAMES en appelant ADsPropGetInitInfo. L’un des avantages de l’utilisation de ADsPropGetInitInfo est qu’il fournit un objet IDirectoryObject utilisé pour travailler par programmation avec l’objet Directory.

Notes

Contrairement à la plupart des méthodes et des fonctions COM, ADsPropGetInitInfo n’incrémente pas le nombre de références pour l’objet IDirectoryObject . Le IDirectoryObject ne doit pas être libéré, sauf si le nombre de références est incrémenté manuellement en premier.

Lorsque la page de propriétés est créée pour la première fois, l’extension doit inscrire la page avec l’objet de notification en appelant ADsPropSetHwnd avec le handle de fenêtre de la page.

ADsPropCheckIfWritable est une fonction utilitaire que l’extension de feuille de propriétés peut utiliser pour déterminer si une propriété peut être écrite.

Divers

Le handle de la page de propriétés est passé à la procédure de la boîte de dialogue de la page. La feuille de propriétés étant le parent direct de la page de propriétés, le handle de la feuille de propriétés peut être obtenu en appelant la fonction GetParent avec le handle de la page de propriétés.

Lorsque le contenu de la page d’extension change, l’extension doit utiliser la macro PropSheet _ Changed pour notifier la feuille de propriétés des modifications. La feuille de propriétés activera ensuite le bouton appliquer.

Multiple-Selection les feuilles de propriétés

avec les systèmes d’exploitation Windows Server 2003 et versions ultérieures, les composants logiciels enfichables de la console MMC Active Directory prennent en charge les extensions de feuille de propriétés pour plusieurs objets d’annuaire. Ces feuilles de propriétés s’affichent lorsque les propriétés sont affichées pour plusieurs éléments à la fois. La principale différence entre une extension de feuille de propriétés à sélection unique et une extension de feuille de propriétés à sélection multiple est que la structure DSOBJECTNAMES fournie par le format de presse-papiers CFSTR _ DSOBJECTNAMES dans IShellExtInit :: Initialize contient plus d’une structure DSOBJECT .

Lorsque l’objet de notification est créé, une extension de feuille de propriétés à sélection multiple doit passer un nom unique fourni par le composant logiciel enfichable au lieu d’un nom créé par l’extension. Pour obtenir le nom unique, demandez le format du presse-papiers CFSTR _ DS _ MULTISELECTPROPPAGE à partir de l' IDataObject obtenu auprès de IShellExtInit :: Initialize. Ces données sont un HGLOBAL qui contient une chaîne Unicode terminée par le caractère null qui est le nom unique. Ce nom unique est ensuite transmis à la fonction ADsPropCreateNotifyObj pour créer l’objet de notification. La fonction exemple CreateADsNotificationObject dans l' exemple de code pour l’implémentation de l’objet com de la feuille de propriétés montre comment effectuer cette opération correctement, ainsi que la compatibilité avec les versions antérieures du composant logiciel enfichable qui ne prennent pas en charge les feuilles de propriétés à sélection multiple.

Pour les feuilles de propriétés à sélection multiple, le système se lie uniquement au premier objet dans le tableau DSOBJECT . Pour cette raison, ADsPropGetInitInfo fournit uniquement les attributs IDirectoryObject et en écriture pour le premier objet du tableau. Les autres objets dans le tableau ne sont pas liés à.

Une extension de feuille de propriétés à sélection multiple est inscrite sous l’attribut adminMultiselectPropertyPages .

nouveauté de Windows Server 2003

les fonctionnalités suivantes sont nouvelles dans Windows Server 2003.

Si la page de propriétés rencontre une erreur, ADsPropSendErrorMessage peut être appelée avec les données d’erreur appropriées. ADsPropSendErrorMessage stocke tous les messages d’erreur dans une file d’attente. Ces messages seront affichés lors de l’appel suivant de ADsPropShowErrorDialog . Quand ADsPropShowErrorDialog retourne, les messages mis en file d’attente sont supprimés.

Windows Le serveur 2003 introduit la fonction ADsPropSetHwndWithTitle . Cette fonction est similaire à ADsPropSetHwnd, mais elle comprend le titre de la page. Cela active la boîte de dialogue d’erreur affichée par ADsPropShowErrorDialog pour fournir des données plus utiles à l’utilisateur. Si l’extension de la feuille de propriétés utilise la fonction ADsPropShowErrorDialog , l’extension doit utiliser ADsPropSetHwndWithTitle au lieu de ADsPropSetHwnd.

Exemple de code pour l’implémentation de l’objet COM de la feuille de propriétés