屏幕捕获代码生成黑色位图

发布于 2024-09-01 09:34:04 字数 4312 浏览 3 评论 0原文

我需要添加截取整个屏幕(而不仅仅是当前窗口)的屏幕截图的功能。以下代码生成具有正确尺寸的 bmp 文件,但图像是全黑的。我做错了什么?

void CaptureScreen(LPCTSTR lpszFilePathName)
{
      BITMAPFILEHEADER   bmfHeader;
      BITMAPINFO                *pbminfo;
      HBITMAP                   hBmp;
      FILE                      *oFile;
      HDC      screen;
   HDC      memDC;
   int      sHeight;  
   int      sWidth;   
      LPBYTE     pBuff;
   BITMAP     bmp;
   WORD      cClrBits; 
   RECT      rcClient;


   screen = GetDC(0);
   memDC = CreateCompatibleDC(screen);

   sHeight = GetDeviceCaps(screen, VERTRES);
   sWidth = GetDeviceCaps(screen, HORZRES);

   //GetObject(screen, sizeof(BITMAP), &bmp);

   hBmp    = CreateCompatibleBitmap ( screen, sWidth, sHeight );

   // Retrieve the bitmap color format, width, and height.  
 GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp) ;

    // Convert the color format to a count of bits.  
    cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); 
    if (cClrBits == 1) 
        cClrBits = 1; 
    else if (cClrBits bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    pbminfo->bmiHeader.biWidth = bmp.bmWidth; 
    pbminfo->bmiHeader.biHeight = bmp.bmHeight; 
    pbminfo->bmiHeader.biPlanes = bmp.bmPlanes; 
    pbminfo->bmiHeader.biBitCount = bmp.bmBitsPixel; 
    if (cClrBits bmiHeader.biClrUsed = (1bmiHeader.biCompression = BI_RGB; 

    // Compute the number of bytes in the array of color  
    // indices and store the result in biSizeImage.  
    // The width must be DWORD aligned unless the bitmap is RLE 
    // compressed. 
    pbminfo->bmiHeader.biSizeImage = ((pbminfo->bmiHeader.biWidth * cClrBits +31) & ~31) /8
                                  * pbminfo->bmiHeader.biHeight; 
    // Set biClrImportant to 0, indicating that all of the  
    // device colors are important.  
     pbminfo->bmiHeader.biClrImportant = 0; 

  CreateBMPFile(lpszFilePathName, pbminfo, hBmp, memDC);
}

void CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, 
                  HBITMAP hBMP, HDC hDC) 
 { 
     HANDLE hf;                 // file handle  
    BITMAPFILEHEADER hdr;       // bitmap file-header  
    PBITMAPINFOHEADER pbih;     // bitmap info-header  
    LPBYTE lpBits;              // memory pointer  
    DWORD dwTotal;              // total count of bytes  
    DWORD cb;                   // incremental count of bytes  
    BYTE *hp;                   // byte pointer  
    DWORD dwTmp; 
 int lines;

    pbih = (PBITMAPINFOHEADER) pbi; 
    lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);

    // Retrieve the color table (RGBQUAD array) and the bits  
    // (array of palette indices) from the DIB.  
    lines = GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, 
        DIB_RGB_COLORS);

    // Create the .BMP file.  
    hf = CreateFile(pszFile, 
                   GENERIC_READ | GENERIC_WRITE, 
                   (DWORD) 0, 
                    NULL, 
                   CREATE_ALWAYS, 
                   FILE_ATTRIBUTE_NORMAL, 
                   (HANDLE) NULL); 

    hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M"  
    // Compute the size of the entire file.  
    hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
                 pbih->biSize + pbih->biClrUsed 
                 * sizeof(RGBQUAD) + pbih->biSizeImage); 
    hdr.bfReserved1 = 0; 
    hdr.bfReserved2 = 0; 

    // Compute the offset to the array of color indices.  
    hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
                    pbih->biSize + pbih->biClrUsed 
                    * sizeof (RGBQUAD); 

    // Copy the BITMAPFILEHEADER into the .BMP file.  
    WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), 
        (LPDWORD) &dwTmp,  NULL);

    // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.  
    WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) 
                  + pbih->biClrUsed * sizeof (RGBQUAD), 
                  (LPDWORD) &dwTmp, ( NULL));

    // Copy the array of color indices into the .BMP file.  
    dwTotal = cb = pbih->biSizeImage; 
    hp = lpBits; 
    WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL);
    // Close the .BMP file.  
 CloseHandle(hf);
    // Free memory.  
    GlobalFree((HGLOBAL)lpBits);
}


I need to add the ability to take a screenshot of the entire screen, not just the current window. The following code produces a bmp file with the correct dimensions, but the image is completely black. What am I doing wrong?

void CaptureScreen(LPCTSTR lpszFilePathName)
{
      BITMAPFILEHEADER   bmfHeader;
      BITMAPINFO                *pbminfo;
      HBITMAP                   hBmp;
      FILE                      *oFile;
      HDC      screen;
   HDC      memDC;
   int      sHeight;  
   int      sWidth;   
      LPBYTE     pBuff;
   BITMAP     bmp;
   WORD      cClrBits; 
   RECT      rcClient;


   screen = GetDC(0);
   memDC = CreateCompatibleDC(screen);

   sHeight = GetDeviceCaps(screen, VERTRES);
   sWidth = GetDeviceCaps(screen, HORZRES);

   //GetObject(screen, sizeof(BITMAP), &bmp);

   hBmp    = CreateCompatibleBitmap ( screen, sWidth, sHeight );

   // Retrieve the bitmap color format, width, and height.  
 GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp) ;

    // Convert the color format to a count of bits.  
    cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); 
    if (cClrBits == 1) 
        cClrBits = 1; 
    else if (cClrBits bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    pbminfo->bmiHeader.biWidth = bmp.bmWidth; 
    pbminfo->bmiHeader.biHeight = bmp.bmHeight; 
    pbminfo->bmiHeader.biPlanes = bmp.bmPlanes; 
    pbminfo->bmiHeader.biBitCount = bmp.bmBitsPixel; 
    if (cClrBits bmiHeader.biClrUsed = (1bmiHeader.biCompression = BI_RGB; 

    // Compute the number of bytes in the array of color  
    // indices and store the result in biSizeImage.  
    // The width must be DWORD aligned unless the bitmap is RLE 
    // compressed. 
    pbminfo->bmiHeader.biSizeImage = ((pbminfo->bmiHeader.biWidth * cClrBits +31) & ~31) /8
                                  * pbminfo->bmiHeader.biHeight; 
    // Set biClrImportant to 0, indicating that all of the  
    // device colors are important.  
     pbminfo->bmiHeader.biClrImportant = 0; 

  CreateBMPFile(lpszFilePathName, pbminfo, hBmp, memDC);
}

void CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, 
                  HBITMAP hBMP, HDC hDC) 
 { 
     HANDLE hf;                 // file handle  
    BITMAPFILEHEADER hdr;       // bitmap file-header  
    PBITMAPINFOHEADER pbih;     // bitmap info-header  
    LPBYTE lpBits;              // memory pointer  
    DWORD dwTotal;              // total count of bytes  
    DWORD cb;                   // incremental count of bytes  
    BYTE *hp;                   // byte pointer  
    DWORD dwTmp; 
 int lines;

    pbih = (PBITMAPINFOHEADER) pbi; 
    lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);

    // Retrieve the color table (RGBQUAD array) and the bits  
    // (array of palette indices) from the DIB.  
    lines = GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, 
        DIB_RGB_COLORS);

    // Create the .BMP file.  
    hf = CreateFile(pszFile, 
                   GENERIC_READ | GENERIC_WRITE, 
                   (DWORD) 0, 
                    NULL, 
                   CREATE_ALWAYS, 
                   FILE_ATTRIBUTE_NORMAL, 
                   (HANDLE) NULL); 

    hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M"  
    // Compute the size of the entire file.  
    hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
                 pbih->biSize + pbih->biClrUsed 
                 * sizeof(RGBQUAD) + pbih->biSizeImage); 
    hdr.bfReserved1 = 0; 
    hdr.bfReserved2 = 0; 

    // Compute the offset to the array of color indices.  
    hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
                    pbih->biSize + pbih->biClrUsed 
                    * sizeof (RGBQUAD); 

    // Copy the BITMAPFILEHEADER into the .BMP file.  
    WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), 
        (LPDWORD) &dwTmp,  NULL);

    // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.  
    WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) 
                  + pbih->biClrUsed * sizeof (RGBQUAD), 
                  (LPDWORD) &dwTmp, ( NULL));

    // Copy the array of color indices into the .BMP file.  
    dwTotal = cb = pbih->biSizeImage; 
    hp = lpBits; 
    WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL);
    // Close the .BMP file.  
 CloseHandle(hf);
    // Free memory.  
    GlobalFree((HGLOBAL)lpBits);
}


如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夏雨凉 2024-09-08 09:34:04

CaptureScreen 函数所做的就是创建一个与屏幕大小相同的兼容位图,然后将其写入磁盘,因此您将看到位图的默认内容(黑色)。要捕获屏幕,您需要创建一个兼容的 DC,选择您制作的位图并从一个 DC 传输到另一个 DC。然后,您需要在开始写入文件之前取消选择目标位图。

All the CaptureScreen function does is create a compatible bitmap the same size as the screen and then write it out to disk, so you're seeing the default contents of the bitmap (black). To capture the screen you need to create a compatible DC, select the bitmap you made into it and blit from one DC to the other. Then you need to unselect your target bitmap before you start writing the file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文