tag 标签: vc project

相关博文
  • 热度 16
    2010-5-5 15:08
    2569 次阅读|
    2 个评论
    续上 8. 现在回到我们关注的 GetExternal 的话题 , 我们需要改写 ROleControlSite  中 GetExternal(): // GetExternal STDMETHODIMP ROleControlSite::XDocHostUIHandler::GetExternal(   /* */ IDispatch __RPC_FAR *__RPC_FAR *ppDispatch) {  METHOD_PROLOGUE(ROleControlSite, DocHostUIHandler)     // return the IDispatch we have for extending the object Model  if(our_web_ctrl) {   IDispatch* pDisp = (IDispatch*)(our_web_ctrl-GetIDispatch(TRUE));   *ppDispatch = pDisp;  }            return S_OK; } 这里清楚说明了 , 我们无法从 MFC 获得 IDocHostUIHandler   的 GetExternal 方法 , 所以我们也许不得不借用 Lake 的贡献 ,  核心用法是替换无论 doc/view or dialog 的 AfxEnableControlContainer(),  用我们重写的 IDocHostUIHandler   方法接管一切 . 既然 IDocHostUIHandler   为我们重写 , 这里对 GetExternal() 我们准确进行改写 ,  把  js 激活的 external.ourcall() 事件对应的 handler, 直接指向我们的 CHtmlCtrl 的实例   instance 上 . 9. 最后的步骤 , 就是完成 js 中 window.external.ourcall() 对应的方法 ourcall. 很多网络资源 , 说明对 instance source 的改写 , 例如主动加上 BEGIN_DISPATCH_MAP, EnableAutomation(), DECLARE_DISPATCH_MAP 定义等等 . 我做不好这些 , 因为我不知道有什么 format 我们表达不好, MFC 不喜欢我写的 . 比方说 , 现在我知道 , 进行方法的写作 , 就要加上 afx_msg 前缀 ( 很令人熟悉 ``` 说明方法与属性的机制 , 与 message 的管理机制的一致性 ). 简单而又合适的方法 , 是在构建 based class 为 CHtmlView 的 CHtmlCtrl class 的时候 , 选择 automation, IDE 将为我们加上前面说一切 . 而我们的 ourcall() 方法 , 也用 class 向导来添加到了合适的地方 . 同使用向导 , 完成其他的重载函数的 coding, 没什么两样 , IDE 给了我们直接写作 ourcall() 的便利 . 10. 另外似乎还要注意到一个重要的地方 , microsoft 认为 CHtmlView 存在着 memory leak, 什么据说 5 种成员调用中 , 导致 leak 的发生 ... 我们很无语 , 但是既然有细节的 microsoft support 去  source fix, 照做就好 . http://support.microsoft.com/kb/241750 实现效果 : 我们在 google map 上绘画区域 , 完成后 , 触发 external.report(), 在型参中并输出了对角 2 个 marker 的经纬度给 host 进行处理 . - Allen 发表于 2010.05.01 于电子工程专刊之Allen Zhan's blog 3/3 OVER 补充 在着手改写 GetExternal 的过程中, 我们不可避免遇到了令人烦恼的 redefine 导致编译失败. 尝试了至少 30mins 的各种手段后, 我们放弃了其他的方式, 直接去改写 IDE 的头文件 occimpl.h, 手动给它加上 #ifndef 去避免 link error. 从工程学的角度出发, 这原本是不应该发生的事情(我们应尽量尊重工具, 并不去改动工具, 这样我们所有人都在同样的环境下讨论和交流). 但我们也要埋怨工具的本身... 这片 source 已经陈旧到没有 writer 去补丁一下, 至少放个 ifndef 去防止 redefine? 或者说, IDE 设计便是不许可该文件被暴露与使用的? 基于 dialog 的vc project 与 内嵌java script的相互调用(一) 基于 dialog 的vc project 与 内嵌java script的相互调用(二) 基于 dialog 的vc project 与 内嵌java script的相互调用(三)
  • 热度 15
    2010-5-5 15:07
    2016 次阅读|
    0 个评论
    续上 4.  使用 CHtmlCtrl 并意味我们要接受原作者的一切 source. 实际上 , CHtmlCtrl sample 上有一个显着的特性 , 非常接近我们的应用 . DiLascia 将 script 中对 button 的点击 event, 利用 a pref 的语法 , 设置一个 lias 传递给了 Host.   因为仅仅是加入 CHtmlCtrl 的 sample,  我们就能够实际相应来自于 web page 上任何 button 的 press event.  引人入胜的特性 ... 沉思了一段时间后 , 或者因为我们自身的愚鲁 , 这个特性似乎不能被我们所用 . 首先我们没有也不会设计各种 button 或者甚至是 false button trigger event 来触发我们的行为 . 另外 ,  我们其实打算在任何 time wanted, send this requirement to host for our requirement. That means, we can call host function in any conditions or at any time, and then, we have to pass the propograte parameters to host also. 因此 , 实际上 , 无需的该段功能代码是被我们 disable 掉了 . 5. 现在我们有 CHtmlCtrl 导入了 CHtmlView. 一个 kernel level import step 是 ,  来自 R. Lake   的 http://www.codeguru.com/cpp/w-d/doc_view/chtmlview/article.php/c3253   这是我们在这 2 个工作日中所能找到的最简洁与最清晰明了的思路和例程 . 用来暴露 IDocHostUIHandler  的实现 . 无论如何 , 简洁到 300 rows 不到的 source code, 对我们的 replantment 以及 know why/how 都是非常有帮助的 . Lake 引入了两个 class, 实际上 Allen  觉得很可能他们是一个 , 因为本来 ROleControlSite  应能 can everything. 增加的一个 ROccManager, 怎么看给人的感觉 ,  就是为了在未来的项目拓展中 , 多个 instance 的管理吧 ?  该超级链接已经清楚说明了一切 , Allen 简单的理解就是 , Lake 用他定义的 ROleControlSite,  接管属于了 MFC IDocHostUIHandler   做的一切 . 因为从 source 中对 IDocHostUIHandler   的全部方法进行重写 , 证明了这个说法 . 6. 现在我们回到网络资源上一个常见的说法 , 那就是因为 doc/view 具有 AfxEnableControlContainer(), 因此我们替换上我们自己的 ROleControlSite, 于是便成功实现了这个 " 接管 " 的工作 . 那么我们自己的尝试 , 充分说明 , 并非只有 doc/view struction 许可这样实现 . dialog based 同样也有 AfxEnableControlContainer(), Lake 替换 AfxEnableControlContainer 的 site 参数的技巧 , 对 dialog based project 亦是有效 . 7.  我们引入了 sample 中的 ROleControlSite source, 但是对 Lake 完成这个工作的目的兴趣缺缺 , 毕竟我们不是像 Lake 那样 ,  主要目的是打算 disable 掉 context Menu 的用法 , 不让 user 去选择观看 web page 的 source code... 因此我们没选择 Lake 的其他 source, but 除了 ... 重载 create(), 当然这是一切的提前 , 不是吗 ? 我们列出这份至关重要的代码 ,  通过代码的执行 , 也证明了在 item6 中我们的讨论 : BOOL CMyHtmlCtrl::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) {  // TODO: Add your specialized code here and/or call the base class    //return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);  ///////////////////////////////////  // The following does the same as MFC source, except that  // AfxEnableControlContainer() is called with our handler.  ///////////////////////////////////  CRect c_clientRect;  GetClientRect(c_clientRect);  ///////////////////////////////////  // create the view window:  m_pCreateContext = pContext;  if (!CView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd,  nID, pContext))  {   return FALSE;  }    AfxEnableControlContainer(m_pROccManager);  ///////////////////////////////////  // create the control window:  if (!m_wndBrowser.CreateControl(CLSID_WebBrowser, lpszWindowName, WS_VISIBLE | WS_CHILD, c_clientRect, this, AFX_IDW_PANE_FIRST))  {   DestroyWindow();   return FALSE;  }  LPUNKNOWN lpUnk = m_wndBrowser.GetControlUnknown();  HRESULT hr = lpUnk-QueryInterface(IID_IWebBrowser2, (void**) m_pBrowserApp);  if (!SUCCEEDED(hr))  {   m_pBrowserApp = NULL;   m_wndBrowser.DestroyWindow();   DestroyWindow();   return FALSE;  }  return TRUE; }   基于 dialog 的vc project 与 内嵌java script的相互调用(一) 基于 dialog 的vc project 与 内嵌java script的相互调用(二) 基于 dialog 的vc project 与 内嵌java script的相互调用(三)
  • 热度 14
    2010-5-5 15:06
    3503 次阅读|
    3 个评论
    排版说明: 似乎遇到了 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的相互调用(三)