mostrar imprimir impresora impresion directamente directa dialogo automaticamente visual-c++ mfc gdi

visual c++ - impresion - Cómo imprimir DIB Backbuffer en la impresora-GDI, MFC



imprimir sin mostrar dialogo impresion javascript (1)

Asegúrese de no tener la DIBSECTION seleccionada en más de un DC a la vez. Eso puede causar todo tipo de comportamiento impredecible.

Para la impresión, probablemente pueda omitir la memoria DC por completo si mantiene sus bmi y pBitmapRawBits mano. Asegúrese de que DIBSECTION no esté seleccionado en ningún DC, y luego llame a SetDIBitsToDevice o StretchDIBits para transferir la imagen a la impresora DC.

Si todavía tiene problemas, es posible que desee comprobar las capacidades de sus impresoras. No todos los controladores son compatibles con todos los métodos de transferencia de mapas de bits. Creo que se supone que el sistema de impresión oculta esas diferencias, pero quizás no. Llame a GetDeviceCaps en su impresora DC, y verifique las RASTERCAPS para RC_BITBLT y sus amigos.

Estoy usando la arquitectura doc / view de MFC para implementar la impresión. Uso doble buffering, dibujo todo en mi backbuffer, que es un mapa de bits DIB. Luego utilizo StretchBlt para copiar ese DIB en la impresora DC.

Lo extraño es que la vista previa de impresión funciona bien. Cuando imprimo en una impresora PDF virtual, ¡está funcionando bien! Pero cuando imprimo en una impresora real (estoy probando en dos impresoras diferentes, los mismos resultados), solo imprime "basura". La "basura" significa que a veces imprime una página totalmente negra, a veces imprime las primeras páginas varias veces, es decir, imprime una parte incorrecta de DIB, como si hubiera desordenado las coordenadas de StretchBlt, pero no metí la pata, comprobé varias veces, además de por qué la vista previa de impresión funciona impecablemente, entonces?

Intenté muchas variaciones:

  1. Uso de memoria DC compatible para pantalla DC, al imprimir.
  2. Usando memoria DC compatible con la impresora DC, y seleccionando mi DIB en ella.
  3. Usando una memoria DC compatible con la impresora DC, y usando un DIB dedicado sobre el cual copio mi DIB Backbuffer original. etc.

Pero los resultados son iguales. A continuación está el código donde creo el DIB. Creo que el formato DIB podría ser el problema, por lo que le aconsejo si hay algún problema con él. Intenté tanto 24 bits como 32 bits como valores para bmiHeader.biBitCount.

// Setup proper backbuffer: _CleanupBackBufferStuff(); _pMemDc = new CDC; _pMemDc->CreateCompatibleDC(&aDC); BITMAPINFO bmi; memset(&bmi, 0, sizeof(BITMAPINFO)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = _sizeBackBuffer.cx; bmi.bmiHeader.biHeight = -_sizeBackBuffer.cy; // top-down bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 24; // Tried 32 as well bmi.bmiHeader.biCompression = BI_RGB; unsigned char *pBitmapRawBits = 0; HANDLE hMemBitmap = CreateDIBSection(aDC.GetSafeHdc(), &bmi, DIB_RGB_COLORS, (void**)&pBitmapRawBits, 0, 0); _hOldSelBitmap = (HBITMAP)_pMemDc->SelectObject(hMemBitmap);

También aquí está el código para StretchBlt (nada especial aquí):

pDC->SetStretchBltMode(HALFTONE); SetBrushOrgEx(pDC->GetSafeHdc(), 0, 0, 0); BOOL bSuccess = pDC->StretchBlt(rectClipBoxPlayground.left, rectClipBoxPlayground.top, rectClipBoxPlayground.Width(), rectClipBoxPlayground.Height(), _pMemDc, rectClipBoxBackBuffer.left, rectClipBoxBackBuffer.top, rectClipBoxBackBuffer.Width(), rectClipBoxBackBuffer.Height(), SRCCOPY);

StretchBlt devuelve verdadero, también (pDC->GetDeviceCaps(RASTERCAPS) & RC_STRETCHBLT) es verdadero.

ACTUALIZACIÓN: Después del comentario de Adrian, cambié mi código para usar StretchDIBits. ¡El problema sigue siendo el mismo! A continuación está el código que estoy usando actualmente:

// Copy back buffer to screen dc: pDC->SetStretchBltMode(HALFTONE); SetBrushOrgEx(pDC->GetSafeHdc(), 0, 0, 0); HBITMAP hMemBitmap = (HBITMAP)_pMemDc->SelectObject(_hOldSelBitmap); DWORD dwLines = StretchDIBits(pDC->GetSafeHdc(), rectClipBoxPlayground.left, rectClipBoxPlayground.top, rectClipBoxPlayground.Width(), rectClipBoxPlayground.Height(), rectClipBoxBackBuffer.left, _sizeBackBuffer.cy - rectClipBoxBackBuffer.top - rectClipBoxBackBuffer.Height(), rectClipBoxBackBuffer.Width(), rectClipBoxBackBuffer.Height(), _pBitmapRawBits, &_bitmapInfo, DIB_RGB_COLORS, SRCCOPY); _pMemDc->SelectObject(hMemBitmap);

Todavía se comporta como si las coordenadas de origen fueran incorrectas. Imprime una de las primeras páginas (sin importar la página que seleccione), o imprime páginas casi completamente negras. La vista previa de impresión funciona a la perfección, así que esto me hace pensar que no debería haber problemas con mi código de cálculo de coordenadas. Funciona en vista previa, funciona con una impresora virtual (pdf), falla al imprimir en una impresora real. ¿Que demonios?....