Fornecendo ativação sem janelas
O código de criação da janela (ou seja, tudo o que acontece quando você chama CreateWindow
) é caro para ser executado. Um controle que mantém uma janela na tela precisa gerenciar mensagens para a janela. Portanto, os controles sem janelas são mais rápidos do que os controles com janelas.
Uma vantagem adicional dos controles sem janelas é que, ao contrário dos controles com janelas, os controles sem janelas dão suporte à pintura transparente e a regiões de tela não retangulares. Um exemplo comum de um controle transparente é um controle de texto com uma tela de fundo transparente. Os controles pintam o texto, mas não o plano de fundo, portanto, o que estiver sob o texto será exibido. Formulários mais recentes geralmente usam controles não retangulares, como setas e botões redondos.
Muitas vezes, um controle não precisa de uma janela própria e, em vez disso, pode usar os serviços de janela de seu contêiner, desde que o contêiner tenha sido gravado para dar suporte a objetos sem janelas. Controles sem janelas são compatíveis com Contêineres mais antigos. Em contêineres mais antigos não gravados para dar suporte a controles sem janelas, os controles sem janelas criam uma janela quando ativos.
Como os controles sem janelas não têm suas próprias janelas, o contêiner (que tem uma janela) é responsável por fornecer serviços que, de outra forma, teriam sido fornecidos pela própria janela do controle. Por exemplo, se o controle precisar consultar o foco do teclado, capturar o mouse ou obter um contexto de dispositivo, essas operações serão gerenciadas pelo contêiner. O contêiner roteia as mensagens de entrada do usuário enviadas para sua janela para o controle sem janelas apropriado, usando a interface IOleInPlaceObjectWindowless
. (Consulte o SDK do ActiveX para obter uma descrição dessa interface.) As funções membro COleControl
invocam esses serviços do contêiner.
Para fazer seu controle usar a ativação sem janelas, inclua o sinalizador WindowlessActivate no conjunto de sinalizadores retornados por COleControl::GetControlFlags. Por exemplo:
DWORD CMyAxOptCtrl::GetControlFlags()
{
DWORD dwFlags = COleControl::GetControlFlags();
// The control can activate without creating a window.
dwFlags |= windowlessActivate;
return dwFlags;
}
O código para incluir esse sinalizador será gerado automaticamente se você selecionar a opção de ativação sem janelas na página Configurações de Controle do Assistente de Controle ActiveX do MFC.
Quando a ativação sem janelas estiver habilitada, o contêiner delegará mensagens de entrada à interface do controle IOleInPlaceObjectWindowless
. A implementação dessa interface pelo COleControl
envia as mensagens por meio do mapa de mensagens do controle, depois de ajustar as coordenadas do mouse adequadamente. Você pode processar as mensagens como mensagens de janela comuns, adicionando as entradas correspondentes ao mapa da mensagem. Em seus manipuladores para essas mensagens, evite usar a variável de membro m_hWnd (ou qualquer função membro que a use) sem primeiro verificar se seu valor não é NULL.
COleControl
fornece funções membro que invocam a captura do mouse, o foco do teclado, a rolagem e outros serviços de janela do contêiner, conforme apropriado, incluindo:
Em controles sem janelas, você sempre deve usar as funções de membro COleControl
em vez das funções de membro correspondentes CWnd
ou suas funções de API Win32 relacionadas.
Talvez você queira que um controle sem janelas seja o destino de uma operação de arrastar e soltar OLE. Normalmente, isso exigiria que a janela do controle fosse registrada como um destino suspenso. Como o controle não tem nenhuma janela própria, o contêiner usa sua própria janela como um destino suspenso. O controle fornece uma implementação da interface IDropTarget
à qual o contêiner pode delegar chamadas no momento apropriado. Para expor essa interface ao contêiner, substitua COleControl::GetWindowlessDropTarget. Por exemplo:
IDropTarget* CMyAxOptCtrl::GetWindowlessDropTarget()
{
m_DropTarget.m_xDropTarget.AddRef();
return &m_DropTarget.m_xDropTarget;
}