【MFC】截图编辑插件技术总结(2):现有截屏API分析

作为系列博文的第一篇,先写些简单的吧,也是对自己学习过的东西的总结。

BitBlt

首先,是最常用的贴图函数之一的BitBlt,作用是从源DC中拷贝指定大小的图片到目标DC中,至于DC是什么,这里就不再赘述了,请自行百度。下面给出该函数的参数列表:

BOOL BitBlt(

HDC hdcDest,// 目标DC的Handle

int nXDest, // 目标位置的左上角X坐标

int nYDest, // 目标位置的左上角Y坐标

int nWidth, // 需要拷贝的图片的宽

int nHeight,// 需要拷贝的图片的高

HDC hdcSrc, // 源DC的Handle

int nXSrc, // 要拷贝图片的左上角X坐标

int nYSrc, // 要拷贝图片的左上角Y坐标

DWORD dwRop // 操作标志

);

需要注意的地方是,这里的坐标都是指DC中的坐标,可以认为DC是一个虚拟的显示设备,该设备以显示区域的左上角作为原点,X轴向右递增,Y轴向下递增,以此建立坐标系。下面以截取全屏为例说明函数用法:

m_width=GetSystemMetrics(SM_CXSCREEN);//获取屏幕分辨率

m_height=GetSystemMetrics(SM_CYSCREEN);

hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);//为屏幕创建设备描述表

hMemDC = CreateCompatibleDC(hScrDC);//创建兼容的内存设备描述表

// 创建一个与屏幕设备描述表兼容的位图

hBitmap = CreateCompatibleBitmap(hScrDC, m_width,m_height);

// 把新位图选到内存设备描述表中

hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);

// 把屏幕设备描述表拷贝到内存设备描述表中

BitBlt(hMemDC, 0, 0, m_width, m_height,

hScrDC, 0, 0, SRCCOPY);

这样就可以把屏幕截取到内存DC中用于后续操作了。最后说说操作标志这个参数,上面的代码中使用的是SRCCOPY,意思是直接复制,它还有很多选择,详情可以查看MSDN,可能用到的有SRCAND、SRCPAINT等,复制时将原图片与目标图片进行逻辑与,异或,或运算。可以产生一些特别的效果。

StretchBlt

StretchBlt是BitBlt的变形,主要用于图片的缩放。下面给出该函数的参数列表:

BOOL StretchBlt(

HDC hdcDest, // 目标DC的Handle

int nXOriginDest,// 目标位置的左上角X坐标

int nYOriginDest,// 目标位置的左上角Y坐标

int nWidthDest, // 图片目标宽度

int nHeightDest, // 图片目标长度

HDC hdcSrc, // 源DC的Handle

int nXOriginSrc, // 要拷贝图片的左上角X坐标

int nYOriginSrc, // 要拷贝图片的左上角Y坐标

int nWidthSrc, // 要拷贝图片的宽度

int nHeightSrc, // 要拷贝图片的高度

DWORD dwRop // 操作标志

);

从参数可以看出StretchBlt比BitBlt多了两个描述宽度和高度的参数,如果目标宽度高度与源宽度高度都相同则该函数的作用与BitBlt一样。通过改变目标宽度和高度,StretchBlt允许用户在拷贝的同时缩放图片。

PrintWindow

接下来要介绍的是PrintWindow函数,该函数的作用是截取整个窗口的内容。有人可能会问,用BitBlt就可以实现截取整个窗口的内容啦,为什么要有这个函数呢?其实,前面介绍的BitBlt函数有一个问题无法解决,那就是窗口遮挡问题,当想要截取的窗口被其他窗口遮挡住时,用BitBlt就无法截取完整的窗口内容了。这个时候就应该使用PrintWindow来截取完整窗口内容。下面给出函数的参数列表:

BOOL PrintWindow(

HWND hwnd, // 要拷贝的窗口句柄

HDC hdcBlt, //图片保存的目标DC

UINT nFlags // 操作标志

);

下面通过截取全屏来演示该函数的使用方法:

HWND hwnd=::GetDesktopWindow();

CRect* rect;

::GetWindowRect(hwnd,rect);

int iWidth=rect->Width();

int iHeight=rect->Height();

HDC hScrDC = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);

HDC BufferDC;

BufferDC=::CreateCompatibleDC(hScrDC);

HBITMAP BufferBmp;

BufferBmp=::CreateCompatibleBitmap(hScrDC,iWidth,iHeight);

::SelectObject(BufferDC,BufferBmp);

::PrintWindow(hwnd,BufferDC,NULL);

操作标志只有一个选项,就是PW_CLIENTONLY,意思是只截取窗口的用户区域部分,否则会全部截取。通过与前面函数的对比就会发现,PrintWindow并没有截取其他窗口的内容。下面说说本人遇到过的一个问题,PrintWindow能否截取带滚动条的窗口的完整内容?答案是不可以,为什么呢?不是说可以截取整个窗口的内容么?这涉及PrintWindow函数的具体实现,对于这个问题本人不想再深挖下去了,有兴趣的同学可以研究下,得出结论后麻烦告知一声啊!这里只提出我的一个猜想,根据MSDN上的资料,PrintWindow函数与WM_PAINT消息相似,众所周知,可以通过SendMessage函数向窗口发送WM_PAINT消息使其刷新窗口。那么,我猜PrintWindow函数是让窗口在指定的DC上刷新了,这样就会只复制该窗口的内容而不会被其他窗口干扰。因为只是进行了刷新,所以就无法截取带滚动条的窗口的全部内容了,只能截取可视区域的内容。

那要怎么解决这个问题呢?参考一些流行截图软件的做法,就是边移动滚动条,边截图,然后再把图片都拼接起来。但是,这又要怎么确保图片对齐呢?这里就不再讨论了,再讨论就跑题了,解决方案会在另一篇博文中作详细介绍,有兴趣的可以期待一下~

IViewObject::Draw

最后这个比较复杂,它主要用于截取IE浏览器的内容,但它不仅仅用于网页,微软的很多控件都实现了该方法,所以它也被用来截取控件内容。这里只对其作简要介绍,后面会写一篇关于网页截图的博文,敬请期待~下面给出函数参数列表:

HRESULT Draw(

DWORD dwAspect,

LONG lindex,

void* pvAspect,

DVTARGETDEVICE* ptd,

HDC hicTargetDev,

HDC hdcDraw,//保存图片的DC

const LPRECTL lprcBounds,

const LPRECTL lprcWBounds,

BOOL (*) (DWORD)pfnContinue,

DWORD dwContinue

);

函数的大致用法:

pViewObject->Draw(DVASPECT_CONTENT,1,NULL,NULL,NULL,hIEMenDC2,&rectl,NULL,NULL,NULL);

好的,截图函数的总结就先到这里了,第一次写博文感觉挺累的,以前做惯了伸手党,现在总算有点东西可以分享了。

本人水平有限,文中难免出现错漏,欢迎各位留言指出,但请注意文明用语,总之轻喷吧!

【MFC】截图编辑插件技术总结(2):现有截屏API分析,布布扣,bubuko.com

时间: 2024-12-14 06:06:21

【MFC】截图编辑插件技术总结(2):现有截屏API分析的相关文章

【MFC】截图编辑插件技术总结(4):IE下网页整页截屏

现在大部分浏览器都已经实现了网页截图的功能,我要说的与这种情况稍有不同,浏览器是从内部获取,而因为我是ActiveX插件,需要从外部获取网页的document.但是,实现的思路基本一致,就是将Webbrowser放大到足够大,使滚动条不出现,然后调用IViewObject接口的Draw方法实现整页的截图.下面先给出代码实现,再对代码进行分析. 1 POINT pnt; 2 3 RECT rc; 4 5 HWND DeskHwnd = ::GetDesktopWindow(); //取得桌面句柄

【腾讯Bugly干货分享】Android 插件技术实战总结

本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/1p5Y0f5XdVXN2EZYT0AM_A 前言 安卓应用开发的大量难题,其实最后都需要插件技术去解决. 现今插件技术的使用非常普遍,比如微信.QQ.淘宝.天猫.空间.携程.大众点评.手机管家等等这些大家在熟悉不过的应用都在使用. 插件技术可以给项目开发带来巨大的好处,比如:并行高效开发.模块解耦.解除单个dex函数不能超过65535的限制.动态更新

WordPress 前端投稿/编辑插件 DJD Site Post(支持游客和已注册用户)

说到前端用户投稿,倡萌之前推荐过3个不错的插件: WordPress匿名投稿插件:DX-Contribute (有朋友反馈不能用) WordPress投稿插件:User Submitted Posts (貌似没有集成编辑器,编辑文章不是很方便) WordPress 前端用户中心插件:WP User Frontend (免费版功能不太齐全) 今天要给大家推荐的这个 WordPress 前端投稿/编辑插件 DJD Site Post,它不仅支持已注册用户投稿,还支持给匿名游客投稿,而且在投稿界面添加

linux 动态库插件技术(c/c++):动态链接库

概述 插件技术的目的是为了更好的扩展性.动态链接库是其中 一种实现方式. 这里主要论述几个问题. 1)linux上关于这些api的描述.看完linux上关于dlopen等函数的描述基本就可以写出简单的动态链接库使用. 2)关于c++使用动态链接库的一些问题和注意事项. 3)扩展,编译器的各选项,动态链接库和静态链接库. linux api:dlopen,dlsym,dlerror,dlclose 摘自ubuntu kylin 14.04,内核3.13.0-32generic #include<d

iOS8新特性扩展(Extension)应用之三——照片编辑插件

iOS8新特性扩展(Extension)应用之三--照片编辑插件 通过前几篇博客的介绍,我们了解到扩展给app提供的更加强大的交互能力,这种强大的交互能力另一方面体现在照片编辑插件的应用. 和通常一样,我们先创建一个工程,然后新建一个Target,选择photo editing: 从模板中,我们可以看到系统为我们创建了一个controller,这个controller就是用于处理照片的controller,其中方法如下: - (BOOL)canHandleAdjustmentData:(PHAd

Atitit.java的浏览器插件技术 Applet japplet attilax总结

Atitit.java的浏览器插件技术  Applet  japplet attilax总结 1. Applet类及各个方法说明 1 2. JApplet类示例 2 3. / 用main方法运行JApplet   2 4. 设置获取参数 2 5. Firefox运行applet提示安全组织的解决 3 6. Japplet调用js 4 7. 调试的清除缓存 4 8. Class文件的位置 -推荐放在webroot下面 5 9. 参考 5 1. Applet类及各个方法说明 Applet类提供一个基

MFC截图和界面刷新相关问题

问题描述: 就是首先用CDC来截图,保存图片的路径通过dlg窗体来手动设置并传入.可是截下来的图片就会连带那个对话框也截图下来. 就是这样,我想截后面那个图,前面这个对话框是要传入一个图片保存路径,可是连这个框也截下来了,就是点击确定后,那个框还没有来得及消失,就截图了, 见图片; 部分代码: 解决方案: 涉及到的函数有: BOOL UpdateWindow(HWND hWnd // 窗口的句柄); 如果窗口更新的区域不为空,UpdateWindow函数通过发送一个WM_PAINT消息来更新指定

eclipse安装Veloeclipse(Velocity编辑插件)

eclipse安装Veloeclipse(Velocity编辑插件) Help-->install new software-->Add 增加 Name:Veloeclipse Value:http://veloeclipse.googlecode.com/svn/trunk/update/ 然后选择Veloeclipse,再单击next 若无法列出该地址下的内容,只要在安装插件的界面中把 Group Items by Catagory 前打钩去掉就可以了!

MFC截图功能

void CVideoWndInst::ToShotScreen(){ CRect vRc; mVideoWnd.GetWindowRect(&vRc); SaveBitmapToFile(CopyScreenToBitmap(&vRc),"c://1.bmp"); } // 将屏幕指定区域存成图片 HBITMAP CVideoWndInst::CopyScreenToBitmap(LPRECT lpRect) //lpRect 代表选定区域 { HDC hScrDC,