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的主要内容,如果未能解决你的问题,请参考以下文章

python将文本转换成语音的代码

怎么将短视频合并成一个视频的方法

怎么将短视频合并成一个视频的方法

VSCode 常用插件

如何在 Win32 控制台应用程序中将 argv[] 设置为不区分大小写?

微信小程序代码片段