1
/////////////////////////////////////////////////////////////////////////////
2
// Name: src/msw/ole/activex.cpp
3
// Purpose: wxActiveXContainer implementation
4
// Author: Ryan Norton <wxprojects@comcast.net>, Lindsay Mathieson <???>
7
// RCS-ID: $Id: activex.cpp 70361 2012-01-15 19:05:34Z SJL $
8
// Copyright: (c) 2003 Lindsay Mathieson, (c) 2005 Ryan Norton
9
// Licence: wxWindows licence
10
/////////////////////////////////////////////////////////////////////////////
12
// ============================================================================
14
// ============================================================================
16
// ----------------------------------------------------------------------------
18
// ----------------------------------------------------------------------------
20
#include "wx/wxprec.h"
29
#include "wx/dcclient.h"
33
#include "wx/msw/dc.h"
35
#include "wx/msw/ole/activex.h"
36
#include "wx/msw/private.h" // for wxCopyRectToRECT
38
// autointerfaces that we only use here
39
typedef wxAutoOleInterface<IOleInPlaceSite> wxAutoIOleInPlaceSite;
40
typedef wxAutoOleInterface<IOleDocument> wxAutoIOleDocument;
41
typedef wxAutoOleInterface<IPersistStreamInit> wxAutoIPersistStreamInit;
42
typedef wxAutoOleInterface<IAdviseSink> wxAutoIAdviseSink;
43
typedef wxAutoOleInterface<IProvideClassInfo> wxAutoIProvideClassInfo;
44
typedef wxAutoOleInterface<ITypeInfo> wxAutoITypeInfo;
45
typedef wxAutoOleInterface<IConnectionPoint> wxAutoIConnectionPoint;
46
typedef wxAutoOleInterface<IConnectionPointContainer> wxAutoIConnectionPointContainer;
48
wxDEFINE_EVENT( wxEVT_ACTIVEX, wxActiveXEvent );
50
// Ole class helpers (sort of MFC-like) from wxActiveX
51
#define DECLARE_OLE_UNKNOWN(cls)\
57
TAutoInitInt() : l(1) {}\
59
TAutoInitInt refCount, lockCount;\
60
static void _GetInterface(cls *self, REFIID iid, void **_interface, const char *&desc);\
63
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject);\
64
ULONG STDMETHODCALLTYPE AddRef();\
65
ULONG STDMETHODCALLTYPE Release();\
66
ULONG STDMETHODCALLTYPE AddLock();\
67
ULONG STDMETHODCALLTYPE ReleaseLock()
69
#define DEFINE_OLE_TABLE(cls)\
70
LONG cls::GetRefCount() {return refCount.l;}\
71
HRESULT STDMETHODCALLTYPE cls::QueryInterface(REFIID iid, void ** ppvObject)\
77
const char *desc = NULL;\
78
cls::_GetInterface(this, iid, ppvObject, desc);\
81
return E_NOINTERFACE;\
83
((IUnknown * )(*ppvObject))->AddRef();\
86
ULONG STDMETHODCALLTYPE cls::AddRef()\
88
InterlockedIncrement(&refCount.l);\
91
ULONG STDMETHODCALLTYPE cls::Release()\
95
InterlockedDecrement(&refCount.l);\
106
ULONG STDMETHODCALLTYPE cls::AddLock()\
108
InterlockedIncrement(&lockCount.l);\
111
ULONG STDMETHODCALLTYPE cls::ReleaseLock()\
113
if (lockCount.l > 0)\
115
InterlockedDecrement(&lockCount.l);\
123
#define DEFINE_OLE_BASE(cls)\
124
void cls::_GetInterface(cls *self, REFIID iid, void **_interface, const char *&desc)\
129
#define OLE_INTERFACE(_iid, _type)\
130
if (IsEqualIID(iid, _iid))\
132
*_interface = (IUnknown *) (_type *) self;\
137
#define OLE_IINTERFACE(_face) OLE_INTERFACE(IID_##_face, _face)
139
#define OLE_INTERFACE_CUSTOM(func)\
140
if (func(self, iid, _interface, desc))\
145
#define END_OLE_TABLE\
148
// ============================================================================
150
// ============================================================================
152
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
155
// Utility to convert from pixels to the himetric values in some COM methods
156
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
159
#define HIMETRIC_PER_INCH 2540
160
#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
162
static void PixelsToHimetric(SIZEL &sz)
170
HDC dc = GetDC(NULL);
171
logX = GetDeviceCaps(dc, LOGPIXELSX);
172
logY = GetDeviceCaps(dc, LOGPIXELSY);
176
#define HIMETRIC_INCH 2540
177
#define CONVERT(x, logpixels) wxMulDivInt32(HIMETRIC_INCH, (x), (logpixels))
179
sz.cx = CONVERT(sz.cx, logX);
180
sz.cy = CONVERT(sz.cy, logY);
187
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
191
// Handles the actual wxActiveX container implementation
193
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
195
public IOleClientSite,
196
public IOleInPlaceSiteEx,
197
public IOleInPlaceFrame,
198
public IOleItemContainer,
200
public IOleCommandTarget,
201
public IOleDocumentSite,
203
public IOleControlSite
206
DECLARE_OLE_UNKNOWN(FrameSite);
209
FrameSite(wxWindow * win, wxActiveXContainer * win2)
212
m_bSupportsWindowlessActivation = true;
213
m_bInPlaceLocked = false;
215
m_bInPlaceActive = false;
216
m_bWindowless = false;
218
m_nAmbientLocale = 0;
219
m_clrAmbientForeColor = ::GetSysColor(COLOR_WINDOWTEXT);
220
m_clrAmbientBackColor = ::GetSysColor(COLOR_WINDOW);
221
m_bAmbientShowHatching = true;
222
m_bAmbientShowGrabHandles = true;
223
m_bAmbientAppearance = true;
226
m_hWndParent = (HWND)win->GetHWND();
228
virtual ~FrameSite(){}
229
//***************************IDispatch*****************************
230
HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID, OLECHAR ** ,
231
unsigned int , LCID ,
233
{ return E_NOTIMPL; }
234
STDMETHOD(GetTypeInfo)(unsigned int, LCID, ITypeInfo **)
235
{ return E_NOTIMPL; }
236
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int *)
237
{ return E_NOTIMPL; }
238
HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID, LCID,
239
WORD wFlags, DISPPARAMS *,
240
VARIANT * pVarResult, EXCEPINFO *,
243
if (!(wFlags & DISPATCH_PROPERTYGET))
246
if (pVarResult == NULL)
249
//The most common case is boolean, use as an initial type
250
V_VT(pVarResult) = VT_BOOL;
252
switch (dispIdMember)
254
case DISPID_AMBIENT_MESSAGEREFLECT:
255
V_BOOL(pVarResult)= FALSE;
258
case DISPID_AMBIENT_DISPLAYASDEFAULT:
259
V_BOOL(pVarResult)= TRUE;
262
case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
263
V_BOOL(pVarResult) = TRUE;
266
case DISPID_AMBIENT_SILENT:
267
V_BOOL(pVarResult)= TRUE;
270
case DISPID_AMBIENT_APPEARANCE:
271
pVarResult->vt = VT_BOOL;
272
pVarResult->boolVal = m_bAmbientAppearance;
275
case DISPID_AMBIENT_FORECOLOR:
276
pVarResult->vt = VT_I4;
277
pVarResult->lVal = (long) m_clrAmbientForeColor;
280
case DISPID_AMBIENT_BACKCOLOR:
281
pVarResult->vt = VT_I4;
282
pVarResult->lVal = (long) m_clrAmbientBackColor;
285
case DISPID_AMBIENT_LOCALEID:
286
pVarResult->vt = VT_I4;
287
pVarResult->lVal = (long) m_nAmbientLocale;
290
case DISPID_AMBIENT_USERMODE:
291
pVarResult->vt = VT_BOOL;
292
pVarResult->boolVal = m_window->m_bAmbientUserMode;
295
case DISPID_AMBIENT_SHOWGRABHANDLES:
296
pVarResult->vt = VT_BOOL;
297
pVarResult->boolVal = m_bAmbientShowGrabHandles;
300
case DISPID_AMBIENT_SHOWHATCHING:
301
pVarResult->vt = VT_BOOL;
302
pVarResult->boolVal = m_bAmbientShowHatching;
306
return DISP_E_MEMBERNOTFOUND;
312
//**************************IOleWindow***************************
313
HRESULT STDMETHODCALLTYPE GetWindow(HWND * phwnd)
317
(*phwnd) = m_hWndParent;
320
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL)
322
//**************************IOleInPlaceUIWindow*****************
323
HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprectBorder)
325
if (lprectBorder == NULL)
327
return INPLACE_E_NOTOOLSPACE;
329
HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
331
if (pborderwidths == NULL)
333
return INPLACE_E_NOTOOLSPACE;
335
HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS)
337
HRESULT STDMETHODCALLTYPE SetActiveObject(
338
IOleInPlaceActiveObject *pActiveObject, LPCOLESTR)
341
pActiveObject->AddRef();
343
m_window->m_oleInPlaceActiveObject = pActiveObject;
347
//********************IOleInPlaceFrame************************
349
STDMETHOD(InsertMenus)(HMENU, LPOLEMENUGROUPWIDTHS){return S_OK;}
350
STDMETHOD(SetMenu)(HMENU, HOLEMENU, HWND){ return S_OK;}
351
STDMETHOD(RemoveMenus)(HMENU){return S_OK;}
352
STDMETHOD(SetStatusText)(LPCOLESTR){ return S_OK;}
353
HRESULT STDMETHODCALLTYPE EnableModeless(BOOL){return S_OK;}
354
HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD)
356
// TODO: send an event with this id
357
if (m_window->m_oleInPlaceActiveObject.IsOk())
358
m_window->m_oleInPlaceActiveObject->TranslateAccelerator(lpmsg);
362
//*******************IOleInPlaceSite**************************
363
HRESULT STDMETHODCALLTYPE CanInPlaceActivate(){return S_OK;}
364
HRESULT STDMETHODCALLTYPE OnInPlaceActivate()
365
{ m_bInPlaceActive = true; return S_OK; }
366
HRESULT STDMETHODCALLTYPE OnUIActivate()
367
{ m_bUIActive = true; return S_OK; }
368
HRESULT STDMETHODCALLTYPE GetWindowContext(IOleInPlaceFrame **ppFrame,
369
IOleInPlaceUIWindow **ppDoc,
372
LPOLEINPLACEFRAMEINFO lpFrameInfo)
374
if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL ||
375
lprcClipRect == NULL || lpFrameInfo == NULL)
384
HRESULT hr = QueryInterface(IID_IOleInPlaceFrame, (void **) ppFrame);
390
hr = QueryInterface(IID_IOleInPlaceUIWindow, (void **) ppDoc);
393
(*ppFrame)->Release();
399
::GetClientRect(m_hWndParent, &rect);
402
lprcPosRect->left = lprcPosRect->top = 0;
403
lprcPosRect->right = rect.right;
404
lprcPosRect->bottom = rect.bottom;
408
lprcClipRect->left = lprcClipRect->top = 0;
409
lprcClipRect->right = rect.right;
410
lprcClipRect->bottom = rect.bottom;
413
memset(lpFrameInfo, 0, sizeof(OLEINPLACEFRAMEINFO));
414
lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
415
lpFrameInfo->hwndFrame = m_hWndParent;
419
HRESULT STDMETHODCALLTYPE Scroll(SIZE){return S_OK;}
420
HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL)
421
{ m_bUIActive = false; return S_OK; }
422
HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate()
423
{ m_bInPlaceActive = false; return S_OK; }
424
HRESULT STDMETHODCALLTYPE DiscardUndoState(){return S_OK;}
425
HRESULT STDMETHODCALLTYPE DeactivateAndUndo(){return S_OK; }
426
HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect)
428
if (m_window->m_oleInPlaceObject.IsOk() && lprcPosRect)
431
// Result of several hours and days of bug hunting -
432
// this is called by an object when it wants to resize
433
// itself to something different then our parent window -
436
// m_window->m_oleInPlaceObject->SetObjectRects(
437
// lprcPosRect, lprcPosRect);
439
::GetClientRect(m_hWndParent, &rcClient);
440
m_window->m_oleInPlaceObject->SetObjectRects(
441
&rcClient, &rcClient);
445
//*************************IOleInPlaceSiteEx***********************
446
HRESULT STDMETHODCALLTYPE OnInPlaceActivateEx(BOOL * pfNoRedraw, DWORD)
449
IRunnableObject* runnable = NULL;
450
HRESULT hr = QueryInterface(
451
IID_IRunnableObject, (void**)(& runnable));
454
runnable->LockRunning(TRUE, FALSE);
457
OleLockRunning(m_window->m_ActiveX, TRUE, FALSE);
460
(*pfNoRedraw) = FALSE;
464
HRESULT STDMETHODCALLTYPE OnInPlaceDeactivateEx(BOOL)
467
IRunnableObject* runnable = NULL;
468
HRESULT hr = QueryInterface(
469
IID_IRunnableObject, (void**)(& runnable));
472
runnable->LockRunning(FALSE, FALSE);
475
OleLockRunning(m_window->m_ActiveX, FALSE, FALSE);
479
STDMETHOD(RequestUIActivate)(){ return S_OK;}
480
//*************************IOleClientSite**************************
481
HRESULT STDMETHODCALLTYPE SaveObject(){return S_OK;}
482
const char *OleGetMonikerToStr(DWORD dwAssign)
486
case OLEGETMONIKER_ONLYIFTHERE : return "OLEGETMONIKER_ONLYIFTHERE";
487
case OLEGETMONIKER_FORCEASSIGN : return "OLEGETMONIKER_FORCEASSIGN";
488
case OLEGETMONIKER_UNASSIGN : return "OLEGETMONIKER_UNASSIGN";
489
case OLEGETMONIKER_TEMPFORUSER : return "OLEGETMONIKER_TEMPFORUSER";
490
default : return "Bad Enum";
494
const char *OleGetWhicMonikerStr(DWORD dwWhichMoniker)
496
switch(dwWhichMoniker)
498
case OLEWHICHMK_CONTAINER : return "OLEWHICHMK_CONTAINER";
499
case OLEWHICHMK_OBJREL : return "OLEWHICHMK_OBJREL";
500
case OLEWHICHMK_OBJFULL : return "OLEWHICHMK_OBJFULL";
501
default : return "Bad Enum";
504
STDMETHOD(GetMoniker)(DWORD, DWORD, IMoniker **){return E_FAIL;}
505
HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER * ppContainer)
507
if (ppContainer == NULL)
509
HRESULT hr = QueryInterface(
510
IID_IOleContainer, (void**)(ppContainer));
511
wxASSERT(SUCCEEDED(hr));
514
HRESULT STDMETHODCALLTYPE ShowObject()
516
if (m_window->m_oleObjectHWND)
517
::ShowWindow(m_window->m_oleObjectHWND, SW_SHOW);
520
STDMETHOD(OnShowWindow)(BOOL){return S_OK;}
521
STDMETHOD(RequestNewObjectLayout)(){return E_NOTIMPL;}
522
//********************IParseDisplayName***************************
523
HRESULT STDMETHODCALLTYPE ParseDisplayName(
524
IBindCtx *, LPOLESTR, ULONG *, IMoniker **){return E_NOTIMPL;}
525
//********************IOleContainer*******************************
526
STDMETHOD(EnumObjects)(DWORD, IEnumUnknown **){return E_NOTIMPL;}
527
HRESULT STDMETHODCALLTYPE LockContainer(BOOL){return S_OK;}
528
//********************IOleItemContainer***************************
529
HRESULT STDMETHODCALLTYPE
530
#if 0 // defined(__WXWINCE__) && __VISUALC__ < 1400
532
#elif defined(_UNICODE)
537
(LPOLESTR pszItem, DWORD, IBindCtx *, REFIID, void ** ppvObject)
539
if (pszItem == NULL || ppvObject == NULL)
542
return MK_E_NOOBJECT;
544
HRESULT STDMETHODCALLTYPE GetObjectStorage(
545
LPOLESTR pszItem, IBindCtx * , REFIID, void ** ppvStorage)
547
if (pszItem == NULL || ppvStorage == NULL)
550
return MK_E_NOOBJECT;
552
HRESULT STDMETHODCALLTYPE IsRunning(LPOLESTR pszItem)
556
return MK_E_NOOBJECT;
558
//***********************IOleControlSite*****************************
559
HRESULT STDMETHODCALLTYPE OnControlInfoChanged()
561
HRESULT STDMETHODCALLTYPE LockInPlaceActive(BOOL fLock)
563
m_bInPlaceLocked = (fLock) ? true : false;
566
HRESULT STDMETHODCALLTYPE GetExtendedControl(IDispatch **)
568
HRESULT STDMETHODCALLTYPE TransformCoords(
569
POINTL * pPtlHimetric, POINTF * pPtfContainer, DWORD)
571
if (pPtlHimetric == NULL || pPtfContainer == NULL)
575
HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG, DWORD)
577
HRESULT STDMETHODCALLTYPE OnFocus(BOOL){return S_OK;}
578
HRESULT STDMETHODCALLTYPE ShowPropertyFrame(){return E_NOTIMPL;}
579
//**************************IOleCommandTarget***********************
580
HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *, ULONG cCmds,
581
OLECMD prgCmds[], OLECMDTEXT *)
583
if (prgCmds == NULL) return E_INVALIDARG;
584
for (ULONG nCmd = 0; nCmd < cCmds; nCmd++)
586
// unsupported by default
587
prgCmds[nCmd].cmdf = 0;
589
return OLECMDERR_E_UNKNOWNGROUP;
592
HRESULT STDMETHODCALLTYPE Exec(const GUID *, DWORD,
593
DWORD, VARIANTARG *, VARIANTARG *)
594
{return OLECMDERR_E_NOTSUPPORTED;}
596
//**********************IAdviseSink************************************
597
void STDMETHODCALLTYPE OnDataChange(FORMATETC *, STGMEDIUM *) {}
598
void STDMETHODCALLTYPE OnViewChange(DWORD, LONG) {}
599
void STDMETHODCALLTYPE OnRename(IMoniker *){}
600
void STDMETHODCALLTYPE OnSave(){}
601
void STDMETHODCALLTYPE OnClose(){}
603
//**********************IOleDocumentSite***************************
604
HRESULT STDMETHODCALLTYPE ActivateMe(
605
IOleDocumentView __RPC_FAR *pViewToActivate)
607
wxAutoIOleInPlaceSite inPlaceSite(
608
IID_IOleInPlaceSite, (IDispatch *) this);
609
if (!inPlaceSite.IsOk())
614
m_window->m_docView = pViewToActivate;
615
m_window->m_docView->SetInPlaceSite(inPlaceSite);
619
wxAutoIOleDocument oleDoc(
620
IID_IOleDocument, m_window->m_oleObject);
624
HRESULT hr = oleDoc->CreateView(inPlaceSite, NULL,
625
0, m_window->m_docView.GetRef());
629
m_window->m_docView->SetInPlaceSite(inPlaceSite);
632
m_window->m_docView->UIActivate(TRUE);
636
friend bool QueryClientSiteInterface(FrameSite *self, REFIID iid, void **_interface, const char *&desc)
638
return self->m_window->QueryClientSiteInterface(iid,_interface,desc);
642
wxActiveXContainer * m_window;
647
bool m_bSupportsWindowlessActivation;
648
bool m_bInPlaceLocked;
649
bool m_bInPlaceActive;
653
LCID m_nAmbientLocale;
654
COLORREF m_clrAmbientForeColor;
655
COLORREF m_clrAmbientBackColor;
656
bool m_bAmbientShowHatching;
657
bool m_bAmbientShowGrabHandles;
658
bool m_bAmbientAppearance;
661
DEFINE_OLE_TABLE(FrameSite)
662
OLE_INTERFACE(IID_IUnknown, IOleClientSite)
663
OLE_IINTERFACE(IOleClientSite)
664
OLE_INTERFACE(IID_IOleWindow, IOleInPlaceSite)
665
OLE_IINTERFACE(IOleInPlaceSite)
666
OLE_IINTERFACE(IOleInPlaceSiteEx)
667
OLE_IINTERFACE(IOleInPlaceUIWindow)
668
OLE_IINTERFACE(IOleInPlaceFrame)
669
OLE_IINTERFACE(IParseDisplayName)
670
OLE_IINTERFACE(IOleContainer)
671
OLE_IINTERFACE(IOleItemContainer)
672
OLE_IINTERFACE(IDispatch)
673
OLE_IINTERFACE(IOleCommandTarget)
674
OLE_IINTERFACE(IOleDocumentSite)
675
OLE_IINTERFACE(IAdviseSink)
676
OLE_IINTERFACE(IOleControlSite)
677
OLE_INTERFACE_CUSTOM(QueryClientSiteInterface)
681
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
685
// Handles and sends activex events received from the ActiveX control
686
// to the appropriate wxEvtHandler
688
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
689
class wxActiveXEvents : public IDispatch
692
DECLARE_OLE_UNKNOWN(wxActiveXEvents);
695
wxActiveXContainer *m_activeX;
699
friend bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc);
703
// a pointer to this static variable is used as an 'invalid_entry_marker'
704
// wxVariants containing a void* to this variables are 'empty' in the sense
705
// that the actual ActiveX OLE parameter has not been converted and inserted
707
static wxVariant ms_invalidEntryMarker;
709
wxActiveXEvents(wxActiveXContainer *ax) : m_activeX(ax), m_haveCustomId(false) {}
710
wxActiveXEvents(wxActiveXContainer *ax, REFIID iid) : m_activeX(ax), m_customId(iid), m_haveCustomId(true) {}
711
virtual ~wxActiveXEvents()
716
STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR**, unsigned int, LCID, DISPID*)
721
STDMETHODIMP GetTypeInfo(unsigned int, LCID, ITypeInfo**)
726
STDMETHODIMP GetTypeInfoCount(unsigned int*)
732
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid,
734
WORD wFlags, DISPPARAMS * pDispParams,
735
VARIANT * pVarResult, EXCEPINFO * pExcepInfo,
736
unsigned int * puArgErr)
738
if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
746
wxActiveXEvent event;
747
event.SetEventType(wxEVT_ACTIVEX);
748
// Create an empty list of Variants
749
// Note that the event parameters use lazy evaluation
750
// They are not actually created until wxActiveXEvent::operator[] is called
751
event.m_params.NullList();
752
event.m_dispid = dispIdMember;
754
// save the native (MSW) event parameters for event handlers that need to access them
755
// this can be done on the stack since wxActiveXEvent is also allocated on the stack
756
wxActiveXEventNativeMSW eventParameters(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
757
event.SetClientData(&eventParameters);
759
// The event parameters are not copied to event.m_params until they are actually
760
// referenced in wxActiveXEvent::operator[]
761
// This increases performance and avoids error messages and/or crashes
762
// when the event has parameters that are not (yet or never) supported
763
// by wxConvertOleToVariant
765
// process the events from the activex method
766
m_activeX->ProcessEvent(event);
767
for (DWORD i = 0; i < pDispParams->cArgs; i++)
769
size_t params_index = pDispParams->cArgs - i - 1;
770
if (params_index < event.m_params.GetCount()) {
771
wxVariant &vx = event.m_params[params_index];
772
// copy the result back to pDispParams only if the event has been accessed
773
// i.e. if vx != ms_invalidEntryMarker
774
if (!vx.IsType(wxActiveXEvents::ms_invalidEntryMarker.GetType()) || vx!=ms_invalidEntryMarker) {
775
VARIANTARG& va = pDispParams->rgvarg[i];
776
wxConvertVariantToOle(vx, va);
781
if(event.GetSkipped())
782
return DISP_E_MEMBERNOTFOUND;
790
// just a unique global variable
791
const int invalid_entry_marker = 0;
794
wxVariant wxActiveXEvents::ms_invalidEntryMarker((void*)&invalid_entry_marker);
796
size_t wxActiveXEvent::ParamCount() const
798
wxActiveXEventNativeMSW *native=GetNativeParameters();
799
// 'native' will always be != if the event has been created
800
// for an actual active X event.
801
// But it may be zero if the event has been created by wx program code.
803
return native->pDispParams ? native->pDispParams->cArgs : 0;
805
return m_params.GetCount();
808
wxVariant &wxActiveXEvent::operator [](size_t idx)
810
wxASSERT(idx < ParamCount());
811
wxActiveXEventNativeMSW *native=GetNativeParameters();
812
// 'native' will always be != if the event has been created
813
// for an actual active X event.
814
// But it may be zero if the event has been created by wx program code.
817
while ( m_params.GetCount()<=idx )
819
m_params.Append(wxActiveXEvents::ms_invalidEntryMarker);
822
wxVariant& vx = m_params[idx];
823
if ( vx.IsType(wxActiveXEvents::ms_invalidEntryMarker.GetType()) &&
824
vx == wxActiveXEvents::ms_invalidEntryMarker)
826
// copy the _real_ parameter into this one
827
// NOTE: m_params stores the parameters in *reverse* order.
828
// Whyever, but this was the case in the original implementation of
829
// wxActiveXEvents::Invoke
830
// Keep this convention.
831
VARIANTARG& va = native->pDispParams->rgvarg[ native->pDispParams->cArgs - idx - 1 ];
832
wxConvertOleToVariant(va, vx);
836
return m_params[idx];
839
bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc)
841
if (self->m_haveCustomId && IsEqualIID(iid, self->m_customId))
843
*_interface = (IUnknown *) (IDispatch *) self;
844
desc = "Custom Dispatch Interface";
851
DEFINE_OLE_TABLE(wxActiveXEvents)
852
OLE_IINTERFACE(IUnknown)
853
OLE_INTERFACE(IID_IDispatch, IDispatch)
854
OLE_INTERFACE_CUSTOM(wxActiveXEventsInterface)
857
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
859
// wxActiveXContainer
861
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
863
//---------------------------------------------------------------------------
864
// wxActiveXContainer Constructor
866
// Initializes members and creates the native ActiveX container
867
//---------------------------------------------------------------------------
868
wxActiveXContainer::wxActiveXContainer(wxWindow * parent,
869
REFIID iid, IUnknown* pUnk)
870
: m_realparent(parent)
872
m_bAmbientUserMode = true;
873
m_docAdviseCookie = 0;
874
CreateActiveX(iid, pUnk);
877
//---------------------------------------------------------------------------
878
// wxActiveXContainer Destructor
880
// Destroys members (the FrameSite et al. are destroyed implicitly
881
// through COM ref counting)
882
//---------------------------------------------------------------------------
883
wxActiveXContainer::~wxActiveXContainer()
885
// disconnect connection points
886
if (m_oleInPlaceObject.IsOk())
888
m_oleInPlaceObject->InPlaceDeactivate();
889
m_oleInPlaceObject->UIDeactivate();
892
if (m_oleObject.IsOk())
894
if (m_docAdviseCookie != 0)
895
m_oleObject->Unadvise(m_docAdviseCookie);
898
OLEIVERB_HIDE, NULL, m_clientSite, 0, (HWND) GetHWND(), NULL);
899
m_oleObject->Close(OLECLOSE_NOSAVE);
900
m_oleObject->SetClientSite(NULL);
903
// m_clientSite uses m_frameSite so destroy it first
907
// our window doesn't belong to us, don't destroy it
911
// VZ: we might want to really report an error instead of just asserting here
913
#define CHECK_HR(hr) \
914
wxASSERT_LEVEL_2_MSG( SUCCEEDED(hr), \
915
wxString::Format("HRESULT = %X", (unsigned)(hr)) )
917
#define CHECK_HR(hr) wxUnusedVar(hr)
920
//---------------------------------------------------------------------------
921
// wxActiveXContainer::CreateActiveX
923
// Actually creates the ActiveX container through the FrameSite
924
// and sets up ActiveX events
926
// TODO: Document this more
927
//---------------------------------------------------------------------------
928
void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
931
hret = m_ActiveX.QueryInterface(iid, pUnk);
935
m_frameSite = new FrameSite(m_realparent, this);
937
hret = m_clientSite.QueryInterface(
938
IID_IOleClientSite, (IDispatch *) m_frameSite);
941
wxAutoIAdviseSink adviseSink(IID_IAdviseSink, (IDispatch *) m_frameSite);
942
wxASSERT(adviseSink.IsOk());
944
// Get Dispatch interface
945
hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX);
949
// SETUP TYPEINFO AND ACTIVEX EVENTS
952
// get type info via class info
953
wxAutoIProvideClassInfo classInfo(IID_IProvideClassInfo, m_ActiveX);
954
wxASSERT(classInfo.IsOk());
957
wxAutoITypeInfo typeInfo;
958
hret = classInfo->GetClassInfo(typeInfo.GetRef());
960
wxASSERT(typeInfo.IsOk());
964
hret = typeInfo->GetTypeAttr(&ta);
967
// this should be a TKIND_COCLASS
968
wxASSERT(ta->typekind == TKIND_COCLASS);
970
// iterate contained interfaces
971
for (int i = 0; i < ta->cImplTypes; i++)
975
// get dispatch type info handle
976
hret = typeInfo->GetRefTypeOfImplType(i, &rt);
977
if (! SUCCEEDED(hret))
980
// get dispatch type info interface
982
hret = typeInfo->GetRefTypeInfo(rt, ti.GetRef());
988
// check if default event sink
989
bool defEventSink = false;
990
int impTypeFlags = 0;
991
typeInfo->GetImplTypeFlags(i, &impTypeFlags);
993
if (impTypeFlags & IMPLTYPEFLAG_FDEFAULT)
995
if (impTypeFlags & IMPLTYPEFLAG_FSOURCE)
997
// WXOLE_TRACEOUT("Default Event Sink");
999
if (impTypeFlags & IMPLTYPEFLAG_FDEFAULTVTABLE)
1001
// WXOLE_TRACEOUT("*ERROR* - Default Event Sink is via vTable");
1002
defEventSink = false;
1003
wxFAIL_MSG(wxT("Default event sink is in vtable!"));
1009
// wxAutoOleInterface<> assumes a ref has already been added
1011
TYPEATTR *ta = NULL;
1012
hret = ti->GetTypeAttr(&ta);
1015
if (ta->typekind == TKIND_DISPATCH)
1017
// WXOLE_TRACEOUT("GUID = " << GetIIDName(ta->guid).c_str());
1020
wxAutoIConnectionPoint cp;
1021
DWORD adviseCookie = 0;
1023
wxAutoIConnectionPointContainer cpContainer(IID_IConnectionPointContainer, m_ActiveX);
1024
wxASSERT( cpContainer.IsOk());
1027
cpContainer->FindConnectionPoint(ta->guid, cp.GetRef());
1029
// Notice that the return value of CONNECT_E_NOCONNECTION is
1030
// expected if the interface doesn't support connection points.
1031
if ( hret != CONNECT_E_NOCONNECTION )
1038
wxActiveXEvents * const
1039
events = new wxActiveXEvents(this, ta->guid);
1040
hret = cp->Advise(events, &adviseCookie);
1042
// We don't need this object any more and cp will keep a
1043
// reference to it if it needs it, i.e. if Advise()
1052
ti->ReleaseTypeAttr(ta);
1056
typeInfo->ReleaseTypeAttr(ta);
1062
// Get IOleObject interface
1063
hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX);
1066
// get IViewObject Interface
1067
hret = m_viewObject.QueryInterface(IID_IViewObject, m_ActiveX);
1071
m_docAdviseCookie = 0;
1072
hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie);
1076
// hret = m_viewObject->SetAdvise(DVASPECT_CONTENT, 0, adviseSink);
1077
m_oleObject->SetHostNames(L"wxActiveXContainer", NULL);
1078
OleSetContainedObject(m_oleObject, TRUE);
1079
OleRun(m_oleObject);
1082
// Get IOleInPlaceObject interface
1083
hret = m_oleInPlaceObject.QueryInterface(
1084
IID_IOleInPlaceObject, m_ActiveX);
1089
m_oleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
1092
// set client site first ?
1093
if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
1094
m_oleObject->SetClientSite(m_clientSite);
1098
wxAutoIPersistStreamInit
1099
pPersistStreamInit(IID_IPersistStreamInit, m_oleObject);
1101
if (pPersistStreamInit.IsOk())
1103
hret = pPersistStreamInit->InitNew();
1107
if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
1108
m_oleObject->SetClientSite(m_clientSite);
1111
m_oleObjectHWND = 0;
1113
if (m_oleInPlaceObject.IsOk())
1115
hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
1116
if (SUCCEEDED(hret))
1117
::SetActiveWindow(m_oleObjectHWND);
1121
if (! (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME))
1124
wxCopyRectToRECT(m_realparent->GetClientSize(), posRect);
1126
if (posRect.right > 0 && posRect.bottom > 0 &&
1127
m_oleInPlaceObject.IsOk())
1129
m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
1132
hret = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL,
1133
m_clientSite, 0, (HWND)m_realparent->GetHWND(), &posRect);
1136
hret = m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0,
1137
(HWND)m_realparent->GetHWND(), &posRect);
1141
if (! m_oleObjectHWND && m_oleInPlaceObject.IsOk())
1143
hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
1147
if (m_oleObjectHWND)
1149
::SetActiveWindow(m_oleObjectHWND);
1150
::ShowWindow(m_oleObjectHWND, SW_SHOW);
1152
this->AssociateHandle(m_oleObjectHWND);
1153
this->Reparent(m_realparent);
1155
wxWindow* pWnd = m_realparent;
1156
int id = m_realparent->GetId();
1158
pWnd->Connect(id, wxEVT_SIZE,
1159
wxSizeEventHandler(wxActiveXContainer::OnSize), 0, this);
1160
// this->Connect(GetId(), wxEVT_PAINT,
1161
// wxPaintEventHandler(wxActiveXContainer::OnPaint), 0, this);
1162
pWnd->Connect(id, wxEVT_SET_FOCUS,
1163
wxFocusEventHandler(wxActiveXContainer::OnSetFocus), 0, this);
1164
pWnd->Connect(id, wxEVT_KILL_FOCUS,
1165
wxFocusEventHandler(wxActiveXContainer::OnKillFocus), 0, this);
1169
//---------------------------------------------------------------------------
1170
// wxActiveXContainer::OnSize
1172
// Called when the parent is resized - we need to do this to actually
1173
// move the ActiveX control to where the parent is
1174
//---------------------------------------------------------------------------
1175
void wxActiveXContainer::OnSize(wxSizeEvent& event)
1178
GetParent()->GetClientSize(&w, &h);
1186
if (w <= 0 || h <= 0)
1189
// extents are in HIMETRIC units
1190
if (m_oleObject.IsOk())
1194
PixelsToHimetric(sz);
1198
m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2);
1199
if (sz2.cx != sz.cx || sz.cy != sz2.cy)
1200
m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
1204
if (m_oleInPlaceObject.IsOk())
1205
m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
1210
//---------------------------------------------------------------------------
1211
// wxActiveXContainer::OnPaint
1213
// Called when the parent is resized - repaints the ActiveX control
1214
//---------------------------------------------------------------------------
1215
void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
1218
// Draw only when control is windowless or deactivated
1222
GetParent()->GetSize(&w, &h);
1229
#if !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
1230
::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
1232
::InvalidateRect(m_oleObjectHWND, NULL, false);
1234
RECTL *prcBounds = (RECTL *) &posRect;
1235
wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl );
1236
m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
1237
(HDC)msw->GetHDC(), prcBounds, NULL, NULL, 0);
1241
//---------------------------------------------------------------------------
1242
// wxActiveXContainer::OnSetFocus
1244
// Called when the focus is set on the parent - activates the activex control
1245
//---------------------------------------------------------------------------
1246
void wxActiveXContainer::OnSetFocus(wxFocusEvent& event)
1248
if (m_oleInPlaceActiveObject.IsOk())
1249
m_oleInPlaceActiveObject->OnFrameWindowActivate(TRUE);
1254
//---------------------------------------------------------------------------
1255
// wxActiveXContainer::OnKillFocus
1257
// Called when the focus is killed on the parent -
1258
// deactivates the activex control
1259
//---------------------------------------------------------------------------
1260
void wxActiveXContainer::OnKillFocus(wxFocusEvent& event)
1262
if (m_oleInPlaceActiveObject.IsOk())
1263
m_oleInPlaceActiveObject->OnFrameWindowActivate(FALSE);
1268
//---------------------------------------------------------------------------
1269
// wxActiveXContainer::MSWTranslateMessage
1271
// Called for every message that needs to be translated.
1272
// Some controls might need more keyboard keys to process (CTRL-C, CTRL-A ect),
1273
// In that case TranslateAccelerator should always be called first.
1274
//---------------------------------------------------------------------------
1275
bool wxActiveXContainer::MSWTranslateMessage(WXMSG* pMsg)
1277
if(m_oleInPlaceActiveObject.IsOk() && m_oleInPlaceActiveObject->TranslateAccelerator(pMsg) == S_OK)
1281
return wxWindow::MSWTranslateMessage(pMsg);
1284
//---------------------------------------------------------------------------
1285
// wxActiveXContainer::QueryClientSiteInterface
1287
// Called in the host's site's query method for other interfaces.
1288
//---------------------------------------------------------------------------
1289
bool wxActiveXContainer::QueryClientSiteInterface(REFIID iid, void **_interface, const char *&desc)
1292
wxUnusedVar(_interface);
1297
#endif // wxUSE_ACTIVEX