排版说明:
似乎遇到了 4000字限制, 不得不将文章拆分3个部分.
同时, 似乎系统拒绝 j-a-v-a-s-c-r-i-p-t 这个单词, 不晓得那里违禁了. 以下将该术语统称为 js.
在这篇文章中, Allen 根据自己的工作经验, 主要想讨论最近的 job task 上遇到的 vc 与 js function 的相互调用执行的 item. 要归纳成文的原因是, 在大量检索资源后, Allen 意识到, 在 internet 的海量资源中, 并没有一份完整的文章, 对这个 topic 进行完整的讨论.
前提:
1. 我们讨论的IDE 环境, 是 VC6.0 + sp6.
2. 我们讨论的脚本语言的交互, 脚本这里指 javacript.
3. 为了避免绕口的术语, 对提及的 VC side 的 project, 我们称为 host.
4. 提示: 作者不是专业的 Activex control 的研究者, 也并非 DOM 技术的精研者, 作者也无意讨论 CHtmlView 与 web control 的异同, 以及两者在 dialog or doc/view struction 的不同表现. 作者仅仅关注在 TTM 紧张的压力下, 为了完成VC dialog project 与 html 文件的相互 trigger/call 以及型参传递的工作, 在尽可能的短时间内完成可靠工作. 因此Allen 请求对可能的错误的谅解.
(A) Host 调用 js function:
原理:
类似的网络实现资源很容易获得, 一般而言, 我们认为无论是使用 web control 还是 CHtmlView 的方式, 执行 js 特定的 function 的步骤都是一致的: 利用 getdocument 获得 web control 的 document 对象. 然后获取相应的 js function 对应之 ID操作对象. 利用 invokehelper 将合适的型参传入该 ID 操作对象, 即完成了对特定 js function 的调用.
实现例程:
(1) microsoft suppot document: http://support.microsoft.com/kb/185127/en-us/
(2) Allen's sample source:
void CGoogleMapDlg::ExecuteResfreshMarkerScriptFunction(double lat, double lng, char* text)
{
MSHTML::IHTMLDocument2Ptr spDoc(m_web.GetHtmlDocument());
if (spDoc)
{
IDispatchPtr spDisp(spDoc->GetScript());
if (spDisp)
{
// Evaluate is the name of the script function.
OLECHAR FAR* szMember = L"refreshMarker";
DISPID dispid;
HRESULT hr = spDisp->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
if (SUCCEEDED(hr))
{
static BYTE parms[] = VTS_R8 VTS_R8 VTS_BSTR;
COleDispatchDriver dispDriver(spDisp, FALSE);
dispDriver.InvokeHelper(dispid, DISPATCH_METHOD, VT_EMPTY, NULL, parms, lat, lng, text);
}
}
}
}
实现效果:
可用上述表现, 实现诸如在 google map v3 上的刷新 gps 数据点, 计算里程, 绘画简单区域的简单功能.
(B) Javascript 调用 Host function:
前提:
我们期望能够达到这样一个目的, 就是 Javascript 的事件, 不仅在脚本语言的本身得到 system callback, 同时还要完成对 Host function 的trigger 并完成函数型参的调用. 我们当然可以简单看成, 两者间 function 的相互调用.
当 Allen 看到, 一些网络资源要求对 OCX 的工程项目的建立, 并完成这种相互call process, Allen 感到不寒而栗. 实际上, 对简单的应用, 不愿意也不应该复杂化.
原理:
1. 现在我们讨论, 是否能在 web control 上完成 call host function 的目的. 答案应是可行, codeproject 上, Jim Xochellis 完成了无论是基于 CHtmlView 还是 web control 的, 令人印象深刻的 job. http://www.codeproject.com/kb/miscctrl/WBCArticle.aspx
但是很遗憾, Allen 调试这个 sample project 却困难重重. 我们保留这个途径在这里, 给使用者参考.
2. 实际上, 在能够举出这个 sample 之前, 我们需要说明, 经过漫长的探索过程, 我们把我们的注意力, 集中在类似 Jim 的方法中, 就是对 IDocHostUIHandler 的使用. 该对象将暴露出我们需要的各种 interface. 一共 15 个方法中. 而我们通过 MFC, 常常是无法直接获取上述方法.
3. 我们获取直接操作 IDocHostUIHandler 的最终目的, 就是为了使用 GetExternal 方法. 这个方法可由 js 中的 window.external.ourcall() 来触发. ourcall()在VC的 host 中定义... 我知道我在说什么, 我也知道, 有兴趣正在仔细研读我的 topic 的 reader 正作出会心微笑的表情. ; )
为了说明 window.external.ourcall() 的用法, 我们只用简单在我们任何一份脚本的 source 中加入:
window.external.AddFavorite('http://www.163.com', '测试');
跳出在眼前的加入收藏夹对话框, 将证实 js external 用法的可靠性, 我们要做的就是 IE 的 AddFavorite 类似的工作.
如果我们没有在 VC 中, 加入ourcall()方法, 我们就会得到提示: "未能找到类似的方法或属性"... 熟悉的错误对话框也是一个调试方向的提示.
实现:
1. 回到实际的 coding 中, 我们面临着一种选择, 那就是使用 CHtmlView or web control 来完成上述工作? 最终我们选择了 CHtmlView, 并非是 CHtmlView 的某些对高级应用的封装引起我们的兴趣, 仅仅是因为 Internet 的大多数 resouce 都是 CHtmlView 完成而已.
2. 考虑到 CHtmlView 在 MFC 专为 doc/view struction 设计, 对一个当前使用的 dialog 项目而言, 我们不得不构造一个 "虚"web control. 很多超人大哥们, 用细致的语言说明, 这样的构建不会引起MFC的误解. 其实Allen 不懂也没时间弄清这些大哥说什么, 但他们言之凿凿让我们足够大胆到, 将这种 "虚"control 的构建应用于我们的项目中. 遗憾的是, CHtmlCtrl 的作者 Paul DiLascia 的 source access 在网络上似乎大多已经失效了. 我们只能找到从vckbase的中文译文(作者未署名, 文中作者自称"罗头", Allen 尽可能在每个列出的 source 处, 尊重作者的版权, 并向他们的 excellent job致敬): http://www.vckbase.com/document/viewdoc/?id=510
另外我们可以从寻找到参考来自 codeproject 中 Joan Murt 的类似文章: http://www.codeproject.com/KB/miscctrl/htmlctrlsample.aspx 文章中, Joan 说明了他的 original source 正是源于 Paul DiLascia.
3. CHtmlCtrl 允许我们现在 dialog based project 中, 也能够使用 LoadFromResource(). 将 html 的各种资源和 script source 统统一起放入 vc 的 project 的resouce -- 它们在HTML 目录下(这是必须的, 否则将会出错).
Allen对此不知道是夸奖还是贬低这个特性: 这是 CHtmlView 特有的能力, 我们的确隐藏了 all script source, 我们也不再需要在发布最终文件, 还要放置 local js file.
在一个工程项目中, 我们也不用一面操作 IDE, 一面开启 UltraEdit 来调试 script source. 现在 IDE do everything.
一切都很美妙, 只是: 它让我们的最终可执行文件的size 又增加了至少 20k bytes``` resource 便是 resource``` ;Q 数分钟的思考后, 对此我们接受.
基于 dialog 的vc project 与 内嵌java script的相互调用(一)
基于 dialog 的vc project 与 内嵌java script的相互调用(二)
基于 dialog 的vc project 与 内嵌java script的相互调用(三)
allen_zhan_752827529 2010-12-16 17:06
用户1586207 2010-12-15 16:49
用户1277994 2010-5-4 15:57
Hi Allen,每篇博文字数限制4000,有英文的话就特别容易超字数。