以CHtmlView为基类的MFC单文档程序,扩展为可以调用JavaScript函数。
void CTestJScriptView::OnDocumentComplete(LPCTSTR lpszURL) 
{
// TODO: Add your specialized code here and/or call the base class
CComPtr<IDispatch> spDisp = CHtmlView::GetHtmlDocument();//»ñÈ¡ÍøÒ³Îĵµ¾ä±ú
m_webPage.SetDocument(spDisp);
CHtmlView::OnDocumentComplete(lpszURL);
         //以下语句可以调用成功
         //m_webPage.CallJScript(_T("a"));
}
线程:
DWORD WINAPI  CallJScriptThread(LPVOID lParam)
{
CTestJScriptView *dlg = (CTestJScriptView *)lParam;
Sleep(5000);
BOOL ret = FALSE;
         //调用失败,出现文章标题列出的错误
ret = dlg->m_webPage.CallJScript(_T("a"));
return 0;
}请高手指点下,谢谢...

解决方案 »

  1.   

    CTestJScriptView *dlg = (CTestJScriptView *)lParam;
    这个dlg不是NULL或者什么?
      

  2.   

    CallJScript可能是这个函数内部出错了!
      

  3.   

    #include <atlbase.h>
    #include <Mshtml.h>class CWebPage  
    {
    public:
    CWebPage();
    virtual ~CWebPage(); bool SetDocument(IDispatch* pDisp);
    LPDISPATCH GetHtmlDocument() const;
    const CString GetLastError() const;
    bool GetJScript(CComPtr<IDispatch>& spDisp);
    bool GetJScripts(CComPtr<IHTMLElementCollection>& spColl); CString ScanJScript(CString& strAText, CStringArray& args); bool CallJScript(const CString strFunc,CComVariant* pVarResult = NULL);
    bool CallJScript(const CString strFunc,const CString strArg1,CComVariant* pVarResult = NULL);
    bool CallJScript(const CString strFunc,const CString strArg1,const CString strArg2,CComVariant* pVarResult = NULL);
    bool CallJScript(const CString strFunc,const CString strArg1,const CString strArg2,const CString strArg3,CComVariant* pVarResult = NULL);
    bool CallJScript(const CString strFunc,const CStringArray& paramArray,CComVariant* pVarResult = NULL);protected:
    void ShowError(LPCSTR lpszText);protected: CComPtr<IHTMLDocument2> m_spDoc;
    CString m_strError;};inline
    void CWebPage::ShowError(LPCSTR lpszText)
    {
    m_strError = "JSCall Error:\n" + CString(lpszText);
    }
    inline 
    const CString CWebPage::GetLastError() const
    {
    return m_strError;
    }
    inline
    LPDISPATCH CWebPage::GetHtmlDocument() const
    {
    return m_spDoc;
    }CString GetNextToken(CString& strSrc, const CString strDelim,bool bTrim = false, bool bFindOneOf = true);
      

  4.   

    #include "WebPage.h"#ifdef _DEBUG
    #undef THIS_FILE
    static char THIS_FILE[]=__FILE__;
    #define new DEBUG_NEW
    #endif#define CHECK_POINTER(p)\
    ATLASSERT(p != NULL);\
    if(p == NULL)\
    {\
    ShowError("NULL pointer");\
    return false;\
    }const CString 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;
    }CString GetNextToken(CString& strSrc, const CString strDelim,bool bTrim, bool bFindOneOf)
    {
    CString strToken;
    int idx = bFindOneOf? strSrc.FindOneOf(strDelim) : strSrc.Find(strDelim);
    if(idx != -1)
    {
    strToken  = strSrc.Left(idx);
    strSrc = strSrc.Right(strSrc.GetLength() - (idx + 1) );
    }
    else
    {
    strToken = strSrc;
    strSrc.Empty();
    }
    if(bTrim)
    {
    strToken.TrimLeft();
    strToken.TrimRight();
    }
    return strToken;
    }//////////////////////////////////////////////////////////////////////
    // Construction/Destruction
    //////////////////////////////////////////////////////////////////////CWebPage::CWebPage()
    {
    }CWebPage::~CWebPage()
    {}bool CWebPage::SetDocument(IDispatch* pDisp)
    {
    CHECK_POINTER(pDisp); m_spDoc = NULL; CComPtr<IDispatch> spDisp = pDisp; HRESULT hr = spDisp->QueryInterface(IID_IHTMLDocument2,(void**)&m_spDoc);
    if(FAILED(hr))
    {
    ShowError("Failed to get HTML document COM object");
    return false;
    }
    return true;
    }bool CWebPage::GetJScript(CComPtr<IDispatch>& spDisp)
    {
    CHECK_POINTER(m_spDoc);
    HRESULT hr = m_spDoc->get_Script(&spDisp);
    ATLASSERT(SUCCEEDED(hr));
    return SUCCEEDED(hr);
    }bool CWebPage::GetJScripts(CComPtr<IHTMLElementCollection>& spColl)
    {
    CHECK_POINTER(m_spDoc);
    HRESULT hr = m_spDoc->get_scripts(&spColl);
    ATLASSERT(SUCCEEDED(hr));
    return SUCCEEDED(hr);
    }bool CWebPage::CallJScript(const CString strFunc,CComVariant* pVarResult)
    {
    CStringArray paramArray;
    return CallJScript(strFunc,paramArray,pVarResult);
    }bool CWebPage::CallJScript(const CString strFunc,const CString strArg1,CComVariant* pVarResult)
    {
    CStringArray paramArray;
    paramArray.Add(strArg1);
    return CallJScript(strFunc,paramArray,pVarResult);
    }bool CWebPage::CallJScript(const CString strFunc,const CString strArg1,const CString strArg2,CComVariant* pVarResult)
    {
    CStringArray paramArray;
    paramArray.Add(strArg1);
    paramArray.Add(strArg2);
    return CallJScript(strFunc,paramArray,pVarResult);
    }bool CWebPage::CallJScript(const CString strFunc,const CString strArg1,const CString strArg2,const CString strArg3,CComVariant* pVarResult)
    {
    CStringArray paramArray;
    paramArray.Add(strArg1);
    paramArray.Add(strArg2);
    paramArray.Add(strArg3);
    return CallJScript(strFunc,paramArray,pVarResult);
    }bool CWebPage::CallJScript(const CString strFunc, const CStringArray& paramArray,CComVariant* pVarResult)
    {
    CComPtr<IDispatch> spScript;
    if(!GetJScript(spScript))
    {
    ShowError("Cannot GetScript");
    return false;
    }
    CComBSTR bstrMember(strFunc);
    DISPID dispid = NULL;
    HRESULT hr = spScript->GetIDsOfNames(IID_NULL,&bstrMember,1,
    LOCALE_SYSTEM_DEFAULT,&dispid);
    if(FAILED(hr))
    {
    ShowError(GetSystemErrorMessage(hr));
    return false;
    } const int arraySize = paramArray.GetSize(); DISPPARAMS dispparams;
    memset(&dispparams, 0, sizeof dispparams);
    dispparams.cArgs = 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);
        CComVariant vaResult;
    UINT nArgErr = (UINT)-1;  // initialize to invalid arg
             
    hr = spScript->Invoke(dispid,IID_NULL,0,
    DISPATCH_METHOD,&dispparams,&vaResult,&excepInfo,&nArgErr); delete [] dispparams.rgvarg;
    if(FAILED(hr))
    {
    ShowError(GetSystemErrorMessage(hr));
    return false;
    }

    if(pVarResult)
    {
    *pVarResult = vaResult;
    }
    return true;
    }// returned java script function name, input string is truncating
    CString CWebPage::ScanJScript(CString& strAText, CStringArray& args)
    {
    args.RemoveAll();
    CString strDelim(" \n\r\t"),strSrc(strAText);
    bool bFound = false;
    while(!strSrc.IsEmpty())
    {
    CString strStart = GetNextToken(strSrc,strDelim);
    if(strStart == "function")
    {
    bFound = true;
    break;
    }
    if(strStart == "/*")
    {
    // Skip comments
    while(!strSrc.IsEmpty())
    {
    CString strStop = GetNextToken(strSrc,strDelim);
    if(strStop == "*/")
    {
    break;
    }
    }
    }
    } if(!bFound)
    return "";

    CString strFunc = GetNextToken(strSrc,"(",true);
    CString strArgs = GetNextToken(strSrc,")",true); // Parse arguments
    CString strArg;
    while(!(strArg = GetNextToken(strArgs,",")).IsEmpty())
    args.Add(strArg); strAText= strSrc;
    return strFunc;
    }
      

  5.   

    我觉得问题可能出在m_webPage.CallJScript函数调用了CTestJScriptView的成员变量,分析:m_webPage作为CTestJScriptView的成员变量,他的成员函数是可以调用CTestJScriptView的成员变量的,因此当你在void CTestJScriptView::OnDocumentComplete(LPCTSTR lpszURL)中调用该函数时无误;但是在线程函数中,并没有对CTestJScriptView的成员变量的任何声明或定义,连CTestJScriptView本身都是通过指针传递进来的,所以当CallJScript调用了CTestJScriptView的成员变量时就会发生错误。
      

  6.   

    解决办法,在线程中以消息驱动,避免在线程中直接调用m_webPage.CallJScript(),感谢6楼(liangchenxuqi)的,当然还在所有人的参入提点。