X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/811712d820a6c3461b8cd4a1f5322d4d1a76f0da..3eac0818ff869f347e7fe3f745079624f3669b57:/wxPython/contrib/iewin/wxactivex.cpp?ds=inline diff --git a/wxPython/contrib/iewin/wxactivex.cpp b/wxPython/contrib/iewin/wxactivex.cpp index 9d4a0f2b3b..a77919344f 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*); @@ -207,7 +209,7 @@ wxActiveX::wxActiveX(wxWindow * parent, wxString progId, wxWindowID id, { m_bAmbientUserMode = true; m_docAdviseCookie = 0; - CreateActiveX((LPOLESTR) (const wchar_t*)progId.wc_str(wxConvUTF8)); + CreateActiveX((LPOLESTR) (const wchar_t *) progId.wc_str(wxConvUTF8)); } wxActiveX::~wxActiveX() @@ -268,7 +270,21 @@ void wxActiveX::CreateActiveX(REFCLSID clsid) // Get IOleObject interface hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX); wxASSERT(SUCCEEDED(hret)); - // Get IOleInPlaceObject interface + + // 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); + WXOLE_WARN(hret, "m_oleObject->Advise(adviseSink, &m_docAdviseCookie),\"Advise\")"); + m_oleObject->SetHostNames(L"wxActiveXContainer", NULL); + OleSetContainedObject(m_oleObject, TRUE); + OleRun(m_oleObject); + + + // Get IOleInPlaceObject interface hret = m_oleInPlaceObject.QueryInterface(IID_IOleInPlaceObject, m_ActiveX); wxASSERT(SUCCEEDED(hret)); @@ -292,13 +308,6 @@ void wxActiveX::CreateActiveX(REFCLSID clsid) WXOLE_WARN(hret, "CreateActiveX::pPersistStreamInit->InitNew()"); }; - // document advise - m_docAdviseCookie = 0; - hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie); - WXOLE_WARN(hret, "m_oleObject->Advise(adviseSink, &m_docAdviseCookie),\"Advise\")"); - m_oleObject->SetHostNames(L"wxActiveXContainer", NULL); - OleSetContainedObject(m_oleObject, TRUE); - if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)) m_oleObject->SetClientSite(m_clientSite); @@ -312,22 +321,26 @@ void wxActiveX::CreateActiveX(REFCLSID clsid) posRect.bottom = h; m_oleObjectHWND = 0; - hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND); - WXOLE_WARN(hret, "m_oleInPlaceObject->GetWindow(&m_oleObjectHWND)"); - if (SUCCEEDED(hret)) - ::SetActiveWindow(m_oleObjectHWND); + + if (m_oleInPlaceObject.Ok()) + { + hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND); + WXOLE_WARN(hret, "m_oleInPlaceObject->GetWindow(&m_oleObjectHWND)"); + if (SUCCEEDED(hret)) + ::SetActiveWindow(m_oleObjectHWND); + }; if (! (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME)) { - if (w > 0 && h > 0) + if (w > 0 && h > 0 && m_oleInPlaceObject.Ok()) m_oleInPlaceObject->SetObjectRects(&posRect, &posRect); hret = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, m_clientSite, 0, (HWND)GetHWND(), &posRect); hret = m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0, (HWND)GetHWND(), &posRect); }; - if (! m_oleObjectHWND) + if (! m_oleObjectHWND && m_oleInPlaceObject.Ok()) { hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND); WXOLE_WARN(hret, "m_oleInPlaceObject->GetWindow(&m_oleObjectHWND)"); @@ -365,33 +378,43 @@ struct less_wxStringI }; }; -typedef map ActiveXEventMap; -static ActiveXEventMap sg_eventMap; +typedef map ActiveXNamedEventMap; +static ActiveXNamedEventMap sg_NamedEventMap; -// one off class for automatic freeing of activeX eventtypes -class ActiveXEventMapFlusher +const wxEventType& RegisterActiveXEvent(const wxChar *eventName) { -public: - ~ActiveXEventMapFlusher() + wxString ev = eventName; + ActiveXNamedEventMap::iterator it = sg_NamedEventMap.find(ev); + if (it == sg_NamedEventMap.end()) { - ActiveXEventMap::iterator it = sg_eventMap.end(); - while (it != sg_eventMap.end()) - { - delete it->second; - it++; - }; + wxEventType *et = new wxEventType(wxNewEventType()); + sg_NamedEventMap[ev] = et; + + return *et; }; + + return *(it->second); }; -static ActiveXEventMapFlusher s_dummyActiveXEventMapFlusher; -const wxEventType& RegisterActiveXEvent(wxString eventName) +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +// 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) { - ActiveXEventMap::iterator it = sg_eventMap.find(eventName); - if (it == sg_eventMap.end()) + ActiveXDISPIDEventMap::iterator it = sg_dispIdEventMap.find(event); + if (it == sg_dispIdEventMap.end()) { wxEventType *et = new wxEventType(wxNewEventType()); - sg_eventMap[eventName] = et; + sg_dispIdEventMap[event] = et; return *et; }; @@ -399,6 +422,33 @@ const wxEventType& RegisterActiveXEvent(wxString eventName) 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++; + }; + + // DISPID events + ActiveXDISPIDEventMap::iterator dit = sg_dispIdEventMap.end(); + while (dit != sg_dispIdEventMap.end()) + { + delete dit->second; + dit++; + }; + }; +}; + +static ActiveXEventMapFlusher s_dummyActiveXEventMapFlusher; + + ////////////////////////////////////////////////////// bool MSWVariantToVariant(VARIANTARG& va, wxVariant& vx) { @@ -479,7 +529,7 @@ private: public: wxActiveXEvents(wxActiveX *ax) : m_activeX(ax) {} - ~wxActiveXEvents() + virtual ~wxActiveXEvents() { } @@ -500,61 +550,47 @@ public: }; - - STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, - WORD wFlags, DISPPARAMS * pDispParams, - VARIANT * pVarResult, EXCEPINFO * pExcepInfo, - unsigned int * puArgErr) - { - if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF)) - return E_NOTIMPL; - - // map dispid to name - 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; - - - wxActiveX::FuncX &func = m_activeX->m_events[idx]; - - ActiveXEventMap::iterator it = sg_eventMap.find(func.name); - if (it == sg_eventMap.end()) - return S_OK; + 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(*(it->second)); + event.SetEventType(eventType); event.m_params.NullList(); + event.m_params.SetName(func.name); // arguments if (pDispParams) { // cdecl call - for (int i = pDispParams->cArgs - 1; i >= 0; i--) + // 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[pDispParams->cArgs - i - 1]; + wxActiveX::ParamX &px = func.params[nArg - i - 1]; wxVariant vx; - MSWVariantToVariant(va, 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 (unsigned int i = 0; i < pDispParams->cArgs; i++) + for (int i = 0; i < nArg; i++) { VARIANTARG& va = pDispParams->rgvarg[i]; - wxActiveX::ParamX &px = func.params[pDispParams->cArgs - i - 1]; + wxActiveX::ParamX &px = func.params[nArg - i - 1]; if (px.IsOut()) { - wxVariant& vx = event.m_params[pDispParams->cArgs - i - 1]; + wxVariant& vx = event.m_params[nArg - i - 1]; VariantToMSWVariant(vx, va); }; @@ -563,6 +599,43 @@ public: else m_activeX->GetParent()->AddPendingEvent(event); + }; + + STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, + WORD wFlags, DISPPARAMS * pDispParams, + VARIANT * pVarResult, EXCEPINFO * pExcepInfo, + unsigned int * puArgErr) + { + if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF)) + return E_NOTIMPL; + + 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 funcIdx = mid->second; + wxActiveX::FuncX &func = m_activeX->m_events[funcIdx]; + + + // try to find dispid event + ActiveXDISPIDEventMap::iterator dit = sg_dispIdEventMap.find(dispIdMember); + if (dit != sg_dispIdEventMap.end()) + { + // Dispatch Event + DispatchEvent(funcIdx, *(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(funcIdx, *(nit->second), pDispParams); return S_OK; } }; @@ -573,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 @@ -606,12 +697,12 @@ wxVariant& wxActiveXEvent::operator[] (wxString name) return m_params[i]; }; - wxString err = "wxActiveXEvent::operator[] invalid name <" + name + ">"; - err += "\r\nValid Names = :\r\n"; + wxString err = wxT("wxActiveXEvent::operator[] invalid name <") + name + wxT(">"); + err += wxT("\r\nValid Names = :\r\n"); for (i = 0; i < m_params.GetCount(); i++) { err += m_params[i].GetName(); - err += "\r\n"; + err += wxT("\r\n"); }; wxASSERT_MSG(false, err); @@ -681,12 +772,12 @@ void wxActiveX::GetTypeInfo() { if (impTypeFlags & IMPLTYPEFLAG_FSOURCE) { - WXOLE_TRACEOUT("Default Event Sink"); + WXOLE_TRACEOUT(wxT("Default Event Sink")); defEventSink = true; } else { - WXOLE_TRACEOUT("Default Interface"); + WXOLE_TRACEOUT(wxT("Default Interface")); } }; @@ -713,7 +804,7 @@ void wxActiveX::GetTypeInfo(ITypeInfo *ti, bool defEventSink) if (ta->typekind == TKIND_DISPATCH) { - WXOLE_TRACEOUT("GUID = " << GetIIDName(ta->guid).c_str()); + WXOLE_TRACEOUT(wxT("GUID = ") << GetIIDName(ta->guid).c_str()); if (defEventSink) { @@ -740,7 +831,7 @@ void wxActiveX::GetTypeInfo(ITypeInfo *ti, bool defEventSink) { wxString name = anames[0]; - WXOLE_TRACEOUT("Name " << i << " = " << name.c_str()); + WXOLE_TRACEOUT(wxT("Name ") << i << wxT(" = ") << name.c_str()); SysFreeString(anames[0]); if (defEventSink) @@ -756,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; @@ -784,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; @@ -857,19 +966,144 @@ void wxActiveX::OnSize(wxSizeEvent& event) if (w <= 0 && h <= 0) return; - if (m_oleInPlaceObject) + // extents are in HIMETRIC units + if (m_oleObject.Ok()) + { + SIZEL sz = {w, h}; + PixelsToHimetric(sz); + + SIZEL sz2; + + m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2); + if (sz2.cx != sz.cx || sz.cy != sz2.cy) + m_oleObject->SetExtent(DVASPECT_CONTENT, &sz); + }; + + if (m_oleInPlaceObject.Ok()) m_oleInPlaceObject->SetObjectRects(&posRect, &posRect); +} - // extents are in HIMETRIC units - SIZEL sz = {w, h}; - PixelsToHimetric(sz); +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; - SIZEL sz2; - m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2); - if (sz2.cx != sz.cx || sz.cy != sz2.cy) - m_oleObject->SetExtent(DVASPECT_CONTENT, &sz); + // 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")); +} + +WXLRESULT 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()) @@ -1541,49 +1775,49 @@ wxString OLEHResultToString(HRESULT hr) switch (hr) { case S_OK: - return ""; + return wxEmptyString; case OLECMDERR_E_UNKNOWNGROUP: - return "The pguidCmdGroup parameter is not NULL but does not specify a recognized command group."; + return wxT("The pguidCmdGroup parameter is not NULL but does not specify a recognized command group."); case OLECMDERR_E_NOTSUPPORTED: - return "The nCmdID parameter is not a valid command in the group identified by pguidCmdGroup."; + return wxT("The nCmdID parameter is not a valid command in the group identified by pguidCmdGroup."); case OLECMDERR_E_DISABLED: - return "The command identified by nCmdID is currently disabled and cannot be executed."; + return wxT("The command identified by nCmdID is currently disabled and cannot be executed."); case OLECMDERR_E_NOHELP: - return "The caller has asked for help on the command identified by nCmdID, but no help is available."; + return wxT("The caller has asked for help on the command identified by nCmdID, but no help is available."); case OLECMDERR_E_CANCELED: - return "The user canceled the execution of the command."; + return wxT("The user canceled the execution of the command."); case E_INVALIDARG: - return "E_INVALIDARG"; + return wxT("E_INVALIDARG"); case E_OUTOFMEMORY: - return "E_OUTOFMEMORY"; + return wxT("E_OUTOFMEMORY"); case E_NOINTERFACE: - return "E_NOINTERFACE"; + return wxT("E_NOINTERFACE"); case E_UNEXPECTED: - return "E_UNEXPECTED"; + return wxT("E_UNEXPECTED"); case STG_E_INVALIDFLAG: - return "STG_E_INVALIDFLAG"; + return wxT("STG_E_INVALIDFLAG"); case E_FAIL: - return "E_FAIL"; + return wxT("E_FAIL"); case E_NOTIMPL: - return "E_NOTIMPL"; + return wxT("E_NOTIMPL"); default: { - char buf[64]; - sprintf(buf, "Unknown - 0x%X", hr); - return wxString(buf); + wxString buf; + buf.Printf(wxT("Unknown - 0x%X"), hr); + return buf; } }; }; @@ -1714,5 +1948,5 @@ wxString GetIIDName(REFIID riid) return s; } else - return "StringFromIID() error"; + return wxT("StringFromIID() error"); }