⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wxactivex.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                          VARIANT * pVarResult, EXCEPINFO * pExcepInfo,
                          unsigned int * puArgErr)
    { 
        if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
            return E_NOTIMPL;

        wxASSERT(m_activeX);

        // find event for dispid 
        wxActiveX::MemberIdMap::iterator mit = m_activeX->m_eventMemberIds.find((MEMBERID) dispIdMember);
        if (mit == m_activeX->m_eventMemberIds.end())
            return S_OK;

        // sanity check
        int midx = mit->second;
        if (midx < 0 || midx >= m_activeX->GetEventCount())
            return S_OK;

        wxActiveX::FuncX &func = m_activeX->m_events[midx];


        // try to find dispid event
        ActiveXDISPIDEventMap::iterator dit = sg_dispIdEventMap.find(dispIdMember);
        if (dit != sg_dispIdEventMap.end())
        {
            // Dispatch Event
            DispatchEvent(func, *(dit->second), pDispParams);
            return S_OK;
        };

        // try named event
        ActiveXNamedEventMap::iterator nit = sg_NamedEventMap.find(func.name);
        if (nit == sg_NamedEventMap.end())
            return S_OK;

        // Dispatch Event
        DispatchEvent(func, *(nit->second), pDispParams);
        return S_OK;
    }
};

bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc)
{
    if (self->m_haveCustomId && IsEqualIID(iid, self->m_customId))
    {
        WXOLE_TRACE("Found Custom Dispatch Interface");
        *_interface = (IUnknown *) (IDispatch *) self;
        desc = "Custom Dispatch Interface";
        return true;
    };

    return false;
};

DEFINE_OLE_TABLE(wxActiveXEvents)
    OLE_IINTERFACE(IUnknown)
    OLE_INTERFACE(IID_IDispatch, IDispatch)
    OLE_INTERFACE_CUSTOM(wxActiveXEventsInterface)
END_OLE_TABLE;

wxString wxActiveXEvent::EventName()
{
    return m_params.GetName();
};

int wxActiveXEvent::ParamCount() const
{
    return m_params.GetCount();
};

wxString wxActiveXEvent::ParamType(int idx)
{
    wxASSERT(idx >= 0 && idx < m_params.GetCount());

    return m_params[idx].GetType();
};

wxString wxActiveXEvent::ParamName(int idx)
{
    wxASSERT(idx >= 0 && idx < m_params.GetCount());

    return m_params[idx].GetName();
};

static wxVariant nullVar;

wxVariant& wxActiveXEvent::operator[] (int idx)
{
    wxASSERT(idx >= 0 && idx < ParamCount());

    return m_params[idx];
};

wxVariant& wxActiveXEvent::operator[] (wxString name)
{
    for (int i = 0; i < m_params.GetCount(); i++)
    {
        if (name.CmpNoCase(m_params[i].GetName()) == 0)
            return m_params[i];
    };

    wxString err = _T("wxActiveXEvent::operator[] invalid name <") + name + _T(">");
    err += _T("\r\nValid Names = :\r\n");
    for (i = 0; i < m_params.GetCount(); i++)
    {
        err += m_params[i].GetName();
        err += _T("\r\n");
    };

    wxASSERT_MSG(false, err);

    return nullVar;
};

void wxActiveX::GetTypeInfo()
{
    /*
    We are currently only interested in the IDispatch interface 
    to the control. For dual interfaces (TypeKind = TKIND_INTERFACE)
    we should drill down through the inheritance 
    (using TYPEATTR->cImplTypes) and GetRefTypeOfImplType(n)
    and retrieve all the func names etc that way, then generate a C++ 
    header  file for it.

    But we don't do this and probably never will, so if we have a DUAL 
    interface then we query for the IDispatch 
    via GetRefTypeOfImplType(-1).
    */

    HRESULT hret = 0;

    // get type info via class info
    wxAutoOleInterface<IProvideClassInfo> classInfo(IID_IProvideClassInfo, m_ActiveX);
    if (! classInfo.Ok())
        return;

    // type info
    wxAutoOleInterface<ITypeInfo> typeInfo;
    hret = classInfo->GetClassInfo(typeInfo.GetRef());
    if (! typeInfo.Ok())
        return;

    // TYPEATTR
    TYPEATTR *ta = NULL;
    hret = typeInfo->GetTypeAttr(&ta);
    if (! ta)
        return;

    // this should be a TKIND_COCLASS
    wxASSERT(ta->typekind == TKIND_COCLASS);

    // iterate contained interfaces
    for (int i = 0; i < ta->cImplTypes; i++)
    {
        HREFTYPE rt = 0;

        // get dispatch type info handle
        hret = typeInfo->GetRefTypeOfImplType(i, &rt);
        if (! SUCCEEDED(hret))
            continue;

        // get dispatch type info interface
        wxAutoOleInterface<ITypeInfo>  ti;
        hret = typeInfo->GetRefTypeInfo(rt, ti.GetRef());
        if (! ti.Ok())
            continue;

        // check if default event sink
        bool defInterface = false;
        bool defEventSink = false;
        int impTypeFlags = 0;
        typeInfo->GetImplTypeFlags(i, &impTypeFlags);

        if (impTypeFlags & IMPLTYPEFLAG_FDEFAULT)
        {
            if (impTypeFlags & IMPLTYPEFLAG_FSOURCE)
            {
                WXOLE_TRACEOUT("Default Event Sink");
                defEventSink = true;
                if (impTypeFlags & IMPLTYPEFLAG_FDEFAULTVTABLE)
                {
                    WXOLE_TRACEOUT("*ERROR* - Default Event Sink is via vTable");
                    defEventSink = false;
                };
            }
            else
            {
                WXOLE_TRACEOUT("Default Interface");
                defInterface = true;
            }
        };


        // process
        GetTypeInfo(ti, defInterface, defEventSink);
    };


    // free
    typeInfo->ReleaseTypeAttr(ta);
};

void ElemDescToParam(const ELEMDESC& ed, wxActiveX::ParamX& param)
{
    param.flags = ed.idldesc.wIDLFlags;
    param.vt = ed.tdesc.vt;
    param.isPtr = (param.vt == VT_PTR);
    param.isSafeArray = (param.vt == VT_SAFEARRAY);
    if (param.isPtr || param.isSafeArray)
        param.vt = ed.tdesc.lptdesc->vt;
};

void wxActiveX::GetTypeInfo(ITypeInfo *ti, bool defInterface, bool defEventSink)
{
    // wxAutoOleInterface<> assumes a ref has already been added
    ti->AddRef();
    wxAutoOleInterface<ITypeInfo> typeInfo(ti);

    // TYPEATTR
    TYPEATTR *ta = NULL;
    HRESULT hret = typeInfo->GetTypeAttr(&ta);
    if (! ta)
        return;

    if (ta->typekind == TKIND_DISPATCH)
    {
        WXOLE_TRACEOUT("GUID = " << GetIIDName(ta->guid).c_str());

        if (defEventSink)
        {
            wxActiveXEvents *disp = new wxActiveXEvents(this, ta->guid);
            ConnectAdvise(ta->guid, disp);
        };

        // Get properties
        // See bug #1280715 in the wxActiveX SF project
        int i;
        for (i = 0; i < ta->cVars; i++) {
            VARDESC FAR *vd = NULL;

            typeInfo->GetVarDesc(i, &vd) ;
            BSTR bstrProperty = NULL;
            typeInfo->GetDocumentation(vd->memid, &bstrProperty,
                                       NULL, NULL, NULL);
            wxString propName(bstrProperty);
            m_props.push_back(PropX());
            int idx = m_props.size() - 1;
            m_propNames[propName] = idx;
            m_props[idx].name = propName;
            m_props[idx].memid = vd->memid;

            ParamX param;
            param.isSafeArray = false;
            param.isPtr = false;
            param.flags = vd->elemdescVar.idldesc.wIDLFlags;
            param.vt = vd->elemdescVar.tdesc.vt;

            m_props[idx].arg = param;
            m_props[idx].type = param;
        }        

        // Get Function Names
        for (i = 0; i < ta->cFuncs; i++)
        {
            FUNCDESC FAR *fd = NULL;

            hret = typeInfo->GetFuncDesc(i, &fd);
            if (! fd)
                continue;

            BSTR anames[1] = {NULL};
            unsigned int n = 0;

            hret = typeInfo->GetNames(fd->memid, anames, 1, &n);

            if (anames[0])
            {
                wxString name = anames[0];

                WXOLE_TRACEOUT("Name " << i << " = " << name.c_str());
                SysFreeString(anames[0]);

                if (defInterface || defEventSink)
                {
                    FuncX func;
                    func.name = name;
                    func.memid = fd->memid;
                    func.hasOut = false;

                    // get Param Names
                    unsigned int maxPNames = fd->cParams + 1;
                    unsigned int nPNames = 0;
                    BSTR *pnames = new BSTR[maxPNames];

                    hret = typeInfo->GetNames(fd->memid, pnames, maxPNames, &nPNames);

                    int pbase = 0;
                    if (fd->cParams < int(nPNames))
                    {
                        pbase++;
                        SysFreeString(pnames[0]);
                    };

                    // params
                    ElemDescToParam(fd->elemdescFunc, func.retType);
                    for (int p = 0; p < fd->cParams; p++)
                    {
                        ParamX param;

                        ElemDescToParam(fd->lprgelemdescParam[p], param);

                        param.name = pnames[pbase + p];
                        SysFreeString(pnames[pbase + p]);

                        param.isOptional = (p > fd->cParams - fd->cParamsOpt);

                        func.hasOut |= (param.IsOut() || param.isPtr);
                        func.params.push_back(param);
                    };
                    delete [] pnames;

                    if (defEventSink)
                    {
                        m_events.push_back(func);
                        m_eventMemberIds[fd->memid] = m_events.size() - 1;
                    }
                    else
                    {
                        if (fd->invkind == INVOKE_FUNC)
                        {
                            m_methods.push_back(func);
                            m_methodNames[func.name] = m_methods.size() - 1;
                        }
                        else
                        {
                            NameMap::iterator it = m_propNames.find(func.name);
                            int idx = -1;
                            if (it == m_propNames.end())
                            {
                                m_props.push_back(PropX());
                                idx = m_props.size() - 1;
                                m_propNames[func.name] = idx;
                                m_props[idx].name = func.name;
                                m_props[idx].memid = func.memid;
                                
                            }
                            else
                                idx = it->second;
                            
                            if (fd->invkind == INVOKE_PROPERTYGET)
                                m_props[idx].type = func.retType;
                            else if (func.params.size() > 0)
                            {
                                m_props[idx].arg = func.params[0];
                                m_props[idx].putByRef = (fd->invkind == INVOKE_PROPERTYPUTREF);
                            };
                        };
                    };
                };
            };

            typeInfo->ReleaseFuncDesc(fd);
        };
    }

    typeInfo->ReleaseTypeAttr(ta);
};

///////////////////////////////////////////////
// Type Info exposure
const wxActiveX::FuncX& wxActiveX::GetEventDesc(int idx) const
{
    wxASSERT(idx >= 0 && idx < GetEventCount());

    return m_events[idx];
};

const wxActiveX::PropX& wxActiveX::GetPropDesc(int idx) const
{
    if (idx < 0 || idx >= GetPropCount())
        throw exception("Property index out of bounds");

    return m_props[idx];
};

const wxActiveX::PropX& wxActiveX::GetPropDesc(const wxString& name) const
{
    NameMap::const_iterator it = m_propNames.find(name);
    if (it == m_propNames.end())
    {
        wxString s;
        s << _T("property <") << name << _T("> not found");
        throw exception(s.mb_str());
    };

    return GetPropDesc(it->second);
};

const wxActiveX::FuncX& wxActiveX::GetMethodDesc(int idx) const
{
    if (idx < 0 || idx >= GetMethodCount())
        throw exception("Method index out of bounds");


    return m_methods[idx];
};


const wxActiveX::FuncX& wxActiveX::GetMethodDesc(const wxString& name) const
{
    NameMap::const_iterator it = m_methodNames.find(name);
    if (it == m_methodNames.end())
    {
        wxString s;
        s << _T("method <") << name << _T("> not found");
        throw exception(s.mb_str());
    };

    return GetMethodDesc(it->second);
};


void wxActiveX::SetProp(MEMBERID name, VARIANTARG& value)
{
    DISPID pids[1] = {DISPID_PROPERTYPUT};
    DISPPARAMS params = {&value, pids, 1, 1};

    EXCEPINFO x;
    memset(&x, 0, sizeof(x));
    unsigned int argErr = 0;

    HRESULT hr = m_Dispatch->Invoke(
        name, 
        IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
        &params, NULL, &x, &argErr);

    WXOLE_WARN(hr, "Invoke Prop(...)");
};

void wxActiveX::SetProp(const wxString &name, const wxVariant &value)
{
    const PropX& prop = GetPropDesc(name);
    if (! prop.CanSet())
    {
        wxString s;
        s << _T("property <") << name << _T("> is readonly");
        throw exception(s.mb_str());
    };

    VARIANT v = {prop.arg.vt};
    VariantToMSWVariant(value, v);
    SetProp(prop.memid, v);
    VariantClear(&v); // this releases any BSTR's etc
};

VARIANT wxActiveX::GetPropAsVariant(MEMBERID name)
{
    VARIANT v;
    VariantInit(&v);

    DISPPARAMS params = {NULL, NULL, 0, 0};

    EXCEPINFO x;
    memset(&x, 0, sizeof(x));
    unsigned int argErr = 0;

    HRESULT hr = m_Dispatch->Invoke(
        name, 
        IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -