zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    活动安排问题
    喵哈哈村的魔法考试 Round #5 (Div.2) C
    梯度下降,牛顿法 ,高斯牛顿法
    SSD模型解析
    训练较深的卷积神经网络时遇到的问题
    手写体识别
    Fast Patch-based Style Transfer of Arbitrary Style 理解
    多任务学习
    迁移学习(训练数据少的可怜时的办法)
    通过训练得出的结果修改模型
  • 原文地址:https://www.cnblogs.com/strive-sun/p/13037528.html
Copyright © 2011-2022 走看看