使用 BitBlt 捕获 Win32 窗口时不显示边框
我编写了一些 C++ 代码来将窗口捕获到 .bmp 文件。
BITMAPFILEHEADER get_bitmap_file_header(int width, int height)
{
BITMAPFILEHEADER hdr;
memset(&hdr, 0, sizeof(BITMAPFILEHEADER));
hdr.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM"
hdr.bfSize = 0;//sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (width * height * sizeof(int));
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
return hdr;
}
BITMAPINFO get_bitmap_info(int width, int height)
{
BITMAPINFO bmi;
memset(&bmi.bmiHeader, 0, sizeof(BITMAPINFOHEADER));
//initialize bitmap header
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 4 * 8;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = width * height * 4;
return bmi;
}
void get_bitmap_from_window(HWND hWnd, int * imageBuff)
{
HDC hDC = GetWindowDC(hWnd);
SIZE size = get_window_size(hWnd);
HDC hMemDC = CreateCompatibleDC(hDC);
RECT r;
HBITMAP hBitmap = CreateCompatibleBitmap(hDC, size.cx, size.cy);
HBITMAP hOld = (HBITMAP)SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, SRCCOPY);
//PrintWindow(hWnd, hMemDC, 0);
BITMAPINFO bmi = get_bitmap_info(size.cx, size.cy);
GetDIBits(hMemDC, hBitmap, 0, size.cy, imageBuff, &bmi, DIB_RGB_COLORS);
SelectObject(hMemDC, hOld);
DeleteDC(hMemDC);
ReleaseDC(NULL, hDC);
}
void save_image(HWND hWnd, char * name)
{
int * buff;
RECT r;
SIZE size;
GetWindowRect(hWnd, &r);
size.cx = r.right-r.left;
size.cy = r.bottom-r.top;
buff = (int*)malloc(size.cx * size.cy * sizeof(int));
get_bitmap_from_window(hWnd, buff);
BITMAPINFO bmi = get_bitmap_info(size.cx, size.cy);
BITMAPFILEHEADER hdr = get_bitmap_file_header(size.cx, size.cy);
FILE * fout = fopen(name, "w");
fwrite(&hdr, 1, sizeof(BITMAPFILEHEADER), fout);
fwrite(&bmi.bmiHeader, 1, sizeof(BITMAPINFOHEADER), fout);
fwrite(buff, 1, size.cx * size.cy * sizeof(int), fout);
fflush(fout);
fclose(fout);
free(buff);
}
在 XP 下可以正常工作,但在 Vista 下窗口边框是透明的。
使用 PrintWindow 解决了该问题,但出于性能原因是不可接受的。
是否有高性能代码更改,或者可以更改设置以使边框不透明?
I have written some c++ code to capture a window to a .bmp file.
BITMAPFILEHEADER get_bitmap_file_header(int width, int height)
{
BITMAPFILEHEADER hdr;
memset(&hdr, 0, sizeof(BITMAPFILEHEADER));
hdr.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM"
hdr.bfSize = 0;//sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (width * height * sizeof(int));
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
return hdr;
}
BITMAPINFO get_bitmap_info(int width, int height)
{
BITMAPINFO bmi;
memset(&bmi.bmiHeader, 0, sizeof(BITMAPINFOHEADER));
//initialize bitmap header
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 4 * 8;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = width * height * 4;
return bmi;
}
void get_bitmap_from_window(HWND hWnd, int * imageBuff)
{
HDC hDC = GetWindowDC(hWnd);
SIZE size = get_window_size(hWnd);
HDC hMemDC = CreateCompatibleDC(hDC);
RECT r;
HBITMAP hBitmap = CreateCompatibleBitmap(hDC, size.cx, size.cy);
HBITMAP hOld = (HBITMAP)SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, SRCCOPY);
//PrintWindow(hWnd, hMemDC, 0);
BITMAPINFO bmi = get_bitmap_info(size.cx, size.cy);
GetDIBits(hMemDC, hBitmap, 0, size.cy, imageBuff, &bmi, DIB_RGB_COLORS);
SelectObject(hMemDC, hOld);
DeleteDC(hMemDC);
ReleaseDC(NULL, hDC);
}
void save_image(HWND hWnd, char * name)
{
int * buff;
RECT r;
SIZE size;
GetWindowRect(hWnd, &r);
size.cx = r.right-r.left;
size.cy = r.bottom-r.top;
buff = (int*)malloc(size.cx * size.cy * sizeof(int));
get_bitmap_from_window(hWnd, buff);
BITMAPINFO bmi = get_bitmap_info(size.cx, size.cy);
BITMAPFILEHEADER hdr = get_bitmap_file_header(size.cx, size.cy);
FILE * fout = fopen(name, "w");
fwrite(&hdr, 1, sizeof(BITMAPFILEHEADER), fout);
fwrite(&bmi.bmiHeader, 1, sizeof(BITMAPINFOHEADER), fout);
fwrite(buff, 1, size.cx * size.cy * sizeof(int), fout);
fflush(fout);
fclose(fout);
free(buff);
}
It works find under XP, but under Vista the border of the window is transparent.
Using PrintWindow solves the problem, but is unacceptable for performance reasons.
Is there a performant code change, or a setting that can be changed to make the border non-transparent?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用下面代替
Use below instead
事实证明,这是由于在窗口上设置了 WS_EX_LAYERED 属性所致。
请参阅http://www.eggheadcafe.com/ software/aspnet/31543575/dwm-composition--get-par.aspx 进行相关问题的讨论。
奇怪的是,使用 PrintWindow 一次,然后使用 BitBlt 解决了问题......
Turns out this was due to the WS_EX_LAYERED attribute being set on the window.
See http://www.eggheadcafe.com/software/aspnet/31543575/dwm-composition--get-par.aspx for a discussion of related issues.
Oddly using PrintWindow once and BitBlt afterwards solves the problem...