CDHtmlDialog探索----Javascript与窗体交互
CDHtmlDialog提供了C++与网页的双向交互,通此一系统简单的宏调用可以把网页中各元素的事件直接映射到C++程序中,而在网页中调用C++功能代码就显的不那么直观了。归根结底交互的基理就是实现相应COM接口。实现方式如下:
1、在窗体初始化时调用EnableAutomation函数。
通常情况下是放在窗体的构造函数中,
EnableAutomation();
当然也可以放在OnInitDialog中,不过要注意顺序,其调用不应该晚于对SetExternalDispatch的调用。此函数在底层的实现就是引用到正确的IDispatch接口(实际就是定位了相应的vtable指针),IDispatch是OLE自动化程序实现的根基。
2、在窗体初始化时调用SetExternalDispatch函数。
通常情况下放在OnInitDialog事件中。
SetExternalDispatch(GetIDispatch(TRUE));
在这个地方就用到了IDispatch接口。所以必须保证EnableAutomation是在SetExternalDispatch之前调用。调用此函数是对网页公布其窗口容器的接口从而在网页中可以通过window.external来调用窗口容器公布的函数、事件、属性。
3、在头文件中添加DECLARE_DISPATCH_MAP()
这个宏定义了对外公布信息需要使用的一些内部数据结构和操作。
4、在实现文件中(*.cpp)添加具体的信息映射
BEGIN_DISPATCH_MAP(CBrowserDlg, CDHtmlDialog)
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)
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、在网页中调用窗体容器公布的函数
<script language="javascript" type="text/javascript">
// <!CDATA[
window.external.testfun("one","two");
// ]]>
</script>
7、重写IsExternalDispatchSafe虚函数
重写此函数可以屏蔽掉网页弹出的ActiveX安全警告对话框。重写CanAccessExternal函数也可以达到同样的目的,但是不推荐这样做,CanAccessExternal中调用IsExternalDispatchSafe并在其值为FALSE时默认做了安全检查,如果重写了此函数那么就破坏了CDHtmlDialog的封装,并且想要再重新获得安全性时就显的不太方便了。
virtual BOOL IsExternalDispatchSafe(){ return TRUE;}