Compartir por


Controles ActiveX MFC: Creación de subclases de un control de Windows

En este artículo, se describe el proceso de creación de subclases de un control de Windows común para crear un control ActiveX. La creación de subclases de un control de Windows existente es una forma rápida de desarrollar un control ActiveX. El control nuevo tendrá las capacidades del control de Windows con subclases, como pintar y responder a los clics del mouse. El ejemplo de controles ActiveX MFC BUTTON es un ejemplo de la creación de subclases de un control de Windows.

Importante

ActiveX es una tecnología heredada que no se debe usar para el nuevo desarrollo. Para más información sobre las tecnologías modernas que reemplazan a ActiveX, vea Controles ActiveX.

Para crear subclases de un control de Windows, complete las tareas siguientes:

Invalidación de IsSubclassedControl y PreCreateWindow

Para invalidar PreCreateWindow y IsSubclassedControl, agregue las líneas de código siguientes a la sección protected de la declaración de clase del control:

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
BOOL IsSubclassedControl();

En el archivo de implementación del control (.CPP), agregue las líneas de código siguientes para implementar las dos funciones invalidadas:

// CMyAxSubCtrl::PreCreateWindow - Modify parameters for CreateWindowEx

BOOL CMyAxSubCtrl::PreCreateWindow(CREATESTRUCT& cs)
{
   cs.lpszClass = _T("BUTTON");
   return COleControl::PreCreateWindow(cs);
}

// CMyAxSubCtrl::IsSubclassedControl - This is a subclassed control

BOOL CMyAxSubCtrl::IsSubclassedControl()
{
   return TRUE;
}

Observe que, en este ejemplo, el control de botón de Windows se especifica en PreCreateWindow. Sin embargo, es posible crear subclases de cualquier control estándar de Windows. Para más información sobre los controles estándar de Windows, consulte Controles.

Al crear subclases de un control de Windows, es posible que quiera especificar marcas de estilo de ventana específico (WS_) o de estilo de ventana extendido (WS_EX_) que se van a usar para crear la ventana del control. Si desea establecer valores para estos parámetros en la función miembro PreCreateWindow, modifique los campos de estructura cs.style y cs.dwExStyle. Las modificaciones de estos campos se deben hacer mediante una función OR a fin de conservar las marcas predeterminadas que establece la clase COleControl. Por ejemplo, si el control crea subclases del control BUTTON y se quiere que el control aparezca como una casilla, inserta la línea de código siguiente en la implementación de CSampleCtrl::PreCreateWindow, antes de la instrucción "return":

cs.style |= BS_CHECKBOX;

Esta operación agrega la marca de estilo BS_CHECKBOX, a la vez que deja intacta la marca de estilo predeterminada (WS_CHILD) de la clase COleControl.

Modificación de la función miembro OnDraw

Si desea que el control con subclases mantenga la misma apariencia que el control de Windows correspondiente, la función miembro OnDraw del control solo debe contener una llamada a la función miembro DoSuperclassPaint, tal como en el ejemplo siguiente:

void CMyAxSubCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& /*rcInvalid*/)
{
   if (!pdc)
      return;

   DoSuperclassPaint(pdc, rcBounds);
}

COleControl implementa la función miembro DoSuperclassPaint que utiliza el procedimiento de ventana del control de Windows para dibujar el control en el contexto de dispositivo especificado dentro del rectángulo delimitador. Esto hace que el control sea visible incluso cuando no está activo.

Nota:

La función miembro DoSuperclassPaint solo funcionará con aquellos tipos de control que permiten pasar un contexto de dispositivo como el parámetro wParam de un mensaje WM_PAINT. Esto incluye algunos de los controles estándar de Windows, como SCROLLBAR y BUTTON, y todos los controles comunes. Para los controles que no admiten este comportamiento, tendrá que proporcionar su propio código para mostrar correctamente un control inactivo.

Control de mensajes de ventana reflejados

Por lo general, los controles de Windows envían determinados mensajes de ventana a su ventana primaria. Algunos de estos mensajes, como WM_COMMAND, proporcionan una notificación de una acción que el usuario realiza. Otros, como WM_CTLCOLOR, se usan para obtener información de la ventana primaria. Un control ActiveX suele comunicarse con la ventana primaria por otros medios. Las notificaciones se comunican mediante la activación de eventos (el envío de notificaciones de eventos) y la información sobre el contenedor de control se obtiene mediante el acceso a las propiedades de ambiente del contenedor. Dado que existen estas técnicas de comunicación, no se espera que los contenedores de controles ActiveX procesen ningún mensaje de ventana enviado por el control.

Para evitar que el contenedor reciba los mensajes de ventana que un control de Windows con subclases envía, COleControl crea una ventana adicional para que actúe como el elemento primario del control. Esta ventana adicional, denominada "reflectora", solo se crea para un control ActiveX que crea subclases de un control de Windows y tiene el mismo tamaño y posición que la ventana de control. La ventana reflectora intercepta determinados mensajes de ventana y los devuelve al control. El control, en su procedimiento de ventana, puede procesar estos mensajes reflejados mediante acciones adecuadas para un control ActiveX (por ejemplo, desencadenar un evento). Consulte Identificadores de mensajes de ventana reflejados para una lista de los mensajes de ventana interceptados y sus correspondientes mensajes reflejados.

Se puede diseñar un contenedor de controles ActiveX para llevar a cabo la reflexión de mensajes, lo que elimina la necesidad de que COleControl cree la ventana reflectora y reduce la sobrecarga en tiempo de ejecución para un control de Windows con subclases. COleControl detecta si el contenedor admite esta funcionalidad; para ello, comprueba si hay una propiedad de ambiente MessageReflect con un valor de TRUE.

Si desea controlar un mensaje de ventana reflejado, agregue una entrada a la asignación de mensajes del control e implemente una función de controlador. Dado que los mensajes reflejados no forman parte del conjunto estándar de mensajes definidos por Windows, la Vista de clases no admite agregar dichos controladores de mensajes. Sin embargo, no es difícil agregar manualmente un controlador.

Si desea agregar manualmente un controlador de mensajes para un mensaje de ventana reflejado, haga lo siguiente:

  • En el archivo .H de la clase del control, declare una función de controlador. La función debe tener un tipo de valor devuelto de LRESULT y dos parámetros, con el tipo WPARAM y el tipo LPARAM, respectivamente. Por ejemplo:

    class CMyAxSubCtrl : public COleControl
    {
    
    protected:
       LRESULT OnOcmCommand(WPARAM wParam, LPARAM lParam);
    };
    
  • En el archivo .CPP de la clase del control, agregue una entrada ON_MESSAGE a la asignación de mensajes. Los parámetros de esta entrada deben ser el identificador de mensaje y el nombre de la función de controlador. Por ejemplo:

    BEGIN_MESSAGE_MAP(CMyAxSubCtrl, COleControl)
       ON_MESSAGE(OCM_COMMAND, &CMyAxSubCtrl::OnOcmCommand)
    END_MESSAGE_MAP()
    
  • Además, en el archivo .CPP, implemente la función miembro OnOcmCommand para procesar el mensaje reflejado. Los parámetros wParam e lParam son iguales a los del mensaje de ventana original.

Para un ejemplo de cómo se procesan los mensajes reflejados, consulte el ejemplo de controles ActiveX MFC BUTTON. Muestra un controlador OnOcmCommand que detecta el código de notificación BN_CLICKED y responde activando (enviando) un evento Click.

Consulte también

Controles ActiveX de MFC