none
ATL Control Events zu Jacascript RRS feed

  • Frage

  • Hi,

    ich möchte in meinem ATL plugin für den Browser ein Event werfen, dass von Javascript aufgefangen werden soll. Ich habe schon vor Ewigkeiten einmal daran gearbeitet und von damals ein Event "OnResourceEvent" definiert. Das funktioniert auch und wird von Javascript aufgefangen. Jetzt wollte ich ein neues Event "OnTemplatePoint" hinzufügen, schaffe es aber irgendwie nicht. Ich habe dazu in der IDL Datei die Methode hinzugefügt:

    library PandaLib
    {
    	importlib("stdole2.tlb");
    	[
    		uuid(835BFAEE-D842-4F1D-9DF1-7418D8E6FBC7)		
    	]
    	coclass CompReg
    	{
    		[default] interface IComponentRegistrar;
    	};
    	[
    		uuid(9178D0A4-6AD9-40C3-987B-A36D43FCD9D8)		
    	]
    	dispinterface _IPandaCtrlEvents
    	{
    		properties:
    		methods:
    			[id(1), helpstring("method OnResourceEvent")] void OnResourceEvent([in] BSTR filename, [in] LONG state);
    			[id(3), helpstring("method OnTemplatePoint")] void OnTemplatePoint([in] LONG x, [in] LONG y, [in] LONG z);
    	};
    	[
    		uuid(227C53AE-4140-4FE0-9F7A-D4B028D48B51),		
    		control
    	]
    	coclass PandaCtrl
    	{
    		[default] interface IPandaCtrl;
    		[default, source] dispinterface _IPandaCtrlEvents;
    	};
    };
    

    Zusätzlich habe ich die Methode in der Datei "_IPandaCtrlEvents_CP.H" hinzugefügt:

    #pragma once
    
    template<class T>
    class CProxy_IPandaCtrlEvents :
    	public ATL::IConnectionPointImpl<T, &__uuidof(_IPandaCtrlEvents)>
    {
    public:
    	HRESULT Fire_OnResourceEvent(BSTR filename, LONG state)
    	{
    		HRESULT hr = S_OK;
    		T * pThis = static_cast<T *>(this);
    		int cConnections = m_vec.GetSize();
    
    		for (int iConnection = 0; iConnection < cConnections; iConnection++)
    		{
    			pThis->Lock();
    			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
    			pThis->Unlock();
    
    			IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
    
    			if (pConnection)
    			{
    				CComVariant avarParams[2];
    				avarParams[1] = filename;
    				avarParams[1].vt = VT_BSTR;
    				avarParams[0] = state;
    				avarParams[0].vt = VT_I4;
    				DISPPARAMS params = { avarParams, NULL, 2, 0 };
    				hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
    			}
    		}
    		return hr;
    	}
    
    	HRESULT Fire_OnTemplatePoint(LONG x, LONG y, LONG z)
    	{
    		HRESULT hr = S_OK;
    		T * pThis = static_cast<T *>(this);
    		int cConnections = m_vec.GetSize();
    
    		for (int iConnection = 0; iConnection < cConnections; iConnection++)
    		{
    			pThis->Lock();
    			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
    			pThis->Unlock();
    
    			IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
    
    			if (pConnection)
    			{
    				CComVariant avarParams[3];
    				avarParams[2] = z;
    				avarParams[2].vt = VT_I4;
    				avarParams[1] = y;
    				avarParams[1].vt = VT_I4;
    				avarParams[0] = x;
    				avarParams[0].vt = VT_I4;
    				DISPPARAMS params = { avarParams, NULL, 3, 0 };
    				hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
    			}
    		}
    		return hr;
    	}
    };
    

    Muss ich außer diesen zwei Schritten noch etwas tun um das Event werfen zu können? Habe ich etwas vergessen? Ich hatte nur diese 2 Dinge in Erinnerung. Das ResourceEvent wird geworfen, das TemplatePointEvent nicht :(

    Bin für jeden Hinweise dankbar!

    Mario M

    Donnerstag, 21. April 2011 14:20

Antworten

  • Ah! Der letzte Hinweis führte mich zur Lösung (Schande über mich):

    Der erste Parameter bei Invoke() muss die ID der Methode sein die durch die IDL Datei festgelegt wurde!

    • Als Antwort markiert Falarys Donnerstag, 21. April 2011 15:12
    Donnerstag, 21. April 2011 15:12

Alle Antworten

  • Ich habe eben noch ein seltsames Verhalten festgestellt das mir zuvor entgangen ist:

    Ich rufe im atl objekt

    Fire_OnTemplatePoint

    auf. Wenn ich mich nun im Javascript für nur das Event registriere mit

    this.embedObj.attachEvent('OnTemplatePoint', this.onTemplatePoint);
    

    dann bekomme ich das Event nicht. Wenn ich jedoch beide Events registriere:

    this.embedObj.attachEvent('OnTemplatePoint', this.onTemplatePoint);
    this.embedObj.attachEvent('OnResourceEvent', this.onResourceEvent);
    

    dann wird die Javascript-Funktion "onResourceEvent" von "Fire_OnTemplatePoint" aufgerufen...

    Donnerstag, 21. April 2011 15:07
  • Ah! Der letzte Hinweis führte mich zur Lösung (Schande über mich):

    Der erste Parameter bei Invoke() muss die ID der Methode sein die durch die IDL Datei festgelegt wurde!

    • Als Antwort markiert Falarys Donnerstag, 21. April 2011 15:12
    Donnerstag, 21. April 2011 15:12