2010-02-10 21 views
9

Tengo una función de dibujo que solo requiere una HDC. Pero necesito mostrar una versión escalada EXACTA de lo que se imprimirá.¿cómo puedo imprimir vista previa en win32 C++?

Actualmente, uso CreateCompatibleDC() con una impresora HDC y CreateCompatibleBitmap() con la HDC de la impresora.

Me imagino que el DC tendrá el ancho y la altura exactos de la impresora. Y cuando selecciono las fuentes en este HDC, el texto se escalará exactamente como lo haría la impresora.

Desafortunadamente, no puedo hacer una StretchBlt() para copiar los píxeles de esta HDC al HDC del control ya que son de diferentes tipos de HDC, supongo.

Si creo el "lienzo memoria" de una ventana con HDC misma w, h como la página de la impresora, las fuentes salen MANERA pequeñito ya que están escalados para la pantalla, no la página ...

¿Debería CreateCompatibleDC() desde el DC de la ventana y CreateCompatibleBitmap() desde el DC de la impresora o algo así?

Si alguien pudiera explicar la forma correcta de hacerlo. (Y todavía tiene algo que se ve EXACTAMENTE como lo haría en la impresora) ...

Bueno, ¡lo agradecería!

... Steve

+0

No estoy demasiado orgulloso de la ruta que decidí ...:/Obtenga la información de DC de la impresora: ancho, alto y logpixelsy. CreateCompatibleDC, Bitmap desde la ventana de vista previa de impresión pero con ancho, altura de la impresora (memoria de tamaño mondo que mata el mapa de bits) Y cuando CreateFont, uso - :: MulDiv (point, logPxlY, 72) para la altura (usando logPxlY desde la impresora dc). Soooooo, espero volver a visitar esta solución no muy óptima, pero tengo otras funcionalidades para agregar primero ...:/http://pianocheater.com fyi :) –

+0

Argh !! Esta no es una buena solución (la que no me enorgullece). En mi máquina Vista con 4 Gigs RAM, no puedo CreateCompatibleBitmap de un mapa de bits compatible con pantalla con w/h de impresora - sin memoria - probablemente la cantidad de memoria de la tarjeta gráfica, estoy seguro, que encajaría en 4 gigas de la memoria regular. De vuelta al tablero de dibujo ... –

+0

Sé que esto fue hace un tiempo, pero ¿alguna vez trataste de crear el mapa de bits a partir de un DC compatible con la impresora, desmarcarlo y seleccionarlo en una nueva pantalla compatible con DC para StretchBlt? Además, puede dividir las dimensiones y las coordenadas del mapa de bits entre 2 para que quepa sin riesgo de demasiada distorsión. –

Respuesta

10

Según la precisión que desee, puede ser difícil.

Hay muchos enfoques. Parece que está intentando dibujar en un mapa de bits del tamaño de una impresora y luego reducirlo. Los pasos para hacerlo son:

  1. Cree un DC (o mejor aún, un contexto de información de IC) para la impresora.
  2. Consultar la impresora DC para conocer la resolución, el tamaño de página, los desplazamientos físicos, etc.
  3. Cree un DC para la ventana/pantalla.
  4. Cree un DC compatible (la memoria DC).
  5. Cree un mapa de bits compatible para la ventana/pantalla, pero el tamaño debe ser el tamaño de píxel de la página de la impresora. (El problema con este enfoque es que este es un mapa de bits ENORME y puede fallar.)
  6. Seleccione el mapa de bits compatible en la memoria DC.
  7. Dibuje en la memoria DC, usando las mismas coordenadas que usaría si dibujara en la impresora real.(Cuando selecciona fuentes, asegúrese de escalarlas a la pulgada lógica de la impresora, no a la pulgada lógica de la pantalla)
  8. StretchBlt la memoria DC a la ventana, lo que reducirá la escala de toda la imagen. Es posible que desee experimentar con el modo de estiramiento para ver qué funciona mejor para el tipo de imagen que va a mostrar.
  9. Libere todos los recursos.

Pero antes de ir en esa dirección, considere las alternativas. Este enfoque implica la asignación de un ENORME mapa de bits fuera de la pantalla. Esto puede fallar en computadoras con pocos recursos. Incluso si no es así, es posible que esté muriendo de hambre otras aplicaciones.

El enfoque del metarchivo dado en otra respuesta es una buena opción para muchas aplicaciones. Comenzaría con esto.

Otro enfoque es averiguar todos los tamaños en alguna unidad ficticia de alta resolución. Por ejemplo, suponga que todo está en milésimas de pulgada. Luego, las rutinas de dibujo escalarían esta unidad imaginaria a los ppp reales utilizados por el dispositivo de destino.

El problema con este último enfoque (y posiblemente el metarchivo) es que las fuentes GDI no se escalan perfectamente linealmente. El ancho de los caracteres individuales se ajusta según la resolución del objetivo. En un dispositivo de alta resolución (como una impresora láser de 300+ dpi), este ajuste es mínimo. Pero en una pantalla de 96 ppp, los ajustes pueden sumar un error significativo sobre la longitud de una línea. Por lo tanto, el texto en la ventana de vista previa puede parecer desproporcionado (generalmente más ancho) que en la página impresa.

Por lo tanto, el enfoque hardcore es medir el texto en el contexto de la impresora, y medir de nuevo en el contexto de la pantalla, y ajustar la discrepancia. Por ejemplo (usando números inventados), puede medir el ancho de algunos textos en el contexto de la impresora, y sale en 900 píxeles de impresora. Supongamos que la relación de píxeles de la impresora a píxeles de la pantalla es de 3: 1. Es de esperar que el mismo texto en la pantalla tenga 300 píxeles de pantalla de ancho. Pero mides en el contexto de la pantalla y obtienes un valor como 325 píxeles de pantalla. Cuando dibuja en la pantalla, de alguna manera debe hacer que el texto sea 25 píxeles más estrecho. Puede ramificar los caracteres más cerca, o elegir una fuente un poco más pequeña y luego estirarlos.

El enfoque hardcore implica más complejidad. Podría, por ejemplo, intentar detectar las sustituciones de fuentes realizadas por el controlador de la impresora y hacerlas coincidir lo más posible con las fuentes de pantalla disponibles.

He tenido buena suerte con un híbrido de los enfoques de big-bitmap y hardcore. En lugar de hacer un mapa de bits gigante para toda la página, creo uno lo suficientemente grande para una línea de texto. Luego dibujo el tamaño de la impresora al mapa de bits fuera de pantalla y StretchBlt al tamaño de la pantalla. Esto elimina lidiar con la discrepancia de tamaño con una ligera degradación de la calidad de fuente. Es adecuado para la vista previa de impresión real, pero no le gustaría construir un editor WYSIWYG como ese. El mapa de bits de una línea es lo suficientemente pequeño como para hacer esto práctico.

La buena noticia es que solo el texto es difícil. El resto del dibujo es una escala simple de coordenadas y tamaños.

No he usado mucho GDI, pero creo que se eliminó con el escalado de fuente no lineal. Entonces, si estás usando GDI +, solo deberías escalar tus coordenadas. El inconveniente es que no creo que la calidad de fuente en GDI + sea tan buena.

Y, por último, si usted es una aplicación nativa en Vista o posterior, asegúrese de que ha marcado su proceso como "DPI-aware". De lo contrario, si el usuario está en una pantalla de PPP alto, Windows le mentirá y alegará que la resolución es de solo 96 ppp y luego realizará una escala ascendente difusa de lo que dibuje.Esto degrada la calidad visual y puede hacer que la depuración de su vista previa de impresión sea aún más complicada. Debido a que muchos programas no se adaptan bien a pantallas DPI más altas, Microsoft agregó "escalamiento de PPP alto" de forma predeterminada comenzando en Vista.

editar para agregar

Otra advertencia: Si se selecciona un HFONT en la memoria de CC con el mapa de bits-impresora de tamaño, es posible que se obtiene un tipo de letra diferente a lo que llegaría la hora de seleccionar el mismo HFONT en la impresora real DC. Esto se debe a que algunos controladores de impresora sustituirán las fuentes comunes por las de memoria. Por ejemplo, algunas impresoras PostScript sustituirán una fuente PostScript interna por ciertas fuentes TrueType comunes.

primera Puede seleccionar el HFONT en la impresora IC, a continuación, utilizar funciones GDI como GetTextFace, GetTextMetrics, y tal vez GetOutlineTextMetrics para averiguar acerca de la fuente real seleccionado. A continuación, puede crear un nuevo LOGFONT para intentar hacer corresponder mejor lo que usaría la impresora, convertirlo en un HFONT y seleccionarlo en la memoria DC. Esta es la marca de una implementación realmente buena.

+0

Holy guacamole. Gracias por todos los detalles. Señalar a alguien en la dirección correcta no es lo suficientemente bueno para ti, ¿eh? Tengo que pavimentar el suelo con ladrillos y arena, sin problemas ... :) Parece que tengo muchas cosas que probar. ¡Muchas gracias! –

+0

GDI + puede que no sea la mejor opción para la salida, pero es una gran escala, mucho mejor que StretchBlt, creo. –

+0

@MarkRansom: cuando se reduce la escala para la vista previa de impresión, la legibilidad del texto en la pantalla generalmente no es la más alta prioridad. –

2

Bueno, no tendrá el mismo aspecto porque tiene una mayor resolución en la impresora DC, por lo que tendrá que escribir una función de conversión de tipo. Me gustaría ir con el método que tienes para trabajar, pero el texto es demasiado pequeño y simplemente multiplicar cada posición/tamaño de fuente por el ancho de la ventana de la impresora y dividir por el ancho de la ventana de origen.

+0

ese fue mi pensamiento inicial, también. pero, parece que tengo mucho más ahora :) –

3

Una cosa que valdría la pena intentar es crear un archivo de metarchivo DC mejorado, dibujarlo como normalmente y luego escalar este metarchivo usando métricas de impresora. Este es el enfoque utilizado por la muestra BmpView WTL - No sé qué tan preciso será, pero podría valer la pena mirarlo (debería ser fácil transportar las clases relevantes a Win32, pero WTL es un gran sustituto para la programación de Win32, podría valer la pena utilizarlo)

+0

Lástima que no puedo elegir 2 respuestas:/ Definitivamente voy a probar este enfoque (también). ¡Muchas gracias! –

Cuestiones relacionadas