Compartir a través de


Controles ActiveX MFC: Usar fuentes

Si el control ActiveX muestra texto, puede permitir que el usuario del control cambie la apariencia del texto cambiando una propiedad de fuente. Las propiedades de fuente se implementan como objetos de fuente y pueden ser de uno de los dos tipos: stock o personalizado. Las propiedades Stock Font son propiedades de fuente implementadas previamente que puede agregar mediante el asistente para agregar propiedades. Las propiedades de fuente personalizadas no se implementan previamente y el desarrollador de controles determina el comportamiento y el uso de la propiedad.

En este artículo se tratan los temas siguientes:

Uso de la propiedad Stock Font

Las propiedades Stock Font se implementan previamente mediante la clase COleControl. Además, también hay disponible una página de propiedades Font estándar, lo que permite al usuario cambiar varios atributos del objeto de fuente, como su nombre, tamaño y estilo.

Acceda al objeto de fuente a través de las funciones GetFont, SetFont e InternalGetFont de COleControl. El usuario de control tendrá acceso al objeto de fuente a través de las funciones GetFont y SetFont de la misma manera que cualquier otra propiedad Get/Set. Cuando se requiera acceso al objeto de fuente desde un control, use la función InternalGetFont.

Como se describe en Controles ActiveX MFC: Propiedades, agregar propiedades de stock es fácil con el Asistente para agregar propiedades. Elija la propiedad Font y el asistente para agregar propiedades insertará automáticamente la entrada Stock Font en el mapa de distribución del control.

Para agregar la propiedad Stock Font mediante el asistente para agregar propiedades

  1. Cargue el proyecto del control.

  2. En la vista de clases, expanda el nodo de biblioteca del control.

  3. Haga clic con el botón derecho en el nodo de interfaz del control (el segundo nodo del nodo de biblioteca) para abrir el menú contextual.

  4. En el menú contextual, haga clic en Agregar y después en Agregar propiedad.

    Se abrirá el Asistente para agregar propiedades.

  5. En el cuadro Nombre de la propiedad, haga clic en Fuente.

  6. Haga clic en Finalizar

El asistente para agregar propiedades agrega la línea siguiente al mapa de distribución de controles, ubicado en el archivo de implementación de la clase de control:

DISP_STOCKPROP_FONT()

Además, el asistente para agregar propiedades agrega la siguiente línea al archivo .IDL de control:

[id(DISPID_FONT)] IFontDisp* Font;

La propiedad Stock Caption es un ejemplo de una propiedad de texto que se puede dibujar mediante la información de la propiedad Stock Font. Al agregar la propiedad Stock Caption al control se usan pasos similares a los usados para la propiedad Stock Font.

Para agregar la propiedad estándar Caption mediante el Asistente para agregar propiedades

  1. Cargue el proyecto del control.

  2. En la vista de clases, expanda el nodo de biblioteca del control.

  3. Haga clic con el botón derecho en el nodo de interfaz del control (el segundo nodo del nodo de biblioteca) para abrir el menú contextual.

  4. En el menú contextual, haga clic en Agregar y después en Agregar propiedad.

    Se abrirá el Asistente para agregar propiedades.

  5. En el cuadro Nombre de propiedad, haga clic en Caption (Título).

  6. Haga clic en Finalizar

El asistente para agregar propiedades agrega la línea siguiente al mapa de distribución de controles, ubicado en el archivo de implementación de la clase de control:

DISP_STOCKPROP_CAPTION()

Modificación de la función OnDraw

La implementación predeterminada de OnDraw usa la fuente del sistema Windows para todo el texto que se muestra en el control. Esto significa que debe modificar el código OnDraw seleccionando el objeto de fuente en el contexto del dispositivo. Para ello, llame a COleControl::SelectStockFont y pase el contexto del dispositivo del control, como se muestra en el ejemplo siguiente:

CFont* pOldFont;
TEXTMETRIC tm;
const CString& strCaption = InternalGetText();

pOldFont = SelectStockFont(pdc);
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
pdc->Ellipse(rcBounds);
pdc->GetTextMetrics(&tm);
pdc->SetTextAlign(TA_CENTER | TA_TOP);
pdc->ExtTextOut((rcBounds.left + rcBounds.right) / 2,
(rcBounds.top + rcBounds.bottom - tm.tmHeight) / 2,
ETO_CLIPPED, rcBounds, strCaption, strCaption.GetLength(), NULL);

pdc->SelectObject(pOldFont);

Una vez modificada la función OnDraw para usar el objeto de fuente, cualquier texto del control se muestra con características de la propiedad Stock Font del control.

Uso de propiedades Custom Font en el control

Además de la propiedad Stock Font, el control ActiveX puede tener propiedades Font personalizadas. Para agregar una propiedad de fuente personalizada, debe:

Implementación de una propiedad Custom Font

Para implementar una propiedad Font personalizada, use el asistente para agregar propiedades para agregar la propiedad y, a continuación, haga algunas modificaciones en el código. En las secciones siguientes se describe cómo agregar la propiedad personalizada HeadingFont al control Sample.

Para agregar la propiedad Font personalizada mediante el asistente para agregar propiedades
  1. Cargue el proyecto del control.

  2. En la vista de clases, expanda el nodo de biblioteca del control.

  3. Haga clic con el botón derecho en el nodo de interfaz del control (el segundo nodo del nodo de biblioteca) para abrir el menú contextual.

  4. En el menú contextual, haga clic en Agregar y después en Agregar propiedad.

    Se abrirá el Asistente para agregar propiedades.

  5. En el cuadro Nombre de la propiedad, escriba un nombre para la propiedad. En este ejemplo, use HeadingFont.

  6. En Tipo de implementación, haga clic en Métodos Get/Set.

  7. En el cuadro Tipo de propiedad, seleccione IDispatch* para el tipo de propiedad.

  8. Haga clic en Finalizar

El asistente para agregar propiedades crea el código para agregar la propiedad personalizada HeadingFont a la clase CSampleCtrl y al archivo SAMPLE.IDL. Dado que HeadingFont es un tipo de propiedad Get/Set, el asistente para agregar propiedades modifica la asignación de distribución de la clase CSampleCtrl para incluir una entrada de macro deDISP_PROPERTY_EX_IDDISP_PROPERTY_EX:

DISP_PROPERTY_EX_ID(CMyAxFontCtrl, "HeadingFont", dispidHeadingFont,
   GetHeadingFont, SetHeadingFont, VT_DISPATCH)

La macro DISP_PROPERTY_EX asocia el nombre de propiedad HeadingFont con sus métodos correspondientes Get y Set de la clase CSampleCtrl, GetHeadingFont y SetHeadingFont. También se especifica el tipo del valor de propiedad; en este caso, VT_FONT.

El asistente para agregar propiedades también agrega una declaración en el archivo de encabezado de control (. H) para las funciones GetHeadingFont y SetHeadingFont, y agrega sus plantillas de función en el archivo de implementación de control (.CPP):

IDispatch* CWizardGenCtrl::GetHeadingFont(void)
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());

   // TODO: Add your dispatch handler code here

   return NULL;
}

void CWizardGenCtrl::SetHeadingFont(IDispatch* /*pVal*/)
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());

   // TODO: Add your property handler code here

   SetModifiedFlag();
}

Por último, el asistente para agregar propiedades modifica el archivo .IDL de control agregando una entrada para la propiedad HeadingFont:

[id(1)] IDispatch* HeadingFont;

Modificaciones en el código de control

Ahora que ha agregado la propiedad HeadingFont al control, debe hacer algunos cambios en el encabezado de control y en los archivos de implementación para admitir completamente la nueva propiedad.

En el archivo de encabezado de control (.H), agregue la siguiente declaración de una variable miembro protegida:

protected:
   CFontHolder m_fontHeading;

En el archivo de implementación de control (.CPP), haga lo siguiente:

  • Inicialice m_fontHeading en el constructor de control.

    CMyAxFontCtrl::CMyAxFontCtrl()
       : m_fontHeading(&m_xFontNotification)
    {
       InitializeIIDs(&IID_DNVC_MFC_AxFont, &IID_DNVC_MFC_AxFontEvents);
    }
    
  • Declare una estructura FONTDESC estática que contenga atributos predeterminados de la fuente.

    static const FONTDESC _fontdescHeading =
    { sizeof(FONTDESC), OLESTR("MS Sans Serif"), FONTSIZE(12), FW_BOLD,
      ANSI_CHARSET, FALSE, FALSE, FALSE };
    
  • En la función miembro DoPropExchange del control, agregue una llamada a la función PX_Font. Esto proporciona inicialización y persistencia para la propiedad Font personalizada.

    void CMyAxFontCtrl::DoPropExchange(CPropExchange* pPX)
    {
       ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
       COleControl::DoPropExchange(pPX);
    
       // [...other PX_ function calls...]
       PX_Font(pPX, _T("HeadingFont"), m_fontHeading, &_fontdescHeading);
    }
    
  • Termine de implementar la función miembro GetHeadingFont del control.

    IDispatch* CMyAxFontCtrl::GetHeadingFont(void)
    {
       AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
       return m_fontHeading.GetFontDispatch();
    }
    
  • Termine de implementar la función miembro SetHeadingFont del control.

    void CMyAxFontCtrl::SetHeadingFont(IDispatch* pVal)
    {
       AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
       m_fontHeading.InitializeFont(&_fontdescHeading, pVal);
       OnFontChanged();    //notify any changes
       SetModifiedFlag();
    }
    
  • Modifique la función miembro OnDraw del control para definir una variable que contenga la fuente seleccionada anteriormente.

    CFont* pOldHeadingFont;
    
  • Modifique la función miembro OnDraw del control para seleccionar la fuente personalizada en el contexto del dispositivo agregando la siguiente línea dondequiera que se use la fuente.

    pOldHeadingFont = SelectFontObject(pdc, m_fontHeading);
    
  • Modifique la función miembro OnDraw del control para seleccionar la fuente anterior en el contexto del dispositivo agregando la siguiente línea después de usar la fuente.

    pdc->SelectObject(pOldHeadingFont);
    

Una vez implementada la propiedad Font personalizada, se debe implementar la página de propiedades Font estándar, lo que permite a los usuarios de control cambiar la fuente actual del control. Para agregar el id. de página de propiedades para la página de propiedades Font estándar, inserte la siguiente línea después de la macro BEGIN_PROPPAGEIDS:

PROPPAGEID(CLSID_CFontPropPage)

También debe incrementar el parámetro de recuento de la macro BEGIN_PROPPAGEIDS en uno. Esto se ilustra en la línea siguiente:

BEGIN_PROPPAGEIDS(CMyAxFontCtrl, 2)

Una vez realizados estos cambios, vuelva a generar todo el proyecto para incorporar la funcionalidad adicional.

Procesamiento de notificaciones Font

En la mayoría de los casos, el control debe saber cuándo se han modificado las características del objeto de fuente. Cada objeto de fuente es capaz de proporcionar notificaciones cuando cambia mediante una llamada a una función miembro de la interfaz IFontNotification, implementada por COleControl.

Si el control usa la propiedad Stock Font, sus notificaciones son controladas por la función miembro OnFontChanged de COleControl. Al agregar propiedades de fuente personalizadas, puede hacer que usen la misma implementación. En el ejemplo de la sección anterior, esto se realizó pasando &m_xFontNotification al inicializar la variable miembro m_fontHeading .

Implementing multiple font object interfaces.
Implementar varias interfaces de objetos de fuente

Las líneas sólidas de la ilustración anterior muestran que ambos objetos de fuente usan la misma implementación de IFontNotification. Esto podría causar problemas si desea distinguir qué fuente cambió.

Una manera de distinguir entre las notificaciones de objeto de fuente del control es crear una implementación independiente de la interfaz IFontNotification para cada objeto de fuente del control. Esta técnica permite optimizar el código de dibujo actualizando solo la cadena o las cadenas que usan la fuente modificada recientemente. En las secciones siguientes se muestran los pasos necesarios para implementar interfaces de notificación independientes para una segunda propiedad Font. Se supone que la segunda propiedad de fuente es la propiedad HeadingFont que se agregó en la sección anterior.

Implementación de una nueva interfaz de notificación de fuente

Para distinguir entre las notificaciones de dos o más fuentes, se debe implementar una nueva interfaz de notificación para cada fuente usada en el control. En las secciones siguientes se describe cómo implementar una nueva interfaz de notificación de fuente modificando el encabezado de control y los archivos de implementación.

Adiciones al archivo de encabezado

En el archivo de encabezado de control (. H), agregue las siguientes líneas a la declaración de clase:

protected:
   BEGIN_INTERFACE_PART(HeadingFontNotify, IPropertyNotifySink)
      INIT_INTERFACE_PART(CMyAxFontCtrl, HeadingFontNotify)
      STDMETHOD(OnRequestEdit)(DISPID);
   STDMETHOD(OnChanged)(DISPID);
   END_INTERFACE_PART(HeadingFontNotify)

Esto crea una implementación de la interfaz IPropertyNotifySink denominada HeadingFontNotify. Esta nueva interfaz contiene un método denominado OnChanged.

Adiciones al archivo de implementación

En el código que inicializa la fuente de encabezado (en el constructor de control), cambie &m_xFontNotification a &m_xHeadingFontNotify. Después agregue el siguiente código:

STDMETHODIMP_(ULONG) CMyAxFontCtrl::XHeadingFontNotify::AddRef()
{
   METHOD_MANAGE_STATE(CMyAxFontCtrl, HeadingFontNotify)
      return 1;
}
STDMETHODIMP_(ULONG) CMyAxFontCtrl::XHeadingFontNotify::Release()
{
   METHOD_MANAGE_STATE(CMyAxFontCtrl, HeadingFontNotify)
      return 0;
}

STDMETHODIMP CMyAxFontCtrl::XHeadingFontNotify::QueryInterface(REFIID iid, LPVOID FAR* ppvObj)
{
   METHOD_MANAGE_STATE(CMyAxFontCtrl, HeadingFontNotify)
      if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IPropertyNotifySink))
      {
         *ppvObj = this;
         AddRef();
         return NOERROR;
      }
   return ResultFromScode(E_NOINTERFACE);
}

STDMETHODIMP CMyAxFontCtrl::XHeadingFontNotify::OnChanged(DISPID)
{
   METHOD_MANAGE_STATE(CMyAxFontCtrl, HeadingFontNotify)
      pThis->InvalidateControl();
   return NOERROR;
}

STDMETHODIMP CMyAxFontCtrl::XHeadingFontNotify::OnRequestEdit(DISPID)
{
   return NOERROR;
}

Los métodos AddRef y Release de la interfaz IPropertyNotifySink realizan un seguimiento del recuento de referencias del objeto de control ActiveX. Cuando el control obtiene acceso al puntero de interfaz, el control llama a AddRef para incrementar el recuento de referencias. Cuando el control finaliza con el puntero, llama a Release, de la misma manera que GlobalFree podría llamarse para liberar un bloque de memoria global. Cuando el recuento de referencias de esta interfaz llega a cero, se puede liberar la implementación de la interfaz. En este ejemplo, la función QueryInterface devuelve un puntero a una interfaz IPropertyNotifySink en un objeto determinado. Esta función permite que un control ActiveX consulte un objeto para determinar qué interfaces admite.

Una vez realizados estos cambios en el proyecto, recompile el proyecto y use un contenedor de pruebas para probar la interfaz. Consulte Probar propiedades y eventos con un contenedor de prueba para obtener información acerca de cómo acceder al contenedor de prueba.

Consulte también

Controles ActiveX de MFC
Controles ActiveX MFC: Usar imágenes en un control ActiveX
Controles ActiveX MFC: Usar páginas de propiedades estándar