Excel自动化 - 使用FindConnectionPoint过滤COM事件

时间:2017-09-07 08:25:37

标签: c++ excel windows automation com

我使用C ++ COM来侦听现有Excel应用程序的事件IID_ApplicationEvents。我的代码放在一个单独的EXE文件中。 使用以下代码初始化连接点:

    IConnectionPointContainer* pCPC = NULL;
    hr = pEventSource->QueryInterface(IID_IConnectionPointContainer,
        (void**)&pCPC);
    if (SUCCEEDED(hr)){
        hr = pCPC->FindConnectionPoint(IID_ApplicationEvents, &m_pConnectionPoint);
        if (SUCCEEDED(hr)){
            hr = m_pConnectionPoint->Advise(this, &m_dwConnection);
            if (FAILED(hr))         
                LOG_ERROR(L"m_pConnectionPoint->Advise - FAIL");
        }
        else
            LOG_ERROR(L"FindConnectionPoint - IID_ApplicationEvents: FAIL");

        pCPC->Release();
    }
    else
        LOG_ERROR(L"IID_IConnectionPointContainer: FAIL");
    return hr;

我通过Invoke函数接收Excel事件:

STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
    WORD wFlags, DISPPARAMS* pDispParams,
    VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
    UINT* puArgErr)

我的问题如下:为了提高我的应用程序的性能而不是减慢运行的Excel,我只对OnBeforeSave和OnClose事件感兴趣。有没有办法在我的进程中过滤掉其他Excel事件(我根本不想调用我的Invoke函数)?

1 个答案:

答案 0 :(得分:0)

正如伊戈尔在上面的评论中提到的,你不能简单地过滤事件。但是,你可以自己构建一些东西来做到这一点。

这是一种方式:

  • 创建将在Excel进程中加载​​的COM加载项。 (见IDTExtensibility2)。
  • 调用OnConnection时:
    • 创建自己的本地事件过滤器类的实例(实现IDispatch来处理事件,IConnectionPointContainer来引发事件。
    • 将该事件过滤器对象设置为“public”,方法是将其IUnknown指针指向AddIn参数提供的AddInIst对象的(未记录的)Object属性{ {3}}。
  • 当您的事件过滤器对象收到事件时,请根据您的规则对其进行过滤。如果事件未被过滤掉,请从过滤器对象中提起它。
  • 在您的外部流程中,在OnConnection集合中找到您的COM加载项,并阅读其Object属性。然后,您可以将其视为事件源,而不是Application对象。