📄 wxactivex.cpp
字号:
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,
¶ms, 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 + -