Implémentation de l’objet COM 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 feuille de propriétés a été inscrite dans le spécificateur d’affichage de la classe.

Implémentation d’IShellExtInit

Une fois l’objet COM d’extension de la feuille de propriétés instancié, la méthode IShellExtInit::Initialize est appelée. IShellExtInit::Initialize fournit l’extension de feuille de propriétés avec un objet IDataObject qui contient des données relatives à l’objet de répertoire appliqué par la feuille de propriétés.

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 de répertoire que l’extension de la 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 . DSDISPLAYSPECOPTIONS contient des données de configuration à utiliser 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 nombre de références de l’objet IDataObject. Cette interface doit être libérée lorsqu’elle n’est plus nécessaire.

Implémentation d’IShellPropSheetExt

Une fois que IShellExtInit::Initialize est retourné, la méthode IShellPropSheetExt::AddPages est appelée. L’extension de 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 transmettant 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 passée à 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 nécessaire pour ajouter des pages à la feuille de propriétés, elle ne doit pas appeler la fonction de rappel passée à 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 feuille de propriétés est indépendant de la page de propriétés. Dans de nombreux cas, il est souhaitable 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 lorsqu’elle traite le 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 passant 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;

N’oubliez pas qu’une fois IShellPropSheetExt::AddPages appelé, la feuille de propriétés libère l’objet d’extension de feuille de propriétés et ne l’utilise plus 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 a été libérée et le pointeur n’est pas valide. Pour corriger ce problème, incrémentez le nombre de références pour l’objet d’extension lorsque la page est ajoutée, puis relâchez 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 de la page de propriétés n’est créée qu’à la première fois que la page s’affiche. Si l’utilisateur ne sélectionne jamais la page d’extension, la page n’est jamais créée et détruite. En conséquence, l’objet d’extension n’est jamais libéré, donc une fuite de mémoire se produit. 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 PSPCB_RELEASE , le paramètre ppsp du 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 Notification

Étant donné que les pages d’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 notification fonctionne 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 passant l’objet IDataObject obtenu à partir de IShellExtInit::Initialize et le nom de l’objet répertoire. Il n’est pas nécessaire d’incrémenter le nombre de références de l’interface IDataObject , car l’objet de notification créé par la fonction ADsPropCreateNotifyObj effectue cette opération. Le handle d’objet de notification fourni par ADsPropCreateNotifyObj doit être enregistré pour une utilisation ultérieure. ADsPropCreateNotifyObj peut être appelé pendant IShellExtInit::Initialize ou IShellPropSheetExt::AddPages. Lorsque l’extension de la feuille de propriétés est arrêtée, elle doit envoyer un message WM_ADSPROP_NOTIFY_EXIT à l’objet de notification. Cela entraîne la destruction de l’objet de notification. Il est préférable d’effectuer cette opération lorsque la fonction PropSheetPageProc reçoit la notification PSPCB_RELEASE .

L’extension de feuille de propriétés peut obtenir des données en plus de celles fournies par le format presse-papiers CFSTR_DSOBJECTNAMES en appelant ADsPropGetInitInfo. L’un des avantages de l’utilisation d’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 fonctions COM, ADsPropGetInitInfo n’incrémente pas le nombre de références pour l’objet IDirectoryObject . L’objet 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 boîte de dialogue de page. La feuille de propriétés étant le parent direct de la page de propriétés, vous pouvez obtenir le handle de la feuille de propriétés en appelant la fonction GetParent avec le handle de 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 active ensuite le bouton Appliquer.

feuilles de propriétés Multiple-Selection

Avec les systèmes d’exploitation Windows Server 2003 et versions ultérieures, les composants logiciels enfichables MMC d’administration 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 presse-papiers CFSTR_DSOBJECTNAMES dans IShellExtInit::Initialize contiendra plusieurs structures 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 plutôt qu’un nom créé par l’extension. Pour obtenir le nom unique, demandez le format de presse-papiers CFSTR_DS_MULTISELECTPROPPAGE à partir du IDataObject obtenu à partir de IShellExtInit::Initialize. Ces données sont un HGLOBAL qui contient une chaîne Unicode terminée par null qui est le nom unique. Ce nom unique est ensuite passé à la fonction ADsPropCreateNotifyObj pour créer l’objet de notification. L’exemple de fonction CreateADsNotificationObject dans Exemple de code pour l’implémentation de l’objet COM de feuille de propriétés montre comment procéder correctement, tout en étant compatible 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 du tableau DSOBJECT . Pour cette raison, ADsPropGetInitInfo fournit uniquement les attributs IDirectoryObject et capables d’écriture pour le premier objet du tableau. Les autres objets du tableau ne sont pas liés à.

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

Nouveautés avec Windows Server 2003

Les fonctionnalités suivantes sont nouvelles avec Windows Server 2003.

Si la page de propriétés rencontre une erreur, ADsPropSendErrorMessage peut être appelé 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 la prochaine fois qu’ADsPropShowErrorDialog sera appelé. Lorsque ADsPropShowErrorDialog retourne, les messages mis en file d’attente sont supprimés.

Windows Server 2003 introduit la fonction ADsPropSetHwndWithTitle . Cette fonction est similaire à ADsPropSetHwnd, mais inclut 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 feuille de propriétés utilise la fonction ADsPropShowErrorDialog , l’extension doit utiliser ADsPropSetHwndWithTitle plutôt que ADsPropSetHwnd.

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