关于截屏截取不到透明窗口的问题

最近试过几套截图软件,发现其中有些无法实现对半透明窗口或主题的图片截取,包括早期版本的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;

}

这样就能够截取到透明的窗体了

时间: 2024-10-09 19:53:04

关于截屏截取不到透明窗口的问题的相关文章

ios 截屏(代码)

//1.首先在storyboard中拖一些控件,包括UIButton控件,将UIButton控件拖线到控制器中(方法.CutImage) //2.在CutImage方法中调用NSTimer方法 - (IBAction)CutImage:(UIButton *)sender { NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 targer:self  selector:@selector(clipImage) userInf

源码0301-图片水印-裁剪-截屏-截取-擦除

// ViewController.m // 01-图片水印 #import "ViewController.h" // 在图片的基础绘制一些文字或者Logo,最终生成一张图片 @interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *imageView; @end @implementation ViewController - (void)viewDidLoad { [super v

iOS 图片截取 截屏

iOS中对图片的截取 转载的话,请标明出自博客园 截取图片的话 需要指定对象.代码不多,我不太会说,贴一下好了 1 /** 2 * 大图切小图 3 * 4 * @param BIGimg 大图 5 * 6 * @return 小图 7 */ 8 -(UIImage *)getImageFromImage :(UIImage*)BIGimg{ 9 10 //大图bigImage 11 //定义myImageRect,截图的区域 相对位置 12 CGRect myImageRect = CGRect

超好用的滚动屏幕截屏工具FastStone Capture

对于超级喜欢整理的技术控,一看到比较好技术文章就想收集下来,单纯的记录网页,又怕作者删除,我只能选择截图,可是有许多文章特别长,直到使用FastStone Capture截图工具,终于可以快速收集这些技术文章了. 1.截图工具是这样的 2.比较好用的滚动截屏使用方法: 图中第六个图标. 1)点击后,可以拖动窗口进行大范围的截图,比如可以将浏览器的网页做为截图对象,截取时,点击选取滚动条箭头就可以完成截图,ESC中断截图滚动! 2)在选定滚动截图图标后还可以按ctrl键进行滚动区域的选择. 3.图

Android自己定义截屏功能,相似QQ截屏

由于公司业务需求 须要对一个屏幕进行截屏.但自带的截屏功能是远远不够项目的功能需求 ,我们是做一个画板软件 .须要的像QQ那样截屏之后 ,能够看到我们自己定义的工具.有画笔,button等等 .android自带的功能非常easy,仅仅须要Intent隐式调用就全然足够了.但他是系统的应用 ,界面固定.无法定制改动.实现方法跟办法有非常多种,以下记录下我实现的方法 .我是这样一个思路 ,重写一个View组件 ,在OnDraw里面仅仅负责不绘图形(包含半透明的四个矩形,亮框矩形,亮框上的四个小圆点

Snipaste强大离线/在线截屏软件的下载、安装和使用

步骤一: https://zh.snipaste.com/  ,去此官网下载. 步骤二:由于此是个绿色软件,直接解压即可. 步骤三:使用,见官网.ttps://zh.snipaste.com  按F1开始截屏 感谢下面哥的精彩微信文章 http://mp.weixin.qq.com/s?__biz=MzIwNzYwODYwMw==&mid=2247483903&idx=1&sn=02121fe920320bbe7b2fae012a18e70a&chksm=970e8f8ba

phantomjs介绍-(js网页截屏、javascript网页解析渲染工具)

phantomjs介绍-(js网页截屏.javascript网页解析渲染工具) phantomjs 是一个基于js的webkit内核无头浏览器 也就是没有显示界面的浏览器,这样访问网页就省去了浏览器的界面绘制所消耗的系统资源,比较适合用于网络测试等应用 .利用这个工具,我们可以轻松的搭建一个接口用于获取我们想要的url的整页截屏. PhantomJS is a headless WebKit with JavaScript API. It has fast and native support

Java邮件发送与屏幕截屏

前几天七夕情人节孤独寂寞的程序猿闲来没事,花了一两个小时写了个小Demo主要实现Java的Mail发送功能和桌面截屏功能. 首先让我们先看看Java sendMail邮件发送和桌面屏幕截屏功能是怎么实现的基础知识. 一.Java  SendMail邮件发送 首先让我们来看看邮件发送的原理图: JavaMail 是一套sun 提供开发邮件收发程序API,JavaMail编写程序就是邮件客户端程序(和outlook.foxmail功能类似) * JavaMail开发需要类库 javamail API

VR中特定相机截屏问题与实现

本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/71136498 作者:cartzhang unity 中的截图与VR中的截图,难度还不一样么?还真有点不一样. 这里就是用HTC Vive头盔下来做为例子. 非常感谢同事让我来帮他解决问题. 一.Unity中的常用截图方式 unity中常用截图的方式有三种: 1. 使用CaptureScreenshot 这个可以参考官方给的例