程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> WebBrowser內嵌頁面的跨域調用問題,webbrowser內嵌頁面

WebBrowser內嵌頁面的跨域調用問題,webbrowser內嵌頁面

編輯:C++入門知識

WebBrowser內嵌頁面的跨域調用問題,webbrowser內嵌頁面


我遇到的問題:

內嵌IE浏覽器控件WebBrowser的內嵌頁host.html中使用iframe又嵌套了一個頁面iframe.html,iframe.html上有個JS方法,我用C++調用不到,而host.html上的JS方法可以正常調用到。

問題分析:
從JS來說,這是個跨域問題,host.html和iframe.html不在一個域內;
JS解決跨域問題的方案其實也是有的,但這個不是我們本文的重點,本文的重點是怎麼通過WebBrowser控件直接來解決這個“跨域調用”的問題。

問題的根本原因在於:
調用網頁的JS需要拿到IHTMLDocument2接口,而每個iframe都有自己對應的IHTMLDocument2,所以我們只要能拿到iframe對應的IHTMLDocument2就能解決問題了。

解決方案:直接上代碼吧

復制代碼
 1 /* -------------------------------------------------------------------------
 2 //    FileName    :    calljs_helper.h
 3 //    Creator        :    linyehui 5 //    Brief        :    調用WebBrowser控件內嵌頁上的JS函數,iframe中的也能調到
 6 //
 7 //    $Id: $
 8 // -----------------------------------------------------------------------*/
 9 #ifndef __CALLJS_HELPER_H__
10 #define __CALLJS_HELPER_H__
11 
12 // -------------------------------------------------------------------------
13 namespace calljs_helper
14 {
15     bool CallFunction(
16         CComPtr<IWebBrowser2> spIWebBrowser, 
17         LPCTSTR lpFuncName,
18         const vector<wstring>& paramArray, 
19         CComVariant * pVarResult = NULL,
20         bool bEnumFrame = true);
21 
22 } // namespace
23 
24 // -------------------------------------------------------------------------
25 // $Log: $
26 
27 #endif /* __CALLJS_HELPER_H__ */
復制代碼 復制代碼
  1 /* -------------------------------------------------------------------------
  2 //    FileName    :    calljs_helper.cpp
  3 //    Creator        :    linyehui  5 //    Brief        :    調用WebBrowser控件內嵌頁上的JS函數,iframe中的也能調到
  6 //
  7 //    $Id: $
  8 // -----------------------------------------------------------------------*/
  9 
 10 #include "stdafx.h"
 11 #include "calljs_helper.h"
 12 
 13 // -------------------------------------------------------------------------
 14 
 15 CComPtr<IWebBrowser2> HtmlWindowToHtmlWebBrowser(CComPtr<IHTMLWindow2> spWindow)
 16 {
 17     ATLASSERT(spWindow != NULL);
 18     CComQIPtr<IServiceProvider>  spServiceProvider = spWindow;
 19     if (spServiceProvider == NULL)
 20     {
 21         return CComPtr<IWebBrowser2>();
 22     }
 23 
 24     CComPtr<IWebBrowser2> spWebBrws;
 25     HRESULT hRes = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrws);
 26     if (hRes != S_OK)
 27     {
 28         return CComPtr<IWebBrowser2>();
 29     }
 30 
 31     return spWebBrws;
 32 }
 33 
 34 // Converts a IHTMLWindow2 object to a IHTMLDocument2. Returns NULL in case of failure.
 35 // It takes into account accessing the DOM across frames loaded from different domains.
 36 CComPtr<IHTMLDocument2> HtmlWindowToHtmlDocument(CComPtr<IHTMLWindow2> spWindow)
 37 {
 38     ATLASSERT(spWindow != NULL);
 39     CComPtr<IHTMLDocument2> spDocument;
 40     HRESULT hRes = spWindow->get_document(&spDocument);
 41     if ((S_OK == hRes) && (spDocument != NULL))
 42     {
 43         // The html document was properly retrieved.
 44         return spDocument;
 45     }
 46 
 47     // hRes could be E_ACCESSDENIED that means a security restriction that
 48     // prevents scripting across frames that loads documents from different internet domains.
 49     CComPtr<IWebBrowser2> spBrws = HtmlWindowToHtmlWebBrowser(spWindow);
 50     if (spBrws == NULL)
 51     {
 52         return CComPtr<IHTMLDocument2>();
 53     }
 54 
 55     // Get the document object from the IWebBrowser2 object.
 56     CComPtr<IDispatch> spDisp;
 57     hRes = spBrws->get_Document(&spDisp);
 58     spDocument = spDisp;
 59     return spDocument;
 60 }
 61 
 62 bool CallFunctionInDocument(
 63                             CComPtr<IHTMLDocument2> spDocument2, 
 64                             LPCTSTR lpFuncName,
 65                             const vector<wstring>& paramArray, 
 66                             CComVariant * pVarResult)
 67 {
 68     if (!spDocument2)
 69         return false;
 70 
 71     CComPtr<IDispatch> spScript; 
 72     if (FAILED(spDocument2->get_Script(&spScript))) { return false; }
 73 
 74     CComBSTR bstrMember(lpFuncName); 
 75     DISPID dispid = NULL; 
 76     HRESULT hr = spScript->GetIDsOfNames(IID_NULL, &bstrMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid); 
 77     if (FAILED(hr)) { return false; }
 78 
 79     const int arraySize = paramArray.size(); 
 80 
 81     DISPPARAMS dispparams; 
 82     memset(&dispparams, 0, sizeof dispparams); 
 83     dispparams.cArgs = arraySize; 
 84     dispparams.rgvarg = new VARIANT[dispparams.cArgs]; 
 85 
 86     for (int i = 0; i < arraySize; i++)
 87     {
 88         CComBSTR bstr = paramArray[arraySize - 1 - i].c_str(); // back reading
 89         bstr.CopyTo(&dispparams.rgvarg[i].bstrVal); 
 90         dispparams.rgvarg[i].vt = VT_BSTR; 
 91     }
 92     dispparams.cNamedArgs = 0; 
 93 
 94     EXCEPINFO excepInfo; 
 95     memset(&excepInfo, 0, sizeof excepInfo); 
 96     CComVariant vaResult; 
 97     UINT nArgErr = (UINT)-1;  // initialize to invalid arg
 98 
 99     hr = spScript->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, &dispparams, &vaResult, &excepInfo, &nArgErr); 
100 
101     delete [] dispparams.rgvarg; 
102     if (FAILED(hr)) { return false; }
103 
104     if (pVarResult) { *pVarResult = vaResult; }
105 
106     return true;
107 }
108 
109 void EnumFrame(
110                               CComPtr<IHTMLDocument2> spIHTMLDocument2, 
111                               LPCTSTR lpFuncName,const vector<wstring>& paramArray, 
112                               CComVariant* pVarResult)
113 {
114     if ( !spIHTMLDocument2 )
115         return;
116 
117     CComPtr< IHTMLFramesCollection2 > spFramesCollection2;
118     spIHTMLDocument2->get_frames( &spFramesCollection2 );
119 
120     long nFrameCount=0;
121     HRESULT hr = spFramesCollection2->get_length( &nFrameCount );
122     if ( FAILED ( hr ) || 0 == nFrameCount )
123         return;
124 
125     for(long i = 0; i < nFrameCount; i++)
126     {
127         CComVariant vDispWin2;
128         hr = spFramesCollection2->item( &CComVariant(i), &vDispWin2 );
129         if ( FAILED ( hr ) ) 
130             continue;
131 
132         CComQIPtr< IHTMLWindow2 > spWin2 = vDispWin2.pdispVal;
133         if( !spWin2 )
134             continue;
135 
136         CComPtr < IHTMLDocument2 > spDoc2;
137         spDoc2 = HtmlWindowToHtmlDocument(spWin2);
138         if (!spDoc2)
139             continue;
140 
141         CallFunctionInDocument(spDoc2, lpFuncName, paramArray, pVarResult);
142     }
143 }
144 
145 bool calljs_helper::CallFunction(
146                   CComPtr<IWebBrowser2> spIWebBrowser, 
147                   LPCTSTR lpFuncName,
148                   const vector<wstring>& paramArray, 
149                   CComVariant * pVarResult,
150                   bool bEnumFrame)
151 {
152     if (!spIWebBrowser) 
153         return false;
154 
155     CComPtr<IDispatch> spDispDoc; 
156     HRESULT hr = spIWebBrowser->get_Document(&spDispDoc); 
157     if (FAILED(hr))
158         return false;
159 
160     CComQIPtr<IHTMLDocument2> spDocument2 = spDispDoc; 
161     if (!spDocument2)
162         return false;
163 
164     CallFunctionInDocument(spDocument2, lpFuncName, paramArray, pVarResult);
165     
166     if (bEnumFrame)
167     {
168         EnumFrame(spDocument2, lpFuncName, paramArray, pVarResult);
169     }
170     
171     return true; 
172 }
173 
174 // -------------------------------------------------------------------------
175 // $Log: $
復制代碼

 

完整的例子代碼在:這裡下載

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved