85ac8ca017
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@27162 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2717 lines
71 KiB
C++
2717 lines
71 KiB
C++
/*
|
|
wxActiveX Library Licence, Version 3
|
|
====================================
|
|
|
|
Copyright (C) 2003 Lindsay Mathieson [, ...]
|
|
|
|
Everyone is permitted to copy and distribute verbatim copies
|
|
of this licence document, but changing it is not allowed.
|
|
|
|
wxActiveX LIBRARY LICENCE
|
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
|
|
This library is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU Library General Public Licence as published by
|
|
the Free Software Foundation; either version 2 of the Licence, or (at
|
|
your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
|
|
General Public Licence for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public Licence
|
|
along with this software, usually in a file named COPYING.LIB. If not,
|
|
write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
Boston, MA 02111-1307 USA.
|
|
|
|
EXCEPTION NOTICE
|
|
|
|
1. As a special exception, the copyright holders of this library give
|
|
permission for additional uses of the text contained in this release of
|
|
the library as licenced under the wxActiveX Library Licence, applying
|
|
either version 3 of the Licence, or (at your option) any later version of
|
|
the Licence as published by the copyright holders of version 3 of the
|
|
Licence document.
|
|
|
|
2. The exception is that you may use, copy, link, modify and distribute
|
|
under the user's own terms, binary object code versions of works based
|
|
on the Library.
|
|
|
|
3. If you copy code from files distributed under the terms of the GNU
|
|
General Public Licence or the GNU Library General Public Licence into a
|
|
copy of this library, as this licence permits, the exception does not
|
|
apply to the code that you add in this way. To avoid misleading anyone as
|
|
to the status of such modified files, you must delete this exception
|
|
notice from such code and/or adjust the licensing conditions notice
|
|
accordingly.
|
|
|
|
4. If you write modifications of your own for this library, it is your
|
|
choice whether to permit this exception to apply to your modifications.
|
|
If you do not wish that, you must delete the exception notice from such
|
|
code and/or adjust the licensing conditions notice accordingly.
|
|
*/
|
|
|
|
#include "wxActiveX.h"
|
|
#include <wx/strconv.h>
|
|
#include <wx/event.h>
|
|
#include <wx/string.h>
|
|
#include <wx/datetime.h>
|
|
#include <wx/log.h>
|
|
#include <oleidl.h>
|
|
#include <winerror.h>
|
|
#include <idispids.h>
|
|
#include <olectl.h>
|
|
using namespace std;
|
|
|
|
// Depending on compilation mode, the wx headers may have undef'd
|
|
// this, but in this case we need it so the virtual method in
|
|
// FrameSite will match what is in oleidl.h.
|
|
#ifndef GetObject
|
|
#ifdef _UNICODE
|
|
#define GetObject GetObjectW
|
|
#else
|
|
#define GetObject GetObjectA
|
|
#endif
|
|
#endif
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
BEGIN_EVENT_TABLE(wxActiveX, wxWindow)
|
|
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()
|
|
|
|
IMPLEMENT_CLASS(wxActiveX, wxWindow)
|
|
|
|
class wxActiveX;
|
|
|
|
class FrameSite :
|
|
public IOleClientSite,
|
|
public IOleInPlaceSiteEx,
|
|
public IOleInPlaceFrame,
|
|
public IOleItemContainer,
|
|
public IDispatch,
|
|
public IOleCommandTarget,
|
|
public IOleDocumentSite,
|
|
public IAdviseSink,
|
|
public IOleControlSite
|
|
{
|
|
private:
|
|
DECLARE_OLE_UNKNOWN(FrameSite);
|
|
|
|
public:
|
|
FrameSite(wxActiveX * win);
|
|
virtual ~FrameSite();
|
|
|
|
//IOleWindow
|
|
STDMETHODIMP GetWindow(HWND*);
|
|
STDMETHODIMP ContextSensitiveHelp(BOOL);
|
|
|
|
//IOleInPlaceUIWindow
|
|
STDMETHODIMP GetBorder(LPRECT);
|
|
STDMETHODIMP RequestBorderSpace(LPCBORDERWIDTHS);
|
|
STDMETHODIMP SetBorderSpace(LPCBORDERWIDTHS);
|
|
STDMETHODIMP SetActiveObject(IOleInPlaceActiveObject*, LPCOLESTR);
|
|
|
|
//IOleInPlaceFrame
|
|
STDMETHODIMP InsertMenus(HMENU, LPOLEMENUGROUPWIDTHS);
|
|
STDMETHODIMP SetMenu(HMENU, HOLEMENU, HWND);
|
|
STDMETHODIMP RemoveMenus(HMENU);
|
|
STDMETHODIMP SetStatusText(LPCOLESTR);
|
|
STDMETHODIMP EnableModeless(BOOL);
|
|
STDMETHODIMP TranslateAccelerator(LPMSG, WORD);
|
|
|
|
//IOleInPlaceSite
|
|
STDMETHODIMP CanInPlaceActivate();
|
|
STDMETHODIMP OnInPlaceActivate();
|
|
STDMETHODIMP OnUIActivate();
|
|
STDMETHODIMP GetWindowContext(IOleInPlaceFrame**, IOleInPlaceUIWindow**,
|
|
LPRECT, LPRECT, LPOLEINPLACEFRAMEINFO);
|
|
STDMETHODIMP Scroll(SIZE);
|
|
STDMETHODIMP OnUIDeactivate(BOOL);
|
|
STDMETHODIMP OnInPlaceDeactivate();
|
|
STDMETHODIMP DiscardUndoState();
|
|
STDMETHODIMP DeactivateAndUndo();
|
|
STDMETHODIMP OnPosRectChange(LPCRECT);
|
|
|
|
//IOleInPlaceSiteEx
|
|
STDMETHODIMP OnInPlaceActivateEx(BOOL*, DWORD);
|
|
STDMETHODIMP OnInPlaceDeactivateEx(BOOL);
|
|
STDMETHODIMP RequestUIActivate();
|
|
|
|
//IOleClientSite
|
|
STDMETHODIMP SaveObject();
|
|
STDMETHODIMP GetMoniker(DWORD, DWORD, IMoniker**);
|
|
STDMETHODIMP GetContainer(LPOLECONTAINER FAR*);
|
|
STDMETHODIMP ShowObject();
|
|
STDMETHODIMP OnShowWindow(BOOL);
|
|
STDMETHODIMP RequestNewObjectLayout();
|
|
|
|
//IOleControlSite
|
|
STDMETHODIMP OnControlInfoChanged();
|
|
STDMETHODIMP LockInPlaceActive(BOOL);
|
|
STDMETHODIMP GetExtendedControl(IDispatch**);
|
|
STDMETHODIMP TransformCoords(POINTL*, POINTF*, DWORD);
|
|
STDMETHODIMP TranslateAccelerator(LPMSG, DWORD);
|
|
STDMETHODIMP OnFocus(BOOL);
|
|
STDMETHODIMP ShowPropertyFrame();
|
|
|
|
//IOleCommandTarget
|
|
STDMETHODIMP QueryStatus(const GUID*, ULONG, OLECMD[], OLECMDTEXT*);
|
|
STDMETHODIMP Exec(const GUID*, DWORD, DWORD, VARIANTARG*, VARIANTARG*);
|
|
|
|
//IParseDisplayName
|
|
STDMETHODIMP ParseDisplayName(IBindCtx*, LPOLESTR, ULONG*, IMoniker**);
|
|
|
|
//IOleContainer
|
|
STDMETHODIMP EnumObjects(DWORD, IEnumUnknown**);
|
|
STDMETHODIMP LockContainer(BOOL);
|
|
|
|
//IOleItemContainer
|
|
STDMETHODIMP GetObject(LPOLESTR, DWORD, IBindCtx*, REFIID, void**);
|
|
STDMETHODIMP GetObjectStorage(LPOLESTR, IBindCtx*, REFIID, void**);
|
|
STDMETHODIMP IsRunning(LPOLESTR);
|
|
|
|
//IDispatch
|
|
STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR**, unsigned int, LCID, DISPID*);
|
|
STDMETHODIMP GetTypeInfo(unsigned int, LCID, ITypeInfo**);
|
|
STDMETHODIMP GetTypeInfoCount(unsigned int*);
|
|
STDMETHODIMP Invoke(DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);
|
|
|
|
//IAdviseSink
|
|
void STDMETHODCALLTYPE OnDataChange(FORMATETC*, STGMEDIUM*);
|
|
void STDMETHODCALLTYPE OnViewChange(DWORD, LONG);
|
|
void STDMETHODCALLTYPE OnRename(IMoniker*);
|
|
void STDMETHODCALLTYPE OnSave();
|
|
void STDMETHODCALLTYPE OnClose();
|
|
|
|
// IOleDocumentSite
|
|
HRESULT STDMETHODCALLTYPE ActivateMe(IOleDocumentView __RPC_FAR *pViewToActivate);
|
|
|
|
protected:
|
|
|
|
wxActiveX * m_window;
|
|
|
|
HDC m_hDCBuffer;
|
|
HWND m_hWndParent;
|
|
|
|
bool m_bSupportsWindowlessActivation;
|
|
bool m_bInPlaceLocked;
|
|
bool m_bInPlaceActive;
|
|
bool m_bUIActive;
|
|
bool m_bWindowless;
|
|
|
|
|
|
|
|
LCID m_nAmbientLocale;
|
|
COLORREF m_clrAmbientForeColor;
|
|
COLORREF m_clrAmbientBackColor;
|
|
bool m_bAmbientShowHatching;
|
|
bool m_bAmbientShowGrabHandles;
|
|
bool m_bAmbientAppearance;
|
|
};
|
|
|
|
DEFINE_OLE_TABLE(FrameSite)
|
|
OLE_INTERFACE(IID_IUnknown, IOleClientSite)
|
|
|
|
OLE_IINTERFACE(IOleClientSite)
|
|
|
|
OLE_INTERFACE(IID_IOleWindow, IOleInPlaceSite)
|
|
OLE_IINTERFACE(IOleInPlaceSite)
|
|
OLE_IINTERFACE(IOleInPlaceSiteEx)
|
|
|
|
//OLE_IINTERFACE(IOleWindow)
|
|
OLE_IINTERFACE(IOleInPlaceUIWindow)
|
|
OLE_IINTERFACE(IOleInPlaceFrame)
|
|
|
|
OLE_IINTERFACE(IParseDisplayName)
|
|
OLE_IINTERFACE(IOleContainer)
|
|
OLE_IINTERFACE(IOleItemContainer)
|
|
|
|
OLE_IINTERFACE(IDispatch)
|
|
|
|
OLE_IINTERFACE(IOleCommandTarget)
|
|
|
|
OLE_IINTERFACE(IOleDocumentSite)
|
|
|
|
OLE_IINTERFACE(IAdviseSink)
|
|
|
|
OLE_IINTERFACE(IOleControlSite)
|
|
|
|
END_OLE_TABLE;
|
|
|
|
|
|
wxActiveX::wxActiveX(wxWindow * parent, REFCLSID clsid, wxWindowID id,
|
|
const wxPoint& pos,
|
|
const wxSize& size,
|
|
long style,
|
|
const wxString& name) :
|
|
wxWindow(parent, id, pos, size, style, name)
|
|
{
|
|
m_bAmbientUserMode = true;
|
|
m_docAdviseCookie = 0;
|
|
CreateActiveX(clsid);
|
|
}
|
|
|
|
wxActiveX::wxActiveX(wxWindow * parent, const wxString& progId, wxWindowID id,
|
|
const wxPoint& pos,
|
|
const wxSize& size,
|
|
long style,
|
|
const wxString& name) :
|
|
wxWindow(parent, id, pos, size, style, name)
|
|
{
|
|
m_bAmbientUserMode = true;
|
|
m_docAdviseCookie = 0;
|
|
CreateActiveX((LPOLESTR) (const wchar_t *) progId.wc_str(wxConvUTF8));
|
|
}
|
|
|
|
wxActiveX::~wxActiveX()
|
|
{
|
|
// disconnect connection points
|
|
wxOleConnectionArray::iterator it = m_connections.begin();
|
|
while (it != m_connections.end())
|
|
{
|
|
wxOleConnectionPoint& cp = it->first;
|
|
cp->Unadvise(it->second);
|
|
|
|
it++;
|
|
};
|
|
m_connections.clear();
|
|
|
|
if (m_oleInPlaceObject.Ok())
|
|
{
|
|
m_oleInPlaceObject->InPlaceDeactivate();
|
|
m_oleInPlaceObject->UIDeactivate();
|
|
}
|
|
|
|
|
|
if (m_oleObject.Ok())
|
|
{
|
|
if (m_docAdviseCookie != 0)
|
|
m_oleObject->Unadvise(m_docAdviseCookie);
|
|
|
|
m_oleObject->DoVerb(OLEIVERB_HIDE, NULL, m_clientSite, 0, (HWND) GetHWND(), NULL);
|
|
m_oleObject->Close(OLECLOSE_NOSAVE);
|
|
m_oleObject->SetClientSite(NULL);
|
|
}
|
|
}
|
|
|
|
void wxActiveX::CreateActiveX(REFCLSID clsid)
|
|
{
|
|
SetTransparent();
|
|
|
|
HRESULT hret;
|
|
|
|
////////////////////////////////////////////////////////
|
|
// FrameSite
|
|
FrameSite *frame = new FrameSite(this);
|
|
// oleClientSite
|
|
hret = m_clientSite.QueryInterface(IID_IOleClientSite, (IDispatch *) frame);
|
|
wxCHECK_RET(SUCCEEDED(hret), _T("m_clientSite.QueryInterface failed"));
|
|
// adviseSink
|
|
wxAutoOleInterface<IAdviseSink> adviseSink(IID_IAdviseSink, (IDispatch *) frame);
|
|
wxCHECK_RET(adviseSink.Ok(), _T("adviseSink not Ok"));
|
|
|
|
|
|
// // Create Object, get IUnknown interface
|
|
m_ActiveX.CreateInstance(clsid, IID_IUnknown);
|
|
wxCHECK_RET(m_ActiveX.Ok(), _T("m_ActiveX.CreateInstance failed"));
|
|
|
|
// Get Dispatch interface
|
|
hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX);
|
|
WXOLE_WARN(hret, "Unable to get dispatch interface");
|
|
|
|
// Type Info
|
|
GetTypeInfo();
|
|
|
|
// Get IOleObject interface
|
|
hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX);
|
|
wxCHECK_RET(SUCCEEDED(hret), _("Unable to get IOleObject interface"));
|
|
|
|
// get IViewObject Interface
|
|
hret = m_viewObject.QueryInterface(IID_IViewObject, m_ActiveX);
|
|
wxCHECK_RET(SUCCEEDED(hret), _T("Unable to get IViewObject Interface"));
|
|
|
|
// 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);
|
|
wxCHECK_RET(SUCCEEDED(hret), _T("Unable to get IOleInPlaceObject interface"));
|
|
|
|
// status
|
|
DWORD dwMiscStatus;
|
|
m_oleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
|
|
wxCHECK_RET(SUCCEEDED(hret), _T("Unable to get oleObject status"));
|
|
|
|
// set client site first ?
|
|
if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
|
|
m_oleObject->SetClientSite(m_clientSite);
|
|
|
|
|
|
// stream init
|
|
wxAutoOleInterface<IPersistStreamInit>
|
|
pPersistStreamInit(IID_IPersistStreamInit, m_oleObject);
|
|
|
|
if (pPersistStreamInit.Ok())
|
|
{
|
|
hret = pPersistStreamInit->InitNew();
|
|
WXOLE_WARN(hret, "CreateActiveX::pPersistStreamInit->InitNew()");
|
|
};
|
|
|
|
if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
|
|
m_oleObject->SetClientSite(m_clientSite);
|
|
|
|
|
|
int w, h;
|
|
GetClientSize(&w, &h);
|
|
RECT posRect;
|
|
posRect.left = 0;
|
|
posRect.top = 0;
|
|
posRect.right = w;
|
|
posRect.bottom = h;
|
|
|
|
m_oleObjectHWND = 0;
|
|
|
|
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 && 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 && m_oleInPlaceObject.Ok())
|
|
{
|
|
hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
|
|
WXOLE_WARN(hret, "m_oleInPlaceObject->GetWindow(&m_oleObjectHWND)");
|
|
};
|
|
|
|
if (m_oleObjectHWND)
|
|
{
|
|
::SetActiveWindow(m_oleObjectHWND);
|
|
::ShowWindow(m_oleObjectHWND, SW_SHOW);
|
|
|
|
// Update by GBR to resize older controls
|
|
wxSizeEvent szEvent;
|
|
szEvent.m_size = wxSize(w, h) ;
|
|
GetEventHandler()->AddPendingEvent(szEvent);
|
|
};
|
|
}
|
|
|
|
void wxActiveX::CreateActiveX(LPOLESTR progId)
|
|
{
|
|
CLSID clsid;
|
|
if (CLSIDFromProgID(progId, &clsid) != S_OK)
|
|
return;
|
|
|
|
CreateActiveX(clsid);
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Case Insensitive Map of Event names 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
|
|
// probably should use a wxWindows hash table here, but I'm lazy ...
|
|
typedef map<wxString, wxEventType *, NS_wxActiveX::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
|
|
{
|
|
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 = 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->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,
|
|
VARIANT * pVarResult, EXCEPINFO * pExcepInfo,
|
|
unsigned int * puArgErr)
|
|
{
|
|
if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
|
|
return E_NOTIMPL;
|
|
|
|
wxASSERT(m_activeX);
|
|
|
|
// find event for dispid
|
|
wxActiveX::MemberIdMap::iterator mit = m_activeX->m_eventMemberIds.find((MEMBERID) dispIdMember);
|
|
if (mit == m_activeX->m_eventMemberIds.end())
|
|
return S_OK;
|
|
|
|
// sanity check
|
|
int midx = mit->second;
|
|
if (midx < 0 || midx >= m_activeX->GetEventCount())
|
|
return S_OK;
|
|
|
|
wxActiveX::FuncX &func = m_activeX->m_events[midx];
|
|
|
|
|
|
// try to find dispid event
|
|
ActiveXDISPIDEventMap::iterator dit = sg_dispIdEventMap.find(dispIdMember);
|
|
if (dit != sg_dispIdEventMap.end())
|
|
{
|
|
// Dispatch Event
|
|
DispatchEvent(func, *(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(func, *(nit->second), pDispParams);
|
|
return S_OK;
|
|
}
|
|
};
|
|
|
|
bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc)
|
|
{
|
|
if (self->m_haveCustomId && IsEqualIID(iid, self->m_customId))
|
|
{
|
|
WXOLE_TRACE("Found Custom Dispatch Interface");
|
|
*_interface = (IUnknown *) (IDispatch *) self;
|
|
desc = "Custom Dispatch Interface";
|
|
return true;
|
|
};
|
|
|
|
return false;
|
|
};
|
|
|
|
DEFINE_OLE_TABLE(wxActiveXEvents)
|
|
OLE_IINTERFACE(IUnknown)
|
|
OLE_INTERFACE(IID_IDispatch, IDispatch)
|
|
OLE_INTERFACE_CUSTOM(wxActiveXEventsInterface)
|
|
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)
|
|
{
|
|
wxASSERT(idx >= 0 && idx < ParamCount());
|
|
|
|
return m_params[idx];
|
|
};
|
|
|
|
wxVariant& wxActiveXEvent::operator[] (wxString name)
|
|
{
|
|
for (int i = 0; i < m_params.GetCount(); i++)
|
|
{
|
|
if (name.CmpNoCase(m_params[i].GetName()) == 0)
|
|
return m_params[i];
|
|
};
|
|
|
|
wxString err = _T("wxActiveXEvent::operator[] invalid name <") + name + _T(">");
|
|
err += _T("\r\nValid Names = :\r\n");
|
|
for (i = 0; i < m_params.GetCount(); i++)
|
|
{
|
|
err += m_params[i].GetName();
|
|
err += _T("\r\n");
|
|
};
|
|
|
|
wxASSERT_MSG(false, err);
|
|
|
|
return nullVar;
|
|
};
|
|
|
|
void wxActiveX::GetTypeInfo()
|
|
{
|
|
/*
|
|
We are currently only interested in the IDispatch interface
|
|
to the control. For dual interfaces (TypeKind = TKIND_INTERFACE)
|
|
we should drill down through the inheritance
|
|
(using TYPEATTR->cImplTypes) and GetRefTypeOfImplType(n)
|
|
and retrieve all the func names etc that way, then generate a C++
|
|
header file for it.
|
|
|
|
But we don't do this and probably never will, so if we have a DUAL
|
|
interface then we query for the IDispatch
|
|
via GetRefTypeOfImplType(-1).
|
|
*/
|
|
|
|
HRESULT hret = 0;
|
|
|
|
// get type info via class info
|
|
wxAutoOleInterface<IProvideClassInfo> classInfo(IID_IProvideClassInfo, m_ActiveX);
|
|
if (! classInfo.Ok())
|
|
return;
|
|
|
|
// type info
|
|
wxAutoOleInterface<ITypeInfo> typeInfo;
|
|
hret = classInfo->GetClassInfo(typeInfo.GetRef());
|
|
if (! typeInfo.Ok())
|
|
return;
|
|
|
|
// TYPEATTR
|
|
TYPEATTR *ta = NULL;
|
|
hret = typeInfo->GetTypeAttr(&ta);
|
|
if (! ta)
|
|
return;
|
|
|
|
// this should be a TKIND_COCLASS
|
|
wxASSERT(ta->typekind == TKIND_COCLASS);
|
|
|
|
// iterate contained interfaces
|
|
for (int i = 0; i < ta->cImplTypes; i++)
|
|
{
|
|
HREFTYPE rt = 0;
|
|
|
|
// get dispatch type info handle
|
|
hret = typeInfo->GetRefTypeOfImplType(i, &rt);
|
|
if (! SUCCEEDED(hret))
|
|
continue;
|
|
|
|
// get dispatch type info interface
|
|
wxAutoOleInterface<ITypeInfo> ti;
|
|
hret = typeInfo->GetRefTypeInfo(rt, ti.GetRef());
|
|
if (! ti.Ok())
|
|
continue;
|
|
|
|
// check if default event sink
|
|
bool defInterface = false;
|
|
bool defEventSink = false;
|
|
int impTypeFlags = 0;
|
|
typeInfo->GetImplTypeFlags(i, &impTypeFlags);
|
|
|
|
if (impTypeFlags & IMPLTYPEFLAG_FDEFAULT)
|
|
{
|
|
if (impTypeFlags & IMPLTYPEFLAG_FSOURCE)
|
|
{
|
|
WXOLE_TRACEOUT("Default Event Sink");
|
|
defEventSink = true;
|
|
if (impTypeFlags & IMPLTYPEFLAG_FDEFAULTVTABLE)
|
|
{
|
|
WXOLE_TRACEOUT("*ERROR* - Default Event Sink is via vTable");
|
|
defEventSink = false;
|
|
};
|
|
}
|
|
else
|
|
{
|
|
WXOLE_TRACEOUT("Default Interface");
|
|
defInterface = true;
|
|
}
|
|
};
|
|
|
|
|
|
// process
|
|
GetTypeInfo(ti, defInterface, defEventSink);
|
|
};
|
|
|
|
|
|
// free
|
|
typeInfo->ReleaseTypeAttr(ta);
|
|
};
|
|
|
|
void ElemDescToParam(const ELEMDESC& ed, wxActiveX::ParamX& param)
|
|
{
|
|
param.flags = ed.idldesc.wIDLFlags;
|
|
param.vt = ed.tdesc.vt;
|
|
param.isPtr = (param.vt == VT_PTR);
|
|
param.isSafeArray = (param.vt == VT_SAFEARRAY);
|
|
if (param.isPtr || param.isSafeArray)
|
|
param.vt = ed.tdesc.lptdesc->vt;
|
|
};
|
|
|
|
void wxActiveX::GetTypeInfo(ITypeInfo *ti, bool defInterface, bool defEventSink)
|
|
{
|
|
// wxAutoOleInterface<> assumes a ref has already been added
|
|
ti->AddRef();
|
|
wxAutoOleInterface<ITypeInfo> typeInfo(ti);
|
|
|
|
// TYPEATTR
|
|
TYPEATTR *ta = NULL;
|
|
HRESULT hret = typeInfo->GetTypeAttr(&ta);
|
|
if (! ta)
|
|
return;
|
|
|
|
if (ta->typekind == TKIND_DISPATCH)
|
|
{
|
|
WXOLE_TRACEOUT("GUID = " << GetIIDName(ta->guid).c_str());
|
|
|
|
if (defEventSink)
|
|
{
|
|
wxActiveXEvents *disp = new wxActiveXEvents(this, ta->guid);
|
|
ConnectAdvise(ta->guid, disp);
|
|
};
|
|
|
|
|
|
// Get Function Names
|
|
for (int i = 0; i < ta->cFuncs; i++)
|
|
{
|
|
FUNCDESC FAR *fd = NULL;
|
|
|
|
hret = typeInfo->GetFuncDesc(i, &fd);
|
|
if (! fd)
|
|
continue;
|
|
|
|
BSTR anames[1] = {NULL};
|
|
unsigned int n = 0;
|
|
|
|
hret = typeInfo->GetNames(fd->memid, anames, 1, &n);
|
|
|
|
if (anames[0])
|
|
{
|
|
wxString name = anames[0];
|
|
|
|
WXOLE_TRACEOUT("Name " << i << " = " << name.c_str());
|
|
SysFreeString(anames[0]);
|
|
|
|
if (defInterface || defEventSink)
|
|
{
|
|
FuncX func;
|
|
func.name = name;
|
|
func.memid = fd->memid;
|
|
func.hasOut = false;
|
|
|
|
// get Param Names
|
|
unsigned int maxPNames = fd->cParams + 1;
|
|
unsigned int nPNames = 0;
|
|
BSTR *pnames = new BSTR[maxPNames];
|
|
|
|
hret = typeInfo->GetNames(fd->memid, pnames, maxPNames, &nPNames);
|
|
|
|
int pbase = 0;
|
|
if (fd->cParams < int(nPNames))
|
|
{
|
|
pbase++;
|
|
SysFreeString(pnames[0]);
|
|
};
|
|
|
|
// params
|
|
ElemDescToParam(fd->elemdescFunc, func.retType);
|
|
for (int p = 0; p < fd->cParams; p++)
|
|
{
|
|
ParamX param;
|
|
|
|
ElemDescToParam(fd->lprgelemdescParam[p], param);
|
|
|
|
param.name = pnames[pbase + p];
|
|
SysFreeString(pnames[pbase + p]);
|
|
|
|
param.isOptional = (p > fd->cParams - fd->cParamsOpt);
|
|
|
|
func.hasOut |= (param.IsOut() || param.isPtr);
|
|
func.params.push_back(param);
|
|
};
|
|
delete [] pnames;
|
|
|
|
if (defEventSink)
|
|
{
|
|
m_events.push_back(func);
|
|
m_eventMemberIds[fd->memid] = m_events.size() - 1;
|
|
}
|
|
else
|
|
{
|
|
if (fd->invkind == INVOKE_FUNC)
|
|
{
|
|
m_methods.push_back(func);
|
|
m_methodNames[func.name] = m_methods.size() - 1;
|
|
}
|
|
else
|
|
{
|
|
NameMap::iterator it = m_propNames.find(func.name);
|
|
int idx = -1;
|
|
if (it == m_propNames.end())
|
|
{
|
|
m_props.push_back(PropX());
|
|
idx = m_props.size() - 1;
|
|
m_propNames[func.name] = idx;
|
|
m_props[idx].name = func.name;
|
|
m_props[idx].memid = func.memid;
|
|
|
|
}
|
|
else
|
|
idx = it->second;
|
|
|
|
if (fd->invkind == INVOKE_PROPERTYGET)
|
|
m_props[idx].type = func.retType;
|
|
else if (func.params.size() > 0)
|
|
{
|
|
m_props[idx].arg = func.params[0];
|
|
m_props[idx].putByRef = (fd->invkind == INVOKE_PROPERTYPUTREF);
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
typeInfo->ReleaseFuncDesc(fd);
|
|
};
|
|
}
|
|
|
|
typeInfo->ReleaseTypeAttr(ta);
|
|
};
|
|
|
|
///////////////////////////////////////////////
|
|
// Type Info exposure
|
|
const wxActiveX::FuncX& wxActiveX::GetEventDesc(int idx) const
|
|
{
|
|
wxASSERT(idx >= 0 && idx < GetEventCount());
|
|
|
|
return m_events[idx];
|
|
};
|
|
|
|
const wxActiveX::PropX& wxActiveX::GetPropDesc(int idx) const
|
|
{
|
|
if (idx < 0 || idx >= GetPropCount())
|
|
throw exception("Property index out of bounds");
|
|
|
|
return m_props[idx];
|
|
};
|
|
|
|
const wxActiveX::PropX& wxActiveX::GetPropDesc(const wxString& name) const
|
|
{
|
|
NameMap::const_iterator it = m_propNames.find(name);
|
|
if (it == m_propNames.end())
|
|
{
|
|
wxString s;
|
|
s << _T("property <") << name << _T("> not found");
|
|
throw exception(s.mb_str());
|
|
};
|
|
|
|
return GetPropDesc(it->second);
|
|
};
|
|
|
|
const wxActiveX::FuncX& wxActiveX::GetMethodDesc(int idx) const
|
|
{
|
|
if (idx < 0 || idx >= GetMethodCount())
|
|
throw exception("Method index out of bounds");
|
|
|
|
|
|
return m_methods[idx];
|
|
};
|
|
|
|
|
|
const wxActiveX::FuncX& wxActiveX::GetMethodDesc(const wxString& name) const
|
|
{
|
|
NameMap::const_iterator it = m_methodNames.find(name);
|
|
if (it == m_methodNames.end())
|
|
{
|
|
wxString s;
|
|
s << _T("method <") << name << _T("> not found");
|
|
throw exception(s.mb_str());
|
|
};
|
|
|
|
return GetMethodDesc(it->second);
|
|
};
|
|
|
|
|
|
void wxActiveX::SetProp(MEMBERID name, VARIANTARG& value)
|
|
{
|
|
DISPID pids[1] = {DISPID_PROPERTYPUT};
|
|
DISPPARAMS params = {&value, pids, 1, 1};
|
|
|
|
EXCEPINFO x;
|
|
memset(&x, 0, sizeof(x));
|
|
unsigned int argErr = 0;
|
|
|
|
HRESULT hr = m_Dispatch->Invoke(
|
|
name,
|
|
IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
|
|
¶ms, NULL, &x, &argErr);
|
|
|
|
WXOLE_WARN(hr, "Invoke Prop(...)");
|
|
};
|
|
|
|
void wxActiveX::SetProp(const wxString &name, const wxVariant &value)
|
|
{
|
|
const PropX& prop = GetPropDesc(name);
|
|
if (! prop.CanSet())
|
|
{
|
|
wxString s;
|
|
s << _T("property <") << name << _T("> is readonly");
|
|
throw exception(s.mb_str());
|
|
};
|
|
|
|
VARIANT v = {prop.arg.vt};
|
|
VariantToMSWVariant(value, v);
|
|
SetProp(prop.memid, v);
|
|
VariantClear(&v); // this releases any BSTR's etc
|
|
};
|
|
|
|
VARIANT wxActiveX::GetPropAsVariant(MEMBERID name)
|
|
{
|
|
VARIANT v;
|
|
VariantInit(&v);
|
|
|
|
DISPPARAMS params = {NULL, NULL, 0, 0};
|
|
|
|
EXCEPINFO x;
|
|
memset(&x, 0, sizeof(x));
|
|
unsigned int argErr = 0;
|
|
|
|
HRESULT hr = m_Dispatch->Invoke(
|
|
name,
|
|
IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
|
|
¶ms, &v, &x, &argErr);
|
|
|
|
WXOLE_WARN(hr, "Invoke Prop(...)");
|
|
|
|
return v;
|
|
};
|
|
|
|
VARIANT wxActiveX::GetPropAsVariant(const wxString& name)
|
|
{
|
|
const PropX& prop = GetPropDesc(name);
|
|
if (! prop.CanGet())
|
|
{
|
|
wxString s;
|
|
s << _T("property <") << name << _T("> is writeonly");
|
|
throw exception(s.mb_str());
|
|
};
|
|
|
|
return GetPropAsVariant(prop.memid);
|
|
};
|
|
|
|
wxVariant wxActiveX::GetPropAsWxVariant(const wxString& name)
|
|
{
|
|
VARIANT v = GetPropAsVariant(name);
|
|
HRESULT hr = VariantChangeType(&v, &v, 0, VT_BSTR);
|
|
if (! SUCCEEDED(hr))
|
|
throw exception("Unable to convert variant");
|
|
|
|
wxVariant wv;
|
|
MSWVariantToVariant(v, wv);
|
|
|
|
VariantClear(&v);
|
|
|
|
return wv;
|
|
};
|
|
|
|
wxString wxActiveX::GetPropAsString(const wxString& name)
|
|
{
|
|
VARIANT v = GetPropAsVariant(name);
|
|
HRESULT hr = VariantChangeType(&v, &v, 0, VT_BSTR);
|
|
if (! SUCCEEDED(hr))
|
|
throw exception("Unable to convert variant");
|
|
|
|
wxString s = v.bstrVal;
|
|
VariantClear(&v);
|
|
|
|
return s;
|
|
};
|
|
|
|
char wxActiveX::GetPropAsChar(const wxString& name)
|
|
{
|
|
VARIANT v = GetPropAsVariant(name);
|
|
HRESULT hr = VariantChangeType(&v, &v, 0, VT_I1);
|
|
if (! SUCCEEDED(hr))
|
|
throw exception("Unable to convert variant");
|
|
|
|
return v.cVal;
|
|
};
|
|
|
|
long wxActiveX::GetPropAsLong(const wxString& name)
|
|
{
|
|
VARIANT v = GetPropAsVariant(name);
|
|
HRESULT hr = VariantChangeType(&v, &v, 0, VT_I4);
|
|
if (! SUCCEEDED(hr))
|
|
throw exception("Unable to convert variant");
|
|
|
|
return v.iVal;
|
|
};
|
|
|
|
bool wxActiveX::GetPropAsBool(const wxString& name)
|
|
{
|
|
VARIANT v = GetPropAsVariant(name);
|
|
HRESULT hr = VariantChangeType(&v, &v, 0, VT_BOOL);
|
|
if (! SUCCEEDED(hr))
|
|
throw exception("Unable to convert variant");
|
|
|
|
return v.boolVal != 0;
|
|
};
|
|
|
|
double wxActiveX::GetPropAsDouble(const wxString& name)
|
|
{
|
|
VARIANT v = GetPropAsVariant(name);
|
|
HRESULT hr = VariantChangeType(&v, &v, 0, VT_R8);
|
|
if (! SUCCEEDED(hr))
|
|
throw exception("Unable to convert variant");
|
|
|
|
return v.dblVal;
|
|
};
|
|
|
|
wxDateTime wxActiveX::GetPropAsDateTime(const wxString& name)
|
|
{
|
|
wxDateTime dt;
|
|
VARIANT v = GetPropAsVariant(name);
|
|
|
|
if (! VariantToWxDateTime(v, dt))
|
|
throw exception("Unable to convert variant to wxDateTime");
|
|
|
|
return dt;
|
|
};
|
|
|
|
void *wxActiveX::GetPropAsPointer(const wxString& name)
|
|
{
|
|
VARIANT v = GetPropAsVariant(name);
|
|
HRESULT hr = VariantChangeType(&v, &v, 0, VT_BYREF);
|
|
if (! SUCCEEDED(hr))
|
|
throw exception("Unable to convert variant");
|
|
|
|
return v.byref;
|
|
};
|
|
|
|
|
|
|
|
// call methods
|
|
VARIANT wxActiveX::CallMethod(MEMBERID name, VARIANTARG args[], int argc)
|
|
{
|
|
DISPPARAMS pargs = {args, NULL, argc, 0};
|
|
VARIANT retVal;
|
|
VariantInit(&retVal);
|
|
|
|
EXCEPINFO x;
|
|
memset(&x, 0, sizeof(x));
|
|
unsigned int argErr = 0;
|
|
|
|
HRESULT hr = m_Dispatch->Invoke(
|
|
name,
|
|
IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD,
|
|
&pargs, &retVal, &x, &argErr);
|
|
|
|
WXOLE_WARN(hr, "Invoke Method(...)");
|
|
return retVal;
|
|
};
|
|
|
|
VARIANT wxActiveX::CallMethod(const wxString& name, VARIANTARG args[], int argc)
|
|
{
|
|
const FuncX& func = GetMethodDesc(name);
|
|
if (argc < 0)
|
|
argc = func.params.size();
|
|
|
|
return CallMethod(func.memid, args, argc);
|
|
};
|
|
|
|
|
|
wxVariant wxActiveX::CallMethod(const wxString& name, wxVariant args[], int nargs)
|
|
{
|
|
const FuncX& func = GetMethodDesc(name);
|
|
|
|
if (args == NULL)
|
|
nargs = 0;
|
|
|
|
VARIANTARG *vargs = NULL;
|
|
if (nargs < 0)
|
|
nargs = func.params.size();
|
|
|
|
if (nargs > 0)
|
|
vargs = new VARIANTARG[nargs];
|
|
|
|
if (vargs)
|
|
{
|
|
// init type of vargs
|
|
for (int i = 0; i < nargs; i++)
|
|
vargs[nargs - i - 1].vt = func.params[i].vt;
|
|
|
|
// put data
|
|
for (i = 0; i < nargs; i++)
|
|
VariantToMSWVariant(args[i], vargs[nargs - i - 1]);
|
|
};
|
|
|
|
VARIANT rv = CallMethod(func.memid, vargs, nargs);
|
|
|
|
// process any by ref params
|
|
if (func.hasOut)
|
|
{
|
|
for (int i = 0; i < nargs; i++)
|
|
{
|
|
VARIANTARG& va = vargs[nargs - i - 1];
|
|
const wxActiveX::ParamX &px = func.params[i];
|
|
|
|
if (px.IsOut())
|
|
{
|
|
wxVariant& vx = args[i];
|
|
|
|
MSWVariantToVariant(va, vx);
|
|
};
|
|
};
|
|
}
|
|
|
|
if (vargs)
|
|
{
|
|
for (int i = 0; i < nargs; i++)
|
|
VariantClear(&vargs[i]);
|
|
delete [] vargs;
|
|
};
|
|
|
|
wxVariant ret;
|
|
|
|
MSWVariantToVariant(rv, ret);
|
|
VariantClear(&rv);
|
|
|
|
return ret;
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
HRESULT wxActiveX::ConnectAdvise(REFIID riid, IUnknown *events)
|
|
{
|
|
wxOleConnectionPoint cp;
|
|
DWORD adviseCookie = 0;
|
|
|
|
wxAutoOleInterface<IConnectionPointContainer> cpContainer(IID_IConnectionPointContainer, m_ActiveX);
|
|
if (! cpContainer.Ok())
|
|
return E_FAIL;
|
|
|
|
HRESULT hret = cpContainer->FindConnectionPoint(riid, cp.GetRef());
|
|
if (! SUCCEEDED(hret))
|
|
return hret;
|
|
|
|
hret = cp->Advise(events, &adviseCookie);
|
|
|
|
if (SUCCEEDED(hret))
|
|
m_connections.push_back(wxOleConnection(cp, adviseCookie));
|
|
else
|
|
{
|
|
WXOLE_WARN(hret, "ConnectAdvise");
|
|
};
|
|
|
|
return hret;
|
|
};
|
|
|
|
HRESULT wxActiveX::AmbientPropertyChanged(DISPID dispid)
|
|
{
|
|
wxAutoOleInterface<IOleControl> oleControl(IID_IOleControl, m_oleObject);
|
|
|
|
if (oleControl.Ok())
|
|
return oleControl->OnAmbientPropertyChange(dispid);
|
|
else
|
|
return S_FALSE;
|
|
};
|
|
|
|
#define HIMETRIC_PER_INCH 2540
|
|
#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
|
|
|
|
static void PixelsToHimetric(SIZEL &sz)
|
|
{
|
|
static int logX = 0;
|
|
static int logY = 0;
|
|
|
|
if (logY == 0)
|
|
{
|
|
// initaliase
|
|
HDC dc = GetDC(NULL);
|
|
logX = GetDeviceCaps(dc, LOGPIXELSX);
|
|
logY = GetDeviceCaps(dc, LOGPIXELSY);
|
|
ReleaseDC(NULL, dc);
|
|
};
|
|
|
|
#define HIMETRIC_INCH 2540
|
|
#define CONVERT(x, logpixels) MulDiv(HIMETRIC_INCH, (x), (logpixels))
|
|
|
|
sz.cx = CONVERT(sz.cx, logX);
|
|
sz.cy = CONVERT(sz.cy, logY);
|
|
|
|
#undef CONVERT
|
|
#undef HIMETRIC_INCH
|
|
}
|
|
|
|
|
|
void wxActiveX::OnSize(wxSizeEvent& event)
|
|
{
|
|
int w, h;
|
|
GetClientSize(&w, &h);
|
|
|
|
RECT posRect;
|
|
posRect.left = 0;
|
|
posRect.top = 0;
|
|
posRect.right = w;
|
|
posRect.bottom = h;
|
|
|
|
if (w <= 0 && h <= 0)
|
|
return;
|
|
|
|
// 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);
|
|
}
|
|
|
|
void wxActiveX::OnPaint(wxPaintEvent& event)
|
|
{
|
|
wxLogTrace(wxT(""),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(""),wxT("no oleInPlaceObject"));
|
|
event.Skip();
|
|
return;
|
|
}
|
|
|
|
wxLogTrace(wxT(""),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(""),wxT("no message"));
|
|
event.Skip(); return;
|
|
};
|
|
|
|
if (!::SendMessage(m_oleObjectHWND, msg, wParam, lParam))
|
|
{
|
|
wxLogTrace(wxT(""),wxT("msg not delivered"));
|
|
event.Skip();
|
|
return;
|
|
};
|
|
|
|
wxLogTrace(wxT(""),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())
|
|
m_oleInPlaceActiveObject->OnFrameWindowActivate(TRUE);
|
|
}
|
|
|
|
void wxActiveX::OnKillFocus(wxFocusEvent& event)
|
|
{
|
|
if (m_oleInPlaceActiveObject.Ok())
|
|
m_oleInPlaceActiveObject->OnFrameWindowActivate(FALSE);
|
|
}
|
|
|
|
|
|
FrameSite::FrameSite(wxActiveX * win)
|
|
{
|
|
m_window = win;
|
|
m_bSupportsWindowlessActivation = true;
|
|
m_bInPlaceLocked = false;
|
|
m_bUIActive = false;
|
|
m_bInPlaceActive = false;
|
|
m_bWindowless = false;
|
|
|
|
m_nAmbientLocale = 0;
|
|
m_clrAmbientForeColor = ::GetSysColor(COLOR_WINDOWTEXT);
|
|
m_clrAmbientBackColor = ::GetSysColor(COLOR_WINDOW);
|
|
m_bAmbientShowHatching = true;
|
|
m_bAmbientShowGrabHandles = true;
|
|
m_bAmbientAppearance = true;
|
|
|
|
m_hDCBuffer = NULL;
|
|
m_hWndParent = (HWND)m_window->GetHWND();
|
|
}
|
|
|
|
FrameSite::~FrameSite()
|
|
{
|
|
}
|
|
|
|
|
|
//IDispatch
|
|
|
|
HRESULT FrameSite::GetIDsOfNames(REFIID riid, OLECHAR ** rgszNames, unsigned int cNames,
|
|
LCID lcid, DISPID * rgDispId)
|
|
{
|
|
WXOLE_TRACE("IDispatch::GetIDsOfNames");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT FrameSite::GetTypeInfo(unsigned int iTInfo, LCID lcid, ITypeInfo ** ppTInfo)
|
|
{
|
|
WXOLE_TRACE("IDispatch::GetTypeInfo");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT FrameSite::GetTypeInfoCount(unsigned int * pcTInfo)
|
|
{
|
|
WXOLE_TRACE("IDispatch::GetTypeInfoCount");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT FrameSite::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
|
|
WORD wFlags, DISPPARAMS * pDispParams,
|
|
VARIANT * pVarResult, EXCEPINFO * pExcepInfo,
|
|
unsigned int * puArgErr)
|
|
{
|
|
WXOLE_TRACE("IDispatch::Invoke");
|
|
|
|
if (!(wFlags & DISPATCH_PROPERTYGET))
|
|
return S_OK;
|
|
|
|
HRESULT hr;
|
|
|
|
if (pVarResult == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
//The most common case is boolean, use as an initial type
|
|
V_VT(pVarResult) = VT_BOOL;
|
|
|
|
switch (dispIdMember)
|
|
{
|
|
case DISPID_AMBIENT_MESSAGEREFLECT:
|
|
WXOLE_TRACE("Invoke::DISPID_AMBIENT_MESSAGEREFLECT");
|
|
V_BOOL(pVarResult)= FALSE;
|
|
return S_OK;
|
|
|
|
case DISPID_AMBIENT_DISPLAYASDEFAULT:
|
|
WXOLE_TRACE("Invoke::DISPID_AMBIENT_DISPLAYASDEFAULT");
|
|
V_BOOL(pVarResult)= TRUE;
|
|
return S_OK;
|
|
|
|
case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
|
|
WXOLE_TRACE("Invoke::DISPID_AMBIENT_OFFLINEIFNOTCONNECTED");
|
|
V_BOOL(pVarResult) = TRUE;
|
|
return S_OK;
|
|
|
|
|
|
case DISPID_AMBIENT_SILENT:
|
|
WXOLE_TRACE("Invoke::DISPID_AMBIENT_SILENT");
|
|
V_BOOL(pVarResult)= TRUE;
|
|
return S_OK;
|
|
|
|
case DISPID_AMBIENT_APPEARANCE:
|
|
pVarResult->vt = VT_BOOL;
|
|
pVarResult->boolVal = m_bAmbientAppearance;
|
|
break;
|
|
|
|
case DISPID_AMBIENT_FORECOLOR:
|
|
pVarResult->vt = VT_I4;
|
|
pVarResult->lVal = (long) m_clrAmbientForeColor;
|
|
break;
|
|
|
|
case DISPID_AMBIENT_BACKCOLOR:
|
|
pVarResult->vt = VT_I4;
|
|
pVarResult->lVal = (long) m_clrAmbientBackColor;
|
|
break;
|
|
|
|
case DISPID_AMBIENT_LOCALEID:
|
|
pVarResult->vt = VT_I4;
|
|
pVarResult->lVal = (long) m_nAmbientLocale;
|
|
break;
|
|
|
|
case DISPID_AMBIENT_USERMODE:
|
|
pVarResult->vt = VT_BOOL;
|
|
pVarResult->boolVal = m_window->m_bAmbientUserMode;
|
|
break;
|
|
|
|
case DISPID_AMBIENT_SHOWGRABHANDLES:
|
|
pVarResult->vt = VT_BOOL;
|
|
pVarResult->boolVal = m_bAmbientShowGrabHandles;
|
|
break;
|
|
|
|
case DISPID_AMBIENT_SHOWHATCHING:
|
|
pVarResult->vt = VT_BOOL;
|
|
pVarResult->boolVal = m_bAmbientShowHatching;
|
|
break;
|
|
|
|
default:
|
|
return DISP_E_MEMBERNOTFOUND;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//IOleWindow
|
|
|
|
HRESULT FrameSite::GetWindow(HWND * phwnd)
|
|
{
|
|
WXOLE_TRACE("IOleWindow::GetWindow");
|
|
if (phwnd == NULL)
|
|
return E_INVALIDARG;
|
|
(*phwnd) = m_hWndParent;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::ContextSensitiveHelp(BOOL fEnterMode)
|
|
{
|
|
WXOLE_TRACE("IOleWindow::ContextSensitiveHelp");
|
|
return S_OK;
|
|
}
|
|
|
|
//IOleInPlaceUIWindow
|
|
|
|
HRESULT FrameSite::GetBorder(LPRECT lprectBorder)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceUIWindow::GetBorder");
|
|
if (lprectBorder == NULL)
|
|
return E_INVALIDARG;
|
|
return INPLACE_E_NOTOOLSPACE;
|
|
}
|
|
|
|
HRESULT FrameSite::RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceUIWindow::RequestBorderSpace");
|
|
if (pborderwidths == NULL)
|
|
return E_INVALIDARG;
|
|
return INPLACE_E_NOTOOLSPACE;
|
|
}
|
|
|
|
HRESULT FrameSite::SetBorderSpace(LPCBORDERWIDTHS pborderwidths)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceUIWindow::SetBorderSpace");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::SetActiveObject(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceUIWindow::SetActiveObject");
|
|
|
|
if (pActiveObject)
|
|
pActiveObject->AddRef();
|
|
|
|
m_window->m_oleInPlaceActiveObject = pActiveObject;
|
|
return S_OK;
|
|
}
|
|
|
|
//IOleInPlaceFrame
|
|
|
|
HRESULT FrameSite::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceFrame::InsertMenus");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceFrame::SetMenu");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::RemoveMenus(HMENU hmenuShared)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceFrame::RemoveMenus");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::SetStatusText(LPCOLESTR pszStatusText)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceFrame::SetStatusText");
|
|
//((wxFrame*)wxGetApp().GetTopWindow())->GetStatusBar()->SetStatusText(pszStatusText);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::EnableModeless(BOOL fEnable)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceFrame::EnableModeless");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::TranslateAccelerator(LPMSG lpmsg, WORD wID)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceFrame::TranslateAccelerator");
|
|
// TODO: send an event with this id
|
|
if (m_window->m_oleInPlaceActiveObject.Ok())
|
|
m_window->m_oleInPlaceActiveObject->TranslateAccelerator(lpmsg);
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
//IOleInPlaceSite
|
|
|
|
HRESULT FrameSite::CanInPlaceActivate()
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSite::CanInPlaceActivate");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::OnInPlaceActivate()
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSite::OnInPlaceActivate");
|
|
m_bInPlaceActive = true;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::OnUIActivate()
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSite::OnUIActivate");
|
|
m_bUIActive = true;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::GetWindowContext(IOleInPlaceFrame **ppFrame,
|
|
IOleInPlaceUIWindow **ppDoc,
|
|
LPRECT lprcPosRect,
|
|
LPRECT lprcClipRect,
|
|
LPOLEINPLACEFRAMEINFO lpFrameInfo)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSite::GetWindowContext");
|
|
if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL ||
|
|
lprcClipRect == NULL || lpFrameInfo == NULL)
|
|
{
|
|
if (ppFrame != NULL)
|
|
(*ppFrame) = NULL;
|
|
if (ppDoc != NULL)
|
|
(*ppDoc) = NULL;
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = QueryInterface(IID_IOleInPlaceFrame, (void **) ppFrame);
|
|
if (! SUCCEEDED(hr))
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSite::IOleInPlaceFrame Error !");
|
|
return E_UNEXPECTED;
|
|
};
|
|
|
|
hr = QueryInterface(IID_IOleInPlaceUIWindow, (void **) ppDoc);
|
|
if (! SUCCEEDED(hr))
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSite::IOleInPlaceUIWindow Error !");
|
|
(*ppFrame)->Release();
|
|
*ppFrame = NULL;
|
|
return E_UNEXPECTED;
|
|
};
|
|
|
|
int w, h;
|
|
m_window->GetClientSize(&w, &h);
|
|
if (lprcPosRect)
|
|
{
|
|
lprcPosRect->left = lprcPosRect->top = 0;
|
|
lprcPosRect->right = w;
|
|
lprcPosRect->bottom = h;
|
|
};
|
|
if (lprcClipRect)
|
|
{
|
|
lprcClipRect->left = lprcClipRect->top = 0;
|
|
lprcClipRect->right = w;
|
|
lprcClipRect->bottom = h;
|
|
};
|
|
|
|
memset(lpFrameInfo, 0, sizeof(OLEINPLACEFRAMEINFO));
|
|
lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
|
|
lpFrameInfo->hwndFrame = m_hWndParent;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::Scroll(SIZE scrollExtent)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSite::Scroll");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::OnUIDeactivate(BOOL fUndoable)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSite::OnUIDeactivate");
|
|
m_bUIActive = false;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::OnInPlaceDeactivate()
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSite::OnInPlaceDeactivate");
|
|
m_bInPlaceActive = false;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::DiscardUndoState()
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSite::DiscardUndoState");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::DeactivateAndUndo()
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSite::DeactivateAndUndo");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::OnPosRectChange(LPCRECT lprcPosRect)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSite::OnPosRectChange");
|
|
if (m_window->m_oleInPlaceObject.Ok() && lprcPosRect)
|
|
m_window->m_oleInPlaceObject->SetObjectRects(lprcPosRect, lprcPosRect);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//IOleInPlaceSiteEx
|
|
|
|
HRESULT FrameSite::OnInPlaceActivateEx(BOOL * pfNoRedraw, DWORD dwFlags)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSiteEx::OnInPlaceActivateEx");
|
|
OleLockRunning(m_window->m_ActiveX, TRUE, FALSE);
|
|
if (pfNoRedraw)
|
|
(*pfNoRedraw) = FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::OnInPlaceDeactivateEx(BOOL fNoRedraw)
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSiteEx::OnInPlaceDeactivateEx");
|
|
OleLockRunning(m_window->m_ActiveX, FALSE, FALSE);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::RequestUIActivate()
|
|
{
|
|
WXOLE_TRACE("IOleInPlaceSiteEx::RequestUIActivate");
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//IOleClientSite
|
|
|
|
HRESULT FrameSite::SaveObject()
|
|
{
|
|
WXOLE_TRACE("IOleClientSite::SaveObject");
|
|
return S_OK;
|
|
}
|
|
|
|
const char *OleGetMonikerToStr(DWORD dwAssign)
|
|
{
|
|
switch (dwAssign)
|
|
{
|
|
case OLEGETMONIKER_ONLYIFTHERE : return "OLEGETMONIKER_ONLYIFTHERE";
|
|
case OLEGETMONIKER_FORCEASSIGN : return "OLEGETMONIKER_FORCEASSIGN";
|
|
case OLEGETMONIKER_UNASSIGN : return "OLEGETMONIKER_UNASSIGN";
|
|
case OLEGETMONIKER_TEMPFORUSER : return "OLEGETMONIKER_TEMPFORUSER";
|
|
default : return "Bad Enum";
|
|
};
|
|
};
|
|
|
|
const char *OleGetWhicMonikerStr(DWORD dwWhichMoniker)
|
|
{
|
|
switch(dwWhichMoniker)
|
|
{
|
|
case OLEWHICHMK_CONTAINER : return "OLEWHICHMK_CONTAINER";
|
|
case OLEWHICHMK_OBJREL : return "OLEWHICHMK_OBJREL";
|
|
case OLEWHICHMK_OBJFULL : return "OLEWHICHMK_OBJFULL";
|
|
default : return "Bad Enum";
|
|
};
|
|
};
|
|
|
|
HRESULT FrameSite::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker,
|
|
IMoniker ** ppmk)
|
|
{
|
|
WXOLE_TRACEOUT("IOleClientSite::GetMoniker(" << OleGetMonikerToStr(dwAssign) << ", " << OleGetWhicMonikerStr(dwWhichMoniker) << ")");
|
|
|
|
|
|
if (! ppmk)
|
|
return E_FAIL;
|
|
|
|
/*
|
|
HRESULT hr = CreateFileMoniker(L"e:\\dev\\wxie\\bug-zap.swf", ppmk);
|
|
if (SUCCEEDED(hr))
|
|
return S_OK;
|
|
*/
|
|
*ppmk = NULL;
|
|
|
|
return E_FAIL ;
|
|
}
|
|
|
|
HRESULT FrameSite::GetContainer(LPOLECONTAINER * ppContainer)
|
|
{
|
|
WXOLE_TRACE("IOleClientSite::GetContainer");
|
|
if (ppContainer == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
HRESULT hr = QueryInterface(IID_IOleContainer, (void**)(ppContainer));
|
|
wxASSERT(SUCCEEDED(hr));
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT FrameSite::ShowObject()
|
|
{
|
|
WXOLE_TRACE("IOleClientSite::ShowObject");
|
|
if (m_window->m_oleObjectHWND)
|
|
::ShowWindow(m_window->m_oleObjectHWND, SW_SHOW);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::OnShowWindow(BOOL fShow)
|
|
{
|
|
WXOLE_TRACE("IOleClientSite::OnShowWindow");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::RequestNewObjectLayout()
|
|
{
|
|
WXOLE_TRACE("IOleClientSite::RequestNewObjectLayout");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
// IParseDisplayName
|
|
|
|
HRESULT FrameSite::ParseDisplayName(IBindCtx *pbc, LPOLESTR pszDisplayName,
|
|
ULONG *pchEaten, IMoniker **ppmkOut)
|
|
{
|
|
WXOLE_TRACE("IParseDisplayName::ParseDisplayName");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//IOleContainer
|
|
|
|
HRESULT FrameSite::EnumObjects(DWORD grfFlags, IEnumUnknown **ppenum)
|
|
{
|
|
WXOLE_TRACE("IOleContainer::EnumObjects");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT FrameSite::LockContainer(BOOL fLock)
|
|
{
|
|
WXOLE_TRACE("IOleContainer::LockContainer");
|
|
// TODO
|
|
return S_OK;
|
|
}
|
|
|
|
//IOleItemContainer
|
|
|
|
HRESULT FrameSite::GetObject(LPOLESTR pszItem, DWORD dwSpeedNeeded,
|
|
IBindCtx * pbc, REFIID riid, void ** ppvObject)
|
|
{
|
|
WXOLE_TRACE("IOleItemContainer::GetObject");
|
|
if (pszItem == NULL)
|
|
return E_INVALIDARG;
|
|
if (ppvObject == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
*ppvObject = NULL;
|
|
return MK_E_NOOBJECT;
|
|
}
|
|
|
|
HRESULT FrameSite::GetObjectStorage(LPOLESTR pszItem, IBindCtx * pbc,
|
|
REFIID riid, void ** ppvStorage)
|
|
{
|
|
WXOLE_TRACE("IOleItemContainer::GetObjectStorage");
|
|
if (pszItem == NULL)
|
|
return E_INVALIDARG;
|
|
if (ppvStorage == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
*ppvStorage = NULL;
|
|
return MK_E_NOOBJECT;
|
|
}
|
|
|
|
HRESULT FrameSite::IsRunning(LPOLESTR pszItem)
|
|
{
|
|
WXOLE_TRACE("IOleItemContainer::IsRunning");
|
|
if (pszItem == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
return MK_E_NOOBJECT;
|
|
}
|
|
|
|
|
|
|
|
//IOleControlSite
|
|
|
|
HRESULT FrameSite::OnControlInfoChanged()
|
|
{
|
|
WXOLE_TRACE("IOleControlSite::OnControlInfoChanged");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::LockInPlaceActive(BOOL fLock)
|
|
{
|
|
WXOLE_TRACE("IOleControlSite::LockInPlaceActive");
|
|
m_bInPlaceLocked = (fLock) ? true : false;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::GetExtendedControl(IDispatch ** ppDisp)
|
|
{
|
|
WXOLE_TRACE("IOleControlSite::GetExtendedControl");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT FrameSite::TransformCoords(POINTL * pPtlHimetric, POINTF * pPtfContainer, DWORD dwFlags)
|
|
{
|
|
WXOLE_TRACE("IOleControlSite::TransformCoords");
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pPtlHimetric == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if (pPtfContainer == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
HRESULT FrameSite::TranslateAccelerator(LPMSG pMsg, DWORD grfModifiers)
|
|
{
|
|
WXOLE_TRACE("IOleControlSite::TranslateAccelerator");
|
|
// TODO: send an event with this id
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT FrameSite::OnFocus(BOOL fGotFocus)
|
|
{
|
|
WXOLE_TRACE("IOleControlSite::OnFocus");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::ShowPropertyFrame()
|
|
{
|
|
WXOLE_TRACE("IOleControlSite::ShowPropertyFrame");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//IOleCommandTarget
|
|
|
|
HRESULT FrameSite::QueryStatus(const GUID * pguidCmdGroup, ULONG cCmds,
|
|
OLECMD * prgCmds, OLECMDTEXT * pCmdTet)
|
|
{
|
|
WXOLE_TRACE("IOleCommandTarget::QueryStatus");
|
|
if (prgCmds == NULL) return E_INVALIDARG;
|
|
bool bCmdGroupFound = false;
|
|
|
|
for (ULONG nCmd = 0; nCmd < cCmds; nCmd++)
|
|
{
|
|
// unsupported by default
|
|
prgCmds[nCmd].cmdf = 0;
|
|
|
|
// TODO
|
|
}
|
|
|
|
if (!bCmdGroupFound) { OLECMDERR_E_UNKNOWNGROUP; }
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT FrameSite::Exec(const GUID * pguidCmdGroup, DWORD nCmdID,
|
|
DWORD nCmdExecOpt, VARIANTARG * pVaIn,
|
|
VARIANTARG * pVaOut)
|
|
{
|
|
WXOLE_TRACE("IOleCommandTarget::Exec");
|
|
bool bCmdGroupFound = false;
|
|
|
|
if (!bCmdGroupFound) { OLECMDERR_E_UNKNOWNGROUP; }
|
|
return OLECMDERR_E_NOTSUPPORTED;
|
|
}
|
|
|
|
//IAdviseSink
|
|
|
|
void STDMETHODCALLTYPE FrameSite::OnDataChange(FORMATETC * pFormatEtc, STGMEDIUM * pgStgMed)
|
|
{
|
|
WXOLE_TRACE("IAdviseSink::OnDataChange");
|
|
}
|
|
|
|
void STDMETHODCALLTYPE FrameSite::OnViewChange(DWORD dwAspect, LONG lIndex)
|
|
{
|
|
WXOLE_TRACE("IAdviseSink::OnViewChange");
|
|
// redraw the control
|
|
}
|
|
|
|
void STDMETHODCALLTYPE FrameSite::OnRename(IMoniker * pmk)
|
|
{
|
|
WXOLE_TRACE("IAdviseSink::OnRename");
|
|
}
|
|
|
|
void STDMETHODCALLTYPE FrameSite::OnSave()
|
|
{
|
|
WXOLE_TRACE("IAdviseSink::OnSave");
|
|
}
|
|
|
|
void STDMETHODCALLTYPE FrameSite::OnClose()
|
|
{
|
|
WXOLE_TRACE("IAdviseSink::OnClose");
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
// IOleDocumentSite
|
|
HRESULT STDMETHODCALLTYPE FrameSite::ActivateMe(
|
|
/* [in] */ IOleDocumentView __RPC_FAR *pViewToActivate)
|
|
{
|
|
wxAutoOleInterface<IOleInPlaceSite> inPlaceSite(IID_IOleInPlaceSite, (IDispatch *) this);
|
|
if (!inPlaceSite.Ok())
|
|
return E_FAIL;
|
|
|
|
if (pViewToActivate)
|
|
{
|
|
m_window->m_docView = pViewToActivate;
|
|
m_window->m_docView->SetInPlaceSite(inPlaceSite);
|
|
}
|
|
else
|
|
{
|
|
wxAutoOleInterface<IOleDocument> oleDoc(IID_IOleDocument, m_window->m_oleObject);
|
|
if (! oleDoc.Ok())
|
|
return E_FAIL;
|
|
|
|
HRESULT hr = oleDoc->CreateView(inPlaceSite, NULL, 0, m_window->m_docView.GetRef());
|
|
if (hr != S_OK)
|
|
return E_FAIL;
|
|
|
|
m_window->m_docView->SetInPlaceSite(inPlaceSite);
|
|
};
|
|
|
|
m_window->m_docView->UIActivate(TRUE);
|
|
|
|
return S_OK;
|
|
};
|
|
|
|
|
|
static IMalloc *iMalloc = NULL;
|
|
|
|
IMalloc *wxOleInit::GetIMalloc()
|
|
{
|
|
assert(iMalloc);
|
|
return iMalloc;
|
|
};
|
|
|
|
wxOleInit::wxOleInit()
|
|
{
|
|
if (OleInitialize(NULL) == S_OK && iMalloc == NULL)
|
|
CoGetMalloc(1, &iMalloc);
|
|
else if (iMalloc)
|
|
iMalloc->AddRef();
|
|
};
|
|
|
|
wxOleInit::~wxOleInit()
|
|
{
|
|
if (iMalloc)
|
|
{
|
|
if (iMalloc->Release() == 0)
|
|
iMalloc = NULL;
|
|
};
|
|
|
|
OleUninitialize();
|
|
}
|
|
|
|
bool GetSysErrMessage(int err, wxString& s)
|
|
{
|
|
wxChar buf[256];
|
|
if (FormatMessage(
|
|
FORMAT_MESSAGE_FROM_SYSTEM, NULL,
|
|
err,0, buf, sizeof(buf), NULL) == 0)
|
|
return false;
|
|
|
|
buf[sizeof(buf) - 1] = 0;
|
|
s = buf;
|
|
return true;
|
|
};
|
|
|
|
wxString OLEHResultToString(HRESULT hr)
|
|
{
|
|
// try formatmessage
|
|
wxString err;
|
|
if (GetSysErrMessage(hr, err))
|
|
return err;
|
|
|
|
switch (hr)
|
|
{
|
|
case S_OK:
|
|
return wxEmptyString;
|
|
|
|
case CONNECT_E_CANNOTCONNECT:
|
|
return _T("Cannot connect to event interface (maybe not there ?) - see MSDN");
|
|
|
|
case DISP_E_MEMBERNOTFOUND:
|
|
return _T("The requested member does not exist, or the call to Invoke tried to set the value of a read-only property.");
|
|
|
|
case DISP_E_BADVARTYPE:
|
|
return _T("One of the parameters in rgvarg is not a valid variant type.");
|
|
|
|
case DISP_E_BADPARAMCOUNT:
|
|
return _T("The number of elements provided to DISPPARAMS is different from the number of parameters accepted by the method or property");
|
|
|
|
case DISP_E_EXCEPTION:
|
|
return _T("The application needs to raise an exception. In this case, the structure passed in pExcepInfo should be filled in.");
|
|
|
|
case DISP_E_TYPEMISMATCH:
|
|
return _T("One or more of the parameters could not be coerced. The index within rgvarg of the first parameter with the incorrect type is returned in the puArgErr parameter.");
|
|
|
|
case DISP_E_PARAMNOTOPTIONAL:
|
|
return _T("A required parameter was omitted.");
|
|
|
|
case DISP_E_PARAMNOTFOUND:
|
|
return _T("One of the parameter DISPIDs does not correspond to a parameter on the method. In this case, puArgErr should be set to the first parameter that contains the error.");
|
|
|
|
case OLECMDERR_E_UNKNOWNGROUP:
|
|
return _T("The pguidCmdGroup parameter is not NULL but does not specify a recognized command group.");
|
|
|
|
case OLECMDERR_E_NOTSUPPORTED:
|
|
return _T("The nCmdID parameter is not a valid command in the group identified by pguidCmdGroup.");
|
|
|
|
case OLECMDERR_E_DISABLED:
|
|
return _T("The command identified by nCmdID is currently disabled and cannot be executed.");
|
|
|
|
case OLECMDERR_E_NOHELP:
|
|
return _T("The caller has asked for help on the command identified by nCmdID, but no help is available.");
|
|
|
|
case OLECMDERR_E_CANCELED:
|
|
return _T("The user canceled the execution of the command.");
|
|
|
|
case E_INVALIDARG:
|
|
return _T("E_INVALIDARG");
|
|
|
|
case E_OUTOFMEMORY:
|
|
return _T("E_OUTOFMEMORY");
|
|
|
|
case E_NOINTERFACE:
|
|
return _T("E_NOINTERFACE");
|
|
|
|
case E_UNEXPECTED:
|
|
return _T("E_UNEXPECTED");
|
|
|
|
case STG_E_INVALIDFLAG:
|
|
return _T("STG_E_INVALIDFLAG");
|
|
|
|
case E_FAIL:
|
|
return _T("E_FAIL");
|
|
|
|
case E_NOTIMPL:
|
|
return _T("E_NOTIMPL");
|
|
|
|
default:
|
|
{
|
|
wxString buf;
|
|
buf.Printf(_T("Unknown - 0x%X"), hr);
|
|
return buf;
|
|
}
|
|
};
|
|
};
|
|
|
|
// borrowed from src/msw/ole/oleutils.cpp
|
|
wxString GetIIDName(REFIID riid)
|
|
{
|
|
// an association between symbolic name and numeric value of an IID
|
|
struct KNOWN_IID
|
|
{
|
|
const IID *pIid;
|
|
const wxChar *szName;
|
|
};
|
|
|
|
// construct the table containing all known interfaces
|
|
#define ADD_KNOWN_IID(name) { &IID_I##name, _T(#name) }
|
|
#define ADD_KNOWN_GUID(name) { &name, _T(#name) }
|
|
|
|
static const KNOWN_IID aKnownIids[] =
|
|
{
|
|
ADD_KNOWN_IID(ServiceProvider),
|
|
ADD_KNOWN_IID(AdviseSink),
|
|
ADD_KNOWN_IID(AdviseSink2),
|
|
ADD_KNOWN_IID(BindCtx),
|
|
ADD_KNOWN_IID(ClassFactory),
|
|
#if ( !defined( __VISUALC__) || (__VISUALC__!=1010) ) && !defined(__MWERKS__)
|
|
ADD_KNOWN_IID(ContinueCallback),
|
|
ADD_KNOWN_IID(EnumOleDocumentViews),
|
|
ADD_KNOWN_IID(OleCommandTarget),
|
|
ADD_KNOWN_IID(OleDocument),
|
|
ADD_KNOWN_IID(OleDocumentSite),
|
|
ADD_KNOWN_IID(OleDocumentView),
|
|
ADD_KNOWN_IID(Print),
|
|
#endif
|
|
ADD_KNOWN_IID(DataAdviseHolder),
|
|
ADD_KNOWN_IID(DataObject),
|
|
ADD_KNOWN_IID(Debug),
|
|
ADD_KNOWN_IID(DebugStream),
|
|
ADD_KNOWN_IID(DfReserved1),
|
|
ADD_KNOWN_IID(DfReserved2),
|
|
ADD_KNOWN_IID(DfReserved3),
|
|
ADD_KNOWN_IID(Dispatch),
|
|
ADD_KNOWN_IID(DropSource),
|
|
ADD_KNOWN_IID(DropTarget),
|
|
ADD_KNOWN_IID(EnumCallback),
|
|
ADD_KNOWN_IID(EnumFORMATETC),
|
|
ADD_KNOWN_IID(EnumGeneric),
|
|
ADD_KNOWN_IID(EnumHolder),
|
|
ADD_KNOWN_IID(EnumMoniker),
|
|
ADD_KNOWN_IID(EnumOLEVERB),
|
|
ADD_KNOWN_IID(EnumSTATDATA),
|
|
ADD_KNOWN_IID(EnumSTATSTG),
|
|
ADD_KNOWN_IID(EnumString),
|
|
ADD_KNOWN_IID(EnumUnknown),
|
|
ADD_KNOWN_IID(EnumVARIANT),
|
|
ADD_KNOWN_IID(ExternalConnection),
|
|
ADD_KNOWN_IID(InternalMoniker),
|
|
ADD_KNOWN_IID(LockBytes),
|
|
ADD_KNOWN_IID(Malloc),
|
|
ADD_KNOWN_IID(Marshal),
|
|
ADD_KNOWN_IID(MessageFilter),
|
|
ADD_KNOWN_IID(Moniker),
|
|
ADD_KNOWN_IID(OleAdviseHolder),
|
|
ADD_KNOWN_IID(OleCache),
|
|
ADD_KNOWN_IID(OleCache2),
|
|
ADD_KNOWN_IID(OleCacheControl),
|
|
ADD_KNOWN_IID(OleClientSite),
|
|
ADD_KNOWN_IID(OleContainer),
|
|
ADD_KNOWN_IID(OleInPlaceActiveObject),
|
|
ADD_KNOWN_IID(OleInPlaceFrame),
|
|
ADD_KNOWN_IID(OleInPlaceObject),
|
|
ADD_KNOWN_IID(OleInPlaceSite),
|
|
ADD_KNOWN_IID(OleInPlaceUIWindow),
|
|
ADD_KNOWN_IID(OleItemContainer),
|
|
ADD_KNOWN_IID(OleLink),
|
|
ADD_KNOWN_IID(OleManager),
|
|
ADD_KNOWN_IID(OleObject),
|
|
ADD_KNOWN_IID(OlePresObj),
|
|
ADD_KNOWN_IID(OleWindow),
|
|
ADD_KNOWN_IID(PSFactory),
|
|
ADD_KNOWN_IID(ParseDisplayName),
|
|
ADD_KNOWN_IID(Persist),
|
|
ADD_KNOWN_IID(PersistFile),
|
|
ADD_KNOWN_IID(PersistStorage),
|
|
ADD_KNOWN_IID(PersistStream),
|
|
ADD_KNOWN_IID(ProxyManager),
|
|
ADD_KNOWN_IID(RootStorage),
|
|
ADD_KNOWN_IID(RpcChannel),
|
|
ADD_KNOWN_IID(RpcProxy),
|
|
ADD_KNOWN_IID(RpcStub),
|
|
ADD_KNOWN_IID(RunnableObject),
|
|
ADD_KNOWN_IID(RunningObjectTable),
|
|
ADD_KNOWN_IID(StdMarshalInfo),
|
|
ADD_KNOWN_IID(Storage),
|
|
ADD_KNOWN_IID(Stream),
|
|
ADD_KNOWN_IID(StubManager),
|
|
ADD_KNOWN_IID(Unknown),
|
|
ADD_KNOWN_IID(ViewObject),
|
|
ADD_KNOWN_IID(ViewObject2),
|
|
ADD_KNOWN_GUID(IID_IDispatch),
|
|
ADD_KNOWN_GUID(IID_IWebBrowser),
|
|
ADD_KNOWN_GUID(IID_IWebBrowserApp),
|
|
ADD_KNOWN_GUID(IID_IWebBrowser2),
|
|
ADD_KNOWN_GUID(IID_IWebBrowser),
|
|
ADD_KNOWN_GUID(DIID_DWebBrowserEvents2),
|
|
ADD_KNOWN_GUID(DIID_DWebBrowserEvents),
|
|
};
|
|
|
|
// don't clobber preprocessor name space
|
|
#undef ADD_KNOWN_IID
|
|
#undef ADD_KNOWN_GUID
|
|
|
|
// try to find the interface in the table
|
|
for ( size_t ui = 0; ui < WXSIZEOF(aKnownIids); ui++ )
|
|
{
|
|
if ( riid == *aKnownIids[ui].pIid )
|
|
{
|
|
return aKnownIids[ui].szName;
|
|
}
|
|
}
|
|
|
|
// unknown IID, just transform to string
|
|
LPOLESTR str = NULL;
|
|
StringFromIID(riid, &str);
|
|
if (str)
|
|
{
|
|
wxString s = str;
|
|
CoTaskMemFree(str);
|
|
return s;
|
|
}
|
|
else
|
|
return _T("StringFromIID() error");
|
|
}
|