工作日志:实现浏览器滚动截屏,并且是指定的iframe在跨域的情况下。

首先拿到这个需求的时候,想了一下,实现滚动截屏并不难,难的具体的情况如下,

在IE浏览器的情况下,在前端实现,并且iframe是跨域的,还要自动上传服务器,万事开头难,尝试了HTML2canvas之后发现,它并不能解决跨域问题,而且不同浏览器其图片会有差异,并且最重要的一点,svg图在IE浏览器中截图是空白。

当然,遇到需求,一定要解决,研究了IE设计接口,终于实现了,整体的思路是,拿到浏览器的接口对象,使用递归遍历,找到指定的iframe,拿到iframe对象,滚动每一屏,拼接起来,最后产生的是一个长图,并且是高清位图,高清的位图占的控件大小非常大,所以使用压缩算法将其大小进行了30倍的压缩。

压缩后的图片大概在100k-500k之间,那么怎么上传呢,这个比较简单了,在内存里直接使用base64编码图片,将字符串传至服务器当中,服务器拿到字符串可以进行转码存储,至于前端显示,可以把图片直接io传输显示,也可以转base64直接由img标签进行解析。

既然思路有了,那就说说具体的实现,首先,采用任意编程语言,创建一个浏览器插件工程,这里,我采用studio,首先,捕获IE浏览器窗口句柄,这个十分简单,调用原生api就可以,代码如下:

BSTR CshotScreenCtrl::shotScreen(void)

{

POINT pNow = { 0,0 };

BSTR base64Data = L"";

if (GetCursorPos(&pNow)) // 获取鼠标当前位置

{

pNow.x = pNow.x+200 ;

pNow.y = pNow.y+200;

HWND hwndPointNow = NULL;

hwndPointNow = WindowFromPoint(pNow)->m_hWnd; // 获取鼠标所在窗口的句柄

if (hwndPointNow)

{

string data = GetIHTMLDocument2Interface(hwndPointNow);

CString str = (CA2W)(data.c_str());

base64Data = str.AllocSysString();

}

}

return base64Data;

}

GetIHTMLDocument2Interface是获取对应的父窗体的接口对象方法,

string GetIHTMLDocument2Interface(HWND BrowserWnd)

{

string data;

CoInitialize(NULL);

HRESULT hr;

// Explicitly load MSAA so we know if it's installed

HINSTANCE hInst = ::LoadLibrary(_T("OLEACC.DLL"));

if (hInst)

{

LRESULT lRes; //SendMessageTimeout后的返回值,用于函数pfObjectFromLresult的第1个参数

UINT nMsg = ::RegisterWindowMessage(_T("WM_HTML_GETOBJECT"));

::SendMessageTimeout(BrowserWnd, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes);

//获取函数pfObjectFromLresult

LPFNOBJECTFROMLRESULT pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)::GetProcAddress(hInst, "ObjectFromLresult");

if (pfObjectFromLresult)

{

CComQIPtr spDoc;

hr = (*pfObjectFromLresult)(lRes, IID_IHTMLDocument, 0, (void**)&spDoc);

if (SUCCEEDED(hr))

{

//获取文档接口

CComPtr spDisp;

spDoc->get_Script(&spDisp);

CComQIPtr spWin = spDisp;

spWin->get_document(&spDoc.p);

// Change background color to red

//spDoc->put_bgColor(CComVariant("red"));

CComQIPtr window;

spDoc->get_parentWindow(&window);

RECT rect;

::GetWindowRect(BrowserWnd, &rect);

int nWidth = rect.right - rect.left;

int nHeigth = rect.bottom - rect.top;

//尝试获取iframe的窗体

CComQIPtr fBody;

spDoc->get_body(&fBody);

CComQIPtr fBase;

EnumFrame(spDoc, rect);

//CaptureToImage(spDoc,rect, BrowserWnd,"C://tempImg//tmp.png");

CompressImageQuality(L"C://tempImg//tmp.png", L"C://tempImg//tmpcompress.jpg", 50);

ReadPhotoFile(L"C://tempImg//tmpcompress.jpg",data);

} // else document not ready

} // else Internet Explorer is not running

::FreeLibrary(hInst);

} // else Active Accessibility is not installed

CoUninitialize();

return data;

}

虽然找到了父窗体的接口,但是这里不能直接拿iframe的,因为我们现在是跨域,浏览器可不会让你这么简单的跨域,毕竟如果强行跨域,那你就可以强行跨站脚本攻击了,但是道理是死的,人是活的,我们换种方法,既然我们调用拿的方法拿不到,那我们就自己取找,把父窗口转成容器接口,枚举递归遍历每一个实现的iwebborwser接口的对象,直到找到名字为我们要的那个iframe为止,代码如下:

void EnumFrame(IHTMLDocument2* pHTML,RECT rect)

{

CComQIPtr spContainer(pHTML);

if (spContainer)

{

CComPtr spEnumerator; // 注:参数OLECONTF_EMBEDDINGS // 表示列举容器内的所有嵌入对象

HRESULT hr = spContainer->EnumObjects(OLECONTF_EMBEDDINGS, &spEnumerator);

if (spEnumerator)

{

CComPtr spUnk;

while (spEnumerator->Next(1, &spUnk, NULL) == S_OK)

{

CComQIPtr spWB(spUnk);

spUnk = NULL;

if (spWB)

{

CComPtr spDocDisp;

hr = spWB->get_Document(&spDocDisp);

CComQIPtr spHTML(spDocDisp);

CComQIPtr sBody;

spHTML->get_body(&sBody);

long sScrollHeight = 0L;

CComQIPtr pBodyElem2(sBody);

pBodyElem2->get_scrollHeight(&sScrollHeight);

CComPtr pWnd2;

S_OK == spHTML->get_parentWindow(&pWnd2);

BSTR frameName;

pWnd2->get_name(&frameName);

string str1 = (_bstr_t)frameName;

if ("childIframe" == str1) {

long width = 0L;

long height = 0L;

spWB->get_Width(&width);

spWB->get_Height(&height);

CaptureToImage(spHTML, rect, NULL, "C://tempImg//tmp.png");

break;

}else {

EnumFrame(spHTML, rect);

}

}

}

}

}

}

到了这里,我们已经拿到iframe,也就是我们要截图的窗体,那么接下来只要调用scrollto,并且计算坐标偏移就可以了,原理十分的简单,至于后面的代码,十分简单,就不贴出来了,到了这一步,我们已经可以跨域拿到iframe里的任何东西啦,想怎么操作就怎么操作,至于压缩算法还有转base64上传的代码百度满天飞,如果你有什么不懂,可以私信,附一张效果图吧。

java 滚动截屏_浏览器实现滚动截屏相关推荐

  1. 小程序scroll-view,滚动到最低_小程序滚动到底部

    小程序scroll-view,滚动到最低_小程序滚动到底部 小程序滚动条,滚到最底部解决方案1 小程序滚动到底部使用Scorll-view实现方案: scrill-view:组件要固定高度. scro ...

  2. java+多显示器截屏_双屏/多显示器截屏

    截屏程序的源码网上到处都有,但是基本都不支持多显示器. 这让我一度以为支持多显示器是一件很困难的事情. (demo http://download.csdn.net/detail/problc/384 ...

  3. 【ElementUI】InfiniteScroll 无限滚动组件在部分浏览器中滚动失效 的 解决方案

    ElementUI 官网 InfiniteScroll 使用:https://element.eleme.cn/#/zh-CN/component/infiniteScroll 首先先叙述一下需求,说 ...

  4. windows录屏_电脑自带录屏软件怎么打开?详细操作教程

    电脑自带录屏软件怎么打开?现在主流的三大PC设备操作系统,即:Windows.Linux.Mac.和两大主流的移动设备操作系统,即安卓和iOS,都是有自带的录屏软件(功能)的.这也是考虑到使用电子设备 ...

  5. 华为nova3e怎么分屏_华为手机怎么分屏?边看视频边聊微信!不是所有手机都能做到...

    阅读本文前,请您先点击上面的蓝色字体"自媒创业",再点击"关注",这样您就可以继续免费收到最新文章了.每天都有分享.完全是免费订阅,请放心关注 为什么很多时候电 ...

  6. 安装黑屏_含能公司黑屏管理助力智能化改造

    近期,含能公司仪表计量检测中心组织人员安装.调试化工一厂.化工六厂黑屏管理软件,为黑屏管理平稳运行奠定基础. 近年来,银光集团在对标学习东岳集团和先进企业管理经验的基础上,陆续在部分生产线推行黑屏管理 ...

  7. 录制出来的是黑屏_打开好哈录屏或者OBS直播软件黑屏问题解决,亲测有效!

    在官网上下载好哈录屏或者是OBS直播软件后,打开软件后,添加"显示器捕捉",但一直黑屏,录制出来的视频文件只有声音,没有具体画面,今天小编给大家讲解如何解决这个问题. Obs黑屏如 ...

  8. vscode win10笔记本 蓝屏_遇到win10电脑蓝屏怎么办_简单解决win10蓝屏的方法

    Win10系统出现蓝屏现象属于比较常见问题之一,想必大家也不陌生了.如果电脑时不时出现蓝屏,会影响正常使用体验,引发win10电脑蓝屏的原因有很多,可能是系统问题,还可能是驱动问题,也有可能是硬件问题 ...

  9. windows录屏_电脑是怎么录屏的呢?推荐三个录屏实用方法

    不管你是大学生还是上班族,在使用电脑的时候都有可能遇到录屏的情况,比如说需要录制一些游戏视频.会议记录视频.录制直播视频等.在电脑上遇到了录屏的方法怎么解决?分享有关录屏的方法,希望可以帮助到你! 方 ...

最新文章

  1. android11和ios,安卓与iOS细节对比:Reno Ace与iPhone 11 Pro Max,结果很意外
  2. Android开发之单例模式初探
  3. GitHub免费支持CI/CD了,开发测试部署高度自动化,支持各种语言,网友:第三方凉凉...
  4. Linux 指令篇:档案目录管理--chown
  5. 图像处理理论(五)——SIFT
  6. LeetCode 777. 在LR字符串中交换相邻字符(双指针)
  7. 安卓应用安全指南 5.6.1 密码学 示例代码
  8. 微课|玩转Python轻松过二级(3.1节):列表推导式与切片
  9. preference java_Java使用Preference类保存上一次记录的方法
  10. shell截取字符串的方法
  11. 51单片机开发第一步 keilC51 以及 proteus 的安装
  12. 【软测面试】找工作前的准备|面试题
  13. 0基础跟着黑马程序员学微信小程序前端开发Day02(自学笔记)
  14. 【2016北京集训】网络战争
  15. 【MySQL篇】第三篇——表的操作
  16. Stata:一文读懂事件研究法EventStudy
  17. 配音软件哪个好用?好用的配音软件有哪些?你不知道的3款配音软件
  18. 产品管理精华:第一,谁是优秀的产品经理?
  19. python识别手写数字字体_基于tensorflow框架对手写字体MNIST数据集的识别
  20. 计算机网络引言(1)

热门文章

  1. 面向对象:中央戏精学院扛把子,emmm我应该是属小火车的吧~
  2. 2007 - 半质数 --- 素数筛+2137 - 质因子2
  3. css中,如何给文字添加描边效果?
  4. springboot引入Redis配置JedisPool连接池
  5. 【矩阵论笔记】正交分解——满秩Schmidt分解(施密特正交化)
  6. 10种最不健康的生活方式
  7. python问题两个乒乓球队进行比赛_Python练习题 017:三支乒乓球队出赛名单
  8. 上反对下反对推理图_2020福建省考行测判断推理:直言命题之上下反对关系
  9. android手机上传不了图片,关于Web Uploader手机上传不了图片的问题
  10. Intel双通道模式解析