TN040: redimensionamento/zoom in-loco MFC/OLE

Observação

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

Essa observação discutirá os problemas relacionados à edição in-loco e como um servidor deve realizar o dimensionamento correto de zoom e in-loco. Com a ativação in-loco, o conceito WYSIWYG é levado um passo adiante nesse contêiner e os servidores cooperam entre si e, em particular, interpretam a especificação OLE da mesma maneira.

Devido à interação próxima entre um contêiner e um servidor que dá suporte à ativação in-loco, várias expectativas do usuário final devem ser mantidas:

  • A exibição da apresentação (o meta-arquivo desenhado na substituição COleServerItem::OnDraw) deve ter exatamente a mesma aparência de quando ele é desenhado para edição (exceto que as ferramentas de edição não estão visíveis).

  • Quando o contêiner é ampliado, a janela do servidor também deve ser.

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

Observação

Como a ativação in-loco só se aplica a itens inseridos (não vinculados), o zoom só se aplica a objetos inseridos. Você verá APIs em COleServerDoc e COleServerItem que são usadas para zoom. O motivo dessa dicotomia é que somente as funções válidas para itens vinculados e inseridos estão em COleServerItem (isso permite que você tenha uma implementação comum) e as funções válidas somente para objetos inseridos estão localizadas na classe (da perspectiva do servidor, é o documentoCOleServerDoc que está inserido).

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

Suporte do 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 taxa de 1:1). Chamá-lo enquanto ativo in-loco pode retornar algo diferente de 100%.

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

COleServerDoc::GetZoomFactor determina o fator de zoom com base em várias métricas diferentes disponíveis no contêiner ou na implementação de suas classes COleServerItem e COleServerDoc. Em suma, o fator de zoom atual é determinado pela seguinte fórmula:

Position Rectangle (PR) / Container Extent (CE)

O POSITION RECTANGLE é determinado pelo contêiner. Ele é retornado ao servidor durante a ativação in-loco local quando COleClientItem::OnGetItemPosition é chamado e é atualizado quando o contêiner chama o servidor COleServerDoc::OnSetItemRects (com uma chamada para COleClientItem::SetItemRects).

A CONTAINER EXTENT é um pouco mais complexa de calcular. Se o contêiner tiver chamado COleServerItem::OnSetExtent (com uma chamada para COleClientItem::SetExtent), a CONTAINER EXTENT será 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 (que geralmente é o caso), CONTAINER EXTENT será o tamanho retornado de COleServerItem::OnGetExtent. Portanto, se o contêiner não tiver chamado SetExtent, a estrutura fará a suposição de que, se tivesse chamado, o contêiner o teria chamado com 100% da extensão natural (o valor retornado de COleServerItem::GetExtent). De outra forma, a estrutura pressupõe que o contêiner esteja exibindo 100% (não mais, nem menos) do item.

É importante observar 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 examinar cada uma das APIs envolvidas, você pode obter uma imagem mais clara:

COleServerItem::OnGetExtent

Essa função deve retornar o "tamanho natural" em unidades HIMETRIC do item. A melhor maneira de pensar no "tamanho natural" é defini-lo como o tamanho que o item teria na impressão. O tamanho retornado aqui é constante para um conteúdo de item específico (assim como o meta-arquivo, que é constante para um item específico). Esse tamanho não muda quando o zoom é aplicado ao item. Normalmente, ele não muda quando o contêiner dá mais ou menos espaço ao item chamando OnSetExtent. Um exemplo de alteração pode ser o de um editor de texto simples sem nenhuma funcionalidade de "margem" que encapsulou texto com base na última extensão enviada pelo contêiner. Se um servidor for alterado, o servidor provavelmente deverá definir o bit OLEMISC_RECOMPOSEONRESIZE no Registro do sistema (confira a documentação do SDK do OLE para mais informações sobre essa opção).

COleServerItem::OnSetExtent

Essa função é chamada quando o contêiner mostra "mais ou menos" do objeto. A maioria dos contêineres não chamará isso. A implementação padrão armazena o último valor recebido do contêiner em 'm_sizeExtent', que é usado em COleServerDoc::GetZoomFactor ao calcular o valor de EXTENSÃO DE CONTÊINER descrito acima.

COleServerDoc::OnSetItemRects

Essa função é chamada somente quando o documento está ativo no local. Ela é chamada quando o contêiner atualiza a posição do item ou o recorte aplicado ao item. O POSITION RECTANGLE, conforme discutido acima, fornece o numerador para o cálculo do fator zoom. Um servidor pode solicitar que a posição do item seja alterada chamando COleServerDoc::RequestPositionChange. O contêiner pode ou não responder a essa solicitação chamando OnSetItemRects (com uma chamada para COleServerItem::SetItemRects).

COleServerDoc::OnDraw

É importante perceber que o meta-arquivo criado pela substituição de COleServerItem::OnDraw produz exatamente o mesmo meta-arquivo, independentemente do fator de zoom atual. O contêiner dimensionará o meta-arquivo conforme apropriado. Essa é uma distinção importante entre OnDraw da exibição e o item do servidor OnDraw. A exibição manipula o zoom, o item apenas cria um meta-arquivo habilitado para zoom e o deixa a critério do contêiner fazer o zoom apropriado.

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

Suporte do MFC para redimensionamento no local

O MFC implementa totalmente a interface de redimensionamento no local conforme descrito na especificação OLE 2. A interface do usuário é compatível com a classe COleResizeBar, uma mensagem personalizada WM_SIZECHILD e um tratamento especial dessa mensagem em COleIPFrameWnd.

Talvez você queira implementar um tratamento dessa mensagem diferente do que o fornecido pela estrutura. Conforme descrito acima, a estrutura deixa os resultados do redimensionamento no local a critério do contêiner. O servidor responde à alteração no fator de zoom. Se o contêiner reagir definindo CONTAINER EXTENT e POSITION RECTANGLE durante o processamento de 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 contêiner reagir apenas definindo o POSITION RECTANGLE durante o processamento de COleClientItem::OnChangeItemPosition, o fator de zoom será alterado e o item será mostrado "ampliado ou fora".

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 durante a edição do item in-loco. Um processador de palavras pode optar por alterar as "margens de página" para que elas sejam iguais à janela e quebrar outra vez o texto para a nova margem. Os servidores implementam isso alterando a extensão natural (do tamanho retornado de COleServerItem::OnGetExtent) quando o redimensionamento é feito. Isso fará com que POSITION RECTANGLE e CONTAINER EXTENT sejam alterados pela mesma quantidade, resultando no mesmo fator de zoom, mas em uma área de exibição maior ou menor. Além disso, mais ou menos do documento ficará visível no meta-arquivo gerado por OnDraw. Nesse caso, o documento em si está mudando quando o usuário redimensiona o item, em vez de apenas a área de exibição.

Você pode implementar o redimensionamento personalizado e ainda aproveitar a interface do usuário fornecida por COleResizeBar substituindo a mensagem de WM_SIZECHILD em sua classe COleIPFrameWnd. Para mais informações sobre as especificidades de WM_SIZECHILD, confira a Nota Técnica 24.

Confira também

Observações técnicas por número
Observações técnicas por categoria