• ActiveX多线程回调JavaScript


    原本JavaScript可以接受ActiveX的事件。不过貌似要知道什么时候产生消息,而且Script要在调用了ActiveX之后马上产生事件,不然就接收不到消息。
    若采用多线程就完全没有办法实现交互了。
    我做的那个东西,是一定要采用多线程的。是调用了ActiveX之后一段时间之后产生才可以事件,如果不采用多线程会导致浏览器假死。
    没有办法,只好采用ActiveX回调JavaScript代码来实现与多线程之间的交互。

    问题又出来了,如果我采用把浏览器中的对象用指针的方式传给新的线程,就会导致接下来产生的对象产生NULL,很郁闷用了很多方法都不行,貌似只要传COM对象都会导致接下来的对象产生空对象。

    最后还是上网查一下,原来这样的方式是不正确的。

    方法如下:
    (1)在类中声明

    private:
    IStream* pStream;

    (2)

    void CSecurityCtrl::Scan(void)
    {
    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    // TODO: 在此添加调度处理程序代码
    // TODO: 在此添加调度处理程序代码
    IOleClientSite* m_spClientSite = GetClientSite();
    IServiceProvider* isp;
    HRESULT hr = m_spClientSite->QueryInterface(IID_IServiceProvider, reinterpret_cast(&isp));
    if(FAILED(hr)) return;
    IWebBrowser2* ppBrowser;
    hr = isp->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, reinterpret_cast(&ppBrowser));
    if(FAILED(hr)) return;
    IDispatch *m_ppDispDoc;
    hr = ppBrowser->get_Document(&m_ppDispDoc);
    if(FAILED(hr)) return;
    IHTMLDocument2 *ppDocument2;
    hr = m_ppDispDoc->QueryInterface(IID_IHTMLDocument2 ,reinterpret_cast(&ppDocument2));
    if(FAILED(hr)) return;
    IDispatch *pScript;
    hr=ppDocument2->get_Script(&pScript);
    if(FAILED(hr)) return;
    ::CoMarshalInterThreadInterfaceInStream(IID_IDispatch, pScript, &pStream);

    pScript->Release();
    ppDocument2->Release();
    m_ppDispDoc->Release();
    ppBrowser->Release();
    m_spClientSite->Release();

    AfxBeginThread(ScanThread,this);
    }

    UINT CSecurityCtrl::ScanThread(LPVOID pParam)
    {
    CSecurityCtrl * pCSecurityCtrl = (CSecurityCtrl *)pParam;

    ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    IDispatch *pScript;
    ::CoGetInterfaceAndReleaseStream( pCSecurityCtrl->pStream, IID_IDispatch,(void**)&pScript);


    //你的操作......................
    // js函数名 参数个数 参数内容
    JsCallback(pScript,_T("ActiveXCallback"),1,_T("ActiveXCallback"));
    pScript->Release();
    return 0;
    }

    int CSecurityCtrl::JsCallback(IDispatch *pScript ,_TCHAR *strName,int nParamCount,...)
    {
    if(pScript == NULL)
    {
    return 1;
    }

    try
    {
    DISPID dispid;
    CComBSTR bstrMember(strName);
    pScript->GetIDsOfNames(IID_NULL,&bstrMember,1,LOCALE_SYSTEM_DEFAULT,&dispid);

    DISPPARAMS dispparams;
    memset(&dispparams, 0, sizeof dispparams);
    dispparams.cArgs = nParamCount;
    dispparams.rgvarg = new VARIANT[dispparams.cArgs];
    va_list ap;
    va_start(ap, nParamCount);
    for(int j = 0; j Invoke(dispid,IID_NULL,0,DISPATCH_METHOD,&dispparams,&vaResult,&excepInfo,&nArgErr);

    }
    catch(_com_error &e)
    {
    AfxMessageBox(e.ErrorMessage());
    }
    return 0;
    }

    上面代码可以实现页面JavaScript代码回调。从而实现页面与ActiveX的交互。

    或者可以使用这段代码把浏览器对象传过去

    ::CoMarshalInterThreadInterfaceInStream(IID_IWebBrowser2,   ppBrowser,   &pStream);

    ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    IWebBrowser2 * ppBrower;
    ::CoGetInterfaceAndReleaseStream(pStream, IID_IWebBrowser2, (void**)&ppBrower);

    因为一个Web窗口,CComPtr 指针是不变的,而IHTMLDocument2指针是会变化的(比如刷新页面时,比如Navigate到其他URL时。)动态取得m_spDoc和pStream,就可以及时地释放。

    总之,总结一下就是,如果要实现多线程,就要用上面红字的方式来传COM对象,具体原因我到现在还没有搞清楚。

    其他相关的资料:
    http://blog.csdn.net/zblue78/archive/2008/07/21/2683883.aspx
    http://topic.csdn.net/u/20070212/20/1011ad32-1ce7-416d-9e6c-cffca7a100fe.html?seed=1066340289
    http://vcfaq.mvps.org/com/11.htm
    http://vcfaq.mvps.org/com/1.htm

  • 相关阅读:
    WPF程序内存泄漏问题文章推荐
    UAC影响读写文件和注册表
    .NET COM Interop 中的ReleaseComObject使用准则
    读Excel数据并导入到数据库中最快的方法
    DEP问题文章推荐
    深入了解GC文章推荐
    IIS 发布网站
    iis5.1安装方法(适用于XP),IIS5.0安装包下载、IIS5.1安装包下载、IIS6.0安装包下载
    单击GridView的某一行 根据此行id得到这行的所有信息
    asp.net背景图片自动适应屏幕大小
  • 原文地址:https://www.cnblogs.com/zdxster/p/1945872.html
Copyright © 2020-2023  润新知