Proporcionar activación sin ventana
El código de creación de ventanas (es decir, todo lo que sucede cuando se llama a CreateWindow
) es costoso al ejecutarse. Un control que mantiene una ventana en la pantalla tiene que administrar los mensajes de la ventana. Por lo tanto, los controles sin ventana son más rápidos que aquellos con ventanas.
Una ventaja adicional de los controles sin ventanas es que, a diferencia de aquellos con ventanas, los controles sin ventana admiten regiones de pantalla transparentes y no rectangulares. Un ejemplo común de un control transparente es un control de texto con un fondo transparente. Los controles pintan el texto pero no el fondo, por lo cual lo que está debajo del texto se ve. Los formularios más recientes suelen usar controles no rectangulares, como flechas y botones redondos.
A menudo, un control no necesita una ventana propia y puede usar los servicios de ventana de su contenedor, siempre que el contenedor se haya escrito para admitir objetos sin ventana. Los controles sin ventana son compatibles con los contenedores de versiones anteriores. En los contenedores antiguos no escritos para admitir los controles sin ventana, los controles sin ventana crean una ventana cuando están activas.
Debido a que los contenedores sin ventanas no las tienen, el contenedor (que sí tiene una ventana) es responsable de proporcionar servicios que, de lo contrario, habrían sido proporcionados por la propia ventana del control. Por ejemplo, si el control necesita consultar el foco del teclado, capture el mouse u obtenga un contexto del dispositivo, el contenedor administra estas operaciones. El contenedor enruta los mensajes de entrada de usuario enviados a su ventana al control sin ventana adecuado, mediante la interfaz IOleInPlaceObjectWindowless
. (Consulte el SDK de ActiveX para obtener una descripción de esta interfaz). las funciones miembro COleControl
invocan estos servicios desde el contenedor.
Para que el control use la activación sin ventanas, incluya la marca windowlessActivate en el conjunto de marcas devueltas por COleControl::GetControlFlags. Por ejemplo:
DWORD CMyAxOptCtrl::GetControlFlags()
{
DWORD dwFlags = COleControl::GetControlFlags();
// The control can activate without creating a window.
dwFlags |= windowlessActivate;
return dwFlags;
}
El código para incluir esta marca se genera automáticamente si se selecciona la opción Activación sin ventanas en la página Configuración de control del asistente de control ActiveX de MFC.
Cuando la activación sin ventanas está habilitada, el contenedor delegará los mensajes de entrada en la interfaz del control IOleInPlaceObjectWindowless
. La implementación COleControl
de esta interfaz envía los mensajes a través del mapa de mensajes del control después de ajustar las coordenadas del mouse correctamente. Se pueden procesar el mensaje igual que los mensajes normales de la ventana, al agregar las entradas correspondientes a la asignación de mensajes. En los controladores de estos mensajes, evite usar la variable miembro m_hWnd (o cualquier función miembro que la use) sin primero comprobar que su valor no es NULL.
COleControl
proporciona funciones miembro que invocan la captura del mouse, el foco del teclado, el desplazamiento y otros servicios de ventana del contenedor según corresponda, entre los que se incluyen:
En los controles sin ventanas, siempre se debe usar las funciones miembro COleControl
en lugar de las funciones miembro correspondientes CWnd
o sus funciones API Win32 relacionadas.
Es posible que desee que un control sin ventana sea el destino de una operación OLE de arrastrar y colocar. Normalmente, esto requeriría que la ventana del control se registre como un destino de colocación. Dado que el control no tiene ninguna ventana propia, el contenedor usa su propia ventana como destino de colocación. El control proporciona una implementación de la interfaz IDropTarget
a la que el contenedor puede delegar llamadas en el momento adecuado. Para exponer esta interfaz al contenedor, invalide COleControl::GetWindowlessDropTarget. Por ejemplo:
IDropTarget* CMyAxOptCtrl::GetWindowlessDropTarget()
{
m_DropTarget.m_xDropTarget.AddRef();
return &m_DropTarget.m_xDropTarget;
}