好贷网好贷款

IE控件编程)

发布时间:2016-12-3 10:24:22 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"IE控件编程)",主要涉及到IE控件编程)方面的内容,对于IE控件编程)感兴趣的同学可以参考一下。

2. IE控件中HTML Page能收到键盘事件 最近做了一个小程序,用到了IE控件,但是里面的HTML Page 无法响应onkeydown等事件。于是建立了一个WTL的工程,发现了关键代码: BOOL PreTranslateMessage(MSG* pMsg) {     if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&     (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))         return FALSE;     // give HTML page a chance to translate this message     return (BOOL)SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg); } 网上也有其他方案,但是感觉这种最地道。 现在能收到事件了,但是你可能会发现,鼠标不能选择上面的文字,并非是鼠标消息没有传递过来,而是--   注意这个方法,put_DocHostFlags和属性 & ~DOCHOSTUIFLAG_DIALOG,是的,把它取消掉即可。否则你的IE呈现出来的页面,真的像Dialog一样了。     3. IE控件怎么得知404,500等Http Code。  【注:我这里说的IE控件,泛指MFC里面的CHtmlView, IHtmlDocument等等相关的,准确说是IE编程相关的。】 今天试图在DISPID_DOCUMENTCOMPLETE事件中,得到HTML的内容等等,来判断是不是断网了等情况,这太不地道了,IE6,IE7,IE8显示的内容都不一样。我又找不到HTTP Code,而且那个ReadyState没有什么用。看了100篇文章都没有找到答案,最后翻了一下头文件,在DISPID_DOCUMENTCOMPLETE附近,还有一个叫做DISPID_NAVIGATEERROR的事件。 整个代码看起来像是这个样子。 CComPtr<IWebBrowser2> spWebBrowser2; HRESULT hRet = QueryControl(IID_IWebBrowser2, (void**)&spWebBrowser2); if(SUCCEEDED(hRet)) {     HRESULT hr = IDispEventSimpleImpl<1, CMyHtmlView, &DIID_DWebBrowserEvents2>::DispEventAdvise(spWebBrowser2, &DIID_DWebBrowserEvents2);     if(FAILED(hr))         ATLASSERT(FALSE); } 那么CMyHtmlView就要继承 IDispEventSimpleImpl<1, CMyHtmlView, &DIID_DWebBrowserEvents2>   SINK_ENTRY_INFO(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete, &DocComplete_Info) SINK_ENTRY_INFO(1, DIID_DWebBrowserEvents2, DISPID_NAVIGATEERROR, OnNavigateError, &NavError_Info) // NOTICE stdcall void __stdcall OnDocumentComplete(LPDISPATCH pDisp, VARIANT FAR* URL); void __stdcall OnNavigateError(LPDISPATCH pDisp, VARIANT*, VARIANT*, VARIANT*, VARIANT_BOOL*); 参考文章:   http://blog.sina.com.cn/s/blog_465c136b010008tn.html http://social.msdn.microsoft.com/Forums/zh-CN/ieextensiondevelopment/thread/eff1e37c-7cf9-41ad-aac1-c5516e5a45db 【NOTICE:文档中有些参数的顺序,有待考证。】       OnNavigateError中有个参数是ErrorCode,值类型为VT_I4,实际一些错误值,直接指向了404这些code~。   http://msdn.microsoft.com/en-us/library/bb268233%28VS.85%29.aspx 最后,最后一个参数,*bCancel  = VARIANT_TRUE;的话,不会再次进入OnDocumentComplete,否则还是会进去溜一圈的。 ========================================================================================  4. IE控件保存选中的图片 这绝对是个稍微复杂一点的事情了: 4.1 得到图片 // 1. 假设我们在CHtmlView一类的容器中,得到IWebBrowser2接口 CComPtr<IWebBrowser2> spWebBrowser2; HRESULT hRet = QueryControl (IID_IWebBrowser2, (void**)&spWebBrowser2); // 2. 得到IHTMLDocument2接口 CComPtr<IDispatch> spDisp; spWebBrowser2->get_Document(&spDisp); CComQIPtr<IHTMLDocument2> spDoc2(spDisp); // 3. 得到IHTMLWindow2接口 CComPtr<IHTMLWindow2> spWindow2; spDoc2->get_parentWindow(&spWindow2); // 4. 得到IHTMLEventObj接口 CComPtr<IHTMLEventObj> spEvent; spWindow2->get_event(&spEvent); // 5.得到IHTMLElement接口 CComPtr<IHTMLElement> spElem; spEvent->get_srcElement(&spElem); // 6. 判断是不是tag<img> spElem->get_tagName(&bstrTagName); // TODO: bstrTagName == img ? // 7. 得到IHTMLImgElement接口 CComQIPtr<IHTMLImgElement> spImg(spElem); 做完一半的工作了。 4.2 拷贝到剪切板 // 1. 从IHtmlDocument2接口获得<body>的IHTMLElement接口 CComPtr<IHTMLElement> spBody; spDoc2->get_body(&spBody); // 2. "转"为IHTMLElement2接口,COM就是麻烦 CComPtr<IHTMLElement2> spBody2; spBody->QueryInterface(IID_IHTMLElement2, (void**)&spBody2); // CComQIPtr<IHTMLElement2> spBody2(spBody); // 3. 创建并得到IHTMLControlRange接口 CComPtr<IDispatch> pdispCtrlRange;    spBody2->createControlRange(&pdispCtrlRange); CComQIPtr<IHTMLControlRange> pCtrlRange(pdispCtrlRange); // 4. 创建图片元素对应的IID_IHTMLControlElement的接口 IHTMLControlElement* pCtrlElement = NULL;     spElem->QueryInterface(IID_IHTMLControlElement, (void**) &pCtrlElement); 或者 CComQIPtr<IHTMLControlElement> pCtrlElement(spElem); // 就不naming为spCtrlElement了。保存前后一致。 // 5. Copy <img>到剪切板 VARIANT_BOOL vbReturn; VARIANT vEmpty; VariantInit(&vEmpty); HRESULT hAdd = pCtrlRange->add(pCtrlElement); HRESULT hCpy = pCtrlRange->execCommand(CComBSTR(L"Copy"), VARIANT_FALSE, vEmpty, &vbReturn); // 6. 这句可能不好使... spWebBrowser2->ExecWB(OLECMDID_SAVECOPYAS, OLECMDEXECOPT_PROMPTUSER, NULL, NULL); 5. IE控件拖放文件 预备   1. spWebBrowser2->put_RegisterAsDropTarget(VARIANT_FALSE or VARIANT_TRUE); 可以控制IE控件是否支持拖拽。 2. 貌似IE控件本身是支持拖拽文件的,所以你再去这样做,是没有用的。   spWebBrowser2->put_RegisterAsDropTarget(VARIANT_FALSE); HWND hIEWnd = FindIEServerWnd(hWnd);        // ASSERT hIEWnd's classname == L"Internet Explorer_Server" HRESULT hr = RegisterDragDrop(hIEWnd, (IDropTarget*)&m_DndHandler); spWebBrowser2->put_RegisterAsDropTarget(VARIANT_TRUE); 没用,我试验了。 你可以实现一个IDocHostUIHandlerDispatch 。然后用SetExternalUIHandler(&m_DocUIHandler); 里面有个重要的方法,实现可以这么写。     virtual HRESULT STDMETHODCALLTYPE GetDropTarget(          /* [in] */ IUnknown *pDropTarget,         /* [out] */ IUnknown **ppDropTarget)     {         ATLASSERT(NULL != m_pDropTarget);         *ppDropTarget = m_pDropTarget;         return S_OK ;     }   pDropTarget就需要你自己实现了IDropTarget了。OK,完事~   6. IE的ContextMenu 讲一下探索的过程吧,以下加重的词汇,就是搜索的关键字: 1) 最开始的时候,创建我的AxWindow,有这个属性,DOCHOSTUIFLAG_DISABLE_HELP_MENU。 并且实现了IDocHostUIHandlerDispatch接口,然后在ShowContextMenu里面做事情。 然后,我要现实我自己的菜单,而不是IE的菜单,我要正确的显示“拷贝”, “粘贴”, “剪切”等Menu Items。 这部分最早我是采用如下代码来判断的,不准确: static BOOL CanShowPaste(IWebBrowser2 * pWebBrowser2) {     CComPtr<IDispatch>  spDisp ;     pWebBrowser2->get_Document(&spDisp) ;     if (!spDisp)         return FALSE ;          CComQIPtr<IHTMLDocument2>  spDoc2 (spDisp) ;     if (!spDoc2)     { ATLASSERT(FALSE); return FALSE; }     CComPtr<IHTMLWindow2>   spWindow2 ;     CComPtr<IHTMLEventObj>   spEvent ;     spDoc2->get_parentWindow (&spWindow2) ;     if (spWindow2)     {         spWindow2->get_event (&spEvent) ;         if (spEvent)         {             CComPtr<IHTMLElement>   spElem ;             spEvent->get_srcElement (&spElem) ;             CComPtr<IHTMLSelectionObject> selObj;             spDoc2->get_selection(&selObj);                          CComBSTR type;             selObj->get_type(&type);                          CComBSTR  bstrTagName ;             spElem->get_tagName(&bstrTagName) ;             CString  strTag = bstrTagName ;             strTag.MakeLower() ;             if ((strTag.Find(L"textarea") != -1) || strTag.Find(L"input") != -1)             {                 if (IsClipboardFormatAvailable(CF_TEXT))                     return TRUE ;             }         }     }     return FALSE ; } Paste还好,但是Copy就很难弄了。因为当你选中的东西不是单纯的text的时候,接口返回的内容,我是弄不清楚。 2) 于是,我问了以下做浏览器的同事,他们没有用自己的菜单。而是自绘IE的菜单,于是,我得到了如下代码,去获得IE菜单的句柄HMENU。     HMODULE hShDoclc = LoadLibrary(L"shdoclc.dll");     if( NULL == hShDoclc )         hShDoclc = LoadLibrary(L"ieframe.dll");     if (hShDoclc == NULL)     {         // Error loading module -- fail as securely as possible         return FALSE;     }     const int IDR_BROWSE_CONTEXT_MENU = 24641;  //###     HMENU hMainMenu = LoadMenu(hShDoclc, MAKEINTRESOURCE(IDR_BROWSE_CONTEXT_MENU));     if (hMainMenu) { ... 这样,我可以用ShowContextMenu的参数wID,它是SubMenu的ID。 但是还是有问题,似乎在这个函数中,GetMenuState,GetMenuItemInfo,都是获取不到那个即将弹出的Menu的Item的State。【原因不得而知】 后来我去掉了属性DOCHOSTUIFLAG_DISABLE_HELP_MENU,似乎也是不行的。 最后我用Detour了,Hook这个API,TrackPopupMenuEx【至少在IE8上面是OK的,我只担心IE6的内核。】。 这个API的第一个参数,就是前面提到过的SubMenu,【现在也不需要从IE的context menu中GetSubMenu了。】 从被Hook API的上下文中,居然可以得到Menu Item的准确State。  最后看这几篇文章:   7. 从内存中加载HTML   http://blog.csdn.net/jiangsheng/archive/2003/11/09/3790.aspx 简直找到了源头。  http://blog.csdn.net/jiangsheng/archive/2003/11/09/3790.aspx  简介: 定位到 about:blank  DHTML 对象模型的有效性 使用 QueryInterface 获得IPersist*等接口 使用IPersist*接口载入和保存HTML内容 载入和保存HTML元素数据 ---此外还要配合以下代码才行: HRESULT CMyHtmlView::LoadWebPage() {     Navigate2(L"about:blank");     HRSRC hWebPageRes = FindResource(NULL, (LPCWSTR)IDR_HTML1, RT_HTML);     DWORD dwSize = SizeofResource(NULL, hWebPageRes);     HGLOBAL hGlobal = LoadResource(NULL, hWebPageRes);     if(hGlobal != NULL)     {         IStream* pStream = NULL;         LPVOID pResContent = LockResource(hGlobal);         if (NULL != pResContent)         {             HGLOBAL hWebPage = GlobalAlloc(GMEM_MOVEABLE, dwSize);             LPVOID lpBuffer = GlobalLock(hWebPage);             ZeroMemory(lpBuffer, dwSize);             CopyMemory(lpBuffer, pResContent, dwSize);             GlobalUnlock(hWebPage);             CreateStreamOnHGlobal(hWebPage, TRUE, &pStream);         }         _LoadHtmlFromStream(NULL, pStream);         return S_OK;     } ... ... }  8. C++调用JavaScript,支持匿名函数 _com_dispatch_method 它描述参数列表的类型的字段太不友好了。  

上一篇:兄弟连 职业素质改进计划个人总结
下一篇:c语言中堆和栈的区别

相关文章

关键词: IE控件编程)

相关评论