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.
Faixas de impressão
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.
Visualização de impressão: papel eletrônico com interface do usuário
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
Derive uma classe de exibição de
CPreviewView
.Adicione manipuladores de comando para os aspectos da interface do usuário desejados.
Se você estiver adicionando aspectos visuais à exibição, substitua
OnDraw
e execute o desenho após chamarCPreviewView::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