Partager via


Dégradation de manière appropriée en l’absence d’une interface

Étant donné qu’un contrôle ne peut prendre en charge aucune interface autre que IUnknown, un conteneur doit se dégrader correctement lorsqu’il rencontre l’absence d’une interface particulière.

On peut s’interroger sur l’utilité d’un contrôle avec rien de plus que IUnknown. Mais tenez compte des avantages qu’un contrôle reçoit de l’environnement de programmation visuelle d’un conteneur (tel que VB) lorsque le conteneur reconnaît l’objet en tant que contrôle :

  • Un bouton pour l’objet s’affiche dans une boîte à outils.
  • Vous pouvez créer un objet en le faisant glisser de la boîte à outils vers un formulaire.
  • Vous pouvez donner à l’objet un nom reconnu dans l’environnement de programmation visuelle.
  • Le même nom dans (3) ci-dessus peut être utilisé immédiatement pour écrire tout autre code pour les contrôles sur le même formulaire (ou même un autre formulaire).
  • Le conteneur peut fournir automatiquement des points d’entrée de code pour tous les événements disponibles à partir de cet objet.
  • Le conteneur fournit sa propre interface utilisateur de navigation de propriétés pour toutes les propriétés disponibles.

Lorsqu’un objet n’est pas reconnu en tant que contrôle, il perd potentiellement toutes ces fonctionnalités d’intégration très puissantes et utiles. Par exemple, dans Visual Basic 4.0, il est très difficile d’intégrer un objet aléatoire qui n’est pas un contrôle au sens complet, mais qui peut encore avoir des propriétés et des événements. Étant donné que l’idée d’un contrôle par Visual Basic 4 est très restrictive, l’objet ne bénéficie d’aucune des fonctionnalités d’intégration ci-dessus. Mais même un contrôle avec IUnknown, où la seule durée de vie du contrôle détermine l’existence d’une ressource, doit être en mesure d’obtenir les fonctionnalités d’intégration décrites ci-dessus.

Comme les outils actuels nécessitent un grand ensemble d’interfaces de contrôle pour obtenir un avantage quelconque, les contrôles sont généralement conduits à une implémentation excessive, de sorte qu’ils contiennent plus de code qu’ils n’en ont vraiment besoin. Les contrôles qui peuvent être de 7 000 peuvent finir par être de 25 000, ce qui constitue un gros problème de performances dans des domaines tels qu’Internet. Cela a également conduit à l’impression que l’on ne peut implémenter un contrôle qu’avec un seul outil comme le CDK en raison de la complexité de l’implémentation de toutes les interfaces, ce qui a des implications lorsqu’une DLL volumineuse comme OC30.DLL est nécessaire pour un tel contrôle, ce qui augmente l’ensemble de travail. Si toutes les interfaces ne sont pas requises, cela permet à de nombreux développeurs d’écrire des contrôles très petits et légers avec OLE droit ou avec d’autres outils, ce qui réduit la surcharge pour chaque contrôle.

C’est pourquoi cette annexe reconnaît un contrôle comme n’importe quel objet avec un CLSID et une interface IUnknown . Même avec rien de plus qu’IUnknown, un conteneur avec un environnement de programmation doit être en mesure de fournir au moins les fonctionnalités #3 et ) entrée de registre, il gagne #1 et #2. Si l’objet fournit IConnectionPointContainer (et IProvideClassInfo en général) pour un ensemble d’événements, il obtient #5, et s’il prend en charge IDispatch pour les propriétés et les méthodes, il gagne #6, ainsi qu’une meilleure intégration du code dans le conteneur.

En bref, un objet doit être en mesure d’implémenter aussi peu que IDispatch et un jeu d’événements exposé via IConnectionPointContainer pour obtenir toutes ces fonctionnalités visuelles ci-dessus.

Dans cette optique, le tableau suivant décrit ce qu’un conteneur peut faire en l’absence d’une interface possible. Notez que seules les interfaces répertoriées que le conteneur obtiendra directement via QueryInterface. D’autres interfaces, comme IOleInPlaceActiveObject, sont obtenues par d’autres moyens.

Interface Signification de l’absence d’interface
IViewObject2
Le contrôle n’a aucun visuel qu’il dessinera lui-même, donc n’a pas d’étendues définies à fournir. Au moment de l’exécution, le conteneur ne tente tout simplement pas de dessiner quoi que ce soit lorsque cette interface est absente. Au moment de la conception, le conteneur doit au moins dessiner un type de rectangle par défaut avec un nom pour un tel contrôle, afin qu’un utilisateur dans un environnement de programmation visuelle puisse sélectionner l’objet et case activée ses propriétés, méthodes et événements existants. La gestion de l’absence d’IViewObject2 est essentielle pour une bonne prise en charge de la programmation visuelle.
IOleObject
Le contrôle n’a pas besoin du site, et il ne participe à aucune négociation de disposition d’objet incorporé. Toutes les informations (telles que les étendues de contrôle) qu’un conteneur peut attendre de cette interface doivent être remplies avec les valeurs par défaut fournies par le conteneur.
IOleInPlaceObject
Le contrôle n’est pas actif sur place (comme une étiquette) et ne tente donc jamais de s’activer de cette manière. Sa seule activation peut être ses pages de propriétés.
IOleControl
Le contrôle n’a pas de mnémonique et n’utilise pas de propriétés ambiantes, et ne se soucie pas si le conteneur ignore les événements. En l’absence de cette interface, le conteneur n’appelle tout simplement pas ses méthodes.
Idataobject
Le contrôle ne fournit aucun jeu de propriétés ni aucun rendu visuel pouvant être mis en cache, de sorte que le conteneur choisit de mettre en cache une présentation par défaut en l’absence de cette interface (prise en charge de CF_METAFILEPICT, en particulier) et de désactiver les fonctionnalités associées au jeu de propriétés.
IDispatch
Le contrôle n’a pas de propriétés ou de méthodes personnalisées. Le conteneur n’a pas besoin d’essayer d’afficher des propriétés de contrôle dans ce cas et doit interdire les appels de méthode personnalisés que le conteneur ne reconnaît pas comme appartenant à ses propres contrôles étendus (qui peuvent prendre en charge des méthodes et des propriétés). Comme les contrôles étendus délèguent généralement certains appels IDispatch au contrôle, un contrôle étendu ne doit pas s’attendre à ce que le contrôle ait IDispatch du tout.
IConnectionPointContainer
Le contrôle n’ayant aucun événement, le conteneur n’a pas à penser à en gérer.
IProvideClassInfo
IProvideClassInfo2
Le contrôle n’a pas d’informations de type ou d’événements, ou le conteneur doit accéder aux informations de type du contrôle via les entrées de Registre du contrôle. L’existence de cette interface est une optimisation.
ISpecifyPropertyPages
Le contrôle n’a pas de pages de propriétés. Par conséquent, si le conteneur a une interface utilisateur qui les appelle, le conteneur doit désactiver cette interface utilisateur.
Navigation IPerProperty
Le contrôle n’a pas de nom d’affichage lui-même, pas de chaînes et de valeurs prédéterminées et aucune propriété à mappage de page. Cette interface étant presque toujours utilisée pour générer une interface utilisateur de conteneur, ces éléments d’interface utilisateur seraient désactivés en l’absence de cette interface.
IPersist*
Le contrôle n’a pas d’état persistant pour parler de, de sorte que le conteneur n’a pas à se soucier de l’enregistrement des données spécifiques au contrôle. Bien sûr, le conteneur enregistrera ses propres informations sur le contrôle sous sa propre forme ou document, mais le contrôle lui-même n’a rien pour contribuer à ces informations.
IOleCache
IOleCache2
L’objet ne prend pas en charge la mise en cache. Un conteneur peut toujours prendre en charge la mise en cache en créant simplement un cache de données lui-même à l’aide de CreateDataCache.

Containers