IonicWind Software

Aurora Compiler => General Discussion => Topic started by: JR on April 24, 2006, 06:54:06 AM

Title: COM Events
Post by: JR on April 24, 2006, 06:54:06 AM
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?
Title: Re: COM Events
Post by: JR on April 24, 2006, 08:07:04 AM
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.
Title: Re: COM Events
Post by: Ionic Wind Support Team on April 24, 2006, 09:05:17 AM
Move the GUID variable outside of the subroutine.  If you need it global to other files use the 'global' keyword.

Title: Re: COM Events
Post by: JR on April 24, 2006, 10:11:44 AM
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);
Title: Re: COM Events
Post by: JR on April 24, 2006, 10:27:21 AM
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.
Title: Re: COM Events
Post by: Ionic Wind Support Team on April 24, 2006, 11:30:37 AM
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.