QT通过QAxWidget嵌入IE浏览器并获取页面源码
2016-12-07 19:54
330 查看
为什么
为了显示微信登录的二维码,引入了整套QtWebEngine,占用非常大的空间。微信登录二维码有自动刷新动作,这些定义在页面脚本中,所以不能直接自绘二维码方式实现,浏览器少不了。
主要原理
通过COM组件可以调用系统自带的浏览器,当然是IE啦。Qt提供QAxObject和QAxWidget对象帮助访问COM,(与其说帮助,还不如说越帮越忙)
怎么做
请注意接下来描述的每一步,在完全理解前,不要擅自调整1. 创建或者基于已有的Qt设计师界面类,就是有.ui文件的那种。但是奇葩来了,完整的设置通过“设计”
是搞不出来的。所以随便拉个QAxWidget吧。
2. 通过用文本编辑器的方式打开对应的ui文件
3. 找到<customwidgets>,往里面插入一组提升设置
4. 把界面上的QAxWidget找到,改成如下样式,objectName会在每次用"设计"改ui的时候被覆盖掉(悲剧),control里面的guid是对应IWebBrowser2接口的,固定就那么写。
5. 照着模样做一个WebAxWidget.h。注意,集成QAxWidget的类不能声明Q_OBJECT,会导致activeqt机制里面moc无效,表现看这里stackoverflow
#ifndef WEBAXWIDGET_H #define WEBAXWIDGET_H #include <ActiveQt/QAxWidget> #include "windows.h" class WebAxWidget : public QAxWidget { public: WebAxWidget(QWidget* parent = 0, Qt::WindowFlags f = 0) : QAxWidget(parent, f) { } protected: bool translateKeyEvent(int message, int keycode) const Q_DECL_OVERRIDE { if (message >= WM_KEYFIRST && message <= WM_KEYLAST) return true; else return QAxWidget::translateKeyEvent(message, keycode); } }; #endif // WEBAXWIDGET_H |
signal mis::WebAxBrowser::DownloadComplete()这样的提示,就是说你的命名对了,槽就会被调用,而不需要手动去连接).稳妥的办法是去qt
sample:webbrowser里面抄几个.
7. 让槽函数转调一个专门处理它的类,我创建了一个WebAxWrapper,把回调处理后转成类似QWebEngineView的信号:loadFinished和loadProgress
8.当然还有load()和url()
9. 最后值得一提的是拿页面源码。找了很多帖子,期间想到Javascript法,结果IHTMLWindow2里面的execScript方法不能拿到返回值,网上文章一大堆,还有反汇编C# InvokeScript()方法的.最后找到了流化方案。我做了一个像QWebEnginePage的toPlainText方法
void WebAxWrapper::toPlainText(void (*f)(const QString &)) { char *output = NULL; QAxObject *document = WebBrowser->querySubObject("Document"); if(document) { IHTMLDocument2 *doc2 = nullptr; document->queryInterface(QUuid(IID_IHTMLDocument2), (void**)&doc2); if (doc2) { IPersistStreamInit *pPSI=NULL; IStream *pStream=NULL; HGLOBAL hHTMLText; if (SUCCEEDED(doc2->QueryInterface(&pPSI))) { const int MaxBuffSize =64*1024; hHTMLText = GlobalAlloc(GMEM_FIXED, MaxBuffSize); CreateStreamOnHGlobal(hHTMLText, TRUE, &pStream); pPSI->Save(pStream, FALSE); LARGE_INTEGER li; li.QuadPart = 0; pStream->Seek(li,0,NULL); output = new char[MaxBuffSize]; output[MaxBuffSize-1] = 0; ULONG readed = 0; pStream->Read((void*)output,MaxBuffSize-1,&readed); output[readed] = 0; pStream->Release(); //GlobalFree(hHTMLText); pPSI->Release(); } doc2->Release(); } } if(output) { qDebug()<<output; f(QString::fromUtf8(output)); delete[] output; } else { f(QString()); } } |
#include <ExDisp.h>
#include <shlguid.h>
#include <MsHTML.h>
#include <QUuid>
10. 二维码,其实最后这个不是重点了,直接把我们的页面(http://passport.timelink.cn/wechat/show)显示出来,当发生loadFinished的时候,获取一下当前url,如果不同了,分析一下页面源码,我们的项目在这一步服务器返回一段json,解析并处理就可以了。
最后
ie浏览器右键菜单真是又多又杂...
欢迎访问我们的轻录课项目,以及分课网 http://fenke.timelink.cn
相关文章推荐
- 通过Web页面获取基站位置(Web端,源码下载)
- JS获取中文拼音首字母并通过拼音首字母快速查找页面内对应中文内容的方法【附demo源码】
- 通过Web页面获取基站位置(Web端,源码下载)转
- js通过获取地址栏参数跳转页面
- c#通过GET/POST获取页面的代码
- 获取指定页面的HTML源码
- 使用Http请求获取web页面源码
- 通过WebRequest 类来获取远端页面。
- C#获取页面的HTML源码
- SilverLight浏览器交互之:Html页面通过Javascript调用SilverLight程序内方法(附源码)
- C#通过url获取页面html
- js通过获取地址栏参数跳转页面
- 通过javascript获取多种主流浏览器显示页面高度
- 通过cURL获取web页面及http header信息
- jsp页面获取Action变量值(不通过标签)
- 获取指定页面的HTML源码
- C#获取指定URL页面的HTML源码
- 通过post方法远程获取一个页面
- 通过WebBrowser网页截图C#源码(抓取完整页面及首屏)
- 通过IFrame获取其他页面中Div的值