New wxActiveX code

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@16419 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2002-08-08 18:29:59 +00:00
parent f6f98ecccd
commit e98fc45512
3 changed files with 362 additions and 123 deletions

View File

@@ -24,9 +24,11 @@ using namespace std;
//////////////////////////////////////////////////////////////////////
BEGIN_EVENT_TABLE(wxActiveX, wxWindow)
EVT_SIZE(OnSize)
EVT_SET_FOCUS(OnSetFocus)
EVT_KILL_FOCUS(OnKillFocus)
EVT_SIZE(wxActiveX::OnSize)
EVT_PAINT(wxActiveX::OnPaint)
EVT_MOUSE_EVENTS(wxActiveX::OnMouse)
EVT_SET_FOCUS(wxActiveX::OnSetFocus)
EVT_KILL_FOCUS(wxActiveX::OnKillFocus)
END_EVENT_TABLE()
class wxActiveX;
@@ -47,7 +49,7 @@ private:
public:
FrameSite(wxActiveX * win);
~FrameSite();
virtual ~FrameSite();
//IOleWindow
STDMETHODIMP GetWindow(HWND*);
@@ -269,6 +271,10 @@ void wxActiveX::CreateActiveX(REFCLSID clsid)
hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX);
wxASSERT(SUCCEEDED(hret));
// get IViewObject Interface
hret = m_viewObject.QueryInterface(IID_IViewObject, m_ActiveX);
wxASSERT(SUCCEEDED(hret));
// document advise
m_docAdviseCookie = 0;
hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie);
@@ -372,8 +378,49 @@ struct less_wxStringI
};
};
typedef map<wxString, wxEventType *, less_wxStringI> ActiveXEventMap;
static ActiveXEventMap sg_eventMap;
typedef map<wxString, wxEventType *, less_wxStringI> ActiveXNamedEventMap;
static ActiveXNamedEventMap sg_NamedEventMap;
const wxEventType& RegisterActiveXEvent(const wxChar *eventName)
{
wxString ev = eventName;
ActiveXNamedEventMap::iterator it = sg_NamedEventMap.find(ev);
if (it == sg_NamedEventMap.end())
{
wxEventType *et = new wxEventType(wxNewEventType());
sg_NamedEventMap[ev] = et;
return *et;
};
return *(it->second);
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Map of Event DISPID's to eventTypes
// created dynamically at run time in:
// EVT_ACTIVEX(eventName, id, fn)
// we map the pointer to them so that:
// const wxEventType& RegisterActiveXEvent(wxString eventName);
// 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
@@ -381,31 +428,26 @@ class ActiveXEventMapFlusher
public:
~ActiveXEventMapFlusher()
{
ActiveXEventMap::iterator it = sg_eventMap.end();
while (it != sg_eventMap.end())
// Named events
ActiveXNamedEventMap::iterator it = sg_NamedEventMap.end();
while (it != sg_NamedEventMap.end())
{
delete it->second;
it++;
};
// DISPID events
ActiveXDISPIDEventMap::iterator dit = sg_dispIdEventMap.end();
while (dit != sg_dispIdEventMap.end())
{
delete dit->second;
dit++;
};
};
};
static ActiveXEventMapFlusher s_dummyActiveXEventMapFlusher;
const wxEventType& RegisterActiveXEvent(wxChar *eventName)
{
wxString ev = eventName;
ActiveXEventMap::iterator it = sg_eventMap.find(ev);
if (it == sg_eventMap.end())
{
wxEventType *et = new wxEventType(wxNewEventType());
sg_eventMap[ev] = et;
return *et;
};
return *(it->second);
};
//////////////////////////////////////////////////////
bool MSWVariantToVariant(VARIANTARG& va, wxVariant& vx)
@@ -487,7 +529,7 @@ private:
public:
wxActiveXEvents(wxActiveX *ax) : m_activeX(ax) {}
~wxActiveXEvents()
virtual ~wxActiveXEvents()
{
}
@@ -508,6 +550,56 @@ public:
};
void DispatchEvent(int eventIdx, const wxEventType& eventType, DISPPARAMS * pDispParams)
{
wxASSERT(eventIdx >= 0 && eventIdx < int(m_activeX->m_events.size()));
wxActiveX::FuncX &func = m_activeX->m_events[eventIdx];
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 = min(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 = min(func.params.size(), pDispParams->cArgs);
m_activeX->GetParent()->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->GetParent()->AddPendingEvent(event);
};
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS * pDispParams,
@@ -517,60 +609,33 @@ public:
if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
return E_NOTIMPL;
// map dispid to name
wxASSERT(m_activeX);
// map dispid to m_eventsIdx
wxActiveX::MemberIdList::iterator mid = m_activeX->m_eventsIdx.find((MEMBERID) dispIdMember);
if (mid == m_activeX->m_eventsIdx.end())
return S_OK;
int idx = mid->second;
int funcIdx = mid->second;
wxActiveX::FuncX &func = m_activeX->m_events[funcIdx];
wxActiveX::FuncX &func = m_activeX->m_events[idx];
ActiveXEventMap::iterator it = sg_eventMap.find(func.name);
if (it == sg_eventMap.end())
return S_OK;
wxActiveXEvent event;
event.SetId(m_activeX->GetId());
event.SetEventType(*(it->second));
event.m_params.NullList();
// arguments
if (pDispParams)
// try to find dispid event
ActiveXDISPIDEventMap::iterator dit = sg_dispIdEventMap.find(dispIdMember);
if (dit != sg_dispIdEventMap.end())
{
// cdecl call
for (int i = pDispParams->cArgs - 1; i >= 0; i--)
{
VARIANTARG& va = pDispParams->rgvarg[i];
wxActiveX::ParamX &px = func.params[pDispParams->cArgs - i - 1];
wxVariant vx;
MSWVariantToVariant(va, vx);
vx.SetName(px.name);
event.m_params.Append(vx);
};
// Dispatch Event
DispatchEvent(funcIdx, *(dit->second), pDispParams);
return S_OK;
};
if (func.hasOut)
{
m_activeX->GetParent()->ProcessEvent(event);
for (unsigned int i = 0; i < pDispParams->cArgs; i++)
{
VARIANTARG& va = pDispParams->rgvarg[i];
wxActiveX::ParamX &px = func.params[pDispParams->cArgs - i - 1];
if (px.IsOut())
{
wxVariant& vx = event.m_params[pDispParams->cArgs - i - 1];
VariantToMSWVariant(vx, va);
};
};
}
else
m_activeX->GetParent()->AddPendingEvent(event);
// try named event
ActiveXNamedEventMap::iterator nit = sg_NamedEventMap.find(func.name);
if (nit == sg_NamedEventMap.end())
return S_OK;
// Dispatch Event
DispatchEvent(funcIdx, *(nit->second), pDispParams);
return S_OK;
}
};
@@ -581,12 +646,30 @@ DEFINE_OLE_TABLE(wxActiveXEvents)
OLE_INTERFACE(IID_IDispatch, IDispatch)
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) const
@@ -764,18 +847,25 @@ void wxActiveX::GetTypeInfo(ITypeInfo *ti, bool defEventSink)
BSTR *pnames = new BSTR[maxPNames];
hret = typeInfo->GetNames(fd->memid, pnames, maxPNames, &nPNames);
wxASSERT(int(nPNames) >= fd->cParams + 1);
SysFreeString(pnames[0]);
// params
for (int p = 0; p < fd->cParams; p++)
{
ParamX param;
param.flags = fd->lprgelemdescParam[p].idldesc.wIDLFlags;
param.vt = fd->lprgelemdescParam[p].tdesc.vt;
param.isPtr = (param.vt == VT_PTR);
param.isSafeArray = (param.vt == VT_SAFEARRAY);
if (param.isPtr || param.isSafeArray)
param.vt = fd->lprgelemdescParam[p].tdesc.lptdesc->vt;
param.name = pnames[p + 1];
SysFreeString(pnames[p + 1]);
func.hasOut |= param.IsOut();
func.hasOut |= (param.IsOut() || param.isPtr);
func.params.push_back(param);
};
delete [] pnames;
@@ -792,6 +882,17 @@ void wxActiveX::GetTypeInfo(ITypeInfo *ti, bool defEventSink)
typeInfo->ReleaseTypeAttr(ta);
};
///////////////////////////////////////////////
// Type Info exposure
const wxActiveX::FuncX& wxActiveX::GetEvent(int idx) const
{
wxASSERT(idx >= 0 && idx < GetEventCount());
return m_events[idx];
};
///////////////////////////////////////////////
HRESULT wxActiveX::ConnectAdvise(REFIID riid, IUnknown *events)
{
wxOleConnectionPoint cp;
@@ -865,9 +966,6 @@ void wxActiveX::OnSize(wxSizeEvent& event)
if (w <= 0 && h <= 0)
return;
if (m_oleInPlaceObject.Ok())
m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
// extents are in HIMETRIC units
if (m_oleObject.Ok())
{
@@ -880,8 +978,132 @@ void wxActiveX::OnSize(wxSizeEvent& event)
if (sz2.cx != sz.cx || sz.cy != sz2.cy)
m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
};
if (m_oleInPlaceObject.Ok())
m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
}
void wxActiveX::OnPaint(wxPaintEvent& event)
{
wxLogTrace(wxT("repainting activex win"));
wxPaintDC dc(this);
dc.BeginDrawing();
int w, h;
GetSize(&w, &h);
RECT posRect;
posRect.left = 0;
posRect.top = 0;
posRect.right = w;
posRect.bottom = h;
// Draw only when control is windowless or deactivated
if (m_viewObject)
{
::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
{
RECTL *prcBounds = (RECTL *) &posRect;
m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
(HDC)dc.GetHDC(), prcBounds, NULL, NULL, 0);
}
}
else
{
dc.SetBrush(*wxRED_BRUSH);
dc.DrawRectangle(0, 0, w, h);
dc.SetBrush(wxNullBrush);
}
dc.EndDrawing();
}
void wxActiveX::OnMouse(wxMouseEvent& event)
{
if (m_oleObjectHWND == NULL)
{
wxLogTrace(wxT("no oleInPlaceObject"));
event.Skip();
return;
}
wxLogTrace(wxT("mouse event"));
UINT msg = 0;
WPARAM wParam = 0;
LPARAM lParam = 0;
LRESULT lResult = 0;
if (event.m_metaDown)
wParam |= MK_CONTROL;
if (event.m_shiftDown)
wParam |= MK_SHIFT;
if (event.m_leftDown)
wParam |= MK_LBUTTON;
if (event.m_middleDown)
wParam |= MK_MBUTTON;
if (event.m_rightDown)
wParam |= MK_RBUTTON;
lParam = event.m_x << 16;
lParam |= event.m_y;
if (event.LeftDown())
msg = WM_LBUTTONDOWN;
else if (event.LeftDClick())
msg = WM_LBUTTONDBLCLK;
else if (event.LeftUp())
msg = WM_LBUTTONUP;
else if (event.MiddleDown())
msg = WM_MBUTTONDOWN;
else if (event.MiddleDClick())
msg = WM_MBUTTONDBLCLK;
else if (event.MiddleUp())
msg = WM_MBUTTONUP;
else if (event.RightDown())
msg = WM_RBUTTONDOWN;
else if (event.RightDClick())
msg = WM_RBUTTONDBLCLK;
else if (event.RightUp())
msg = WM_RBUTTONUP;
else if (event.Moving() || event.Dragging())
msg = WM_MOUSEMOVE;
wxString log;
if (msg == 0)
{
wxLogTrace(wxT("no message"));
event.Skip(); return;
};
if (!::SendMessage(m_oleObjectHWND, msg, wParam, lParam))
{
wxLogTrace(wxT("msg not delivered"));
event.Skip();
return;
};
wxLogTrace(wxT("msg sent"));
}
long wxActiveX::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{
if (m_oleObjectHWND == NULL)
return wxWindow::MSWWindowProc(nMsg, wParam, lParam);
switch(nMsg)
{
case WM_CHAR:
case WM_DEADCHAR:
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSCHAR:
case WM_SYSDEADCHAR:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
PostMessage(m_oleObjectHWND, nMsg, wParam, lParam);
default:
return wxWindow::MSWWindowProc(nMsg, wParam, lParam);
};
};
void wxActiveX::OnSetFocus(wxFocusEvent& event)
{
if (m_oleInPlaceActiveObject.Ok())