Partilhar via


Controles ActiveX MFC: usando fontes

Se o controle ActiveX exibir texto, você poderá permitir que o usuário de controle altere a aparência do texto alterando uma propriedade de fonte. As propriedades da fonte são implementadas como objetos de fonte e podem ser um dos dois tipos: estoque ou personalizado. As propriedades da Fonte de Estoque são propriedades de fonte pré-implementadas que você pode adicionar usando o Assistente para Adicionar Propriedade. As propriedades da Fonte Personalizada não são pré-implementadas e o desenvolvedor de controle determina o comportamento e o uso da propriedade.

Este artigo aborda os seguintes tópicos:

Usando a propriedade da Fonte de Estoque

As propriedades da Fonte de Estoque são pre-implementadas pela classe COleControl. Além disso, uma página de propriedade de Fonte padrão também está disponível, permitindo que o usuário altere vários atributos do objeto de fonte, como seu nome, tamanho e estilo.

Acesse o objeto de fonte por meio das funções GetFont, SetFont e InternalGetFont de COleControl. O usuário de controle acessará o objeto de fonte por meio das funções GetFont e SetFont da mesma maneira que qualquer outra propriedade de Get/Set. Quando o acesso ao objeto de fonte for necessário de dentro de um controle, use a função InternalGetFont.

Conforme discutido nos Controles ActiveX do MFC: Propriedades, adicionar propriedades de estoque é fácil com o Assistente para Adicionar Propriedade. Você escolhe a propriedade de Fonte e o Assistente para Adicionar Propriedade insere automaticamente a entrada de fonte de estoque no mapa de expedição do controle.

Para adicionar a propriedade de fonte de estoque usando o Assistente para Adicionar Propriedade

  1. Carregue o projeto do controle.

  2. No Modo de Exibição de Classe, expanda o nó de biblioteca do controle.

  3. Clique com o botão direito do mouse no nó de interface do controle (o segundo nó do nó da biblioteca) para abrir o menu de atalho.

  4. No menu de atalho, clique em Adicionar e, em seguida, em Adicionar Propriedade.

    Isso abre o Assistente para Adicionar Propriedade.

  5. Na caixa Nome da propriedade, clique em Fonte.

  6. Clique em Concluir.

O Assistente para Adicionar Propriedade adiciona a seguinte linha ao mapa de expedição do controle, localizado no arquivo de implementação da classe de controle:

DISP_STOCKPROP_FONT()

Além disso, o Assistente para Adicionar Propriedade adiciona a linha a seguir ao controle. Arquivo IDL:

[id(DISPID_FONT)] IFontDisp* Font;

A propriedade legenda de estoque é um exemplo de uma propriedade de texto que pode ser desenhada usando as informações da propriedade de Fonte de Estoque. Adicionar a propriedade legenda de estoque ao controle usa etapas semelhantes às usadas para a propriedade fonte de estoque.

Para adicionar a propriedade de legenda de estoque usando o Assistente para Adicionar Propriedade

  1. Carregue o projeto do controle.

  2. No Modo de Exibição de Classe, expanda o nó de biblioteca do controle.

  3. Clique com o botão direito do mouse no nó de interface do controle (o segundo nó do nó da biblioteca) para abrir o menu de atalho.

  4. No menu de atalho, clique em Adicionar e, em seguida, em Adicionar Propriedade.

    Isso abre o Assistente para Adicionar Propriedade.

  5. Na caixa Nome da propriedade, clique em Legenda.

  6. Clique em Concluir.

O Assistente para Adicionar Propriedade adiciona a seguinte linha ao mapa de expedição do controle, localizado no arquivo de implementação da classe de controle:

DISP_STOCKPROP_CAPTION()

Modificando o método OnDraw

A implementação padrão usa OnDraw a fonte do sistema Windows para todo o texto exibido no controle. Isso significa que você deve modificar o código OnDraw selecionando o objeto de fonte no contexto do dispositivo. Para fazer isso, chame COleControl::SelectStockFont e passe o contexto do dispositivo do controle, conforme mostrado no exemplo a seguir:

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);

Depois que a função OnDraw tiver sido modificada para usar o objeto de fonte, qualquer texto dentro do controle será exibido com características da propriedade fonte de estoque do controle.

Usando propriedades da Fonte Personalizadas em seu controle

Além da propriedade fonte de estoque, o controle ActiveX pode ter propriedades de fonte personalizadas. Para adicionar uma propriedade de fonte personalizada, você deve:

Implementar uma Propriedade de Fonte Personalizada

Para implementar uma propriedade de fonte personalizada, use o Assistente para Adicionar Propriedade para adicionar a propriedade e, em seguida, faça algumas modificações no código. As seções a seguir descrevem como adicionar a propriedade personalizada HeadingFont ao controle de Amostra.

Para adicionar a propriedade de fonte de personalizada usando o Assistente para Adicionar Propriedade
  1. Carregue o projeto do controle.

  2. No Modo de Exibição de Classe, expanda o nó de biblioteca do controle.

  3. Clique com o botão direito do mouse no nó de interface do controle (o segundo nó do nó da biblioteca) para abrir o menu de atalho.

  4. No menu de atalho, clique em Adicionar e, em seguida, em Adicionar Propriedade.

    Isso abre o Assistente para Adicionar Propriedade.

  5. Na caixa Nome da propriedade, digite um nome para a propriedade. Para este exemplo, use HeadingFont.

  6. Para o Tipo de Implementação, clique em Métodos Get/Set.

  7. Na caixa Tipo de Propriedade, selecione IDispatch* para o tipo da propriedade.

  8. Clique em Concluir.

O Assistente para Adicionar Propriedade cria o código para adicionar a propriedade personalizada HeadingFont à classe CSampleCtrl e ao SAMPLE. Arquivo IDL. Como HeadingFont é um tipo de propriedade de Get/Set, o Assistente para Adicionar Propriedade modifica o mapa CSampleCtrl de expedição da classe para incluir uma DISP_PROPERTY_EX_IDDISP_PROPERTY_EX entrada de macro:

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

A macro DISP_PROPERTY_EX associa o nome da propriedade HeadingFont aos métodos Get e Set de classe CSampleCtrl correspondentes GetHeadingFont e SetHeadingFont. O tipo do valor da propriedade também é especificado, nesse caso, VT_FONT.

O Assistente para Adicionar Propriedade também adiciona uma declaração no arquivo de cabeçalho de controle (. H) para as funções GetHeadingFont e SetHeadingFont, e adiciona seus modelos de função no arquivo de implementação de controle (. 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 fim, o Assistente para Adicionar Propriedade modifica o controle. Arquivo IDL adicionando uma entrada para a propriedade HeadingFont:

[id(1)] IDispatch* HeadingFont;

Modificações no código de controle

Agora que você adicionou a propriedade HeadingFont ao controle, você deve fazer algumas alterações no cabeçalho de controle e nos arquivos de implementação para dar suporte total à nova propriedade.

No arquivo de cabeçalho de controle (. H), adicione a seguinte declaração de uma variável de membro protegida:

protected:
   CFontHolder m_fontHeading;

No arquivo de implementação de controle (. CPP), faça o seguinte:

  • Inicialize m_fontHeading no construtor de controle.

    CMyAxFontCtrl::CMyAxFontCtrl()
       : m_fontHeading(&m_xFontNotification)
    {
       InitializeIIDs(&IID_DNVC_MFC_AxFont, &IID_DNVC_MFC_AxFontEvents);
    }
    
  • Declare uma estrutura FONTDESC estática contendo atributos padrão da fonte.

    static const FONTDESC _fontdescHeading =
    { sizeof(FONTDESC), OLESTR("MS Sans Serif"), FONTSIZE(12), FW_BOLD,
      ANSI_CHARSET, FALSE, FALSE, FALSE };
    
  • Na função membro de controle DoPropExchange, adicione uma chamada à função PX_Font. Isso fornece inicialização e persistência para sua propriedade de fonte 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);
    }
    
  • Conclua a implementação da função membro GetHeadingFont de controle .

    IDispatch* CMyAxFontCtrl::GetHeadingFont(void)
    {
       AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
       return m_fontHeading.GetFontDispatch();
    }
    
  • Conclua a implementação da função membro SetHeadingFont de controle .

    void CMyAxFontCtrl::SetHeadingFont(IDispatch* pVal)
    {
       AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
       m_fontHeading.InitializeFont(&_fontdescHeading, pVal);
       OnFontChanged();    //notify any changes
       SetModifiedFlag();
    }
    
  • Modifique a função de membro OnDraw de controle para definir uma variável para manter a fonte selecionada anteriormente.

    CFont* pOldHeadingFont;
    
  • Modifique a função de membro OnDraw de controle para selecionar a fonte personalizada no contexto do dispositivo adicionando a linha a seguir onde quer que a fonte seja usada.

    pOldHeadingFont = SelectFontObject(pdc, m_fontHeading);
    
  • Modifique a função de membro OnDraw de controle para selecionar a fonte anterior novamente ao contexto do dispositivo adicionando a linha a seguir após a fonte ter sido usada.

    pdc->SelectObject(pOldHeadingFont);
    

Depois que a propriedade fonte personalizada foi implementada, a página de propriedade fonte padrão deverá ser implementada, permitindo que os usuários de controle alterem a fonte atual do controle. Para adicionar a ID da página de propriedades para a página de propriedade fonte padrão, insira a seguinte linha após a macro BEGIN_PROPPAGEIDS:

PROPPAGEID(CLSID_CFontPropPage)

Você também deve incrementar o parâmetro de contagem de sua macro BEGIN_PROPPAGEIDS em um. A linha abaixo ilustra o seguinte:

BEGIN_PROPPAGEIDS(CMyAxFontCtrl, 2)

Depois que essas alterações forem feitas, recompile todo o projeto para incorporar a funcionalidade adicional.

Processar Notificações de Fonte

Na maioria dos casos, o controle precisa saber quando as características do objeto de fonte foram modificadas. Cada objeto de fonte é capaz de fornecer notificações quando ele é alterado chamando uma função membro da interface IFontNotification, implementada por COleControl.

Se o controle usar a propriedade fonte de estoque, suas notificações serão tratadas pela função de OnFontChanged membro de COleControl. Ao adicionar propriedades de fonte personalizadas, você pode fazer com que elas usem a mesma implementação. No exemplo da seção anterior, isso foi feito passando &m_xFontNotification ao inicializar a variável de membro m_fontHeading .

Implementing multiple font object interfaces.
Implementar várias interfaces de objeto de Fonte

As linhas sólidas na figura acima mostram que ambos os objetos de fonte estão usando a mesma implementação de IFontNotification. Isso poderia causar problemas se você quisesse distinguir qual fonte foi alterada.

Uma maneira de distinguir entre as notificações de objeto de fonte do controle é criar uma implementação separada da interface IFontNotification para cada objeto de fonte no controle. Essa técnica permite otimizar o código de desenho atualizando apenas a cadeia de caracteres ou cadeias de caracteres que usam a fonte modificada recentemente. As seções a seguir demonstram as etapas necessárias para implementar interfaces de notificação separadas para uma segunda propriedade de fonte. A segunda propriedade de fonte é considerada a propriedade HeadingFont que foi adicionada na seção anterior.

Implementando uma nova interface de notificação de fonte

Para distinguir entre as notificações de duas ou mais fontes, uma nova interface de notificação deve ser implementada para cada fonte usada no controle. As seções a seguir descrevem como implementar uma nova interface de notificação de fonte modificando o cabeçalho de controle e os arquivos de implementação.

Adições ao arquivo de cabeçalho

No arquivo de cabeçalho de controle (. H), adicione as seguintes linhas à declaração de classe:

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

Isso cria uma implementação da interface IPropertyNotifySink chamada HeadingFontNotify. Essa nova interface contém um método chamado OnChanged.

Adições ao Arquivo de Implementação

No código que inicializa a fonte do título (no construtor de controle), altere &m_xFontNotification para &m_xHeadingFontNotify. Em seguida, adicione o seguinte 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;
}

Os métodos AddRef e Release na interface IPropertyNotifySink controlam a contagem de referência para o objeto de controle ActiveX. Quando o controle obtém acesso ao ponteiro de interface, o controle chama AddRef para incrementar a contagem de referências. Quando o controle é concluído com o ponteiro, ele chama Release, da mesma forma que GlobalFree pode ser chamado para liberar um bloco de memória global. Quando a contagem de referências para essa interface for zero, a implementação da interface poderá ser liberada. Neste exemplo, a função QueryInterface retorna um ponteiro para uma interface IPropertyNotifySink em um objeto específico. Essa função permite que um controle ActiveX consulte um objeto para determinar quais interfaces ele dá suporte.

Depois que essas alterações forem feitas em seu projeto, recompile o projeto e use o Contêiner de Teste para testar a interface. Confira Testar Propriedades e Eventos com o Contêiner de Testes para obter informações sobre como acessar o contêiner de testes.

Confira também

Controles ActiveX do MFC
Controles ActiveX do MFC: usando imagens em um controle ActiveX
Controles ActiveX do MFC: usando páginas de propriedade de estoque