1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/ole/activex.cpp
3 // Purpose: wxActiveXContainer implementation
4 // Author: Ryan Norton <wxprojects@comcast.net>, Lindsay Mathieson <???>
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;
1114 if (! (dwMiscStatus
& OLEMISC_INVISIBLEATRUNTIME
))
1116 hret
= m_oleObject
->DoVerb(OLEIVERB_INPLACEACTIVATE
, NULL
,
1117 m_clientSite
, 0, (HWND
)m_realparent
->GetHWND(), NULL
);
1120 if (m_oleInPlaceObject
.IsOk())
1122 hret
= m_oleInPlaceObject
->GetWindow(&m_oleObjectHWND
);
1124 ::SetActiveWindow(m_oleObjectHWND
);
1128 wxCopyRectToRECT(m_realparent
->GetClientSize(), posRect
);
1130 if (posRect
.right
> 0 && posRect
.bottom
> 0 &&
1131 m_oleInPlaceObject
.IsOk())
1133 m_oleInPlaceObject
->SetObjectRects(&posRect
, &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