CDHtmlDialog探索----Javascript与窗体交互
CDHtmlDialog提供了C++与网页的双向交互,通此一系统简单的宏调用可以把网页中各元素的事件直接映射到C++程序中,而在网页中调用C++功能代码就显的不那么直观了。归根结底交互的基理就是实现相应COM接口。实现方式如下:
1、在窗体初始化时调用EnableAutomation函数。
通常情况下是放在窗体的构造函数中,
当然也可以放在OnInitDialog中,不过要注意顺序,其调用不应该晚于对SetExternalDispatch的调用。此函数在底层的实现就是引用到正确的IDispatch接口(实际就是定位了相应的vtable指针),IDispatch是OLE自动化程序实现的根基。
2、在窗体初始化时调用SetExternalDispatch函数。
通常情况下放在OnInitDialog事件中。
在这个地方就用到了IDispatch接口。所以必须保证EnableAutomation是在SetExternalDispatch之前调用。调用此函数是对网页公布其窗口容器的接口从而在网页中可以通过window.external来调用窗口容器公布的函数、事件、属性。
3、在头文件中添加DECLARE_DISPATCH_MAP()
这个宏定义了对外公布信息需要使用的一些内部数据结构和操作。
4、在实现文件中(*.cpp)添加具体的信息映射
DECLARE_DISPATCH_MAP()
DISP_FUNCTION(CBrowserDlg,"testfun",TestFunction,VT_EMPTY,VTS_VARIANT VTS_VARIANT)
END_DISPATCH_MAP()
testfun是对网页公布的函数名称,TestFunction是在CBrowserDlg的成员函数,VT_EMPTY表示此函数没有返回值,VTS_VARIANT表示函数参数,多个参数之间使用空格。需要注意的一点是js或vbs这类的脚本语言的数据类型都对应于COM中的变体类型,假如说testfun函数传递两个参数分别是整型和字符串类型(示例中的两个参数都当做字符串来处理),在定义的时候可以使用VTS_I4和VTS_VARIANT来表示这两个参数的类型,虽然VTS_PBSTR是用于表示字符串的但却不对应脚本语言的字符串类型所以应该使用VTS_VARIANT,使用VTS_VARIANT来代替VTS_I4也是正确的。其它复杂数据类型比如说对象等都应用使用VTS_VARIANT数据类型表示。
5、实现对外公布的函数(在此示例中是TestFunction)
1
2
3
4
5
6
7
8
9
10
|
void CBrowserDlg::TestFunction(VARIANT& vStr1,VARIANT& vStr2) { CComVariant varStr1(vStr1),varStr2(vStr2); varStr1.ChangeType(VT_BSTR); varStr2.ChangeType(VT_BSTR); USES_CONVERSION; CString strMsg; strMsg.Format(_T( "varStr1:%s,varStr2:%s" ),OLE2T(varStr1.bstrVal),OLE2T(varStr2.bstrVal)); AfxMessageBox(strMsg); } |
6、在网页中调用窗体容器公布的函数
1
|
<script language= "javascript" type= "text/javascript" ><br> // <!CDATA[<br> window.external.testfun("one","two");<br>// ]]><br> </script><br> |
7、重写IsExternalDispatchSafe虚函数
重写此函数可以屏蔽掉网页弹出的ActiveX安全警告对话框。重写CanAccessExternal函数也可以达到同样的目的,但是不推荐这样做,CanAccessExternal中调用IsExternalDispatchSafe并在其值为FALSE时默认做了安全检查,如果重写了此函数那么就破坏了CDHtmlDialog的封装,并且想要再重新获得安全性时就显的不太方便了。
1
|
virtual BOOL IsExternalDispatchSafe(){ return TRUE;} |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现