Mise à disposition de l'activation sans fenêtre
Le code de création de fenêtre (autrement dit, tout ce qui se passe lorsque vous appelez CreateWindow
) est coûteux à exécuter. Un contrôle qui gère une fenêtre affichée à l'écran doit gérer les messages de la fenêtre. Les contrôles sans fenêtre sont donc plus rapides que les contrôles avec fenêtre.
Un autre avantage des contrôles sans fenêtre est que, contrairement aux contrôles fenêtrés, ils prennent en charge les zones d'affichage sans teinte non-rectangulaires. Un exemple classique d'un contrôle transparent est un contrôle de texte avec un arrière-plan transparent. Les contrôles peignent le texte mais pas l'arrière-plan, ainsi tout ce qui est sous le texte transparaît. De nouvelles formes utilisent souvent des contrôles non-rectangulaires, tels que les flèches et les boutons arrondis.
Souvent, un contrôle n'a pas besoin d'avoir sa propre fenêtre, mais peut utiliser les services de fenêtre de son conteneur, à condition que le conteneur ait été écrit pour prendre en charge les objets sans fenêtre. Les contrôles sans fenêtre sont à compatibilité descendante avec les conteneurs plus anciens. Dans les conteneurs anciens et non écrits pour prendre en charge les contrôles sans fenêtre, les contrôles sans fenêtre créent une fenêtre lorsqu'ils sont actifs.
Les contrôles sans fenêtre n'ont pas leurs propres fenêtres, le conteneur (qui lui possède une fenêtre) est chargé de fournir des services qui auraient dans tous les cas été fournis par la propre fenêtre du contrôle. Par exemple, si votre contrôle a besoin d'interroger le focus clavier, d'intercepter la souris ou d'obtenir le contexte de périphérique, ces opérations sont gérées par le conteneur. Le conteneur achemine les messages d'entrée utilisateur envoyés dans la fenêtre au contrôle sans fenêtre approprié, à l'aide de l'interface IOleInPlaceObjectWindowless
. (Voir le Kit de développement logiciel (SDK) ActiveX pour une description de cette interface.) COleControl
les fonctions membres appellent ces services à partir du conteneur.
Pour que votre contrôle utilise l’activation sans fenêtre, incluez l’indicateur windowlessActivate dans l’ensemble d’indicateurs retournés par COleControl ::GetControlFlags. Par exemple :
DWORD CMyAxOptCtrl::GetControlFlags()
{
DWORD dwFlags = COleControl::GetControlFlags();
// The control can activate without creating a window.
dwFlags |= windowlessActivate;
return dwFlags;
}
Le code à inclure cet indicateur est généré automatiquement si vous sélectionnez l’option d’activation sans fenêtre dans la page Contrôle Paramètres de l’Assistant Contrôle ActiveX MFC.
Lorsque l'activation sans fenêtre est opérationnelle, le conteneur délègue les messages d'entrée à l'interface IOleInPlaceObjectWindowless
du contrôle. L'implémentation de COleControl
pour cette interface distribue les messages via la table des messages de votre contrôle, après avoir analysé les coordonnées de la souris correctement. Vous pouvez traiter les messages comme des messages de fenêtre ordinaires, en ajoutant des entrées correspondantes dans la table des messages. Dans vos gestionnaires pour ces messages, évitez d’utiliser la variable membre m_hWnd (ou toute fonction membre qui l’utilise) sans case activée d’abord que sa valeur n’est pas NULL.
COleControl
fournit les fonctions membres qui appellent la capture de la souris, le focus clavier, le défilement et d'autres services de la fenêtre du conteneur selon le cas, notamment :
Dans les contrôles sans fenêtre, vous devez toujours utiliser les fonctions membres COleControl
au lieu des fonctions membres CWnd
correspondantes ou leurs fonctions API Win32 associées.
Vous pouvez souhaiter qu'un contrôle sans fenêtre soit la cible d'une opération glisser-déplacer OLE. Normalement, cela suppose que la fenêtre de contrôle soit stockée en tant que cible de déplacement. Puisque le contrôle n'a aucune fenêtre qui lui est propre, le conteneur utilise sa propre fenêtre comme cible de déplacement. Le contrôle fournit une implémentation de l'interface de IDropTarget
à laquelle le conteneur peut déléguer des appels au moment opportun. Pour exposer cette interface au conteneur, remplacez COleControl ::GetWindowlessDropTarget. Par exemple :
IDropTarget* CMyAxOptCtrl::GetWindowlessDropTarget()
{
m_DropTarget.m_xDropTarget.AddRef();
return &m_DropTarget.m_xDropTarget;
}