一个远程监控的ActiveX控件, 嵌入到如下test.html文件中:
<HTML>
<HEAD>
<TITLE> YTNetCamCtrl tet page </TITLE>
<SCRIPT LANGUAGE="VBScript"> 
<!--
Public Sub YTNetCameraCtrl_OnVideoSizeChange ( w , h )
MsgBox "OnImageSizeChange : " & "width = " & w & " height = " & h
End Sub
-->
</SCRIPT>
</HEAD>
<BODY>
<OBJECT
ID="YTNetCameraCtrl"
WIDTH = 640
HEIGHT = 480
CLASSID="CLSID:B9134952-0AA3-49F0-BC7A-94E2AEF30543">
<PARAM NAME = "NetCamIP" VALUE = "192.168.0.150">
<PARAM NAME = "NetCamPort" VALUE = 45034>
<PARAM NAME = "AudioVolumeLeft" VALUE = 100>
<PARAM NAME = "AudioVolumeRight" VALUE = 100>
<PARAM NAME = "Connected" VALUE = true >
</OBJECT>
</BODY>
</HTML>事件OnImageSizeChange会在<PARAM NAME = "Connected" VALUE = true >执行时被触发一次, 以后每6秒也会触发一次, 但是实际结果是第一次触发时VBScript过程YTNetCameraCtrl_OnVideoSizeChange并没有被调用, 而以后的每次触发都能正确调用.
跟踪发现事件第一次触发的时候, 连接点上没有任何sink连接. 考虑到可能IE连接到该连接点时, 第一次事件已经触发过了. 因此我重载了IConnectionPointImpl类的Advise, 在正常的Advise成功后直接触发事件. 可是结果还是第一次事件没有响应. 
再次跟踪触发事件的代码, 发现此时确实有一个sink连接到连接点上了, 也调用了该sink的IDispatch接口的Invoke方法. 可是VBScript中的YTNetCameraCtrl_OnVideoSizeChange过程仍然没有被调用. 
为什么IE在连接到连接点之后, 马上触发事件, VBScript中的事件响应函数不被调用呢?
对于我的应用第一次事件不能被漏掉, 希望你的解答!  :)
另, 从什么时候开始, VBScript中的事件处理函数可以开始正常响应事件?

解决方案 »

  1.   

    又跟了一次, 发现调用 pDispatch->Invoke 返回 S_OK , 但是 varResult.scode 的值却是 0xCCCCCCCC. 不知道是什么原因??
      

  2.   

    改用JavaScript, 第一次事件可以正确响应了. 
    VBScript为何不能响应第一个事件原因还不清楚, 猜测可能是VBScript的消息响应的绑定有一定的延时吧
      

  3.   

    比较奇怪的问题,你有继承Invoke吗?
      

  4.   

    用ATL ActiveX控件向导生成的, 事件触发由向导生成的CProxy_IYTNetCameraCtrlEvents类代理, 控件类继承自该类. CProxy_IYTNetCameraCtrlEvents类中的事件触发代码如下:
    HRESULT Fire_OnVideoSizeChange(LONG nWidth, LONG nHeight)
    {
    CComVariant varResult;
    T* pT = static_cast<T*>(this);
    int nConnectionIndex;
    CComVariant* pvars = new CComVariant[2];
    int nConnections = m_vec.GetSize();

    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
    {
    pT->Lock();
    CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
    pT->Unlock();
    IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
    if (pDispatch != NULL)
    {
    VariantClear(&varResult);
    pvars[1] = nWidth;
    pvars[0] = nHeight;
    DISPPARAMS disp = { pvars, NULL, 2, 0 };
    pDispatch->Invoke(0x4, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
    }
    }
    delete[] pvars;
    return varResult.scode;

    }
      

  5.   

    另外还有一个问题, 一起问了:
    在事件中使用安全数组(SafeArray), 向导生成的代理代码不正确, VARIANT 中的安全数组赋值后变为 BOOL 类型, 事件接口和向导生成的代码如下:事件接口:
    [
    uuid(2A0E60B5-5F4A-498B-9106-4F005228CD9C),
    helpstring("_IYTNetCameraCtrlEvents Interface")
    ]
    dispinterface _IYTNetCameraCtrlEvents
    {
    properties:
    methods:
    ......
    [id(10), helpstring("event for motion detect region changed")] HRESULT OnMotionDetectRegionChange(VARIANT_BOOL bAlert, long nSensitivity, VARIANT aMDRgnValid);
    };向导生成的代码, 注意其中注释的代码是我手工修改的, 修改后的代码执行正常:
    template <class T>
    class CProxy_IYTNetCameraCtrlEvents : public IConnectionPointImpl<T, &DIID__IYTNetCameraCtrlEvents, CComDynamicUnkArray>
    {
    //Warning this class may be recreated by the wizard.
    public:
    ......
    HRESULT Fire_OnMotionDetectRegionChange(VARIANT_BOOL bAlert, LONG nSensitivity, VARIANT aMDRgnValid)
    {
    CComVariant varResult;
    T* pT = static_cast<T*>(this);
    int nConnectionIndex;
    CComVariant* pvars = new CComVariant[3];
    int nConnections = m_vec.GetSize();

    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
    {
    pT->Lock();
    CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
    pT->Unlock();
    IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
    if (pDispatch != NULL)
    {
    VariantClear(&varResult);
    pvars[2] = bAlert;
    pvars[1] = nSensitivity;
    //pvars[0] = &aMDRgnValid; // 这里执行不正确, aMDRgnValid的类型为VT_ARRAY | VT_VARIANT, 而赋值后 pvars[0] 的类型为 VT_BOOL . 修改为如下手动赋值, 结果正常
    pvars[0].vt = VT_BYREF|VT_VARIANT;
    pvars[0].pvarVal = &aMDRgnValid;
    DISPPARAMS disp = { pvars, NULL, 3, 0 };
    pDispatch->Invoke(0xa, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
    }
    }
    delete[] pvars;
    return varResult.scode;

    }
      

  6.   

    使用JavaScript响应事件,问题解决