Partilhar via


TN030: personalizando impressão e visualização de impressão

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.

Esta nota descreve o processo de personalização da impressão e da visualização de impressão, bem como as finalidades das rotinas de retorno de chamada usadas em CView e das rotinas de retorno de chamada e funções de membro de CPreviewView.

O problema

O MFC fornece uma solução completa para a maioria das necessidades de impressão e visualização de impressão. Na maioria dos casos, é necessário um pouco de código adicional para ter uma exibição capaz de imprimir e visualizar. No entanto, há maneiras de otimizar a impressão que exigem esforço significativo por parte do desenvolvedor, e alguns aplicativos precisam adicionar elementos específicos da interface do usuário ao modo de visualização de impressão.

Impressão eficiente

Quando um aplicativo MFC imprime usando os métodos padrão, o Windows direciona todas as chamadas de saída da GDI (Interface Gráfica do Dispositivo) para um meta-arquivo na memória. Quando EndPage é chamado, o Windows reproduz o meta-arquivo uma vez para cada faixa física que a impressora requer para imprimir uma página. Durante essa renderização, a GDI consulta frequentemente o Procedimento de Anulação para determinar se deve continuar. Normalmente, o procedimento de anulação permite que as mensagens sejam processadas de modo que o usuário possa anular o trabalho de impressão usando uma caixa de diálogo de impressão.

Infelizmente, isso pode deixar o processo de impressão lento. Se a impressão no aplicativo precisar ser mais rápida do que ocorre usando a técnica padrão, você precisa implementar as faixas manuais.

Para fazer criar as faixas manualmente, você precisa implementar novamente o loop de impressão de modo que OnPrint seja chamado várias vezes por página (uma vez por faixa). O loop de impressão é implementado na função OnFilePrint em viewprnt.cpp. Em sua classe derivada de CView, você sobrecarrega essa função para que a entrada do mapa de mensagens para manipular o comando de impressão chame sua função de impressão. Copie a rotina OnFilePrint e altere o loop de impressão para implementar a faixa. Você provavelmente também quer passar o retângulo de faixas para suas funções de impressão para que possa otimizar o desenho com base na seção da página que está sendo impressa.

Em segundo lugar, você precisa chamar QueryAbort com frequência ao desenhar a faixa. Caso contrário, o Procedimento de Anulação não será chamado e o usuário não poderá cancelar o trabalho de impressão.

A Visualização de Impressão, em essência, tenta transformar a exibição em uma emulação de uma impressora. Por padrão, a área do cliente da janela principal é usada para exibir uma ou duas páginas totalmente dentro da janela. O usuário consegue de ampliar uma área da página para vê-la mais detalhadamente. Com suporte adicional, o usuário pode até mesmo conseguir editar o documento no modo de visualização.

Personalizando a visualização de impressão

Esta nota aborda apenas um aspecto da modificação da visualização de impressão: adicionar a interface do usuário ao modo de visualização. Outras modificações são possíveis, mas estão fora do escopo desta discussão.

Para adicionar a interface do usuário ao modo de visualização

  1. Derive uma classe de exibição de CPreviewView.

  2. Adicione manipuladores de comando para os aspectos da interface do usuário desejados.

  3. Se você estiver adicionando aspectos visuais à exibição, substitua OnDraw e execute o desenho após chamar CPreviewView::OnDraw.

OnFilePrintPreview

Esse é o manipulador de comandos para a visualização de impressão. Sua implementação padrão é:

void CView::OnFilePrintPreview()
{
    // In derived classes, implement special window handling here
    // Be sure to Unhook Frame Window close if hooked.

    // must not create this on the frame. Must outlive this function
    CPrintPreviewState* pState = new CPrintPreviewState;

    if (!DoPrintPreview(AFX_IDD_PREVIEW_TOOLBAR, this,
        RUNTIME_CLASS(CPreviewView), pState))
    {
        // In derived classes, reverse special window handling
        // here for Preview failure case

        TRACE0("Error: DoPrintPreview failed");
        AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
        delete pState;  // preview failed to initialize, delete State now
    }
}

DoPrintPreview ocultará o painel principal do aplicativo. Barras de Controle, como a barra de status, podem ser mantidas especificando-as no membro pState->dwStates (essa é uma máscara de bits, e os bits das barras de controle individuais são definidos por AFX_CONTROLBAR_MASK( AFX_IDW_MYBAR)). A janela pState->nIDMainPane é a janela que será automaticamente ocultada e exibida novamente. DoPrintPreview, então, criará uma barra de botões para a interface do usuário de visualização padrão. Se for necessário algum tratamento especial da janela, como ocultar ou mostrar outras janelas, isso deverá ser feito antes de DoPrintPreview ser chamado.

Por padrão, quando a visualização de impressão é concluída, ela retorna as barras de controle para os estados originais e deixa o painel principal visível. Se tratamento especial for necessário, ele deverá ser feito em uma substituição de EndPrintPreview. Se DoPrintPreview falhar, também forneça tratamento especial.

DoPrintPreview é chamado com:

  • A ID de recurso do modelo de caixa de diálogo para a barra de ferramentas de visualização.

  • Um ponteiro para o modo de exibição para executar a impressão da visualização de impressão.

  • A classe de tempo de execução da classe de Exibição da Visualização. Será criada dinamicamente em DoPrintPreview.

  • O ponteiro CPrintPreviewState. Observe que a estrutura CPrintPreviewState (ou a estrutura derivada se o aplicativo precisar ter mais estado preservado) não deve ser criada no quadro. DoPrintPreview é sem modo e essa estrutura deve sobreviver até que EndPrintPreview seja chamado.

    Observação

    Se uma exibição ou classe de exibição separada for necessária para dar suporte à impressão, um ponteiro para esse objeto deverá ser passado como o segundo parâmetro.

EndPrintPreview

É chamado para encerrar o modo de visualização de impressão. Geralmente, é desejável mover para a página no documento que foi exibida pela última vez na visualização de impressão. EndPrintPreview é a chance do aplicativo fazer isso. O membro pInfo->m_nCurPage é a página exibida pela última vez (mais à esquerda se duas páginas foram exibidas) e o ponteiro é uma dica sobre o local na página em que o usuário estava interessado. Como a estrutura do modo de exibição do aplicativo é desconhecida pela estrutura, você precisa fornecer o código para mover para o ponto escolhido.

Execute a maioria das ações antes de chamar CView::EndPrintPreview. Essa chamada reverte os efeitos de DoPrintPreview e exclui pView, pDC e pInfo.

// Any further cleanup should be done here.
CView::EndPrintPreview(pDC, pInfo, point, pView);

CWinApp::OnFilePrintSetup

Deve ser mapeado para o item de menu Configuração de Impressão. Na maioria dos casos, não é necessário substituir a implementação.

Nomenclatura da Página

Outro problema é o da numeração e da ordem das páginas. Para aplicativos simples de processamento de palavras, esse é um problema simples. A maioria dos sistemas de visualização de impressão pressupõe que cada página impressa corresponde a uma página no documento.

Ao tentar fornecer uma solução generalizada, há várias coisas a serem consideradas. Imagine um sistema CAD. O usuário tem um desenho que abrange várias folhas do tamanho E. Em um plotador de tamanho E (ou menor, em escala), a numeração das páginas seria igual à do caso simples. Mas em uma impressora a laser, que imprime 16 páginas de tamanho A por folha, o que a visualização de impressão considera uma "página"?

Como afirma o parágrafo introdutório, a Visualização de Impressão age como uma impressora. Portanto, o usuário verá o que sairia da impressora específica selecionada. Cabe ao modo de exibição determinar qual imagem é impressa em cada página.

A cadeia de caracteres de descrição da página na estrutura CPrintInfo fornecerá um meio de exibir o número da página para o usuário se ela puder ser representada como um número por página (como na "Página 1" ou "Páginas 1-2"). Essa cadeia de caracteres é usada pela implementação padrão de CPreviewView::OnDisplayPageNumber. Se uma exibição diferente for necessária, será possível substituir essa função virtual para fornecer, por exemplo, "Planilha1, Seções A, B".

Confira também

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