Compartir por


Documentos de varias páginas

En este artículo se describe el protocolo de impresión de Windows y se explica cómo imprimir documentos que contienen más de una página. En el artículo se tratan los temas siguientes:

El protocolo de impresión

Para imprimir un documento de varias páginas, el marco y la vista interactúan de la siguiente manera. En primer lugar, el marco muestra el cuadro de diálogo Imprimir, crea un contexto de dispositivo para la impresora y llama a la función miembro StartDoc del objeto CDC. A continuación, para cada página del documento, el marco llama a la función miembro StartPage del objeto CDC, indica al objeto de vista que imprima la página y llama a la función miembro EndPage. Si el modo de impresora debe cambiarse antes de iniciar una página determinada, la vista llama a ResetDC, que actualiza la estructura DEVMODE que contiene la información del nuevo modo de impresora. Cuando se ha impreso todo el documento, el marco llama a la función miembro EndDoc.

Invalidación de funciones de clase de vista

La clase CView define varias funciones miembro a las que llama el marco durante la impresión. Al invalidar estas funciones en la clase de vista, se proporcionan las conexiones entre la lógica de impresión del marco y la lógica de impresión de la clase de vista. En la tabla siguiente se enumeran estas funciones miembro.

Funciones reemplazables de CView para la impresión

Nombre Motivo para invalidar
OnPreparePrinting Para insertar valores en el cuadro de diálogo Imprimir, especialmente la longitud del documento.
OnBeginPrinting Para asignar fuentes u otros recursos de GDI.
OnPrepareDC Para ajustar los atributos del contexto del dispositivo para una página determinada, o para realizar la paginación en tiempo de impresión.
OnPrint Para imprimir una página determinada.
OnEndPrinting Para desasignar recursos de GDI.

También puede realizar el procesamiento relacionado con la impresión en otras funciones, pero estas funciones son las que determinan el proceso de impresión.

En la ilustración siguiente se muestran los pasos implicados en el proceso de impresión y dónde se llama a cada una de las funciones miembro de impresión de CView. En el resto de este artículo se explica la mayoría de estos pasos con más detalle. Otras partes del proceso de impresión se describen en el artículo Asignación de recursos de GDI.

Printing loop process.
El bucle de impresión

Paginación

El marco almacena gran parte de la información sobre un trabajo de impresión en una estructura CPrintInfo. Varios de los valores de CPrintInfo pertenecen a la paginación; estos valores son accesibles como se muestra en la tabla siguiente.

Información de número de página almacenada en CPrintInfo

Variable miembro o

nombre(s) de función
Número de página al que se hace referencia
GetMinPage/SetMinPage Primera página del documento
GetMaxPage/SetMaxPage Última página del documento
GetFromPage Primera página que se va a imprimir
GetToPage Última página que se va a imprimir
m_nCurPage Página que se imprime actualmente

Los números de página comienzan en 1, es decir, la primera página está numerada 1, no 0. Para más información sobre estos y otros miembros de CPrintInfo, consulte la referencia de MFC.

Al principio del proceso de impresión, el marco llama a la función miembro OnPreparePrinting de la vista, pasando un puntero a una estructura CPrintInfo. El Asistente para aplicaciones proporciona una implementación de OnPreparePrinting que llama a DoPreparePrinting, otra función miembro de CView. DoPreparePrinting es la función que muestra el cuadro de diálogo Imprimir y crea un contexto de dispositivo de impresora.

En este momento, la aplicación no sabe cuántas páginas hay en el documento. Usa los valores predeterminados 1 y 0xFFFF para los números de la primera y la última página del documento. Si sabe cuántas páginas tiene el documento, invalide OnPreparePrinting y llame a [SetMaxPage]--brokenlink--(reference/cprintinfo-class.md#setmaxpage) para la estructura CPrintInfo antes de enviarlo a DoPreparePrinting. Esto le permite especificar la longitud del documento.

DoPreparePrinting muestra entonces el cuadro de diálogo Imprimir. Cuando devuelve resultados, la estructura CPrintInfo contiene los valores especificados por el usuario. Si el usuario quiere imprimir solo un intervalo seleccionado de páginas, puede especificar los números de página inicial y final en el cuadro de diálogo Imprimir. El marco recupera estos valores mediante las funciones GetFromPage y GetToPage de CPrintInfo. Si el usuario no especifica un intervalo de páginas, el marco llama a GetMinPage y GetMaxPage y usa los valores devueltos para imprimir todo el documento.

Con cada página de un documento que se va a imprimir, el marco llama a dos funciones miembro de la clase de vista, OnPrepareDC y OnPrint, y pasa a cada función dos parámetros: un puntero a un objeto CDC y un puntero a una estructura CPrintInfo. Cada vez que el marco llama a OnPrepareDC y OnPrint, pasa un valor diferente al miembro m_nCurPage de la estructura CPrintInfo. De este modo, el marco indica a la vista qué página se debe imprimir.

La función miembro OnPrepareDC también se usa para la presentación de pantalla. Realiza ajustes en el contexto del dispositivo antes de que se produzca el dibujo. OnPrepareDC desempeña un rol similar en la impresión, pero hay un par de diferencias: en primer lugar, el objeto CDC representa un contexto de dispositivo de impresora en lugar de un contexto de dispositivo de pantalla y, en segundo lugar, se pasa un objeto CPrintInfo como segundo parámetro. (Este parámetro es NULL cuando se llama a OnPrepareDC para la presentación de pantalla). Invalide OnPrepareDC para realizar ajustes en el contexto de dispositivo en función de la página que se va a imprimir. Por ejemplo, puede mover el origen del área de visualización y la zona de recorte para asegurarse de que se imprime la parte adecuada del documento.

La función miembro OnPrint realiza la impresión real de la página. En el artículo Cómo se realiza la impresión predeterminada se muestra cómo el marco llama a OnDraw con un contexto de dispositivo de impresora para realizar la impresión. De forma más precisa, el marco llama a OnPrint con una estructura CPrintInfo y un contexto de dispositivo y OnPrint pasa el contexto de dispositivo a OnDraw. Invalide OnPrint para realizar cualquier representación que deba hacerse solo durante la impresión y no durante la presentación de pantalla. Por ejemplo, para imprimir encabezados o pies de página (consulte el artículo Encabezados y pies de página para más información). A continuación, llame a OnDraw desde la invalidación de OnPrint para realizar la representación común a la presentación de pantalla y la impresión.

El hecho de que OnDraw haga la representación tanto para la presentación de pantalla como para la impresión significa que la aplicación es WYSIWYG: "Lo que se ve es lo que se imprime". Sin embargo, supongamos que no está escribiendo una aplicación WYSIWYG. Por ejemplo, considere un editor de texto que use una fuente en negrita para imprimir, pero muestre códigos de control para indicar texto en negrita en la pantalla. En tal situación, se usa OnDraw estrictamente para la presentación de pantalla. Al invalidar OnPrint, sustituya la llamada a OnDraw por una llamada a una función de dibujo independiente. Esa función dibuja el documento de la forma en que aparece en papel, usando los atributos que no se muestran en la pantalla.

Páginas de impresora frente a páginas de documentos

Cuando se hace referencia a números de página, a veces es necesario distinguir entre el concepto de página de una impresora y el concepto de página de un documento. Desde el punto de vista de la impresora, una página es una hoja de papel. Sin embargo, una hoja de papel no es necesariamente igual a una página del documento. Por ejemplo, si va a imprimir un boletín, donde las hojas se pliegan, una hoja de papel puede contener las páginas primera y última del documento, en paralelo. Del mismo modo, si va a imprimir una hoja de cálculo, el documento no consta de páginas. En su lugar, una hoja de papel puede contener filas de 1 a 20, columnas de 6 a 10.

Todos los números de página de la estructura CPrintInfo hacen referencia a las páginas de la impresora. El marco llama a OnPrepareDC y OnPrint una vez para cada hoja de papel que pase por la impresora. Al invalidar la función OnPreparePrinting para especificar la longitud del documento, debe usar páginas de impresora. Si hay una correspondencia uno a uno (es decir, una página de impresora es igual a una página de documento), esto es fácil. Si, por otro lado, las páginas de documento y las páginas de impresora no se corresponden directamente, debe realizar conversiones entre ellas. Por ejemplo, imagine que imprime una hoja de cálculo. Al invalidar OnPreparePrinting, debe calcular cuántas hojas de papel se necesitarán para imprimir toda la hoja de cálculo y, luego, usar ese valor al llamar a la función miembro SetMaxPage de CPrintInfo. De forma similar, al invalidar OnPrepareDC, debe convertir m_nCurPage al intervalo de filas y columnas que aparecerán en esa hoja concreta y, luego, ajustar el origen del área de visualización en consecuencia.

Paginación en tiempo de impresión

En algunas situaciones, es posible que la clase de vista no sepa con antelación cuál es la longitud del documento hasta que se haya impreso realmente. Por ejemplo, supongamos que la aplicación no es WYSIWYG, por lo que la longitud de un documento en la pantalla no se corresponde con su longitud cuando se imprime.

Esto provoca un problema al invalidar OnPreparePrinting para la clase de vista: no se puede pasar un valor a la función SetMaxPage de la estructura CPrintInfo, ya que no conoce la longitud de un documento. Si el usuario no especifica un número de página donde parar mediante el cuadro de diálogo Imprimir, el marco no sabe cuándo detener el bucle de impresión. La única manera de determinar cuándo detener el bucle de impresión es imprimir el documento y ver cuándo finaliza. La clase de vista debe comprobar el final del documento mientras se imprime y, luego, informar al marco cuando se llega al final.

El marco se basa en la función OnPrepareDC de la clase de vista para indicar cuándo detenerse. Después de cada llamada a OnPrepareDC, el marco comprueba un miembro de la estructura CPrintInfo llamado m_bContinuePrinting. Su valor predeterminado es TRUE. Siempre que permanezca así, el marco continúa el bucle de impresión. Si se establece en FALSE, el marco se detiene. Para realizar la paginación en tiempo de impresión, invalide OnPrepareDC para comprobar si se ha alcanzado el final del documento y establezca m_bContinuePrinting en FALSE cuando se haya hecho.

La implementación predeterminada de OnPrepareDC establece m_bContinuePrinting en FALSE si la página actual es mayor que 1. Esto significa que si no se especificó la longitud del documento, el marco supone que el documento es de una página. Una consecuencia de esto es que debe tener cuidado si llama a la versión de clase base de OnPrepareDC. No suponga que m_bContinuePrinting será TRUE después de llamar a la versión de la clase base.

Qué más quieres saber

Consulte también

Impresión
CView (clase)
CDC (clase)