在MFC对话框里利用CHtmlView加载界面(一)中,对如何利用CHtmlView加载网页进行了介绍。
本文,我们将在上一篇文章的基础上,对如何利用CHtmlView加载HTML,以及MFC如何调用JaveScript的方法进行讲解。
在MFC对话框里利用CHtmlView加载界面(一)中,我们新建了一个继承自CHtmlView的CBaseHtmlView类,本文我们将继续在CBaseHtmlView中添加内容,以实现MFC调用JaveScript的方法。
以上就是在MFC 调用 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;现在我们队上述的函数进行一一的说明和实现:
此函数的主要作用是 获取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; }此函数的主要作用是获取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); }此函数的作用是解析错误信息。
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; }此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对话框里利用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); }在OnDocumentComplete中,发送消息,以通知主对话框加载完成,使主对话框调用JaveScript方法。
void CBaseHtmlView::OnDocumentComplete(LPCTSTR lpszURL) { // TODO: 在此添加专用代码和/或调用基类 CHtmlView::OnDocumentComplete(lpszURL); SetScriptDocument(); //初始化com组件 IID_IHTMLDocument2接口 ::PostMessage(GetParent()->GetSafeHwnd(), WM_MAINJS_INITDATA, NULL, NULL); }
上图中的曲线图、饼状图的数据就是MFC传递给JaveScript的。
本文示范Dome下载地址:http://download.csdn.net/detail/qq_20828983/9894706