I want to add an option to my TypeLib Browser for Aurora to generate classes for events sink. I already have made a test with hand made classes and got the events working. However, there is an small problem: The guid of the events interface is needed in three places. Is there a way to make it global?
Here is how the class for ShockWave Flash will look:
class IShockwaveFlashEvents_IUnknownImpl : IUnknown
{
declare virtual QueryInterface(GUID *riid, void *ppvObject), int;
declare virtual AddRef(), unsigned int;
declare virtual Release(), unsigned int;
int m_refs;
}
IShockwaveFlashEvents_IUnknownImpl :: QueryInterface(GUID *riid, void *ppvObject), int
{
GUID _IID__IShockwaveFlashEvents;
DEFINE_GUID(_IID__IShockwaveFlashEvents, 0xD27CDB6D, 0xAE6D, 0x11CF, 0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);
if IsEqualGUID(riid, _IID_IUnknown) or IsEqualGUID(riid, _IID_IDispatch) or IsEqualGUID(riid, _IID__IShockwaveFlashEvents)
{
*(pointer)ppvObject = this;
AddRef();
return S_OK;
}
*(pointer)ppvObject = null;
return E_NOINTERFACE;
}
IShockwaveFlashEvents_IUnknownImpl :: AddRef(), unsigned int
{
m_refs++;
return m_refs;
}
IShockwaveFlashEvents_IUnknownImpl :: Release(), unsigned int
{
m_refs--;
if (!m_refs)
{
delete this;
return 0;
}
return m_refs;
}
class IShockwaveFlashEvents_IDispatchImpl : IShockwaveFlashEvents_IUnknownImpl
{
declare virtual GetTypeInfoCount(unsigned int *pctinfo), int;
declare virtual GetTypeInfo(unsigned int iTInfo, int lcid, pointer *ppTInfo), int;
declare virtual GetIDsOfNames(GUID *riid, unsigned word *rgszNames, unsigned int cNames, int lcid, int *rgDispID), int;
declare virtual Invoke(int dispIdMember, GUID *riid, int lcid, unsigned word wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, unsigned int *puArgErr), int;
declare virtual OnReadyStateChange(DISPPARAMS *pdispparams);
declare virtual OnProgress(DISPPARAMS *pdispparams);
declare virtual FSCommand(DISPPARAMS *pdispparams);
}
IShockwaveFlashEvents_IDispatchImpl :: GetTypeInfoCount(unsigned int *pctinfo), int
{
*pctinfo = null;
return S_OK;
}
IShockwaveFlashEvents_IDispatchImpl :: GetTypeInfo(unsigned int iTInfo, int lcid, pointer *ppTInfo), int
{
return E_NOTIMPL;
}
IShockwaveFlashEvents_IDispatchImpl :: GetIDsOfNames(GUID *riid, unsigned word *rgszNames, unsigned int cNames, int lcid, int *rgDispID), int
{
return E_NOTIMPL;
}
IShockwaveFlashEvents_IDispatchImpl :: OnReadyStateChange(DISPPARAMS *pdispparams)
{
int newState;
VARIANT *vArg;
// Unpack the arguments
vArg = *pdispparams.*(VARIANT)rgvarg[0];
newState = vArg->lVal;
return 0;
}
IShockwaveFlashEvents_IDispatchImpl :: OnProgress(DISPPARAMS *pdispparams)
{
int percentDone;
VARIANT *vArg;
// Unpack the arguments
vArg = *pdispparams.*(VARIANT)rgvarg[0];
percentDone = vArg->lVal;
return 0;
}
IShockwaveFlashEvents_IDispatchImpl :: FSCommand(DISPPARAMS *pdispparams)
{
pointer pbstrcommand;
pointer args;
VARIANT *vArg;
// Unpack the arguments
vArg = *pdispparams.*(VARIANT)rgvarg[1];
pbstrcommand = vArg->bstrVal;
vArg = *pdispparams.*(VARIANT)rgvarg[0];
args = vArg->bstrVal;
return 0;
}
IShockwaveFlashEvents_IDispatchImpl :: Invoke(int dispIdMember, GUID *riid, int lcid, unsigned word wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, unsigned int *puArgErr), int
{
select (dispIdMember)
{
case 0xFFFFFD9F: // OnReadyStateChange
OnReadyStateChange(pdispparams);
case 0x000007A6: // OnProgress
OnProgress(pdispparams);
case 0x00000096: // FSCommand
FSCommand(pdispparams);
default:
return DISP_E_MEMBERNOTFOUND;
}
return S_OK;
}
Niote: The attached file contains the full testing code.
Move the GUID variable outside of the subroutine. If you need it global to other files use the 'global' keyword.
If I declare it as global, the call to AtlAdvise fails. I must be missing something.
GLOBAL _IID__IShockwaveFlashEvents;
GUID _IID__IShockwaveFlashEvents;
DEFINE_GUID(_IID__IShockwaveFlashEvents, 0xD27CDB6D, 0xAE6D, 0x11CF, 0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);
......
hr = AtlAdvise(win.m_pFlash, win.m_pFlashEvents, _IID__IShockwaveFlashEvents, win.m_FlashCookie);
Apparently I can't assign the value of the guid outside the subroutine with DEFINE_GUID. The compiler doesn't complain, but the guid is null.
DEFINE_GUID in C is a macro. I assume your using a function.
You'll need to execute that call somewhere in the path of execution.
Or have a separate project file and just do it in assembly, making them all global.
#asm
global _IID_IShockwaveFlashEvents
_IID_IShockwaveFlashEvents:
dd 0xD27CDB6D
dw 0xAE6D
dw 0x11CF
db 0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00
#endasm
Then in the project file that uses them it's just
extern _IID_IShockwaveFlashEvents as GUID;
Once I have the built in data statements this will be a bit easier.