Compartilhar via


Degradando-se graciosamente na ausência de uma interface

Como um controle pode não oferecer suporte a qualquer interface diferente de IUnknown, um contêiner precisa degradar normalmente quando encontrar a ausência de qualquer interface específica.

Pode-se questionar a utilidade de um controle com nada mais do que IUnknown. Mas considere as vantagens que um controle recebe do ambiente de programação visual de um contêiner (como VB) quando o contêiner reconhece o objeto como um controle:

  • Um botão para o objeto aparece em uma caixa de ferramentas.
  • Pode-se criar um objeto arrastando-o da caixa de ferramentas para um formulário.
  • Pode-se dar ao objeto um nome que é reconhecido no ambiente de programação visual.
  • O mesmo nome em (3) acima pode ser usado imediatamente na escrita de qualquer outro código para controles no mesmo formulário (ou mesmo em um formulário diferente).
  • O contêiner pode fornecer automaticamente pontos de entrada de código para quaisquer eventos disponíveis a partir desse objeto.
  • O contêiner fornece sua própria interface do usuário de navegação de propriedade para todas as propriedades disponíveis.

Quando um objeto não é reconhecido como um controle, ele potencialmente perde todos esses recursos de integração muito poderosos e benéficos. Por exemplo, no Visual Basic 4.0 é muito difícil realmente integrar algum objeto aleatório que não é um controle no sentido completo, mas ainda pode ter propriedades e eventos. Como a ideia do Visual Basic 4 de um controle é muito restritiva, o objeto não ganha nenhum dos recursos de integração acima. Mas mesmo um controle com IUnknown, onde o mero tempo de vida do controle determina a existência de algum recurso, deve ser capaz de obter os recursos de integração descritos acima.

Como as ferramentas atuais exigem um grande conjunto de interfaces de controle para obter qualquer vantagem, os controles geralmente são levados a uma implementação excessiva, de modo que eles contêm mais código do que realmente precisam. Controles que poderiam ser 7K podem acabar sendo 25K, o que é um grande problema de desempenho em áreas como a Internet. Isso também levou à percepção de que só se pode implementar um controle com uma ferramenta como o CDK devido à complexidade de implementar todas as interfaces, e isso tem implicações quando uma grande DLL como OC30.DLL é necessária para tal controle, aumentando o conjunto de trabalho. Se nem todas as interfaces são necessárias, isso abre muitos desenvolvedores para escrever controles muito pequenos e leves com OLE direto ou com outras ferramentas também, minimizando a sobrecarga para cada controle.

É por isso que este apêndice reconhece um controle como qualquer objeto com um CLSID e uma interface IUnknown. Mesmo com nada mais do que IUnknown, um contêiner com um ambiente de programação deve ser capaz de fornecer pelo menos os recursos #3 e ) entrada de registro, ele ganha #1 e #2. Se o objeto fornecer IConnectionPointContainer (e IProvideClassInfo em geral) para algum conjunto de eventos, ele ganhará #5 e, se oferecer suporte a IDispatch para propriedades e métodos, ganhará #6, bem como melhor integração de código no contêiner.

Em resumo, um objeto deve ser capaz de implementar tão pouco quanto IDispatch e um conjunto de eventos expostos por meio de IConnectionPointContainer para obter todos esses recursos visuais acima.

Com isso em mente, a tabela a seguir descreve o que um contêiner pode fazer na ausência de qualquer interface possível. Observe que somente as interfaces estão listadas que o contêiner obterá diretamente por meio de QueryInterface. Outras interfaces, como IOleInPlaceActiveObject, são obtidas por outros meios.

Interface Significado de Ausência de Interface
IViewObject2
O controle não tem visuais que ele mesmo desenhará, então não tem extensões definidas para fornecer. Em tempo de execução, o contêiner simplesmente não tenta desenhar nada quando essa interface está ausente. Em tempo de design, o contêiner deve pelo menos desenhar algum tipo de retângulo padrão com um nome para tal controle, para que um usuário em um ambiente de programação visual possa selecionar o objeto e verificar suas propriedades, métodos e eventos existentes. Lidar com a ausência de IViewObject2 é fundamental para um bom suporte à programação visual.
IOleObject
O controle não precisa do site de forma alguma, nem participa de qualquer negociação de layout de objeto incorporado. Qualquer informação (como extensões de controle) que um contêiner possa esperar dessa interface deve ser preenchida com padrões fornecidos pelo contêiner.
IOleInPlaceObject
O controle não fica ativo no local (como um rótulo) e, portanto, nunca tenta ativar dessa maneira. Sua única ativação pode ser suas páginas de propriedades.
IOleControl
O controle não tem mnemônicos e não usa propriedades ambientais, e não se importa se o contêiner ignora eventos. Na ausência dessa interface, o contêiner simplesmente não chama seus métodos.
IDataObject
O controle não fornece conjuntos de propriedades nem renderizações visuais que possam ser armazenadas em cache, portanto, o contêiner optaria por armazenar em cache alguma apresentação padrão na ausência dessa interface (suporte para CF_METAFILEPICT, especificamente) e desabilitar qualquer funcionalidade relacionada ao conjunto de propriedades.
IDispatch
O controle não tem propriedades ou métodos personalizados. O contêiner não precisa tentar mostrar nenhuma propriedade de controle nesse caso e não deve permitir quaisquer chamadas de método personalizadas que o contêiner não reconheça como pertencentes a seus próprios controles estendidos (que podem oferecer suporte a métodos e propriedades). Como os controles estendidos geralmente delegam determinadas chamadas IDispatch ao controle, um controle estendido não deve esperar que o controle tenha IDispatch.
IConnectionPointContainer
O controle não tem eventos, então o contêiner não precisa pensar em lidar com nenhum.
IProvideClassInfo
IProvideClassInfo2
O controle não tem informações de tipo ou eventos, ou o contêiner precisa entrar nas informações de tipo do controle por meio das entradas de registro do controle. A existência dessa interface é uma otimização.
ISpecifyPropertyPages
O controle não tem páginas de propriedades, portanto, se o contêiner tiver qualquer interface do usuário que as invoque, o contêiner deverá desabilitar essa interface do usuário.
IPerPropertyBrowsing
O controle não tem nenhum nome de exibição em si, nenhuma cadeia de caracteres e valores predeterminados e nenhuma propriedade para mapeamento de página. Essa interface é quase sempre usada para gerar a interface do usuário do contêiner, portanto, esses elementos da interface do usuário seriam desabilitados na ausência dessa interface.
IPersist*
O controle não tem nenhum estado persistente para falar, portanto, o contêiner não precisa se preocupar em salvar dados específicos do controle. O contêiner, é claro, salvará suas próprias informações sobre o controle em seu próprio formulário ou documento, mas o controle em si não tem nada a contribuir para essa informação.
IOleCache
IOleCache2
O objeto não oferece suporte ao cache. Um contêiner ainda pode oferecer suporte ao cache apenas criando um cache de dados usando CreateDataCache.

Contêineres