win32-StretchDIBits
Posted 好好学习,天天向上
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了win32-StretchDIBits相关的知识,希望对你有一定的参考价值。
使用StretchDIBits将位图数据传输到printer的dc中
#include <Windows.h> #include <algorithm> int main() { int nWidth = 16, nHeight = 16; BYTE byteBitmap[768]; std::fill_n(byteBitmap, 768, 0xFF); // Test for a red cross bitmap int nIndices[] = { 0, 1, 45, 46, 51, 52, 90, 91, 102, 103, 135, 136, 153, 154, 180, 181, 204, 205, 225, 226, 255, 256, 270, 271, 306, 307, 315, 316, 357, 358, 360, 361, 405, 406, 408, 409, 450, 451, 459, 460, 495, 496, 510, 511, 540, 541, 561, 562, 585, 586, 612, 613, 630, 631, 663, 664, 675, 676, 714, 715, 720, 721, 765, 766 }; int nNbElements = sizeof(nIndices) / sizeof(nIndices[0]); for (int i = 0; i < nNbElements; i++) { byteBitmap[nIndices[i]] = 0; } HDC hDC = GetDC(NULL); BITMAPINFO bi; memset(&bi, 0, sizeof(bi)); bi.bmiHeader.biSize = sizeof(bi.bmiHeader); bi.bmiHeader.biWidth = nWidth; bi.bmiHeader.biHeight = nHeight; bi.bmiHeader.biBitCount = 24; bi.bmiHeader.biSizeImage = nWidth * nHeight * 24 / 8; bi.bmiHeader.biPlanes = 1; /*bi.bmiHeader.biXPelsPerMeter = 7874; bi.bmiHeader.biYPelsPerMeter = 7874;*/ //HBITMAP hBitmap = CreateDIBitmap(hDC, &bi.bmiHeader, CBM_INIT, byteBitmap, &bi, DIB_RGB_COLORS); PRINTDLG pdlg = { 0 }; pdlg.lStructSize = sizeof(pdlg); pdlg.Flags = PD_RETURNDC; if (PrintDlg(&pdlg) == TRUE) { HDC hPrinterDC = pdlg.hDC; DOCINFO di; ZeroMemory(&di, sizeof(di)); di.cbSize = sizeof(di); di.lpszDocName = TEXT("Test"); if (StartDoc(hPrinterDC, &di) > 0) { if (StartPage(hPrinterDC) > 0) { int nPrinterWidth = GetDeviceCaps(hPrinterDC, HORZRES); int nPrinterHeight = GetDeviceCaps(hPrinterDC, VERTRES); int nLogPixelsXScreen = GetDeviceCaps(hDC, LOGPIXELSX); int nLogPixelsYScreen = GetDeviceCaps(hDC, LOGPIXELSY); int nLogPixelsXPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSX); int nLogPixelsYPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSY); int nScaleX = max(nLogPixelsXScreen, nLogPixelsXPrinter) / min(nLogPixelsXScreen, nLogPixelsXPrinter); int nScaleY = max(nLogPixelsYScreen, nLogPixelsYPrinter) / min(nLogPixelsYScreen, nLogPixelsYPrinter); SetMapMode(hPrinterDC, MM_ISOTROPIC); SetWindowExtEx(hPrinterDC, nPrinterWidth, nPrinterHeight, 0); SetViewportExtEx(hPrinterDC, nPrinterWidth, nPrinterHeight, 0); SetViewportOrgEx(hPrinterDC, 0, 0, 0); SetStretchBltMode(hPrinterDC, COLORONCOLOR); StretchDIBits(hPrinterDC, 0, 0, nWidth * nScaleX, nHeight * nScaleY, 0, 0, nWidth, nHeight, byteBitmap, (LPBITMAPINFO)&bi, DIB_RGB_COLORS, SRCCOPY); EndPage(hPrinterDC); } EndDoc(hPrinterDC); } } ReleaseDC(NULL, hDC); }
上面是打印一个红色就×
也可以结合官方示例,将屏幕截图打印到printer的dc中
int CaptureAnImage(HWND hWnd) { HDC hdcScreen; HDC hdcWindow; HDC hdcMemDC = NULL; HBITMAP hbmScreen = NULL; BITMAP bmpScreen; // Retrieve the handle to a display device context for the client // area of the window. hdcScreen = GetDC(NULL); hdcWindow = GetDC(hWnd); // Create a compatible DC which is used in a BitBlt from the window DC hdcMemDC = CreateCompatibleDC(hdcWindow); if (!hdcMemDC) { MessageBox(hWnd, L"CreateCompatibleDC has failed", L"Failed", MB_OK); // goto done; } // Get the client area for size calculation RECT rcClient; GetClientRect(hWnd, &rcClient); //This is the best stretch mode SetStretchBltMode(hdcWindow, HALFTONE); //The source DC is the entire screen and the destination DC is the current window (HWND) if (!StretchBlt(hdcWindow, 0, 0, rcClient.right, rcClient.bottom, hdcScreen, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SRCCOPY)) { MessageBox(hWnd, L"StretchBlt has failed", L"Failed", MB_OK); // goto done; } // Create a compatible bitmap from the Window DC hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); if (!hbmScreen) { MessageBox(hWnd, L"CreateCompatibleBitmap Failed", L"Failed", MB_OK); // goto done; } // Select the compatible bitmap into the compatible memory DC. SelectObject(hdcMemDC, hbmScreen); // Bit block transfer into our compatible memory DC. if (!BitBlt(hdcMemDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hdcWindow, 0, 0, SRCCOPY)) { MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK); // goto done; } // Get the BITMAP from the HBITMAP GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen); BITMAPFILEHEADER bmfHeader; BITMAPINFOHEADER bi; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bmpScreen.bmWidth; bi.biHeight = bmpScreen.bmHeight; bi.biPlanes = 1; bi.biBitCount = 32; bi.biCompression = BI_RGB; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight; // Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that // call HeapAlloc using a handle to the process‘s default heap. Therefore, GlobalAlloc and LocalAlloc // have greater overhead than HeapAlloc. HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize); char* lpbitmap = (char*)GlobalLock(hDIB); // Gets the "bits" from the bitmap and copies them into a buffer // which is pointed to by lpbitmap. GetDIBits(hdcWindow, hbmScreen, 0, (UINT)bmpScreen.bmHeight, lpbitmap, (BITMAPINFO*)&bi, DIB_RGB_COLORS); PRINTDLG pdlg = { 0 }; pdlg.lStructSize = sizeof(pdlg); pdlg.Flags = PD_RETURNDC; if (PrintDlg(&pdlg) == TRUE) { HDC hPrinterDC = pdlg.hDC; DOCINFO di; ZeroMemory(&di, sizeof(di)); di.cbSize = sizeof(di); di.lpszDocName = TEXT("Test"); if (StartDoc(hPrinterDC, &di) > 0) { if (StartPage(hPrinterDC) > 0) { int nPrinterWidth = GetDeviceCaps(hPrinterDC, HORZRES); int nPrinterHeight = GetDeviceCaps(hPrinterDC, VERTRES); int nLogPixelsXScreen = GetDeviceCaps(hdcScreen, LOGPIXELSX); int nLogPixelsYScreen = GetDeviceCaps(hdcScreen, LOGPIXELSY); int nLogPixelsXPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSX); int nLogPixelsYPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSY); int nScaleX = max(nLogPixelsXScreen, nLogPixelsXPrinter) / min(nLogPixelsXScreen, nLogPixelsXPrinter); int nScaleY = max(nLogPixelsYScreen, nLogPixelsYPrinter) / min(nLogPixelsYScreen, nLogPixelsYPrinter); SetMapMode(hPrinterDC, MM_ISOTROPIC); SetWindowExtEx(hPrinterDC, nPrinterWidth, nPrinterHeight, 0); SetViewportExtEx(hPrinterDC, nPrinterWidth, nPrinterHeight, 0); SetViewportOrgEx(hPrinterDC, 0, 0, 0); SetStretchBltMode(hPrinterDC, COLORONCOLOR); StretchDIBits(hPrinterDC, 0, 0, bmpScreen.bmWidth * nScaleX, bmpScreen.bmHeight * nScaleY, 0, 0, bmpScreen.bmWidth, bmpScreen.bmHeight, lpbitmap, (LPBITMAPINFO)&bi, DIB_RGB_COLORS, SRCCOPY); EndPage(hPrinterDC); } EndDoc(hPrinterDC); } } //Clean up done: DeleteObject(hbmScreen); DeleteObject(hdcMemDC); ReleaseDC(NULL, hdcScreen); ReleaseDC(hWnd, hdcWindow); return 0; }
Note: 输出到printer截图会因为纸张的限制而被截取一部分,具体解决方法,参考: https://stackoverflow.com/questions/47642947/windows-gdi-scaling-a-screen-dc-to-a-printer-dc-without-modifying-the-draw-f
以上是关于win32-StretchDIBits的主要内容,如果未能解决你的问题,请参考以下文章