convert COM arguments to wx lazily to improve performance and allow calling Invoke/handling events involving parameters which can't be mapped to wx types at all (new GetNativeParameters() method can be used to access them) (closes #9606)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58384 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
bb24f84b70
commit
2ddb8ccf60
@ -174,6 +174,27 @@ protected:
|
||||
void CreateActiveX(REFIID, IUnknown*);
|
||||
};
|
||||
|
||||
///\brief Store native event parameters.
|
||||
///\detail Store OLE 'Invoke' parameters for event handlers that need to access them.
|
||||
/// These are the exact values for the event as they are passed to the wxActiveXContainer.
|
||||
struct wxActiveXEventNativeMSW
|
||||
{
|
||||
DISPID dispIdMember;
|
||||
REFIID riid;
|
||||
LCID lcid;
|
||||
WORD wFlags;
|
||||
DISPPARAMS *pDispParams;
|
||||
VARIANT *pVarResult;
|
||||
EXCEPINFO *pExcepInfo;
|
||||
unsigned int *puArgErr;
|
||||
|
||||
wxActiveXEventNativeMSW
|
||||
(DISPID a_dispIdMember, REFIID a_riid, LCID a_lcid, WORD a_wFlags, DISPPARAMS *a_pDispParams,
|
||||
VARIANT *a_pVarResult, EXCEPINFO *a_pExcepInfo, unsigned int *a_puArgErr)
|
||||
:dispIdMember(a_dispIdMember), riid(a_riid), lcid(a_lcid), wFlags(a_wFlags), pDispParams(a_pDispParams),
|
||||
pVarResult(a_pVarResult), pExcepInfo(a_pExcepInfo), puArgErr(a_puArgErr)
|
||||
{ }
|
||||
};
|
||||
|
||||
// Events
|
||||
class WXDLLIMPEXP_CORE wxActiveXEvent : public wxCommandEvent
|
||||
@ -187,29 +208,27 @@ public:
|
||||
virtual wxEvent *Clone() const
|
||||
{ return new wxActiveXEvent(*this); }
|
||||
|
||||
size_t ParamCount() const
|
||||
{ return m_params.GetCount(); }
|
||||
size_t ParamCount() const;
|
||||
|
||||
wxString ParamType(size_t idx) const
|
||||
{
|
||||
wxASSERT(idx < m_params.GetCount());
|
||||
wxASSERT(idx < ParamCount());
|
||||
return m_params[idx].GetType();
|
||||
}
|
||||
|
||||
wxString ParamName(size_t idx) const
|
||||
{
|
||||
wxASSERT(idx < m_params.GetCount());
|
||||
wxASSERT(idx < ParamCount());
|
||||
return m_params[idx].GetName();
|
||||
}
|
||||
|
||||
wxVariant& operator[] (size_t idx)
|
||||
{
|
||||
wxASSERT(idx < ParamCount());
|
||||
return m_params[idx];
|
||||
}
|
||||
wxVariant& operator[] (size_t idx);
|
||||
|
||||
DISPID GetDispatchId() const
|
||||
{ return m_dispid; }
|
||||
|
||||
wxActiveXEventNativeMSW *GetNativeParameters() const
|
||||
{ return (wxActiveXEventNativeMSW*)GetClientData(); }
|
||||
};
|
||||
|
||||
// #define wxACTIVEX_ID 14001
|
||||
|
@ -22,6 +22,15 @@
|
||||
ActiveX event.
|
||||
@endEventTable
|
||||
|
||||
ActiveX event parameters can get extremely complex and may be beyond the
|
||||
abilities of wxVariant. If 'operator[]' fails, prints an error messages or
|
||||
crashes the application, event handlers should use GetNativeParameters()
|
||||
instead to obtain the original event information.
|
||||
Calls to operator[] and GetNativeParmeters() can be mixed. It is valid
|
||||
to handle some parameters of an event with operator[] and others directly
|
||||
through GetNativeParameters(). It is \b not valid however to manipulate
|
||||
the same parameter using both approaches at the same time.
|
||||
|
||||
@onlyfor{wxmsw}
|
||||
|
||||
@library{wxcore}
|
||||
@ -55,6 +64,16 @@ public:
|
||||
Obtains the actual parameter value specified by idx.
|
||||
*/
|
||||
wxVariant operator[](size_t idx);
|
||||
|
||||
/**
|
||||
Obtain the original MSW parameters for the event.
|
||||
Event handlers can use this information to handle complex event parameters
|
||||
that are beyond the scope of wxVariant.
|
||||
The information returned here is the information passed to the original
|
||||
'Invoke' method call.
|
||||
\return a pointer to a struct containing the original MSW event parameters
|
||||
*/
|
||||
wxActiveXEventNativeMSW *GetNativeParameters() const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -694,6 +694,14 @@ private:
|
||||
friend bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc);
|
||||
|
||||
public:
|
||||
|
||||
// a pointer to this static variable is used as an 'invalid_entry_marker'
|
||||
// wxVariants containing a void* to this variables are 'empty' in the sense
|
||||
// that the actual ActiveX OLE parameter has not been converted and inserted
|
||||
// into m_params.
|
||||
static const int ptr_invalid_entry_marker = 0;
|
||||
static wxVariant g_invalid_entry_marker;
|
||||
|
||||
wxActiveXEvents(wxActiveXContainer *ax) : m_activeX(ax), m_haveCustomId(false) {}
|
||||
wxActiveXEvents(wxActiveXContainer *ax, REFIID iid) : m_activeX(ax), m_customId(iid), m_haveCustomId(true) {}
|
||||
virtual ~wxActiveXEvents()
|
||||
@ -717,11 +725,11 @@ public:
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID WXUNUSED(riid),
|
||||
LCID WXUNUSED(lcid),
|
||||
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid,
|
||||
LCID lcid,
|
||||
WORD wFlags, DISPPARAMS * pDispParams,
|
||||
VARIANT * WXUNUSED(pVarResult), EXCEPINFO * WXUNUSED(pExcepInfo),
|
||||
unsigned int * WXUNUSED(puArgErr))
|
||||
VARIANT * pVarResult, EXCEPINFO * pExcepInfo,
|
||||
unsigned int * puArgErr)
|
||||
{
|
||||
if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
|
||||
return E_NOTIMPL;
|
||||
@ -733,31 +741,37 @@ public:
|
||||
// Dispatch Event
|
||||
wxActiveXEvent event;
|
||||
event.SetEventType(wxEVT_ACTIVEX);
|
||||
// Create an empty list of Variants
|
||||
// Note that the event parameters use lazy evaluation
|
||||
// They are not actually created until wxActiveXEvent::operator[] is called
|
||||
event.m_params.NullList();
|
||||
event.m_dispid = dispIdMember;
|
||||
|
||||
// arguments
|
||||
if (pDispParams)
|
||||
{
|
||||
for (DWORD i = pDispParams->cArgs; i > 0; i--)
|
||||
{
|
||||
VARIANTARG& va = pDispParams->rgvarg[i-1];
|
||||
wxVariant vx;
|
||||
// save the native (MSW) event parameters for event handlers that need to access them
|
||||
// this can be done on the stack since wxActiveXEvent is also allocated on the stack
|
||||
wxActiveXEventNativeMSW eventParameters(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
|
||||
event.SetClientData(&eventParameters);
|
||||
|
||||
// vx.SetName(px.name);
|
||||
wxConvertOleToVariant(va, vx);
|
||||
event.m_params.Append(vx);
|
||||
}
|
||||
}
|
||||
// The event parameters are not copied to event.m_params until they are actually
|
||||
// referenced in wxActiveXEvent::operator[]
|
||||
// This increases performance and avoids error messages and/or crashes
|
||||
// when the event has parameters that are not (yet or never) supported
|
||||
// by wxConvertOleToVariant
|
||||
|
||||
// process the events from the activex method
|
||||
m_activeX->ProcessEvent(event);
|
||||
m_activeX->ProcessEvent(event);
|
||||
for (DWORD i = 0; i < pDispParams->cArgs; i++)
|
||||
{
|
||||
VARIANTARG& va = pDispParams->rgvarg[i];
|
||||
wxVariant& vx =
|
||||
event.m_params[pDispParams->cArgs - i - 1];
|
||||
wxConvertVariantToOle(vx, va);
|
||||
size_t params_index = pDispParams->cArgs - i - 1;
|
||||
if (params_index < event.m_params.GetCount()) {
|
||||
wxVariant &vx = event.m_params[params_index];
|
||||
// copy the result back to pDispParams only if the event has been accessed
|
||||
// i.e. if vx != g_invalid_entry_marker
|
||||
if (!vx.IsType(wxActiveXEvents::g_invalid_entry_marker.GetType()) || vx!=g_invalid_entry_marker) {
|
||||
VARIANTARG& va = pDispParams->rgvarg[i];
|
||||
wxConvertVariantToOle(vx, va);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(event.GetSkipped())
|
||||
@ -767,6 +781,46 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
wxVariant wxActiveXEvents::g_invalid_entry_marker((void*)&wxActiveXEvents::ptr_invalid_entry_marker);
|
||||
|
||||
size_t wxActiveXEvent::ParamCount() const
|
||||
{
|
||||
wxActiveXEventNativeMSW *native=GetNativeParameters();
|
||||
// 'native' will always be != if the event has been created
|
||||
// for an actual active X event.
|
||||
// But it may be zero if the event has been created by wx program code.
|
||||
if (native)
|
||||
return native->pDispParams ? native->pDispParams->cArgs : 0;
|
||||
|
||||
return m_params.GetCount();
|
||||
}
|
||||
|
||||
wxVariant &wxActiveXEvent::operator [](size_t idx)
|
||||
{
|
||||
wxASSERT(idx < ParamCount());
|
||||
wxActiveXEventNativeMSW *native=GetNativeParameters();
|
||||
// 'native' will always be != if the event has been created
|
||||
// for an actual active X event.
|
||||
// But it may be zero if the event has been created by wx program code.
|
||||
if (native) {
|
||||
while (m_params.GetCount()<=idx) {
|
||||
m_params.Append(wxActiveXEvents::g_invalid_entry_marker);
|
||||
}
|
||||
wxVariant &vx(m_params[idx]);
|
||||
if (vx.IsType(wxActiveXEvents::g_invalid_entry_marker.GetType()) && vx==wxActiveXEvents::g_invalid_entry_marker) {
|
||||
// copy the _real_ parameter into this one
|
||||
// NOTE: m_params stores the parameters in *reverse* order.
|
||||
// Whyever, but this was the case in the original implementation of
|
||||
// wxActiveXEvents::Invoke
|
||||
// Keep this convention.
|
||||
VARIANTARG& va = native->pDispParams->rgvarg[ native->pDispParams->cArgs - idx - 1 ];
|
||||
wxConvertOleToVariant(va, vx);
|
||||
}
|
||||
return vx;
|
||||
}
|
||||
return m_params[idx];
|
||||
}
|
||||
|
||||
bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc)
|
||||
{
|
||||
if (self->m_haveCustomId && IsEqualIID(iid, self->m_customId))
|
||||
|
Loading…
Reference in New Issue
Block a user