MFC对话框里利用CHtmlView加载界面(二)————MFC调用JaveScript

xiaoxiao2021-02-28  97

在MFC对话框里利用CHtmlView加载界面(一)中,对如何利用CHtmlView加载网页进行了介绍。

本文,我们将在上一篇文章的基础上,对如何利用CHtmlView加载HTML,以及MFC如何调用JaveScript的方法进行讲解。

在MFC对话框里利用CHtmlView加载界面(一)中,我们新建了一个继承自CHtmlView的CBaseHtmlView类,本文我们将继续在CBaseHtmlView中添加内容,以实现MFC调用JaveScript的方法。

一、关于MFC call HTML(JaveScript)涉及到的相关函数

1、获取IWebBrowser(ActiveX 插件) 初始化对象接口

LPDISPATCH GetHtmlDocument() const; 示范:

CComPtr<IDispatch> spDisp = GetHtmlDocument(); //获取com 初始对象 接口指针 if (spDisp == NULL) { ASSERT(FALSE); return FALSE; }

2、根据1中的初始化接口, 获取组件的 IID_IHTMLDocument2 对象 接口m_spDoc

CComPtr<IHTMLDocument2> m_spDoc = NULL; spDisp->QueryInterface(IID_IHTMLDocument2, (void**)&m_spDoc);

3、根据2中的 m_spDoc接口 获取 组件的 Script接口

CComPtr<IDispatch> spDisp; HRESULT hr = m_spDoc->get_Script(&spDisp); //获取com组件 Script接口 ATLASSERT(SUCCEEDED(hr)); return SUCCEEDED(hr);

4、利用 spDisp接口, 调用OLE自动化接口

HRESULT hr = spScript->GetIDsOfNames(IID_NULL, &bstrFunc, 1, LOCALE_SYSTEM_DEFAULT, &dispid); //调用JaveScript接口 hr = spScript->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, &dispparams, &vaResult, &excepInfo, &nArgErr); 关于GetIDsOfNames和Invoke的解释,网上有大量相关知识,不了解的朋友可以自行百度。

以上就是在MFC 调用 JaveScript方法将要涉及到的函数。

 二、对MFC call HTML(JaveScript)函数的封装实现

有了一中的简单理解,我们需要将上述函数简单的封装到CBaseHtmlView类中,以便使用者的调用。

我们先看看CBaseHtmlView类中需要添加的声明:

/****************************************** ****** MFC call Javascript 相关函数******** *******************************************/ //MFC 通过com 调用 JavaScript接口 CComPtr<IHTMLDocument2> m_spDoc; //com组件的 IHTMLDocument2接口 BOOL SetScriptDocument(); //获取IHTMLDocument2接口m_spDoc BOOL GetJScript(CComPtr<IDispatch>& spDisp); //获取JScript接口 const CString GetSystemErrorMessage(DWORD dwError); //无参调用 BOOL CallJScript(const CString strFunc, _variant_t* pVarResult = NULL); //一个CString参数的调用 BOOL CallJScript(const CString strFunc, const CString strArg1, _variant_t* pVarResult = NULL); //两个CString参数的调用 BOOL CallJScript(const CString strFunc, const CString strArg1, const CString strArg2, _variant_t* pVarResult = NULL); //三个CString参数的调用 BOOL CallJScript(const CString strFunc, const CString strArg1, const CString strArg2, const CString strArg3, _variant_t* pVarResult = NULL); //真正的调用JavaScript方法 BOOL CallJScript(const CString strFunc, const CStringArray& paramArray, _variant_t* pVarResult = NULL); 我们声明了一个COM接口指针变量:CComPtr<IHTMLDocument2>    m_spDoc;

现在我们队上述的函数进行一一的说明和实现:

1、BOOL SetScriptDocument(); 

此函数的主要作用是 获取IHTMLDocument2接口m_spDoc。通常是指OnDocumentComplete函数中调用,以确保每次html或者网页加载完成后,第一时间刷新接口。

BOOL CBaseHtmlView::SetScriptDocument() { CComPtr<IDispatch> spDisp = GetHtmlDocument(); //获取com 初始接口指针 if (spDisp == NULL) { ASSERT(FALSE); return FALSE; } m_spDoc = NULL; HRESULT hr = spDisp->QueryInterface(IID_IHTMLDocument2, (void **)&m_spDoc); if (FAILED(hr)) { MessageBox(L"Failed to get HTML document COM object"); return FALSE; } return TRUE; }

2、BOOL GetJScript(CComPtr<IDispatch>& spDisp);

此函数的主要作用是获取JScript接口。

BOOL CBaseHtmlView::GetJScript(CComPtr<IDispatch>& spDisp) { if (m_spDoc == NULL) return FALSE; HRESULT hr = m_spDoc->get_Script(&spDisp); //获取Script接口 ATLASSERT(SUCCEEDED(hr)); return SUCCEEDED(hr); }

3、const CString GetSystemErrorMessage(DWORD dwError);

此函数的作用是解析错误信息。

const CString CBaseHtmlView::GetSystemErrorMessage(DWORD dwError) { CString strError; LPTSTR lpBuffer; if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT), (LPTSTR)&lpBuffer, 0, NULL)) { strError = "FormatMessage Netive Error"; } else { strError = lpBuffer; LocalFree(lpBuffer); } return strError; }

4、重载的5个CallJScript函数

此5个函数实现的MFC 调用 JaveScript的方法。方便用户调用。

主要的实现细节在BOOL CallJScript(const CString strFunc, const CStringArray& paramArray, _variant_t* pVarResult = NULL)函数中。

BOOL CBaseHtmlView::CallJScript(const CString strFunc, const CStringArray& paramArray, _variant_t* pVarResult /*= NULL*/) { CComPtr<IDispatch> spScript; if (!GetJScript(spScript)) { MessageBox(L"函数GetJScrip调用失败!"); return FALSE; } CComBSTR bstrFunc(strFunc); DISPID dispid = NULL; //根据名称strFunc 获取 ids HRESULT hr = spScript->GetIDsOfNames(IID_NULL, &bstrFunc, 1, LOCALE_SYSTEM_DEFAULT, &dispid); if (FAILED(hr)) { MessageBox(GetSystemErrorMessage(hr)); return FALSE; } DISPPARAMS dispparams; memset(&dispparams, 0, sizeof dispparams); INT_PTR arraySize = paramArray.GetSize(); dispparams.cArgs = (UINT)arraySize; //参数个数 dispparams.rgvarg = new VARIANT[dispparams.cArgs]; for (int i = 0; i < arraySize; i++) { CComBSTR bstr = paramArray.GetAt(arraySize - 1 - i); // back reading bstr.CopyTo(&dispparams.rgvarg[i].bstrVal); dispparams.rgvarg[i].vt = VT_BSTR; } dispparams.cNamedArgs = 0; EXCEPINFO excepInfo; memset(&excepInfo, 0, sizeof excepInfo); _variant_t vaResult; UINT nArgErr = (UINT)-1; // initialize to invalid arg //调用JaveScript接口 hr = spScript->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, &dispparams, &vaResult, &excepInfo, &nArgErr); delete[] dispparams.rgvarg; if (FAILED(hr)) { MessageBox(GetSystemErrorMessage(hr)); return FALSE; } if (pVarResult) { *pVarResult = vaResult; } return TRUE; }在看看其他4个函数的实现:

BOOL CBaseHtmlView::CallJScript(const CString strFunc, _variant_t* pVarResult /*= NULL*/) { CStringArray paramArray; return CallJScript(strFunc, paramArray, pVarResult); } BOOL CBaseHtmlView::CallJScript(const CString strFunc, const CString strArg1, _variant_t* pVarResult /*= NULL*/) { CStringArray paramArray; paramArray.Add(strArg1); return CallJScript(strFunc, paramArray, pVarResult); } BOOL CBaseHtmlView::CallJScript(const CString strFunc, const CString strArg1, const CString strArg2, _variant_t* pVarResult /*= NULL*/) { CStringArray paramArray; paramArray.Add(strArg1); paramArray.Add(strArg2); return CallJScript(strFunc, paramArray, pVarResult); } BOOL CBaseHtmlView::CallJScript(const CString strFunc, const CString strArg1, const CString strArg2, const CString strArg3, _variant_t* pVarResult /*= NULL*/) { CStringArray paramArray; paramArray.Add(strArg1); paramArray.Add(strArg2); paramArray.Add(strArg3); return CallJScript(strFunc, paramArray, pVarResult); } 它们都调用了BOOL CallJScript(const CString strFunc, const CStringArray& paramArray, _variant_t* pVarResult = NULL)函数。

好了,有了上面的函数,我们就实现了MFC 对JaveScript的调用。

三、MFC call HTML(JaveScript)的示范

1、在OnInitialUpdate()在加载的网页

我们将在MFC对话框里利用CHtmlView加载界面(一)中OnInitialUpdate()在加载的网页,改为我们需要加载的html文件:

void CBaseHtmlView::OnInitialUpdate() { CHtmlView::OnInitialUpdate(); // TODO: 在此添加专用代码和/或调用基类 //Navigate2(L"http://blog.csdn.net/qq_20828983?viewmode=contents", NULL, NULL); Navigate2(L"E:\\代码\\CHTMLDome2\\IE2\\index.html", NULL, NULL); }

2、在OnDocumentComplete中发送消息

在OnDocumentComplete中,发送消息,以通知主对话框加载完成,使主对话框调用JaveScript方法。

void CBaseHtmlView::OnDocumentComplete(LPCTSTR lpszURL) { // TODO: 在此添加专用代码和/或调用基类 CHtmlView::OnDocumentComplete(lpszURL); SetScriptDocument(); //初始化com组件 IID_IHTMLDocument2接口 ::PostMessage(GetParent()->GetSafeHwnd(), WM_MAINJS_INITDATA, NULL, NULL); }

3、在主界面中实现消息响应

LRESULT CCHTMLDome2Dlg::OnInitData(WPARAM wParam, LPARAM lParam) { CString szLineData; szLineData = L"{ \"code\" :\"1\", \ \"time\" : \"month\", \ \"xAxis\" : [\"One\", \"Two\", \"Three\", \"Four\", \"Five\"], \ \"data\" : [\"254\", \"545\", \"167\", \"92\", \"45\"] }"; CString szPieData; szPieData = L"{ \"code\" :\"1\", \ \"time\" : \"Fri\", \ \"data\" : [ { \"value\":\"345\", \"name\" : \"Others\"},\ { \"value\":\"110\", \"name\" : \"iTunes\" },\ { \"value\":\"234\", \"name\" : \"Netflix\" },\ { \"value\":\"935\", \"name\" : \"Dropbox\" },\ { \"value\":\"98\", \"name \": \"Chrome\" } ] }" ; mHtmlView.CallJScript(L"showLiner", szLineData); mHtmlView.CallJScript(L"showPie", szPieData); return 0; } 这里我们通常以JSON格式传递信息给JaveScript。 如上述函数,我们传递了两个数据:szLineData和szPieData, 分别调用了JaveScript中名为:"showLiner" 和 "showPie"的方法。

上图中的曲线图、饼状图的数据就是MFC传递给JaveScript的。

本文示范Dome下载地址:http://download.csdn.net/detail/qq_20828983/9894706

转载请注明原文地址: https://www.6miu.com/read-48774.html

最新回复(0)