MSNFanatic has sample code for Messenger events, but it's needlessly complicated in my view, and doesn't really hint as to how to achieve the same effect in Plus. So, I'm writing this tutorial to take developers through step-by-step.
First of all, copy the header and CPP code below into separate files.
Second, in Initialize(), either typecast (quick and dirty) or use QueryInterface() (sensible but long-winded) the iMessengerObj pointer to IMessenger3*. Save this in a global variable.
Third, create a new MessengerEvents object, saving that in a global variable as well.
Fourth, and last, fill in the Invoke() function in MessengerEvents.cpp with your code.
Easy when you know how
NB: Remember to delete the MessengerEvents pointer in Uninitialize()!
Header:
code:
// I think you can see where this is all used
class MessengerEvents : public IDispatch {
public:
MessengerEvents();
~MessengerEvents();
STDMETHODIMP QueryInterface(REFIID iid, void **obj);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int *info);
HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int info, LCID lcid, ITypeInfo **iTInfo);
HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID iid, OLECHAR **names, unsigned int cNames, LCID lcid, DISPID *dispId);
HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIDMember, REFIID iid, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepInfo, unsigned int *argErr);
private:
IConnectionPoint *sink;
DWORD cookie;
int refCount;
};
CPP:
code:
#include <windows.h>
// Part of the Messenger API package
#include "msgrua.h"
#include "msgruaid.h"
// Rename this to match the name of the variable in the file with
Initialize()
extern IMessenger3 *MSN;
// COnnects to Messenger to provide an event sink
MessengerEvents::MessengerEvents() {
IConnectionPointContainer *sinkBox;
refCount = 1;
// Ask MSN for a collection of event interfaces
HRESULT hr =
MSN->QueryInterface(IID_IConnectionPointContainer, (void**)&sinkBox);
cookie = 0;
if (SUCCEEDED(hr)) {
// Ask the collection for the interface we want
(DMessengerEvents)
hr =
sinkBox->FindConnectionPoint(DIID_DMessengerEvents, &sink);
if (SUCCEEDED(hr))
// Tell Messenger we want to intercept events
sink->Advise(this, &cookie);
if (sinkBox) sinkBox->Release();
}
}
MessengerEvents::~MessengerEvents() {
// Tell Messenger we no longer want to intercept events
sink->Unadvise(cookie);
sink->Release();
}
// Don't worry too much about this one: it's here so we can actually
compile
STDMETHODIMP MessengerEvents::QueryInterface(REFIID iid, void **obj)
{
if (obj == NULL) return E_INVALIDARG;
*obj = NULL;
if (iid == IID_IUnknown) *obj = (IUnknown*)this;
if (iid == DIID_DMessengerEvents || iid == IID_IDispatch)
*obj = (IDispatch*)this;
if (*obj == NULL) return E_NOINTERFACE;
AddRef();
return S_OK;
}
ULONG STDMETHODCALLTYPE MessengerEvents::AddRef() {
return ++refCount;
}
ULONG STDMETHODCALLTYPE MessengerEvents::Release() {
return --refCount;
}
HRESULT STDMETHODCALLTYPE MessengerEvents::GetTypeInfoCount(unsigned
int *info) {
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MessengerEvents::GetTypeInfo(unsigned int
info, LCID lcid, ITypeInfo **iTInfo) {
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MessengerEvents::GetIDsOfNames(REFIID iid,
OLECHAR **names, unsigned int cNames, LCID lcid, DISPID *dispId) {
return E_NOTIMPL;
}
// OK, this is the most important part. Use 'msgruaid.h' to find the
event codes
HRESULT STDMETHODCALLTYPE MessengerEvents::Invoke(DISPID event,
REFIID iid, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT
*result, EXCEPINFO *excepInfo, unsigned int *argErr) {
if (!params)
return E_INVALIDARG;
switch (event) {
// Put here your 'case' statements, one per event
}
return S_OK;
}
Get the Messenger API stuff - the .h files need to be placed with the files above, and the .lib file needs to be there too, as well as listed to be linked to.