关于截屏截取不到透明窗口的问题
来源:互联网 发布:淘宝特卖入口 编辑:程序博客网 时间:2024/06/03 16:01
最近试过几套截图软件,发现其中有些无法实现对半透明窗口或主题的图片截取,包括早期版本的QQ截图工具也无法截取,写一个简单抓屏函数的来测试下,以下采用Win32 API方式编写:
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
HWND hwnd = (HWND)::GetDesktopWindow();
HDC dstDC = ::GetDC(NULL);
HDC srcDC = ::GetWindowDC(hwnd); //full window (::GetDC(hwnd); = clientarea)
HDC memDC = ::CreateCompatibleDC(NULL);
CRect CaptureRect;
::GetWindowRect(hwnd,&CaptureRect);
int xScreen,yScreen;//check if the window is out of the screen | maximixed <Qiang>
int xshift = 0, yshift = 0;
xScreen = GetSystemMetrics(SM_CXSCREEN);
yScreen = GetSystemMetrics(SM_CYSCREEN);
if(CaptureRect.right > xScreen)
CaptureRect.right = xScreen;
if(CaptureRect.bottom > yScreen)
CaptureRect.bottom = yScreen;
if(CaptureRect.left < 0){
xshift = -CaptureRect.left;
CaptureRect.left = 0;
}
if(CaptureRect.top < 0){
yshift = -CaptureRect.top;
CaptureRect.top = 0;
}
CSize sz(CaptureRect.Width(), CaptureRect.Height());
HBITMAP hBitmap = ::CreateCompatibleBitmap(dstDC, sz.cx, sz.cy);
HBITMAP hOldBitmap = (HBITMAP)::SelectObject(memDC,hBitmap);
::BitBlt(memDC, 0, 0, sz.cx, sz.cy, srcDC, xshift, yshift, SRCCOPY);
if (OpenClipboard(NULL))
{
//清空剪贴板
EmptyClipboard();
//把屏幕内容粘贴到剪贴板上,
//hBitmap 为刚才的屏幕位图句柄
SetClipboardData(CF_BITMAP, hBitmap);
//关闭剪贴板
CloseClipboard();
}
HDC hDC;//Device Context(设备环境、设备描述表、设备上下文)的句柄
//当前显示分辨率下每个像素所占字节数
WORD wBitCount = 8;//v_iBitCount
//计算调色板大小
DWORD dwPaletteSize = 0;
if(wBitCount <= 8)//小于八位按八位处理
dwPaletteSize = (1 << wBitCount) * sizeof(RGBQUAD);
//设置位图信息头结构
BITMAP bm;//位图属性结构
BITMAPINFOHEADER bi;//位图信息头结构
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
//位图中像素字节大小
DWORD dwBmpBitsSize = ((bm.bmWidth * wBitCount+31)/32)* 4 * bm.bmHeight;
//为位图内容分配内存
HANDLE hDib = GlobalAlloc(GHND, dwBmpBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
//处理调色板
HANDLE hPal = NULL;
HANDLE hOldPal = NULL;
hPal = GetStockObject(DEFAULT_PALETTE);
if(hPal)
{
hDC = ::GetDC(NULL);
hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
//获取该调色板下新的像素值
GetDIBits(hDC, hBitmap, 0, (UINT)bm.bmHeight,
(LPSTR)lpbi + sizeof(BITMAPINFOHEADER) + dwPaletteSize,
(BITMAPINFO*)lpbi, DIB_RGB_COLORS);
//恢复调色板
if(hOldPal)
{
SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}
HANDLE hFile = CreateFile(_T("c:\\screen.bmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(hFile == INVALID_HANDLE_VALUE)
return FALSE;
//设置位图文件头
BITMAPFILEHEADER bf;//位图文件头结构
bf.bfType = 0x4d42;//"bm"
DWORD dwDibSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
dwPaletteSize + dwBmpBitsSize;//位图文件大小
bf.bfSize = dwDibSize;
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
bf.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER)+ dwPaletteSize;
//写入位图文件头
DWORD dwWritten;//写入文件字节数
WriteFile(hFile, (LPSTR)&bf, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
//写入位图文件其余内容
WriteFile(hFile, (LPSTR)lpbi, dwDibSize, &dwWritten, NULL);
//清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(hFile);
//没有压缩保存
/*BITMAP bmp;
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bmp);//获得位图信息
FILE *fp = fopen("c:\\screen.bmp", "w+b");
BITMAPINFOHEADER bih = {0};//位图信息头
bih.biBitCount = bmp.bmBitsPixel;//每个像素字节大小
bih.biCompression = BI_RGB;
bih.biHeight = bmp.bmHeight;//高度
bih.biPlanes = 1;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;//图像数据大小
bih.biWidth = bmp.bmWidth;//宽度
BITMAPFILEHEADER bfh = {0};//位图文件头
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//到位图数据的偏移量
bfh.bfSize = bfh.bfOffBits + bmp.bmWidthBytes * bmp.bmHeight;//文件总的大小
bfh.bfType = (WORD)0x4d42;
fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);//写入位图文件头
fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);//写入位图信息头
byte * p = new byte[bmp.bmWidthBytes * bmp.bmHeight];//申请内存保存位图数据
GetDIBits(memDC, hBitmap, 0, bmp.bmHeight, p, (LPBITMAPINFO) &bih, DIB_RGB_COLORS);//获取位图数据
fwrite(p, 1, bmp.bmWidthBytes * bmp.bmHeight, fp);//写入位图数据
delete [] p;
fclose(fp);*/
//DeleteObject(hBitmap);
//hBitmap=NULL;
SelectObject(memDC,hOldBitmap);
DeleteObject( hOldBitmap );
hOldBitmap=NULL;
DeleteDC( memDC );
ReleaseDC( NULL, dstDC );
ReleaseDC( hwnd, srcDC );
}
return nRetCode;
}
测试发现果然无法截取到使用WindowBlinds模拟vista半透明主题的窗口栏,还有所有半透明的窗口!
发现原BitBlt最后一个参数组合上CAPTUREBLT就能解决这个问题:
BOOL BitBlt(
HDC hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
HDC hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
DWORD dwRop // raster operation code
);
不过在引用这个参数时貌似要先更新vc6的SDK,否则会提示CAPTUREBLT未定义,不过也可以手工来给它作个宏定义:
#ifndef CAPTUREBLT
#define CAPTUREBLT 0x40000000
#endif
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
HWND hwnd = (HWND)::GetDesktopWindow();
HDC dstDC = ::GetDC(NULL);
HDC srcDC = ::GetWindowDC(hwnd); //full window (::GetDC(hwnd); = clientarea)
HDC memDC = ::CreateCompatibleDC(NULL);
CRect CaptureRect;
::GetWindowRect(hwnd,&CaptureRect);
int xScreen,yScreen;//check if the window is out of the screen | maximixed <Qiang>
int xshift = 0, yshift = 0;
xScreen = GetSystemMetrics(SM_CXSCREEN);
yScreen = GetSystemMetrics(SM_CYSCREEN);
if(CaptureRect.right > xScreen)
CaptureRect.right = xScreen;
if(CaptureRect.bottom > yScreen)
CaptureRect.bottom = yScreen;
if(CaptureRect.left < 0){
xshift = -CaptureRect.left;
CaptureRect.left = 0;
}
if(CaptureRect.top < 0){
yshift = -CaptureRect.top;
CaptureRect.top = 0;
}
CSize sz(CaptureRect.Width(), CaptureRect.Height());
HBITMAP hBitmap = ::CreateCompatibleBitmap(dstDC, sz.cx, sz.cy);
HBITMAP hOldBitmap = (HBITMAP)::SelectObject(memDC,hBitmap);
::BitBlt(memDC, 0, 0, sz.cx, sz.cy, srcDC, xshift, yshift, SRCCOPY | CAPTUREBLT);
if (OpenClipboard(NULL))
{
//清空剪贴板
EmptyClipboard();
//把屏幕内容粘贴到剪贴板上,
//hBitmap 为刚才的屏幕位图句柄
SetClipboardData(CF_BITMAP, hBitmap);
//关闭剪贴板
CloseClipboard();
}
HDC hDC;//Device Context(设备环境、设备描述表、设备上下文)的句柄
//当前显示分辨率下每个像素所占字节数
WORD wBitCount = 8;//v_iBitCount
//计算调色板大小
DWORD dwPaletteSize = 0;
if(wBitCount <= 8)//小于八位按八位处理
dwPaletteSize = (1 << wBitCount) * sizeof(RGBQUAD);
//设置位图信息头结构
BITMAP bm;//位图属性结构
BITMAPINFOHEADER bi;//位图信息头结构
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
//位图中像素字节大小
DWORD dwBmpBitsSize = ((bm.bmWidth * wBitCount+31)/32)* 4 * bm.bmHeight;
//为位图内容分配内存
HANDLE hDib = GlobalAlloc(GHND, dwBmpBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
//处理调色板
HANDLE hPal = NULL;
HANDLE hOldPal = NULL;
hPal = GetStockObject(DEFAULT_PALETTE);
if(hPal)
{
hDC = ::GetDC(NULL);
hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
//获取该调色板下新的像素值
GetDIBits(hDC, hBitmap, 0, (UINT)bm.bmHeight,
(LPSTR)lpbi + sizeof(BITMAPINFOHEADER) + dwPaletteSize,
(BITMAPINFO*)lpbi, DIB_RGB_COLORS);
//恢复调色板
if(hOldPal)
{
SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}
HANDLE hFile = CreateFile(_T("c:\\screen.bmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(hFile == INVALID_HANDLE_VALUE)
return FALSE;
//设置位图文件头
BITMAPFILEHEADER bf;//位图文件头结构
bf.bfType = 0x4d42;//"bm"
DWORD dwDibSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
dwPaletteSize + dwBmpBitsSize;//位图文件大小
bf.bfSize = dwDibSize;
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
bf.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER)+ dwPaletteSize;
//写入位图文件头
DWORD dwWritten;//写入文件字节数
WriteFile(hFile, (LPSTR)&bf, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
//写入位图文件其余内容
WriteFile(hFile, (LPSTR)lpbi, dwDibSize, &dwWritten, NULL);
//清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(hFile);
//没有压缩保存
/*BITMAP bmp;
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bmp);//获得位图信息
FILE *fp = fopen("c:\\screen.bmp", "w+b");
BITMAPINFOHEADER bih = {0};//位图信息头
bih.biBitCount = bmp.bmBitsPixel;//每个像素字节大小
bih.biCompression = BI_RGB;
bih.biHeight = bmp.bmHeight;//高度
bih.biPlanes = 1;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;//图像数据大小
bih.biWidth = bmp.bmWidth;//宽度
BITMAPFILEHEADER bfh = {0};//位图文件头
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//到位图数据的偏移量
bfh.bfSize = bfh.bfOffBits + bmp.bmWidthBytes * bmp.bmHeight;//文件总的大小
bfh.bfType = (WORD)0x4d42;
fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);//写入位图文件头
fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);//写入位图信息头
byte * p = new byte[bmp.bmWidthBytes * bmp.bmHeight];//申请内存保存位图数据
GetDIBits(memDC, hBitmap, 0, bmp.bmHeight, p, (LPBITMAPINFO) &bih, DIB_RGB_COLORS);//获取位图数据
fwrite(p, 1, bmp.bmWidthBytes * bmp.bmHeight, fp);//写入位图数据
delete [] p;
fclose(fp);*/
//DeleteObject(hBitmap);
//hBitmap=NULL;
SelectObject(memDC,hOldBitmap);
DeleteObject( hOldBitmap );
hOldBitmap=NULL;
DeleteDC( memDC );
ReleaseDC( NULL, dstDC );
ReleaseDC( hwnd, srcDC );
}
return nRetCode;
}
这样就能够截取到透明的窗体了
- 关于截屏截取不到透明窗口的问题
- 关于透明窗口的一些收集
- 关于透明窗口制造假象的精髓
- 关于字符串的截取问题
- 透明窗口问题
- 关于调用不到方法的问题
- php 关于抓取不到数据的问题
- 关于${ctx}拿不到值的问题
- 关于listener加载不到的问题
- 关于窗口嵌入桌面及透明的注意事项
- 关于分层窗口文字输出透明的处理方法
- 子窗口的透明
- 透明窗口的实现
- 【转载】关于graphicsview背景透明的问题
- 关于EDIT控件透明的问题!!!!!!!!!!!!!!!!
- 关于自定义透明状态栏的问题
- 关于字符串截取的一个小问题
- 透明窗口截屏无效解决方法
- 一个普通人
- Contains Duplicate III 重复数 堆实现
- 3.MFC的运行流程
- Redis学习心得
- std::string实现原理1
- 关于截屏截取不到透明窗口的问题
- sctp AIX
- 刚刚在看52单片机和GPS通信程序的时候,看到了一个函数,absacc.h,貌似从来没有遇到过,百度了一下,结合自己的理解,整理如下: http://blog.sina.com.cn/s/blog_4
- 5.3.1 Unique Binary Sear Trees
- Google Developing for Android系列文章翻译
- eclipse创建Maven web项目
- Mybatis学习(2)以接口的方式编程
- VS2013中使用QT编程时visual assisent(VA)不能自动补全
- Java路径和java获取项目内文件