diff --git a/wxPython/contrib/iewin/IEHtmlWin.cpp b/wxPython/contrib/iewin/IEHtmlWin.cpp index 5aa4a8f87f..6214694d96 100644 --- a/wxPython/contrib/iewin/IEHtmlWin.cpp +++ b/wxPython/contrib/iewin/IEHtmlWin.cpp @@ -37,7 +37,7 @@ private: public: FS_DWebBrowserEvents2(wxIEHtmlWin *iewin) : m_iewin(iewin) {} - ~FS_DWebBrowserEvents2() + virtual ~FS_DWebBrowserEvents2() { } diff --git a/wxPython/contrib/iewin/wxactivex.cpp b/wxPython/contrib/iewin/wxactivex.cpp index ac6df87513..779042ed0b 100644 --- a/wxPython/contrib/iewin/wxactivex.cpp +++ b/wxPython/contrib/iewin/wxactivex.cpp @@ -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 ActiveXEventMap; -static ActiveXEventMap sg_eventMap; +typedef map 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 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()) diff --git a/wxPython/contrib/iewin/wxactivex.h b/wxPython/contrib/iewin/wxactivex.h index f62ac9830e..36c86538b9 100644 --- a/wxPython/contrib/iewin/wxactivex.h +++ b/wxPython/contrib/iewin/wxactivex.h @@ -261,60 +261,13 @@ class wxOleInit class wxActiveX : public wxWindow { public: - wxActiveX(wxWindow * parent, REFCLSID clsid, wxWindowID id = -1, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = 0, - const wxString& name = wxPanelNameStr); - wxActiveX(wxWindow * parent, wxString progId, wxWindowID id = -1, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = 0, - const wxString& name = wxPanelNameStr); - virtual ~wxActiveX(); - - void CreateActiveX(REFCLSID clsid); - void CreateActiveX(LPOLESTR progId); - - void GetTypeInfo(); - void GetTypeInfo(ITypeInfo *ti, bool defEventSink); - - HRESULT ConnectAdvise(REFIID riid, IUnknown *eventSink); - - void OnSize(wxSizeEvent&); - void OnSetFocus(wxFocusEvent&); - void OnKillFocus(wxFocusEvent&); - - DECLARE_EVENT_TABLE(); - -protected: - friend class FrameSite; - friend class wxActiveXEvents; - - typedef wxAutoOleInterface wxOleConnectionPoint; - typedef pair wxOleConnection; - typedef vector wxOleConnectionArray; - - wxAutoOleInterface m_clientSite; - wxAutoOleInterface m_ActiveX; - wxAutoOleInterface m_oleObject; - wxAutoOleInterface m_oleInPlaceObject; - wxAutoOleInterface - - m_oleInPlaceActiveObject; - wxAutoOleInterface m_docView; - HWND m_oleObjectHWND; - bool m_bAmbientUserMode; - DWORD m_docAdviseCookie; - wxOleConnectionArray m_connections; - - HRESULT AmbientPropertyChanged(DISPID dispid); - + //////////////////////////////////////// // type stuff class ParamX // refer to ELEMDESC, IDLDESC in MSDN { public: USHORT flags; + bool isPtr, isSafeArray; VARTYPE vt; wxString name; @@ -338,13 +291,72 @@ protected: typedef vector FuncXArray; typedef map MemberIdList; + wxActiveX(wxWindow * parent, REFCLSID clsid, wxWindowID id = -1, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxString& name = wxPanelNameStr); + wxActiveX(wxWindow * parent, wxString progId, wxWindowID id = -1, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxString& name = wxPanelNameStr); + virtual ~wxActiveX(); + + void CreateActiveX(REFCLSID clsid); + void CreateActiveX(LPOLESTR progId); + + // expose type info + inline int GetEventCount() const {return m_events.size();} + const FuncX& GetEvent(int idx) const; + + HRESULT ConnectAdvise(REFIID riid, IUnknown *eventSink); + + void OnSize(wxSizeEvent&); + void OnPaint(wxPaintEvent& event); + void OnMouse(wxMouseEvent& event); + void OnSetFocus(wxFocusEvent&); + void OnKillFocus(wxFocusEvent&); + + DECLARE_EVENT_TABLE(); + +protected: + friend class FrameSite; + friend class wxActiveXEvents; + + typedef wxAutoOleInterface wxOleConnectionPoint; + typedef pair wxOleConnection; + typedef vector wxOleConnectionArray; + + wxAutoOleInterface m_clientSite; + wxAutoOleInterface m_ActiveX; + wxAutoOleInterface m_oleObject; + wxAutoOleInterface m_oleInPlaceObject; + wxAutoOleInterface + + m_oleInPlaceActiveObject; + wxAutoOleInterface m_docView; + wxAutoOleInterface m_viewObject; + HWND m_oleObjectHWND; + bool m_bAmbientUserMode; + DWORD m_docAdviseCookie; + wxOleConnectionArray m_connections; + + HRESULT AmbientPropertyChanged(DISPID dispid); + + void GetTypeInfo(); + void GetTypeInfo(ITypeInfo *ti, bool defEventSink); + + // events FuncXArray m_events; MemberIdList m_eventsIdx; + + long MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam); }; // events -class wxActiveXEvent : public wxNotifyEvent +class wxActiveXEvent : public wxCommandEvent { private: friend class wxActiveXEvents; @@ -355,18 +367,23 @@ public: virtual wxEvent *Clone() const { return new wxActiveXEvent(*this); } + wxString EventName(); int ParamCount() const; + wxString ParamType(int idx); + wxString ParamName(int idx); wxVariant operator[] (int idx) const; wxVariant& operator[] (int idx); wxVariant operator[] (wxString name) const; wxVariant& operator[] (wxString name); }; -const wxEventType& RegisterActiveXEvent(wxChar *eventName); +const wxEventType& RegisterActiveXEvent(const wxChar *eventName); +const wxEventType& RegisterActiveXEvent(DISPID event); typedef void (wxEvtHandler::*wxActiveXEventFunction)(wxActiveXEvent&); #define EVT_ACTIVEX(id, eventName, fn) DECLARE_EVENT_TABLE_ENTRY(RegisterActiveXEvent(wxT(eventName)), id, -1, (wxObjectEventFunction) (wxEventFunction) (wxActiveXEventFunction) & fn, (wxObject *) NULL ), +#define EVT_ACTIVEX_DISPID(id, eventDispId, fn) DECLARE_EVENT_TABLE_ENTRY(RegisterActiveXEvent(eventDispId), id, -1, (wxObjectEventFunction) (wxEventFunction) (wxActiveXEventFunction) & fn, (wxObject *) NULL ), //util bool MSWVariantToVariant(VARIANTARG& va, wxVariant& vx);