Documentos multipágina
Este artigo descreve o protocolo de impressão do Windows e explica como imprimir documentos que contêm mais de uma página. O artigo aborda os seguintes tópicos:
O protocolo de impressão
Para imprimir um documento multipágina, a estrutura e a exibição interagem da maneira a seguir. Primeiro, a estrutura exibe a caixa de diálogo Imprimir, cria um contexto de dispositivo para a impressora e chama a função membro StartDoc do objeto CDC. Em seguida, para cada página do documento, a estrutura chama a função membro StartPage do objeto CDC
, instrui o objeto de exibição a imprimir a página e chama a função membro EndPage. Se o modo de impressora precisar ser alterado antes de iniciar uma página específica, a exibição chamará ResetDC, que atualiza a estrutura DEVMODE que contém as novas informações do modo de impressora. Quando todo o documento tiver sido impresso, a estrutura chamará a função membro EndDoc.
Substituição de funções de classe de exibição
A classe CView define várias funções de membro que são chamadas pela estrutura durante a impressão. Ao substituir essas funções na classe de exibição, você fornece as conexões entre a lógica de impressão da estrutura e a lógica de impressão da classe de exibição. A tabela a seguir lista essas funções de membro.
Funções substituíveis do CView para impressão
Nome | Motivo para substituição |
---|---|
OnPreparePrinting | Para inserir valores na caixa de diálogo Imprimir, especialmente o tamanho do documento |
OnBeginPrinting | Para alocar fontes ou outros recursos de GDI |
OnPrepareDC | Para ajustar atributos do contexto de dispositivo para uma determinada página ou para fazer paginação em tempo de impressão |
OnPrint | Para imprimir uma determinada página |
OnEndPrinting | Para desalocar recursos de GDI |
Você também pode fazer processamento relacionado à impressão em outras funções, mas essas funções são as que controlam o processo de impressão.
A figura a seguir ilustra as etapas envolvidas no processo de impressão e mostra onde cada uma das funções de membro de impressão da CView
são chamadas. O restante deste artigo explica a maioria dessas etapas com mais detalhes. Partes adicionais do processo de impressão são descritas no artigo Alocar recursos de GDI.
O loop de impressão
Paginação
A estrutura armazena grande parte das informações sobre um trabalho de impressão em uma estrutura CPrintInfo. Vários dos valores em CPrintInfo
pertencem à paginação e esses valores são acessíveis conforme mostrado na tabela a seguir.
Informações de número de página armazenadas na CPrintInfo
Variável de membro ou nome(s) de função |
Número da página referenciada |
---|---|
GetMinPage /SetMinPage |
Primeira página do documento |
GetMaxPage /SetMaxPage |
Última página do documento |
GetFromPage |
Primeira página a ser impressa |
GetToPage |
Última página a ser impressa |
m_nCurPage |
Página sendo impressa no momento |
Os números de página começam em 1, ou seja, a primeira página é numerada com 1, e não com 0. Para obter mais informações sobre esses e outros membros da CPrintInfo, consulte a Referência do MFC.
No início do processo de impressão, a estrutura chama a função membro OnPreparePrinting do modo de exibição, passando um ponteiro para uma estrutura CPrintInfo
. O Assistente de Aplicativo fornece uma implementação da OnPreparePrinting
que chama DoPreparePrinting, outra função membro da CView
. DoPreparePrinting
é a função que exibe a caixa de diálogo Imprimir e cria um contexto de dispositivo de impressora.
Neste ponto, o aplicativo não sabe quantas páginas estão no documento. Ele usa os valores padrão 1 e 0xFFFF para os números da primeira e da última página do documento. Se você souber quantas páginas o documento tem, substitua OnPreparePrinting
e chame [SetMaxPage]--brokenlink--(reference/cprintinfo-class.md#setmaxpage) para a estrutura CPrintInfo
antes de enviá-la para DoPreparePrinting
. Isso permite que você especifique o tamanho do documento.
DoPreparePrinting
exibe a caixa de diálogo Imprimir. Quando retorna, a estrutura CPrintInfo
contém os valores especificados pelo usuário. Se o usuário quiser imprimir apenas um intervalo selecionado de páginas, ele ou ela poderá especificar os números de página inicial e final na caixa de diálogo Imprimir. A estrutura recupera esses valores usando as funções GetFromPage
e GetToPage
daCPrintInfo. Se o usuário não especificar um intervalo de páginas, a estrutura chamará GetMinPage
e GetMaxPage
, e usará os valores retornados para imprimir o documento inteiro.
Para cada página de um documento a ser impresso, a estrutura chama duas funções de membro na classe de exibição, OnPrepareDC e OnPrint, e passa a cada função dois parâmetros: um ponteiro para um objeto CDC e um ponteiro para uma estrutura CPrintInfo
. Cada vez que a estrutura chama OnPrepareDC
e OnPrint
, ela passa um valor diferente no membro m_nCurPage da estrutura CPrintInfo
. Dessa forma, a estrutura informa ao modo de exibição qual página deve ser impressa.
A função membro OnPrepareDC também é usada para exibição em tela. Ela faz ajustes no contexto de dispositivo antes que o desenho seja feito. OnPrepareDC
serve uma função semelhante na impressão, mas há algumas diferenças: primeiro, o objeto CDC
representa um contexto de dispositivo de impressora em vez de um contexto de dispositivo de tela e, em segundo lugar, um objeto CPrintInfo
é passado como um segundo parâmetro. (Esse parâmetro é NULL quando OnPrepareDC
é chamada para exibição em tela.) Substitua OnPrepareDC
para fazer ajustes no contexto de dispositivo com base em qual página está sendo impressa. Por exemplo, você pode mover a origem do visor e a área de recorte para garantir que a parte apropriada do documento seja impressa.
A função membro OnPrint executa a impressão real da página. O artigo Como a impressão padrão é feita mostra como a estrutura chama OnDraw com um contexto de dispositivo de impressora para realizar a impressão. Mais precisamente, a estrutura chama OnPrint
com uma estrutura CPrintInfo
e um contexto de dispositivo, e OnPrint
passa o contexto do dispositivo para OnDraw
. Substitua OnPrint
para executar qualquer renderização que deve ser feita somente durante a impressão e não para exibição em tela. Por exemplo, para imprimir cabeçalhos ou rodapés (consulte o artigo Cabeçalhos e Rodapés para obter mais informações). Em seguida, chame OnDraw
da substituição de OnPrint
para fazer a renderização comum para exibição em tela e impressão.
O fato de OnDraw
fazer a renderização para exibição em tela e impressão de significa que o aplicativo é WYSIWYG: "O que você vê é o que você obtém". No entanto, suponha que você não esteja gravando um aplicativo WYSIWYG. Por exemplo, considere um editor de texto que usa uma fonte em negrito para impressão, mas exibe códigos de controle para indicar texto em negrito na tela. Nessa situação, você usa OnDraw
estritamente para exibição em tela. Ao substituir OnPrint
, substitua a chamada para OnDraw
por uma chamada para uma função de desenho separada. Essa função desenha o documento da maneira como ele aparece no papel, usando os atributos que não são exibidos na tela.
Páginas da impressora vs. páginas do documento
Quando você se refere a números de página, às vezes é necessário distinguir entre o conceito da impressora de uma página e o conceito do documento de uma página. Do ponto de vista da impressora, uma página é uma folha de papel. No entanto, uma folha de papel não é necessariamente igual a uma página do documento. Por exemplo, se você estiver imprimindo um boletim informativo, em que as folhas devem ser dobradas, uma folha de papel poderá conter a primeira e a última páginas do documento, lado a lado. Da mesma forma, se você estiver imprimindo uma planilha, o documento não consistirá em páginas. Em vez disso, uma folha de papel talvez contenha linhas de 1 a 20 e colunas de 6 a 10.
Todos os números de página na estrutura CPrintInfo se referem às páginas da impressora. A estrutura chama OnPrepareDC
e OnPrint
uma vez para cada folha de papel que passará pela impressora. Ao substituir a função OnPreparePrinting para especificar o tamanho do documento, você deve usar as páginas da impressora. Se houver uma correspondência um-para-um (ou seja, uma página da impressora é igual a uma página do documento), isso será fácil. Se, por outro lado, as páginas do documento e as páginas da impressora não corresponderem diretamente, você deverá mover entre elas. Por exemplo, considere imprimir uma planilha. Ao substituir OnPreparePrinting
, você deve calcular quantas folhas de papel serão necessárias para imprimir a planilha inteira e, em seguida, usar esse valor ao chamar a função membro SetMaxPage
da CPrintInfo
. Da mesma forma, ao substituir OnPrepareDC
, você deve mover m_nCurPage para o intervalo de linhas e colunas que aparecerão nessa planilha específica e, em seguida, ajustar a origem do visor adequadamente.
Paginação em tempo de impressão
Em algumas situações, a classe de exibição pode não saber com antecedência quanto tempo o documento permanece até que ele seja realmente impresso. Por exemplo, suponha que o aplicativo não seja WYSIWYG e, portanto, o tamanho de um documento na tela não corresponde ao seu tamanho quando impresso.
Isso causa um problema quando você substitui o OnPreparePrinting para a classe de exibição: não é possível passar um valor para a função SetMaxPage
da estrutura CPrintInfo porque você não sabe o tamanho de um documento. Se o usuário não especificar um número de página no qual parar usando a caixa de diálogo Imprimir, a estrutura não saberá quando interromper o loop de impressão. A única maneira de determinar quando interromper o loop de impressão é imprimir o documento e ver quando ele termina. A classe de exibição deve verificar o fim do documento enquanto ele está sendo impresso e informar a estrutura quando o fim for alcançado.
A estrutura depende da função OnPrepareDC da classe de exibição para dizer quando parar a impressão. Após cada chamada para OnPrepareDC
, a estrutura verifica um membro da estrutura CPrintInfo
chamada m_bContinuePrinting. Seu valor padrão é TRUE. Enquanto permanecer assim, a estrutura continuará o loop de impressão. Se estiver definido como FALSE, a estrutura interromperá o loop. Para executar a paginação em tempo de impressão, substitua OnPrepareDC
para verificar se o fim do documento foi alcançado e defina m_bContinuePrinting como FALSE quando ele tiver alcançado o fim.
A implementação padrão de OnPrepareDC
define m_bContinuePrinting como FALSE se a página atual for maior que 1. Isso significa que, se o tamanho do documento não foi especificado, a estrutura pressupõe que o documento tem uma página. Uma consequência disso é que você deve ter cuidado se chamar a versão da classe base da OnPrepareDC
. Não presuma que m_bContinuePrinting será TRUE depois de chamar a versão da classe base.