TN040: MFC/OLE In-Place redimensionamento e zoom

Observação

A biblioteca Microsoft Foundation Classes (MFC) continua a ser suportada. No entanto, já não estamos a adicionar funcionalidades nem a atualizar a documentação.

Observação

A nota técnica a seguir não foi atualizada desde que foi incluída pela primeira vez na documentação on-line. Como resultado, alguns procedimentos e tópicos podem estar desatualizados ou incorretos. Para obter as informações mais recentes, recomenda-se que pesquise o tópico de interesse no índice de documentação online.

Esta nota discutirá os problemas relacionados à edição no local e como um servidor deve realizar o zoom correto e o redimensionamento no local. Com a ativação in-loco, o conceito WYSIWYG é levado um passo adiante, com contentores e servidores a cooperar entre si e, em particular, a interpretar a especificação OLE de forma semelhante.

Devido à estreita interação entre um contentor e um servidor que suporta a ativação no local, deve corresponder a certas expectativas dos utilizadores finais.

  • A exibição da apresentação (o metarquivo desenhado no COleServerItem::OnDraw override) deve ter exatamente o mesmo aspeto que quando é desenhada para edição (exceto que as ferramentas de edição não estejam visíveis).

  • Quando o contêiner aumenta o zoom, a janela do servidor também deve!

  • Tanto o contêiner quanto o servidor devem exibir objetos para edição usando as mesmas métricas. Isso significa usar um modo de mapeamento baseado no número de pixels lógicos por polegada — e não pixels físicos por polegada, ao renderizar no dispositivo de exibição.

Observação

Como a ativação in-loco só se aplica a itens incorporados (não vinculados), o zoom só se aplica a objetos incorporados. Você verá APIs em ambos COleServerDoc e COleServerItem que são usadas para zoom. A razão para essa dicotomia é que apenas as funções que são válidas para itens vinculados e incorporados estão em COleServerItem (isso permite que você tenha uma implementação comum) e as COleServerDoc funções que são válidas apenas para objetos incorporados estão localizadas na classe (da perspetiva do servidor, é o documento que está incorporado).

A maior parte da carga é colocada no implementador do servidor, na medida em que o servidor deve estar ciente do fator de zoom do contêiner e modificar sua interface de edição conforme apropriado. Mas como o servidor determina o fator de zoom que o contêiner está usando

Suporte MFC para zoom

O fator de zoom atual pode ser determinado chamando COleServerDoc::GetZoomFactor. Chamar isso quando o documento não estiver ativo no local sempre resultará em um fator de zoom de 100% (ou proporção 1:1). Chamá-lo enquanto estiver ativo no local pode retornar algo diferente de 100%.

Para obter um exemplo de zoom corretamente, consulte o exemplo de MFC OLE HIERSVR. O zoom no HIERSVR é complicado pelo fato de exibir texto, e o texto, em geral, não é dimensionado de forma linear (dicas, convenções tipográficas, larguras de design e alturas complicam a questão). Ainda assim, o HIERSVR é uma referência razoável para implementar o zoom corretamente, assim como o MFC Tutorial SCRIBBLE (etapa 7).

COleServerDoc::GetZoomFactor determina o fator de zoom com base em várias métricas diferentes disponíveis, seja do contentor ou da implementação das suas classes COleServerItem e COleServerDoc. Em resumo, o fator de zoom atual é determinado pela seguinte fórmula:

Position Rectangle (PR) / Container Extent (CE)

O Retângulo de Posição é determinado pelo contentor. É devolvido ao servidor durante a ativação no local quando COleClientItem::OnGetItemPosition é chamado e é atualizado quando o contêiner chama COleServerDoc::OnSetItemRects do servidor, com uma chamada para COleClientItem::SetItemRects.

A EXTENSÃO DO RECIPIENTE é um pouco mais complexa de calcular. Se o contêiner tiver chamado COleServerItem::OnSetExtent (com uma chamada para COleClientItem::SetExtent), então a EXTENSÃO DO CONTÊINER é esse valor convertido em pixels com base no número de pixels por polegada lógica. Se o contêiner não tiver chamado SetExtent (o que geralmente é o caso), então o CONTAINER EXTENT é o tamanho retornado de COleServerItem::OnGetExtent. Assim, se o contêiner não chamou SetExtent, a estrutura assume que, se o fizesse, o contêiner o teria chamado com 100% da extensão natural (o valor retornado de COleServerItem::GetExtent). Dito de outra forma, a estrutura assume que o contêiner está exibindo 100% (nem mais, nem menos) do item.

É importante notar que, embora COleServerItem::OnSetExtent e COleServerItem::OnGetExtent tenham nomes semelhantes, eles não manipulam o mesmo atributo do item. OnSetExtent é chamado para informar ao servidor quanto do objeto está visível no contêiner (independentemente do fator de zoom) e OnGetExtent é chamado pelo contêiner para determinar o tamanho ideal do objeto.

Ao analisar cada uma das APIs envolvidas, você pode obter uma imagem mais clara:

COleServerItem::OnGetExtent

Esta função deve retornar o "tamanho natural" em unidades HIMÉTRICAS do item. A melhor maneira de pensar no "tamanho natural" é defini-lo como o tamanho que pode aparecer quando impresso. O tamanho retornado aqui é constante para um determinado conteúdo de item (muito parecido com o metaarquivo, que é constante para um item específico). Esse tamanho não muda quando o zoom é aplicado ao item. Geralmente não muda quando o recipiente dá ao item mais ou menos espaço chamando OnSetExtent. Um exemplo de alteração pode ser o de um editor de texto simples, sem capacidade de "margem", que organiza o texto com base na última extensão enviada pelo contentor. Se um servidor mudar, o servidor provavelmente deve definir o OLEMISC_RECOMPOSEONRESIZE bit no registro do sistema (consulte a documentação do OLE SDK para obter mais informações sobre essa opção).

COleServerItem::OnSetExtent

Esta função é chamada quando o contêiner mostra "mais ou menos" do objeto. A maioria dos contêineres não vai chamar isso. A implementação padrão armazena o último valor recebido do contêiner em 'm_sizeExtent', que é usado no COleServerDoc::GetZoomFactor cálculo do valor CONTAINER EXTENT descrito acima.

COleServerDoc::OnSetItemRects

Esta função é chamada apenas quando o documento está ativo em lugar. Ele é chamado quando o contêiner atualiza a posição do item ou o recorte aplicado ao item. O RETÂNGULO DE POSIÇÃO, como discutido acima, fornece o numerador para o cálculo do fator de zoom. Um servidor pode solicitar que a posição do item seja alterada chamando COleServerDoc::RequestPositionChange. O contentor pode ou não responder a este pedido chamando OnSetItemRects (através de uma chamada para COleServerItem::SetItemRects).

COleServerDoc::OnDraw

É importante perceber que o metaarquivo criado pela substituição de COleServerItem::OnDraw produz exatamente o mesmo metaarquivo, independentemente do fator de zoom atual. O contêiner dimensionará o metarquivo conforme apropriado. Esta é uma distinção importante entre a OnDraw da vista e o OnDraw do servidor. A exibição lida com o zoom, o item apenas cria um metaarquivo com zoom e deixa para o contêiner fazer o zoom apropriado.

A melhor maneira de garantir que o seu servidor se comporte corretamente é usar a implementação de COleServerDoc::GetZoomFactor se o documento estiver ativo localmente.

Suporte MFC para redimensionamento de In-Place

MFC implementa totalmente a interface de redimensionamento no local conforme descrito na especificação OLE 2. A interface do utilizador é suportada pela classe COleResizeBar, uma mensagem WM_SIZECHILD personalizada, e tratamento especial desta mensagem no COleIPFrameWnd.

Você pode querer implementar um tratamento diferente dessa mensagem do que é fornecido pela estrutura. Conforme descrito acima, a estrutura deixa os resultados do redimensionamento no local ao cuidado do contentor — o servidor responde à alteração no fator de zoom. Se o contêiner reagir definindo a EXTENSÃO DO CONTÊINER e o RETÂNGULO DE POSIÇÃO durante o processamento do seu COleClientItem::OnChangeItemPosition (chamado como resultado de uma chamada para COleServerDoc::RequestPositionChange), o redimensionamento in-loco resultará em mostrar "mais ou menos" do item na janela de edição. Se o recipiente reagir apenas definindo o RETÂNGULO DE POSIÇÃO durante o processamento de COleClientItem::OnChangeItemPosition, o fator de zoom mudará e o item será mostrado "ampliado ou reduzido".

Um servidor pode controlar (até certo ponto) o que acontece durante essa negociação. Uma planilha, por exemplo, pode optar por mostrar mais ou menos células quando o usuário redimensiona a janela enquanto edita o item no local. Um processador de texto pode optar por alterar as "margens da página" para que sejam iguais à janela e reempacotar o texto para a nova margem. Os servidores implementam isso alterando a extensão natural (o tamanho retornado de COleServerItem::OnGetExtent) quando o redimensionamento é feito. Isso fará com que tanto o retângulo de POSIÇÃO quanto a EXTENSÃO DO CONTÊINER mudem na mesma quantidade, resultando no mesmo fator de zoom, mas em uma área de visualização maior ou menor. Além disso, mais ou menos do documento será visível no metaficheiro gerado pelo OnDraw. Nesse caso, o próprio documento é alterado quando o usuário redimensiona o item, em vez de apenas a área de visualização.

Você pode implementar o redimensionamento personalizado e ainda aproveitar a interface do utilizador fornecida por COleResizeBar substituindo a mensagem WM_SIZECHILD na classe COleIPFrameWnd. Para obter mais informações sobre as especificidades do WM_SIZECHILD, consulte a Nota Técnica 24.

Ver também

Notas técnicas por número
Notas técnicas por categoria