屏幕捕获代码生成黑色位图
我需要添加截取整个屏幕(而不仅仅是当前窗口)的屏幕截图的功能。以下代码生成具有正确尺寸的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
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.