There is currently no direct way to send event calls to VBScript. You can, however, manually trigger events from your COM object by using the GetRef method of VBScript which basically gives you a function pointer, but you have to jump through a bunch of hoops to get it to your COM object and be able to call it.
If you call GetRef from VBScript, it will try to look up the name of the sub you put in as a parameter and check that it is a valid sub procedure defined in your script it will then create a new IDispatch object which has a default method that points to the sub procedure you passed in. Once you have this object, all you have to do is get it to your COM object and store it so every time you need to fire an event you just have to Invoke the default method of the object.
To add event calling capability to our previous example
1. Make sure you can see the class view
- Right click on your IExampleObject interface
- Choose Add->Add Method
- Call the method "SetEventObject"
- Add a IDispatch* parameter called pDispatch
- Click Finish to have the wizard generate the function stub for you
2. Add a private CComPtr<IDispatch> member variable to the CExampleObject. This will store our object interface that we recieve from GetRef in VBScript that points to the sub procedure we want to call when the event fires.
Code:
CComPtr<IDispatch> m_pEventObject;
3. Implement the SetEventMethod to set the event object pointer to reference the passed in IDispatch parameter.
Code:
STDMETHODIMP CExampleObject::SetEventMethod(IDispatch* pDispatch)
{
m_pEventObject = pDispatch;
return S_OK;
}
4. To call the event from someplace in the COM object, simply call the Invoke method of the IDispatch event object for the default method. For our example, we will change the message box to a MB_YESNO message box and call our event after we recieve a response from the user. The event will have a single integer argument with the result from the message box.
Code:
STDMETHODIMP CExampleObject::MsgBox(BSTR Description, BSTR Caption)
{
int iRetVal = MessageBox(NULL, CString(Description), CString(Caption), MB_YESNO);
if (m_pEventObject.p != NULL)
{
VARIANT var;
DISPPARAMS dp;
// Allocate memory for the rgvarg member of the DISPPARAMS struct.
dp.rgvarg = new VARIANTARG[1];
dp.rgvarg[0] = CComVariant((long)iRetVal);
// set cArgs to the total number of arguments passed.
dp.cArgs = 1;
dp.cNamedArgs = 0;
HRESULT hr = m_pEventObject->Invoke(0, IID_NULL, LOCALE_USER_DEFAULT,
DISPATCH_METHOD,&dp, &var, NULL, NULL);
// Delete the memory we allocated above for dp.rgvarg.
delete[] dp.rgvarg;
}
return S_OK;
}
5. Compile the code and then startup the StreetDeck Development Enviornment and add the following code to the script after the CreateObject function to register the sub as an event with our COM object.
Code:
Set oCOMObject = CreateObject("SDCOMObject.ExampleObject")
oCOMObject.SetEventMethod GetRef("TestEvent")
6. Add the following sub procedure to the script that will be called whenever our event is fired.
Code:
Sub TestEvent(iRetVal)
Module.MsgBox "Return Value = " & iRetVal, "TestEvent Fired!"
End Sub