问:如题

解决方案 »

  1.   

    2002年我曾经碰到过这个问题。答:
        为某个类的一个(目前只支持一个)虚函数动态的创建一个IDispatch接口
    想知道更多的内容请在MSDN中查CreateStdDispatch
    #define BEGIN_METHOD_PARAM() static  LPPARAMDATA GetParamData(LPUINT pCount) {     static  PARAMDATA   paras[] = {#define METHOD_PARAM(NAME, TYPE)    {OLESTR(#NAME), TYPE},#define END_METHOD_PARAM() {NULL, VT_EMPTY}     };     *pCount = sizeof(paras)/sizeof(paras[0])-1;     return paras; };template <class T, VARENUM TRET, int iMethod, CALLCONV cc = CC_STDCALL>
    class ICallBackImpl : public IUnknown {
        typedef ICallBackImpl<T, TRET, iMethod, cc> _Myt;
        INTERFACEDATA   InterfaceData;
        METHODDATA      MethodData;
        IUnknown*       punkStdDispatch;
        LONG    ref;
        ICallBackImpl () : ref(0), punkStdDispatch(NULL) {
            UINT    count;
            InterfaceData.pmethdata = &MethodData;
            InterfaceData.cMembers = 1;
            MethodData.szName = L"";
            MethodData.ppdata = T::GetParamData(&count);
            MethodData.dispid = DISPID_VALUE;
            MethodData.iMeth = iMethod;
            MethodData.cc = cc;
            MethodData.cArgs = count;
            MethodData.wFlags = DISPATCH_METHOD;
            MethodData.vtReturn = TRET;
        }
        ~ICallBackImpl() {
            if(punkStdDispatch)
                punkStdDispatch->Release();
        }public:
        HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObj) {
            if(riid == IID_IUnknown) {
                *ppvObj = this;
            } else if(riid == IID_IDispatch) {
                return punkStdDispatch->QueryInterface(riid, ppvObj);
            } else
                return E_NOINTERFACE;
            AddRef();        return S_OK;
        }
        ULONG STDMETHODCALLTYPE AddRef() {
            ::InterlockedIncrement(&ref);
            ods("++ %d\n", ref);
            return ref;
        }
        ULONG STDMETHODCALLTYPE Release() {
            ULONG prev = ::InterlockedDecrement(&ref);
            if(ref == 0) {
            ods("-- %d\n", 0);
                delete this;
                return 0;
            }
            ods("-- %d\n", ref);
            return ref;
        }
        static  HRESULT CreateInstance(T* pExposeObj, _Myt** pThis) {
            HRESULT hr;
            ITypeInfo* pTypeInfo;
            if(IsBadWritePtr(pThis, sizeof(*pThis)))
                return E_POINTER;
            _Myt* pobj = new _Myt();
            pobj->AddRef();
            if(pobj == NULL)
                return E_OUTOFMEMORY;
            hr = ::CreateDispTypeInfo(&pobj->InterfaceData, LOCALE_SYSTEM_DEFAULT,
     &pTypeInfo);
            if(FAILED(hr))
                goto error;
            hr = ::CreateStdDispatch(pobj, pExposeObj, pTypeInfo,
    &pobj->punkStdDispatch);
            pTypeInfo->Release();
            if(FAILED(hr))
                goto error;
            *pThis = pobj;
            return S_OK;
    error:
            pobj->Release();
            return hr;
        }