📄 wxactivex.cpp
字号:
// can return a const reference, which is neccessary for event tables
typedef map<DISPID, wxEventType *> ActiveXDISPIDEventMap;
static ActiveXDISPIDEventMap sg_dispIdEventMap;
const wxEventType& RegisterActiveXEvent(DISPID event)
{
ActiveXDISPIDEventMap::iterator it = sg_dispIdEventMap.find(event);
if (it == sg_dispIdEventMap.end())
{
wxEventType *et = new wxEventType(wxNewEventType());
sg_dispIdEventMap[event] = et;
return *et;
};
return *(it->second);
};
// one off class for automatic freeing of activeX eventtypes
class ActiveXEventMapFlusher
{
public:
~ActiveXEventMapFlusher()
{
// Named events
ActiveXNamedEventMap::iterator it = sg_NamedEventMap.end();
while (it != sg_NamedEventMap.end())
{
delete it->second;
it++;
};
sg_NamedEventMap.clear();
// DISPID events
ActiveXDISPIDEventMap::iterator dit = sg_dispIdEventMap.end();
while (dit != sg_dispIdEventMap.end())
{
delete dit->second;
dit++;
};
sg_dispIdEventMap.clear();
};
};
static ActiveXEventMapFlusher s_dummyActiveXEventMapFlusher;
//////////////////////////////////////////////////////
VARTYPE wxTypeToVType(const wxVariant& v)
{
wxString type = v.GetType();
if (type == wxT("bool"))
return VT_BOOL;
else if (type == wxT("char"))
return VT_I1;
else if (type == wxT("datetime"))
return VT_DATE;
else if (type == wxT("double"))
return VT_R8;
else if (type == wxT("list"))
return VT_ARRAY;
else if (type == wxT("long"))
return VT_I4;
else if (type == wxT("string"))
return VT_BSTR;
else if (type == wxT("stringlist"))
return VT_ARRAY;
else if (type == wxT("date"))
return VT_DATE;
else if (type == wxT("time"))
return VT_DATE;
else if (type == wxT("void*"))
return VT_VOID | VT_BYREF;
else
return VT_NULL;
};
bool wxDateTimeToDATE(wxDateTime dt, DATE& d)
{
SYSTEMTIME st;
memset(&st, 0, sizeof(st));
st.wYear = dt.GetYear();
st.wMonth = dt.GetMonth() + 1;
st.wDay = dt.GetDay();
st.wHour = dt.GetHour();
st.wMinute = dt.GetMinute();
st.wSecond = dt.GetSecond();
st.wMilliseconds = dt.GetMillisecond();
return SystemTimeToVariantTime(&st, &d) != FALSE;
};
bool wxDateTimeToVariant(wxDateTime dt, VARIANTARG& va)
{
return wxDateTimeToDATE(dt, va.date);
};
bool DATEToWxDateTime(DATE date, wxDateTime& dt)
{
SYSTEMTIME st;
if (! VariantTimeToSystemTime(date, &st))
return false;
dt = wxDateTime(
st.wDay,
wxDateTime::Month(int(wxDateTime::Jan) + st.wMonth - 1),
st.wYear,
st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
return true;
};
bool VariantToWxDateTime(VARIANTARG va, wxDateTime& dt)
{
HRESULT hr = VariantChangeType(&va, &va, 0, VT_DATE);
if (! SUCCEEDED(hr))
return false;
return DATEToWxDateTime(va.date, dt);
};
bool MSWVariantToVariant(VARIANTARG& va, wxVariant& vx)
{
bool byRef = false;
VARTYPE vt = va.vt;
if (vt & VT_ARRAY)
return false; // don't support arrays yet
if (vt & VT_BYREF)
{
byRef = true;
vt &= ~(VT_BYREF);
};
switch(vt)
{
case VT_VARIANT:
if (byRef)
return MSWVariantToVariant(*va.pvarVal, vx);
else
{
VARIANT tmp = va;
VariantChangeType(&tmp, &tmp, 0, wxTypeToVType(vx));
bool rc = MSWVariantToVariant(tmp, vx);
VariantClear(&tmp);
return rc;
};
// 1 byte chars
case VT_I1:
case VT_UI1:
if (byRef)
vx = (char) *va.pbVal;
else
vx = (char) va.bVal;
return true;
// 2 byte shorts
case VT_I2:
case VT_UI2:
if (byRef)
vx = (long) *va.puiVal;
else
vx = (long) va.uiVal;
return true;
// 4 bytes longs
case VT_I4:
case VT_UI4:
case VT_INT:
case VT_UINT:
case VT_ERROR:
if (byRef)
vx = (long) *va.pulVal;
else
vx = (long) va.ulVal;
return true;
// 4 byte floats
case VT_R4:
if (byRef)
vx = *va.pfltVal;
else
vx = va.fltVal;
return true;
// 8 byte doubles
case VT_R8:
if (byRef)
vx = *va.pdblVal;
else
vx = va.dblVal;
return true;
case VT_BOOL:
if (byRef)
vx = (*va.pboolVal ? true : false);
else
vx = (va.boolVal ? true : false);
return true;
case VT_CY:
vx.MakeNull();
return false; // what the hell is a CY ?
case VT_DECIMAL:
{
double d = 0;
HRESULT hr;
if (byRef)
hr = VarR8FromDec(va.pdecVal, &d);
else
hr = VarR8FromDec(&va.decVal, &d);
vx = d;
return SUCCEEDED(hr);
};
case VT_DATE:
{
wxDateTime dt;
bool rc = false;
if (byRef)
rc = DATEToWxDateTime(*va.pdate, dt);
else
rc = VariantToWxDateTime(va, dt);
vx = dt;
return rc;
};
case VT_BSTR:
if (byRef)
vx = wxString(*va.pbstrVal);
else
vx = wxString(va.bstrVal);
return true;
case VT_UNKNOWN: // should do a custom wxVariantData for this
if (byRef)
vx = (void *) *va.ppunkVal;
else
vx = (void *) va.punkVal;
return false;
case VT_DISPATCH: // should do a custom wxVariantData for this
if (byRef)
vx = (void *) *va.ppdispVal;
else
vx = (void *) va.pdispVal;
return false;
default:
vx.MakeNull();
return false;
};
};
bool VariantToMSWVariant(const wxVariant& vx, VARIANTARG& va)
{
bool byRef = false;
VARTYPE vt = va.vt;
if (vt & VT_ARRAY)
return false; // don't support arrays yet
if (vt & VT_BYREF)
{
byRef = true;
vt &= ~(VT_BYREF);
};
switch(vt)
{
case VT_VARIANT:
if (byRef)
return VariantToMSWVariant(vx, *va.pvarVal);
else
{
va.vt = wxTypeToVType(vx);
return VariantToMSWVariant(vx, va);
};
// 1 byte chars
case VT_I1:
case VT_UI1:
if (byRef)
*va.pbVal = (char) vx;
else
va.bVal = (char) vx;
return true;
// 2 byte shorts
case VT_I2:
case VT_UI2:
if (byRef)
*va.puiVal = (long) vx;
else
va.uiVal = (long) vx;
return true;
// 4 bytes longs
case VT_I4:
case VT_UI4:
case VT_INT:
case VT_UINT:
case VT_ERROR:
if (byRef)
*va.pulVal = (long) vx;
else
va.ulVal = (long) vx;
return true;
// 4 byte floats
case VT_R4:
if (byRef)
*va.pfltVal = (double) vx;
else
va.fltVal = (double) vx;
return true;
// 8 byte doubles
case VT_R8:
if (byRef)
*va.pdblVal = (double) vx;
else
va.dblVal = (double) vx;
return true;
case VT_BOOL:
if (byRef)
*va.pboolVal = ((bool) vx) ? TRUE : FALSE;
else
va.boolVal = ((bool) vx) ? TRUE : FALSE;
return true;
case VT_CY:
return false; // what the hell is a CY ?
case VT_DECIMAL:
if (byRef)
return SUCCEEDED(VarDecFromR8(vx, va.pdecVal));
else
return SUCCEEDED(VarDecFromR8(vx, &va.decVal));
case VT_DATE:
if (byRef)
return wxDateTimeToDATE(vx, *va.pdate);
else
return wxDateTimeToVariant(vx,va);
case VT_BSTR:
if (byRef)
*va.pbstrVal = SysAllocString(vx.GetString().wc_str(wxConvUTF8));
else
va.bstrVal = SysAllocString(vx.GetString().wc_str(wxConvUTF8));
return true;
case VT_UNKNOWN: // should do a custom wxVariantData for this
if (byRef)
*va.ppunkVal = (IUnknown *) (void *) vx;
else
va.punkVal = (IUnknown *) (void *) vx;
return false;
case VT_DISPATCH: // should do a custom wxVariantData for this
if (byRef)
*va.ppdispVal = (IDispatch *) (void *) vx;
else
va.pdispVal = (IDispatch *) (void *) vx;
return false;
default:
return false;
};
};
IMPLEMENT_CLASS(wxActiveXEvent, wxCommandEvent)
class wxActiveXEvents : public IDispatch
{
private:
DECLARE_OLE_UNKNOWN(wxActiveXEvents);
wxActiveX *m_activeX;
IID m_customId;
bool m_haveCustomId;
friend bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc);
public:
wxActiveXEvents(wxActiveX *ax) : m_activeX(ax), m_haveCustomId(false) {}
wxActiveXEvents(wxActiveX *ax, REFIID iid) : m_activeX(ax), m_haveCustomId(true), m_customId(iid) {}
virtual ~wxActiveXEvents()
{
}
//IDispatch
STDMETHODIMP GetIDsOfNames(REFIID r, OLECHAR** o, unsigned int i, LCID l, DISPID* d)
{
return E_NOTIMPL;
};
STDMETHODIMP GetTypeInfo(unsigned int i, LCID l, ITypeInfo** t)
{
return E_NOTIMPL;
};
STDMETHODIMP GetTypeInfoCount(unsigned int* i)
{
return E_NOTIMPL;
};
void DispatchEvent(wxActiveX::FuncX &func, const wxEventType& eventType, DISPPARAMS * pDispParams)
{
wxActiveXEvent event;
event.SetId(m_activeX->GetId());
event.SetEventType(eventType);
event.m_params.NullList();
event.m_params.SetName(func.name);
// arguments
if (pDispParams)
{
// cdecl call
// sometimes the pDispParams does not match the param info for a activex control
int nArg = wxMin(func.params.size(), pDispParams->cArgs);
for (int i = nArg - 1; i >= 0; i--)
{
VARIANTARG& va = pDispParams->rgvarg[i];
wxActiveX::ParamX &px = func.params[nArg - i - 1];
wxVariant vx;
vx.SetName(px.name);
MSWVariantToVariant(va, vx);
event.m_params.Append(vx);
};
};
if (func.hasOut)
{
int nArg = wxMin(func.params.size(), pDispParams->cArgs);
m_activeX->GetEventHandler()->ProcessEvent(event);
for (int i = 0; i < nArg; i++)
{
VARIANTARG& va = pDispParams->rgvarg[i];
wxActiveX::ParamX &px = func.params[nArg - i - 1];
if (px.IsOut())
{
wxVariant& vx = event.m_params[nArg - i - 1];
VariantToMSWVariant(vx, va);
};
};
}
else
m_activeX->GetEventHandler()->AddPendingEvent(event);
};
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS * pDispParams,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -