浏览器实现滚动截屏

article/2025/10/6 11:07:30

工作日志:实现浏览器滚动截屏,并且是指定的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);//获取函数pfObjectFromLresultLPFNOBJECTFROMLRESULT pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)::GetProcAddress(hInst, "ObjectFromLresult");if (pfObjectFromLresult){CComQIPtr<IHTMLDocument2> spDoc;hr = (*pfObjectFromLresult)(lRes, IID_IHTMLDocument, 0, (void**)&spDoc);if (SUCCEEDED(hr)){//获取文档接口CComPtr<IDispatch> spDisp;spDoc->get_Script(&spDisp);CComQIPtr<IHTMLWindow2> spWin = spDisp;spWin->get_document(&spDoc.p);//  Change background color to red//spDoc->put_bgColor(CComVariant("red"));CComQIPtr<IHTMLWindow2> window;spDoc->get_parentWindow(&window);RECT rect;::GetWindowRect(BrowserWnd, &rect);int nWidth = rect.right - rect.left;int nHeigth = rect.bottom - rect.top;//尝试获取iframe的窗体CComQIPtr<IHTMLElement> fBody;spDoc->get_body(&fBody);CComQIPtr<IHTMLFrameBase2> 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 installedCoUninitialize();
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<IUnknown> spUnk;while (spEnumerator->Next(1, &spUnk, NULL) == S_OK){CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> spWB(spUnk);spUnk = NULL;if (spWB){   CComPtr<IDispatch> spDocDisp;hr = spWB->get_Document(&spDocDisp);CComQIPtr<IHTMLDocument2> spHTML(spDocDisp);CComQIPtr<IHTMLElement> sBody;spHTML->get_body(&sBody);long sScrollHeight = 0L;CComQIPtr<IHTMLElement2> pBodyElem2(sBody);pBodyElem2->get_scrollHeight(&sScrollHeight);CComPtr<IHTMLWindow2> 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上传的代码百度满天飞,如果你有什么不懂,可以私信,附一张效果图吧。
在这里插入图片描述


http://chatgpt.dhexx.cn/article/DwbmOXDR.shtml

相关文章

Chrome浏览器如何完美实现滚动截图技巧

Chrome浏览器如何完美实现滚动截图技巧 - Chrome插件网 一、前言 我们平时在浏览网页时&#xff0c;想把碰到好的网页内容或者文章截屏保存&#xff0c;但是网页的长度常常会超出屏幕高度&#xff0c;一般的截屏功能只能截取显示在屏幕上的内容&#xff0c;那我们该如何方便快…

snipaste滚动截图方法

在需要截长图的时候&#xff0c;经常会到处找怎么在电脑上截长图的教程&#xff0c;其实我们可以借助第三方工具&#xff0c;snipaste就是一款非常好用的截图工具&#xff0c;在用户滚动截图时能发挥极大的作用。 snipaste怎么滚动截长图 1、打开snipaste软件&#xff0c;鼠标右…

浏览器如何截图整个滚动屏 ?

如果你在开发工作中&#xff0c;需要浏览器的整个滚动屏进行截图的话&#xff0c;那么不妨按下面方式进行操作。 【1】将浏览器滚动条滚动到顶部。 【2】按下 F12 &#xff0c;打开开发者窗口&#xff08;方式二&#xff1a;鼠标右键&#xff0c;点击【检查】&#xff09;。 【…

snipaste如何滚动截图_一文解决几乎所有截图需求:我多年来用过的优秀截图软件和插件推荐...

本系列所述软件均为我自己用过很久后的良心推荐,均为在领域内广受好评或者颇具特点的软件,请放心食用 前言 截图大概是普通人最常用的办公操作之一了: 看到不错的内容,截图以后续查看;工作、购物出问题了,截个图反馈下;日常和女朋友、男朋友聊天,截个图保存黑历史………

网页界面滚动截图(长图)的三种实用方法总结

简言 有些时候我们需要把整个网页的截图下来进行保存存档&#xff0c;但是像微信QQ等工具也只能截取看到的部分。当我们要截取的部分比价大时&#xff0c;这里在网上统计了三个简单方法&#xff0c;来和大家分享一下&#xff1a; QQ默认为CtrlAltA 微信默认为AltA(可以手动修改…

电脑怎么滚动截图的方法

电脑截图常见的有矩形截图、任意形状截图、全屏幕截图、窗口截图等等&#xff0c;那你知道怎么在电脑上滚动截图吗&#xff1f;有时候可能会需要用到滚动截长图&#xff0c;但是很多 用户都不清楚怎么操作&#xff0c;下面小编就来教教大家电脑怎么滚动截图的方法&#xff08;除…

一文说透模拟退火算法

模拟退火算法是一种用于解决全局优化问题的算法。它是一种概率演算法&#xff0c;基于物理学中材料退火的概念。算法的基本思想是通过随机游走在解空间中来找到全局最优解。算法的主要步骤是&#xff1a; 选择一个初始解作为当前解&#xff1b;在当前解的邻域中随机选择一个新…

模拟退火学习笔记

目录 关于模拟退火的简言思路具体实现总结 关于模拟退火的简言 模拟退火&#xff0c;一种著名的神奇玄学算法&#xff0c;因为正确性是靠随机来保证的&#xff0c;所以是AC纯看rp。但是因为其思路的优越性&#xff0c;正确率并不低。再很多题目都不失为一种优秀的算法。甚至在…

模拟退火

模拟退火 1. 模拟退火原理 原理 模拟退火&#xff1a;是一种随机算法&#xff0c;用于解决最优化问题。要求求解的问题对应的函数要有连续性。模拟退火算法是模拟物理过程&#xff0c;有如下参数&#xff1a; &#xff08;1&#xff09;温度t&#xff1a;即步长。分为初始温度…

VS2017 下载离线MSDN文档

VS2017 下载离线MSDN文档 点开帮助窗口的时候发现没有添加和删除帮助内容选项。处理方法如下&#xff1a; 1.打开vs2017安装包&#xff0c;如果你找不到安装包&#xff0c;可在相应你下载vs2017的浏览器上找到下载内容&#xff0c;然后点击在文件夹中显示&#xff0c;找到安装包…

vs 2017官网下载、QT下载

QT官网下载地址&#xff1a;https://download.qt.io/archive/qt/https://download.qt.io/archive/qt/Visual Studio 2017 15.9 Release Notes | Microsoft DocsRelease notes for the latest features and improvements in Visual Studio 2017 v15.9. Plan better, code togeth…

VS2017下载更新

一&#xff1a;官网地址 https://www.visualstudio.com/zh-hans/downloads/ 二&#xff1a;下载vs下载器 比如我们将它下载放在C:\Users\baijinwen\Downloads\vs_community.exe 三&#xff1a;下载离线安装文件 我们希望将离线安装文件下载到H:\vs2017文件夹&#xff0c; …

VS2017下载安装C#版本jieba库

先去https://www.nuget.org/downloads官网下载页面下载最新的nuget&#xff0c;双击运行。 出现Nuget包管理器&#xff0c;调出控制台。 Packages页面下搜索jieba&#xff0c;点击第一个jieba.NET。 先将Dependencies下的packages下载安装好&#xff0c;如果dependencies对应的…

vs2017怎么安装python_vs2017怎么添加python

1、Python环境的搭建&#xff1a; 这里我选择的是Anaconda可以傻瓜式的帮我们将python环境搭建完毕&#xff0c;贴上Anaconda的下载地址&#xff1a;https://www.anaconda.com/download/#download 选择适合的版本下载即可&#xff0c;我这选择的Python3.6 version 64位的&#…

关于Visual Studio 2017安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法

Visual Studio 2017中的安装问题详细解决方法 1.VS2017下载地址&#xff1a; https://my.visualstudio.com/Downloads?qvisual%20studio%202017&wt.mc_idomsftvscom~older-downloads 2.这里有社区版、企业版、专业版等&#xff0c;一般选择社区版&#xff08;免费版&…

最全的VS 2017下载与安装

#Visual Studio 2017下载与安装 Microsoft Visual Studio&#xff08;以下简称VS&#xff09;&#xff0c;是微软公司开发的一系列工具包产品&#xff0c;满足多种语言开发&#xff0c;包括&#xff1a;C、C、C#、F#等&#xff0c;适用于微软支持的所有平台。 目前VS更新到2019…

VS2017离线下载及安装方式

vs2017下载 目前微软官网提供Visual Studio 2017在线安装版本&#xff0c;对于离线安装只提供说明。 Visual Studio 2017官网提供四个版本&#xff0c;这里个人学习&#xff0c;所以选择社区版的&#xff0c;下面说的也是社区版的安装步骤。 一、离线下载器下载 在微软官网h…

vs2017如何下载?

visual studio2017的下载与安装 visual studio是一款非常强大的软件。相信大家都知道vs是什么了,我就不在这里介绍了。 不过,大家可能会在visual studio的下载上遇到瓶颈,没关系,我们一步一步来吧! 首先,进入下面的网址: https://visualstudio.microsoft.com/vs/whatsn…

关于Google身份验证器、基于时间的一次性密码 (TOTP)算法的初步了解

一、Google Authenticator 1、概述 Google Authenticator是基于双因素身份验证 ( 2FA ) 的应用程序&#xff0c;有助于识别用户身份并确认用户声称自己是谁以及他是否真的是这个人。 当您启用两步验证&#xff08;也称为双重身份验证&#xff09;时&#xff0c;您会为您的帐户…

深度学习--十折交叉验证

用scikit-learn来评价模型质量&#xff0c;为了更好地挑拣出结果的差异&#xff0c;采用了十折交叉验证&#xff08;10-fold cross validation&#xff09;方法。 本程序在输入层和第一个隐含层之间加入20%Dropout 采用十折交叉验证的方法进行测试。 # dropout in the input …