Compartir por


Controles ActiveX MFC: Pintar un control ActiveX

En este artículo se describe el proceso de dibujo de controles ActiveX y cómo se puede modificar el código de pintura para optimizar el proceso. (Consulte Optimización del dibujo de controles para obtener técnicas sobre cómo optimizar el dibujo al no tener controles que restauren individualmente objetos GDI previamente seleccionados. Una vez dibujados todos los controles, el contenedor puede restaurar automáticamente los objetos originales).

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.

Los ejemplos de este artículo proceden de un control que crea el Asistente para controles ActiveX de MFC con la configuración predeterminada. Para obtener más información sobre cómo crear una aplicación de control de esqueleto mediante el Asistente para controles ActiveX de MFC, consulte el artículo Asistente para controles ActiveX de MFC.

Se tratan los temas siguientes:

Proceso de dibujo de un control ActiveX

Cuando los controles ActiveX se muestran inicialmente o se vuelven a dibujar, siguen un proceso de dibujo similar a otras aplicaciones desarrolladas mediante MFC, con una distinción importante: los controles ActiveX pueden estar en un estado activo o inactivo.

Un control activo se representa en un contenedor de controles ActiveX mediante una ventana secundaria. Al igual que otras ventanas, es responsable de dibujarse cuando se recibe un mensaje de WM_PAINT. La clase base del control, COleControl, controla este mensaje en su función OnPaint. Esta implementación predeterminada llama a la función OnDraw del control.

Los controles inactivos se dibujan de forma diferente. Cuando el control está inactivo, su ventana es invisible o inexistente, por lo que no puede recibir un mensaje de dibujo. En su lugar, el contenedor de controles llama directamente a la función OnDraw del control. Esto difiere del proceso de dibujo de un control activo en que nunca se llama a la función miembro OnPaint.

Como se describe en los párrafos anteriores, la forma en que se actualiza un control ActiveX depende del estado del control. Sin embargo, dado que el marco llama a la función miembro OnDraw en ambos casos, se agrega la mayoría del código de dibujo en esta función miembro.

La función miembro OnDraw controla la pintura del control. Cuando un control está inactivo, el contenedor de controles llama a OnDraw y pasa el contexto del dispositivo del contenedor de control y las coordenadas del área rectangular ocupada por el control.

El rectángulo que pasa el marco a la función miembro OnDraw contiene el área ocupada por el control. Si el control está activo, la esquina superior izquierda es (0, 0) y el contexto del dispositivo pasado es para la ventana secundaria que contiene el control. Si el control está inactivo, la coordenada superior izquierda no es necesariamente (0, 0) y el contexto del dispositivo pasado es para el contenedor de control que contiene el control.

Nota:

Es importante que sus modificaciones OnDraw no dependan de que el punto superior izquierdo del rectángulo sea igual a (0, 0) y que se dibuje solo dentro del rectángulo que se pasa a OnDraw. Se pueden producir resultados inesperados si dibuja más allá del área del rectángulo.

La implementación predeterminada que proporciona el Asistente para controles ActiveX de MFC en el archivo de implementación de control (.CPP), que se muestra a continuación, dibuja el rectángulo con un pincel blanco y rellena la elipse con el color de fondo actual.

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

   // TODO: Replace the following code with your own drawing code.
   pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
   pdc->Ellipse(rcBounds);
}

Nota:

Al dibujar un control, no deben realizar suposiciones sobre el estado del contexto del dispositivo que se pasa como parámetro pdc a la función OnDraw. En ocasiones, la aplicación contenedora proporciona el contexto del dispositivo y no se inicializará necesariamente en el estado predeterminado. En concreto, seleccione explícitamente los lápices, pinceles, colores, fuentes y otros recursos de los que depende el código de dibujo.

Optimización del código de dibujo

Después de que el control se haya dibujado correctamente, el siguiente paso es optimizar la función OnDraw.

La implementación predeterminada de la pintura de controles ActiveX dibuja la totalidad del área de control. Esto es suficiente para controles simples, pero en muchos casos volver a dibujar el control sería más rápido si solo se volviese a dibujar la parte que necesitaba la actualización, en lugar de todo el control.

La función OnDraw proporciona un método sencillo de optimización al pasar rcInvalid, el área rectangular del control que necesita volver a dibujarse. Use esta área, normalmente más pequeña que toda la área de control, para acelerar el proceso de dibujo.

Dibujo del control mediante metarchivos

En la mayoría de los casos, el parámetro pdc a la función OnDraw apunta a un contexto de dispositivo de pantalla (DC). Sin embargo, al imprimir imágenes del control o durante una sesión de vista previa de impresión, el controlador de dominio recibido para la representación es un tipo especial denominado "dc de metarchivo". A diferencia de un controlador de dominio de pantalla, que controla inmediatamente las solicitudes enviadas, un controlador de dominio de metarchivo almacena las solicitudes que se reproducirán más adelante. Algunas aplicaciones contenedoras también pueden optar por representar la imagen de control mediante un dc de metarchivo cuando está en modo de diseño.

El contenedor puede realizar solicitudes de dibujo de metarchivo a través de dos funciones de interfaz: IViewObject::Draw (también se puede llamar a esta función para el dibujo sin metarchivo) y IDataObject::GetData. Cuando se pasa un DC de metarchivo como uno de los parámetros, el marco de trabajo de MFC realiza una llamada a COleControl::OnDrawMetafile. Dado que se trata de una función miembro virtual, invalide esta función en la clase de control para realizar cualquier procesamiento especial. El comportamiento predeterminado llama a COleControl::OnDraw.

Para asegurarse de que el control se puede dibujar en contextos de dispositivo de metarchivo y de pantalla, solo debe usar funciones miembro compatibles tanto en una pantalla como en un controlador de dominio de metarchivo. Tenga en cuenta que es posible que el sistema de coordenadas no se mida en píxeles.

Dado que la implementación predeterminada de OnDrawMetafile llama a la función OnDraw del control, use solo funciones miembro adecuadas para un metarchivo y un contexto de dispositivo de pantalla, a menos que invalide OnDrawMetafile. A continuación se muestra el subconjunto de funciones miembro CDC que se pueden usar en un metarchivo y en un contexto de dispositivo de pantalla. Para obtener más información sobre estas funciones, vea la clase CDC en la referencia de MFC.

Arc BibBlt Acorde
Ellipse Escape ExcludeClipRect
ExtTextOut FloodFill IntersectClipRect
LineTo MoveTo OffsetClipRgn
OffsetViewportOrg OffsetWindowOrg PatBlt
Pie Polygon Polyline
PolyPolygon RealizePalette RestoreDC
RoundRect SaveDC ScaleViewportExt
ScaleWindowExt SelectClipRgn SelectObject
SelectPalette SetBkColor SetBkMode
SetMapMode SetMapperFlags SetPixel
SetPolyFillMode SetROP2 SetStretchBltMode
SetTextColor SetTextJustification SetViewportExt
SetViewportOrg SetWindowExt SetWindowORg
StretchBlt TextOut

Además de las funciones miembro CDC, hay muchas otras funciones que son compatibles con un controlador de dominio de metarchivo. Entre estas se incluyen las funciones CPalette::AnimatePalette, CFont::CreateFontIndirect y tres funciones miembro de CBrush: CreateBrushIndirect, CreateDIBPatternBrush y CreatePatternBrush.

Las funciones que no se registran en un metarchivo son: DrawFocusRect, DrawIcon, DrawText, ExcludeUpdateRgn, FillRect, FrameRect, GrayString, InvertRect, ScrollDC y TabbedTextOut. Dado que un DC de metarchivo no está asociado realmente a ningún dispositivo, no puede usar SetDIBits, GetDIBits y CreateDIBitmap con un DC de metarchivo. Puede usar SetDIBitsToDevice y StretchDIBits con un DC de metarchivo como destino. CreateCompatibleDC, CreateCompatibleBitmap y CreateDiscardableBitmap no son significativos con un DC de metarchivo.

Otro punto que se debe tener en cuenta al usar un DC de metarchivo es que el sistema de coordenadas puede no medirse en píxeles. Por este motivo, todo el código de dibujo debe ajustarse para ajustarse al rectángulo que se pasa a OnDraw en el parámetro rcBounds. Esto evita el dibujo accidental fuera del control porque rcBounds representa el tamaño de la ventana del control.

Después de implementar la representación del metarchivo para el control, use el contenedor de pruebas para probar el metarchivo. Consulte Probar propiedades y eventos con un contenedor de prueba para obtener información acerca de cómo acceder al contenedor de prueba.

Para probar el metarchivo del control mediante el contenedor de pruebas

  1. En el menú Editar del contenedor de pruebas, haga clic en Insertar nuevo control.

  2. En el cuadro Insertar nuevo control, seleccione el control y haga clic en Aceptar.

    El control aparecerá en el contenedor de prueba.

  3. En el menú Control, haga clic en Dibujar metarchivo.

    Aparecerá una ventana independiente en la que se mostrará el metarchivo. Puede cambiar el tamaño de esta ventana para ver cómo afecta el escalado al metarchivo del control. Puede cerrar esta ventana en cualquier momento.

Consulte también

Controles ActiveX de MFC