1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/msw/ole/activex.cpp
3 // Purpose:     wxActiveXContainer implementation
4 // Author:      Ryan Norton <wxprojects@comcast.net>, Lindsay Mathieson <???>
5 // Modified by:
6 // Created:     11/07/04
7 // Copyright:   (c) 2003 Lindsay Mathieson, (c) 2005 Ryan Norton
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 #include "wx/wxprec.h"
20 
21 #ifdef __BORLANDC__
22     #pragma hdrstop
23 #endif
24 
25 #if wxUSE_ACTIVEX
26 
27 #ifndef WX_PRECOMP
28     #include "wx/dcclient.h"
29     #include "wx/math.h"
30 #endif
31 
32 #include "wx/msw/dc.h"
33 
34 #include "wx/msw/ole/activex.h"
35 #include "wx/msw/private.h" // for wxCopyRectToRECT
36 
37 // autointerfaces that we only use here
38 typedef wxAutoOleInterface<IOleInPlaceSite> wxAutoIOleInPlaceSite;
39 typedef wxAutoOleInterface<IOleDocument> wxAutoIOleDocument;
40 typedef wxAutoOleInterface<IPersistStreamInit> wxAutoIPersistStreamInit;
41 typedef wxAutoOleInterface<IAdviseSink> wxAutoIAdviseSink;
42 typedef wxAutoOleInterface<IProvideClassInfo> wxAutoIProvideClassInfo;
43 typedef wxAutoOleInterface<ITypeInfo> wxAutoITypeInfo;
44 typedef wxAutoOleInterface<IConnectionPoint> wxAutoIConnectionPoint;
45 typedef wxAutoOleInterface<IConnectionPointContainer> wxAutoIConnectionPointContainer;
46 
47 wxDEFINE_EVENT( wxEVT_ACTIVEX, wxActiveXEvent );
48 
49 // Ole class helpers (sort of MFC-like) from wxActiveX
50 #define DECLARE_OLE_UNKNOWN(cls)\
51     private:\
52     class TAutoInitInt\
53     {\
54         public:\
55         LONG l;\
56         TAutoInitInt() : l(1) {}\
57     };\
58     TAutoInitInt refCount, lockCount;\
59     static void _GetInterface(cls *self, REFIID iid, void **_interface, const char *&desc);\
60     public:\
61     LONG GetRefCount();\
62     HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject);\
63     ULONG STDMETHODCALLTYPE AddRef();\
64     ULONG STDMETHODCALLTYPE Release();\
65     ULONG STDMETHODCALLTYPE AddLock();\
66     ULONG STDMETHODCALLTYPE ReleaseLock()
67 
68 #define DEFINE_OLE_TABLE(cls)\
69     LONG cls::GetRefCount() {return refCount.l;}\
70     HRESULT STDMETHODCALLTYPE cls::QueryInterface(REFIID iid, void ** ppvObject)\
71     {\
72         if (! ppvObject)\
73         {\
74             return E_FAIL;\
75         }\
76         const char *desc = NULL;\
77         cls::_GetInterface(this, iid, ppvObject, desc);\
78         if (! *ppvObject)\
79         {\
80             return E_NOINTERFACE;\
81         }\
82         ((IUnknown * )(*ppvObject))->AddRef();\
83         return S_OK;\
84     }\
85     ULONG STDMETHODCALLTYPE cls::AddRef()\
86     {\
87         InterlockedIncrement(&refCount.l);\
88         return refCount.l;\
89     }\
90     ULONG STDMETHODCALLTYPE cls::Release()\
91     {\
92         if (refCount.l > 0)\
93         {\
94             InterlockedDecrement(&refCount.l);\
95             if (refCount.l == 0)\
96             {\
97                 delete this;\
98                 return 0;\
99             }\
100             return refCount.l;\
101         }\
102         else\
103             return 0;\
104     }\
105     ULONG STDMETHODCALLTYPE cls::AddLock()\
106     {\
107         InterlockedIncrement(&lockCount.l);\
108         return lockCount.l;\
109     }\
110     ULONG STDMETHODCALLTYPE cls::ReleaseLock()\
111     {\
112         if (lockCount.l > 0)\
113         {\
114             InterlockedDecrement(&lockCount.l);\
115             return lockCount.l;\
116         }\
117         else\
118             return 0;\
119     }\
120     DEFINE_OLE_BASE(cls)
121 
122 #define DEFINE_OLE_BASE(cls)\
123     void cls::_GetInterface(cls *self, REFIID iid, void **_interface, const char *&desc)\
124     {\
125         *_interface = NULL;\
126         desc = NULL;
127 
128 #define OLE_INTERFACE(_iid, _type)\
129     if (IsEqualIID(iid, _iid))\
130     {\
131         *_interface = (IUnknown *) (_type *) self;\
132         desc = # _iid;\
133         return;\
134     }
135 
136 #define OLE_IINTERFACE(_face) OLE_INTERFACE(IID_##_face, _face)
137 
138 #define OLE_INTERFACE_CUSTOM(func)\
139     if (func(self, iid, _interface, desc))\
140     {\
141         return;\
142     }
143 
144 #define END_OLE_TABLE\
145     }
146 
147 // ============================================================================
148 // implementation
149 // ============================================================================
150 
151 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
152 // PixelsToHimetric
153 //
154 // Utility to convert from pixels to the himetric values in some COM methods
155 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
156 
157 
158 #define HIMETRIC_PER_INCH   2540
159 #define MAP_PIX_TO_LOGHIM(x,ppli)   MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
160 
PixelsToHimetric(SIZEL & sz)161 static void PixelsToHimetric(SIZEL &sz)
162 {
163     static int logX = 0;
164     static int logY = 0;
165 
166     if (logY == 0)
167     {
168         // initaliase
169         HDC dc = GetDC(NULL);
170         logX = GetDeviceCaps(dc, LOGPIXELSX);
171         logY = GetDeviceCaps(dc, LOGPIXELSY);
172         ReleaseDC(NULL, dc);
173     };
174 
175 #define HIMETRIC_INCH   2540
176 #define CONVERT(x, logpixels)   wxMulDivInt32(HIMETRIC_INCH, (x), (logpixels))
177 
178     sz.cx = CONVERT(sz.cx, logX);
179     sz.cy = CONVERT(sz.cy, logY);
180 
181 #undef CONVERT
182 #undef HIMETRIC_INCH
183 }
184 
185 
186 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
187 //
188 // FrameSite
189 //
190 // Handles the actual wxActiveX container implementation
191 //
192 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
193 class FrameSite :
194     public IOleClientSite,
195     public IOleInPlaceSiteEx,
196     public IOleInPlaceFrame,
197     public IOleItemContainer,
198     public IDispatch,
199     public IOleCommandTarget,
200     public IOleDocumentSite,
201     public IAdviseSink,
202     public IOleControlSite
203 {
204 private:
205     DECLARE_OLE_UNKNOWN(FrameSite);
206 
207 public:
FrameSite(wxWindow * win,wxActiveXContainer * win2)208     FrameSite(wxWindow * win, wxActiveXContainer * win2)
209     {
210         m_window = win2;
211         m_bSupportsWindowlessActivation = true;
212         m_bInPlaceLocked = false;
213         m_bUIActive = false;
214         m_bInPlaceActive = false;
215         m_bWindowless = false;
216 
217         m_nAmbientLocale = 0;
218         m_clrAmbientForeColor = ::GetSysColor(COLOR_WINDOWTEXT);
219         m_clrAmbientBackColor = ::GetSysColor(COLOR_WINDOW);
220         m_bAmbientShowHatching = true;
221         m_bAmbientShowGrabHandles = true;
222         m_bAmbientAppearance = true;
223 
224         m_hDCBuffer = NULL;
225         m_hWndParent = (HWND)win->GetHWND();
226     }
~FrameSite()227     virtual ~FrameSite(){}
228     //***************************IDispatch*****************************
GetIDsOfNames(REFIID,OLECHAR **,unsigned int,LCID,DISPID *)229     HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID, OLECHAR ** ,
230                                             unsigned int , LCID ,
231                                             DISPID * )
232     {   return E_NOTIMPL;   }
STDMETHOD(GetTypeInfo)233     STDMETHOD(GetTypeInfo)(unsigned int, LCID, ITypeInfo **)
234     {   return E_NOTIMPL;   }
GetTypeInfoCount(unsigned int *)235     HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int *)
236     {   return E_NOTIMPL;   }
Invoke(DISPID dispIdMember,REFIID,LCID,WORD wFlags,DISPPARAMS *,VARIANT * pVarResult,EXCEPINFO *,unsigned int *)237     HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID, LCID,
238                             WORD wFlags, DISPPARAMS *,
239                             VARIANT * pVarResult, EXCEPINFO *,
240                             unsigned int *)
241     {
242         if (!(wFlags & DISPATCH_PROPERTYGET))
243             return S_OK;
244 
245         if (pVarResult == NULL)
246             return E_INVALIDARG;
247 
248         //The most common case is boolean, use as an initial type
249         V_VT(pVarResult) = VT_BOOL;
250 
251         switch (dispIdMember)
252         {
253             case DISPID_AMBIENT_MESSAGEREFLECT:
254                 V_BOOL(pVarResult)= VARIANT_FALSE;
255                 return S_OK;
256 
257             case DISPID_AMBIENT_DISPLAYASDEFAULT:
258                 V_BOOL(pVarResult)= VARIANT_TRUE;
259                 return S_OK;
260 
261             case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
262                 V_BOOL(pVarResult) = VARIANT_TRUE;
263                 return S_OK;
264 
265             case DISPID_AMBIENT_SILENT:
266                 V_BOOL(pVarResult)= VARIANT_TRUE;
267                 return S_OK;
268 
269             case DISPID_AMBIENT_APPEARANCE:
270                 pVarResult->vt = VT_BOOL;
271                 pVarResult->boolVal = m_bAmbientAppearance ? VARIANT_TRUE : VARIANT_FALSE;
272                 break;
273 
274             case DISPID_AMBIENT_FORECOLOR:
275                 pVarResult->vt = VT_I4;
276                 pVarResult->lVal = (long) m_clrAmbientForeColor;
277                 break;
278 
279             case DISPID_AMBIENT_BACKCOLOR:
280                 pVarResult->vt = VT_I4;
281                 pVarResult->lVal = (long) m_clrAmbientBackColor;
282                 break;
283 
284             case DISPID_AMBIENT_LOCALEID:
285                 pVarResult->vt = VT_I4;
286                 pVarResult->lVal = (long) m_nAmbientLocale;
287                 break;
288 
289             case DISPID_AMBIENT_USERMODE:
290                 pVarResult->vt = VT_BOOL;
291                 pVarResult->boolVal = m_window->m_bAmbientUserMode ? VARIANT_TRUE : VARIANT_FALSE;
292                 break;
293 
294             case DISPID_AMBIENT_SHOWGRABHANDLES:
295                 pVarResult->vt = VT_BOOL;
296                 pVarResult->boolVal = m_bAmbientShowGrabHandles ? VARIANT_TRUE : VARIANT_FALSE;
297                 break;
298 
299             case DISPID_AMBIENT_SHOWHATCHING:
300                 pVarResult->vt = VT_BOOL;
301                 pVarResult->boolVal = m_bAmbientShowHatching ? VARIANT_TRUE : VARIANT_FALSE;
302                 break;
303 
304             default:
305                 return DISP_E_MEMBERNOTFOUND;
306         }
307 
308         return S_OK;
309     }
310 
311     //**************************IOleWindow***************************
GetWindow(HWND * phwnd)312     HRESULT STDMETHODCALLTYPE GetWindow(HWND * phwnd)
313     {
314         if (phwnd == NULL)
315             return E_INVALIDARG;
316         (*phwnd) = m_hWndParent;
317         return S_OK;
318     }
ContextSensitiveHelp(BOOL)319     HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL)
320     {return S_OK;}
321     //**************************IOleInPlaceUIWindow*****************
GetBorder(LPRECT lprectBorder)322     HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprectBorder)
323     {
324         if (lprectBorder == NULL)
325             return E_INVALIDARG;
326         return INPLACE_E_NOTOOLSPACE;
327     }
RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)328     HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
329     {
330         if (pborderwidths == NULL)
331             return E_INVALIDARG;
332         return INPLACE_E_NOTOOLSPACE;
333     }
SetBorderSpace(LPCBORDERWIDTHS)334     HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS)
335     {return S_OK;}
SetActiveObject(IOleInPlaceActiveObject * pActiveObject,LPCOLESTR)336     HRESULT STDMETHODCALLTYPE SetActiveObject(
337         IOleInPlaceActiveObject *pActiveObject, LPCOLESTR)
338     {
339         if (pActiveObject)
340             pActiveObject->AddRef();
341 
342         m_window->m_oleInPlaceActiveObject = pActiveObject;
343         return S_OK;
344     }
345 
346     //********************IOleInPlaceFrame************************
347 
STDMETHOD(InsertMenus)348     STDMETHOD(InsertMenus)(HMENU, LPOLEMENUGROUPWIDTHS){return S_OK;}
STDMETHOD(SetMenu)349     STDMETHOD(SetMenu)(HMENU, HOLEMENU, HWND){  return S_OK;}
STDMETHOD(RemoveMenus)350     STDMETHOD(RemoveMenus)(HMENU){return S_OK;}
STDMETHOD(SetStatusText)351     STDMETHOD(SetStatusText)(LPCOLESTR){ return S_OK;}
EnableModeless(BOOL)352     HRESULT STDMETHODCALLTYPE EnableModeless(BOOL){return S_OK;}
TranslateAccelerator(LPMSG lpmsg,WORD)353     HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD)
354     {
355         // TODO: send an event with this id
356         if (m_window->m_oleInPlaceActiveObject.IsOk())
357             m_window->m_oleInPlaceActiveObject->TranslateAccelerator(lpmsg);
358         return S_FALSE;
359     }
360 
361     //*******************IOleInPlaceSite**************************
CanInPlaceActivate()362     HRESULT STDMETHODCALLTYPE CanInPlaceActivate(){return S_OK;}
OnInPlaceActivate()363     HRESULT STDMETHODCALLTYPE OnInPlaceActivate()
364     {   m_bInPlaceActive = true;    return S_OK;    }
OnUIActivate()365     HRESULT STDMETHODCALLTYPE OnUIActivate()
366     {   m_bUIActive = true;         return S_OK;    }
GetWindowContext(IOleInPlaceFrame ** ppFrame,IOleInPlaceUIWindow ** ppDoc,LPRECT lprcPosRect,LPRECT lprcClipRect,LPOLEINPLACEFRAMEINFO lpFrameInfo)367     HRESULT STDMETHODCALLTYPE GetWindowContext(IOleInPlaceFrame **ppFrame,
368                                         IOleInPlaceUIWindow **ppDoc,
369                                         LPRECT lprcPosRect,
370                                         LPRECT lprcClipRect,
371                                         LPOLEINPLACEFRAMEINFO lpFrameInfo)
372     {
373         if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL ||
374             lprcClipRect == NULL || lpFrameInfo == NULL)
375         {
376             if (ppFrame != NULL)
377                 (*ppFrame) = NULL;
378             if (ppDoc != NULL)
379                 (*ppDoc) = NULL;
380             return E_INVALIDARG;
381         }
382 
383         HRESULT hr = QueryInterface(IID_IOleInPlaceFrame, (void **) ppFrame);
384         if (! SUCCEEDED(hr))
385         {
386             return E_UNEXPECTED;
387         }
388 
389         hr = QueryInterface(IID_IOleInPlaceUIWindow, (void **) ppDoc);
390         if (! SUCCEEDED(hr))
391         {
392             (*ppFrame)->Release();
393             *ppFrame = NULL;
394             return E_UNEXPECTED;
395         }
396 
397         RECT rect;
398         ::GetClientRect(m_hWndParent, &rect);
399         if (lprcPosRect)
400         {
401             lprcPosRect->left = lprcPosRect->top = 0;
402             lprcPosRect->right = rect.right;
403             lprcPosRect->bottom = rect.bottom;
404         }
405         if (lprcClipRect)
406         {
407             lprcClipRect->left = lprcClipRect->top = 0;
408             lprcClipRect->right = rect.right;
409             lprcClipRect->bottom = rect.bottom;
410         }
411 
412         memset(lpFrameInfo, 0, sizeof(OLEINPLACEFRAMEINFO));
413         lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
414         lpFrameInfo->hwndFrame = m_hWndParent;
415 
416         return S_OK;
417     }
Scroll(SIZE)418     HRESULT STDMETHODCALLTYPE Scroll(SIZE){return S_OK;}
OnUIDeactivate(BOOL)419     HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL)
420     {   m_bUIActive = false;         return S_OK;    }
OnInPlaceDeactivate()421     HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate()
422     {   m_bInPlaceActive = false;    return S_OK;    }
DiscardUndoState()423     HRESULT STDMETHODCALLTYPE DiscardUndoState(){return S_OK;}
DeactivateAndUndo()424     HRESULT STDMETHODCALLTYPE DeactivateAndUndo(){return S_OK; }
OnPosRectChange(LPCRECT lprcPosRect)425     HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect)
426     {
427         if (m_window->m_oleInPlaceObject.IsOk() && lprcPosRect)
428         {
429            //
430            // Result of several hours and days of bug hunting -
431            // this is called by an object when it wants to resize
432            // itself to something different then our parent window -
433            // don't let it :)
434            //
435 //            m_window->m_oleInPlaceObject->SetObjectRects(
436 //                lprcPosRect, lprcPosRect);
437            RECT rcClient;
438            ::GetClientRect(m_hWndParent, &rcClient);
439             m_window->m_oleInPlaceObject->SetObjectRects(
440                 &rcClient, &rcClient);
441         }
442         return S_OK;
443     }
444     //*************************IOleInPlaceSiteEx***********************
OnInPlaceActivateEx(BOOL * pfNoRedraw,DWORD)445     HRESULT STDMETHODCALLTYPE OnInPlaceActivateEx(BOOL * pfNoRedraw, DWORD)
446     {
447 #ifdef __WXWINCE__
448         IRunnableObject* runnable = NULL;
449         HRESULT hr = QueryInterface(
450             IID_IRunnableObject, (void**)(& runnable));
451         if (SUCCEEDED(hr))
452         {
453             runnable->LockRunning(TRUE, FALSE);
454         }
455 #else
456         OleLockRunning(m_window->m_ActiveX, TRUE, FALSE);
457 #endif
458         if (pfNoRedraw)
459             (*pfNoRedraw) = FALSE;
460         return S_OK;
461     }
462 
OnInPlaceDeactivateEx(BOOL)463     HRESULT STDMETHODCALLTYPE OnInPlaceDeactivateEx(BOOL)
464     {
465 #ifdef __WXWINCE__
466         IRunnableObject* runnable = NULL;
467         HRESULT hr = QueryInterface(
468             IID_IRunnableObject, (void**)(& runnable));
469         if (SUCCEEDED(hr))
470         {
471             runnable->LockRunning(FALSE, FALSE);
472         }
473 #else
474         OleLockRunning(m_window->m_ActiveX, FALSE, FALSE);
475 #endif
476         return S_OK;
477     }
STDMETHOD(RequestUIActivate)478     STDMETHOD(RequestUIActivate)(){ return S_OK;}
479     //*************************IOleClientSite**************************
SaveObject()480     HRESULT STDMETHODCALLTYPE SaveObject(){return S_OK;}
OleGetMonikerToStr(DWORD dwAssign)481     const char *OleGetMonikerToStr(DWORD dwAssign)
482     {
483         switch (dwAssign)
484         {
485         case OLEGETMONIKER_ONLYIFTHERE  : return "OLEGETMONIKER_ONLYIFTHERE";
486         case OLEGETMONIKER_FORCEASSIGN  : return "OLEGETMONIKER_FORCEASSIGN";
487         case OLEGETMONIKER_UNASSIGN     : return "OLEGETMONIKER_UNASSIGN";
488         case OLEGETMONIKER_TEMPFORUSER  : return "OLEGETMONIKER_TEMPFORUSER";
489         default                         : return "Bad Enum";
490         }
491     }
492 
OleGetWhicMonikerStr(DWORD dwWhichMoniker)493     const char *OleGetWhicMonikerStr(DWORD dwWhichMoniker)
494     {
495         switch(dwWhichMoniker)
496         {
497         case OLEWHICHMK_CONTAINER   : return "OLEWHICHMK_CONTAINER";
498         case OLEWHICHMK_OBJREL      : return "OLEWHICHMK_OBJREL";
499         case OLEWHICHMK_OBJFULL     : return "OLEWHICHMK_OBJFULL";
500         default                     : return "Bad Enum";
501         }
502     }
STDMETHOD(GetMoniker)503     STDMETHOD(GetMoniker)(DWORD, DWORD, IMoniker **){return E_FAIL;}
GetContainer(LPOLECONTAINER * ppContainer)504     HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER * ppContainer)
505     {
506         if (ppContainer == NULL)
507             return E_INVALIDARG;
508         HRESULT hr = QueryInterface(
509             IID_IOleContainer, (void**)(ppContainer));
510         wxASSERT(SUCCEEDED(hr));
511         return hr;
512     }
ShowObject()513     HRESULT STDMETHODCALLTYPE ShowObject()
514     {
515         if (m_window->m_oleObjectHWND)
516             ::ShowWindow(m_window->m_oleObjectHWND, SW_SHOW);
517         return S_OK;
518     }
STDMETHOD(OnShowWindow)519     STDMETHOD(OnShowWindow)(BOOL){return S_OK;}
STDMETHOD(RequestNewObjectLayout)520     STDMETHOD(RequestNewObjectLayout)(){return E_NOTIMPL;}
521     //********************IParseDisplayName***************************
ParseDisplayName(IBindCtx *,LPOLESTR,ULONG *,IMoniker **)522     HRESULT STDMETHODCALLTYPE ParseDisplayName(
523         IBindCtx *, LPOLESTR, ULONG *, IMoniker **){return E_NOTIMPL;}
524     //********************IOleContainer*******************************
STDMETHOD(EnumObjects)525     STDMETHOD(EnumObjects)(DWORD, IEnumUnknown **){return E_NOTIMPL;}
LockContainer(BOOL)526     HRESULT STDMETHODCALLTYPE LockContainer(BOOL){return S_OK;}
527     //********************IOleItemContainer***************************
528     HRESULT STDMETHODCALLTYPE
529     #if 0 // defined(__WXWINCE__) && __VISUALC__ < 1400
530     GetObject
531     #elif defined(_UNICODE)
532     GetObjectW
533     #else
GetObjectA(LPOLESTR pszItem,DWORD,IBindCtx *,REFIID,void ** ppvObject)534     GetObjectA
535     #endif
536     (LPOLESTR pszItem, DWORD, IBindCtx *, REFIID, void ** ppvObject)
537     {
538         if (pszItem == NULL || ppvObject == NULL)
539             return E_INVALIDARG;
540         *ppvObject = NULL;
541         return MK_E_NOOBJECT;
542     }
GetObjectStorage(LPOLESTR pszItem,IBindCtx *,REFIID,void ** ppvStorage)543     HRESULT STDMETHODCALLTYPE GetObjectStorage(
544         LPOLESTR pszItem, IBindCtx * , REFIID, void ** ppvStorage)
545     {
546         if (pszItem == NULL || ppvStorage == NULL)
547             return E_INVALIDARG;
548         *ppvStorage = NULL;
549         return MK_E_NOOBJECT;
550     }
IsRunning(LPOLESTR pszItem)551     HRESULT STDMETHODCALLTYPE IsRunning(LPOLESTR pszItem)
552     {
553         if (pszItem == NULL)
554             return E_INVALIDARG;
555         return MK_E_NOOBJECT;
556     }
557     //***********************IOleControlSite*****************************
OnControlInfoChanged()558     HRESULT STDMETHODCALLTYPE OnControlInfoChanged()
559     {return S_OK;}
LockInPlaceActive(BOOL fLock)560     HRESULT STDMETHODCALLTYPE LockInPlaceActive(BOOL fLock)
561     {
562         m_bInPlaceLocked = (fLock) ? true : false;
563         return S_OK;
564     }
GetExtendedControl(IDispatch **)565     HRESULT STDMETHODCALLTYPE GetExtendedControl(IDispatch **)
566     {return E_NOTIMPL;}
TransformCoords(POINTL * pPtlHimetric,POINTF * pPtfContainer,DWORD)567     HRESULT STDMETHODCALLTYPE TransformCoords(
568         POINTL * pPtlHimetric, POINTF * pPtfContainer, DWORD)
569     {
570         if (pPtlHimetric == NULL || pPtfContainer == NULL)
571             return E_INVALIDARG;
572         return E_NOTIMPL;
573     }
TranslateAccelerator(LPMSG,DWORD)574     HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG, DWORD)
575     {return E_NOTIMPL;}
OnFocus(BOOL)576     HRESULT STDMETHODCALLTYPE OnFocus(BOOL){return S_OK;}
ShowPropertyFrame()577     HRESULT STDMETHODCALLTYPE ShowPropertyFrame(){return E_NOTIMPL;}
578     //**************************IOleCommandTarget***********************
QueryStatus(const GUID *,ULONG cCmds,OLECMD prgCmds[],OLECMDTEXT *)579     HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *, ULONG cCmds,
580                                 OLECMD prgCmds[], OLECMDTEXT *)
581     {
582         if (prgCmds == NULL) return E_INVALIDARG;
583         for (ULONG nCmd = 0; nCmd < cCmds; nCmd++)
584         {
585             // unsupported by default
586             prgCmds[nCmd].cmdf = 0;
587         }
588         return OLECMDERR_E_UNKNOWNGROUP;
589     }
590 
Exec(const GUID *,DWORD,DWORD,VARIANTARG *,VARIANTARG *)591     HRESULT STDMETHODCALLTYPE Exec(const GUID *, DWORD,
592                             DWORD, VARIANTARG *, VARIANTARG *)
593     {return OLECMDERR_E_NOTSUPPORTED;}
594 
595     //**********************IAdviseSink************************************
OnDataChange(FORMATETC *,STGMEDIUM *)596     void STDMETHODCALLTYPE OnDataChange(FORMATETC *, STGMEDIUM *) {}
OnViewChange(DWORD,LONG)597     void STDMETHODCALLTYPE OnViewChange(DWORD, LONG) {}
OnRename(IMoniker *)598     void STDMETHODCALLTYPE OnRename(IMoniker *){}
OnSave()599     void STDMETHODCALLTYPE OnSave(){}
OnClose()600     void STDMETHODCALLTYPE OnClose(){}
601 
602     //**********************IOleDocumentSite***************************
ActivateMe(IOleDocumentView __RPC_FAR * pViewToActivate)603     HRESULT STDMETHODCALLTYPE ActivateMe(
604         IOleDocumentView __RPC_FAR *pViewToActivate)
605     {
606         wxAutoIOleInPlaceSite inPlaceSite(
607             IID_IOleInPlaceSite, (IDispatch *) this);
608         if (!inPlaceSite.IsOk())
609             return E_FAIL;
610 
611         if (pViewToActivate)
612         {
613             m_window->m_docView = pViewToActivate;
614             m_window->m_docView->SetInPlaceSite(inPlaceSite);
615         }
616         else
617         {
618             wxAutoIOleDocument oleDoc(
619                 IID_IOleDocument, m_window->m_oleObject);
620             if (! oleDoc.IsOk())
621                 return E_FAIL;
622 
623             HRESULT hr = oleDoc->CreateView(inPlaceSite, NULL,
624                                     0, m_window->m_docView.GetRef());
625             if (hr != S_OK)
626                 return E_FAIL;
627 
628             m_window->m_docView->SetInPlaceSite(inPlaceSite);
629         }
630 
631         m_window->m_docView->UIActivate(TRUE);
632         return S_OK;
633     }
634 
QueryClientSiteInterface(FrameSite * self,REFIID iid,void ** _interface,const char * & desc)635     friend bool QueryClientSiteInterface(FrameSite *self, REFIID iid, void **_interface, const char *&desc)
636     {
637         return self->m_window->QueryClientSiteInterface(iid,_interface,desc);
638     }
639 
640 protected:
641     wxActiveXContainer * m_window;
642 
643     HDC m_hDCBuffer;
644     HWND m_hWndParent;
645 
646     bool m_bSupportsWindowlessActivation;
647     bool m_bInPlaceLocked;
648     bool m_bInPlaceActive;
649     bool m_bUIActive;
650     bool m_bWindowless;
651 
652     LCID m_nAmbientLocale;
653     COLORREF m_clrAmbientForeColor;
654     COLORREF m_clrAmbientBackColor;
655     bool m_bAmbientShowHatching;
656     bool m_bAmbientShowGrabHandles;
657     bool m_bAmbientAppearance;
658 };
659 
660 DEFINE_OLE_TABLE(FrameSite)
661     OLE_INTERFACE(IID_IUnknown, IOleClientSite)
662     OLE_IINTERFACE(IOleClientSite)
663     OLE_INTERFACE(IID_IOleWindow, IOleInPlaceSite)
664     OLE_IINTERFACE(IOleInPlaceSite)
665     OLE_IINTERFACE(IOleInPlaceSiteEx)
666     OLE_IINTERFACE(IOleInPlaceUIWindow)
667     OLE_IINTERFACE(IOleInPlaceFrame)
668     OLE_IINTERFACE(IParseDisplayName)
669     OLE_IINTERFACE(IOleContainer)
670     OLE_IINTERFACE(IOleItemContainer)
671     OLE_IINTERFACE(IDispatch)
672     OLE_IINTERFACE(IOleCommandTarget)
673     OLE_IINTERFACE(IOleDocumentSite)
674     OLE_IINTERFACE(IAdviseSink)
675     OLE_IINTERFACE(IOleControlSite)
676     OLE_INTERFACE_CUSTOM(QueryClientSiteInterface)
677 END_OLE_TABLE
678 
679 
680 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
681 //
682 // wxActiveXEvents
683 //
684 // Handles and sends activex events received from the ActiveX control
685 // to the appropriate wxEvtHandler
686 //
687 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
688 class wxActiveXEvents : public IDispatch
689 {
690 private:
691     DECLARE_OLE_UNKNOWN(wxActiveXEvents);
692 
693 
694     wxActiveXContainer *m_activeX;
695     IID m_customId;
696     bool m_haveCustomId;
697 
698     friend bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc);
699 
700 public:
701 
702     // a pointer to this static variable is used as an 'invalid_entry_marker'
703     // wxVariants containing a void* to this variables are 'empty' in the sense
704     // that the actual ActiveX OLE parameter has not been converted and inserted
705     // into m_params.
706     static wxVariant ms_invalidEntryMarker;
707 
wxActiveXEvents(wxActiveXContainer * ax)708     wxActiveXEvents(wxActiveXContainer *ax) : m_activeX(ax), m_haveCustomId(false) {}
wxActiveXEvents(wxActiveXContainer * ax,REFIID iid)709     wxActiveXEvents(wxActiveXContainer *ax, REFIID iid) : m_activeX(ax), m_customId(iid), m_haveCustomId(true) {}
~wxActiveXEvents()710     virtual ~wxActiveXEvents()
711     {
712     }
713 
714     // IDispatch
GetIDsOfNames(REFIID,OLECHAR **,unsigned int,LCID,DISPID *)715     STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR**, unsigned int, LCID, DISPID*)
716     {
717         return E_NOTIMPL;
718     }
719 
GetTypeInfo(unsigned int,LCID,ITypeInfo **)720     STDMETHODIMP GetTypeInfo(unsigned int, LCID, ITypeInfo**)
721     {
722         return E_NOTIMPL;
723     }
724 
GetTypeInfoCount(unsigned int *)725     STDMETHODIMP GetTypeInfoCount(unsigned int*)
726     {
727         return E_NOTIMPL;
728     }
729 
730 
Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,unsigned int * puArgErr)731     STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid,
732                         LCID lcid,
733                           WORD wFlags, DISPPARAMS * pDispParams,
734                           VARIANT * pVarResult, EXCEPINFO * pExcepInfo,
735                           unsigned int * puArgErr)
736     {
737         if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
738             return E_NOTIMPL;
739 
740         wxASSERT(m_activeX);
741 
742         // ActiveX Event
743 
744         // Dispatch Event
745         wxActiveXEvent  event;
746         event.SetEventType(wxEVT_ACTIVEX);
747         // Create an empty list of Variants
748         // Note that the event parameters use lazy evaluation
749         // They are not actually created until wxActiveXEvent::operator[] is called
750         event.m_params.NullList();
751         event.m_dispid = dispIdMember;
752 
753         // save the native (MSW) event parameters for event handlers that need to access them
754         // this can be done on the stack since wxActiveXEvent is also allocated on the stack
755         wxActiveXEventNativeMSW eventParameters(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
756         event.SetClientData(&eventParameters);
757 
758         // The event parameters are not copied to event.m_params until they are actually
759         // referenced in wxActiveXEvent::operator[]
760         // This increases performance and avoids error messages and/or crashes
761         // when the event has parameters that are not (yet or never) supported
762         // by wxConvertOleToVariant
763 
764         // process the events from the activex method
765         m_activeX->ProcessEvent(event);
766         for (DWORD i = 0; i < pDispParams->cArgs; i++)
767         {
768             size_t params_index = pDispParams->cArgs - i - 1;
769             if (params_index < event.m_params.GetCount()) {
770                 wxVariant &vx = event.m_params[params_index];
771                 // copy the result back to pDispParams only if the event has been accessed
772                 //  i.e.  if vx != ms_invalidEntryMarker
773                 if (!vx.IsType(wxActiveXEvents::ms_invalidEntryMarker.GetType()) || vx!=ms_invalidEntryMarker) {
774                     VARIANTARG& va = pDispParams->rgvarg[i];
775                     wxConvertVariantToOle(vx, va);
776                 }
777             }
778         }
779 
780         if(event.GetSkipped())
781             return DISP_E_MEMBERNOTFOUND;
782 
783         return S_OK;
784     }
785 };
786 
787 namespace
788 {
789 // just a unique global variable
790 const int invalid_entry_marker = 0;
791 }
792 
793 wxVariant wxActiveXEvents::ms_invalidEntryMarker((void*)&invalid_entry_marker);
794 
ParamCount() const795 size_t wxActiveXEvent::ParamCount() const
796 {
797     wxActiveXEventNativeMSW *native=GetNativeParameters();
798     // 'native' will always be != if the event has been created
799     // for an actual active X event.
800     // But it may be zero if the event has been created by wx program code.
801     if (native)
802         return native->pDispParams ? native->pDispParams->cArgs : 0;
803 
804     return m_params.GetCount();
805 }
806 
operator [](size_t idx)807 wxVariant &wxActiveXEvent::operator [](size_t idx)
808 {
809     wxASSERT(idx < ParamCount());
810     wxActiveXEventNativeMSW *native=GetNativeParameters();
811     // 'native' will always be != if the event has been created
812     // for an actual active X event.
813     // But it may be zero if the event has been created by wx program code.
814     if (native)
815     {
816         while ( m_params.GetCount()<=idx )
817         {
818             m_params.Append(wxActiveXEvents::ms_invalidEntryMarker);
819         }
820 
821         wxVariant& vx = m_params[idx];
822         if ( vx.IsType(wxActiveXEvents::ms_invalidEntryMarker.GetType()) &&
823                 vx == wxActiveXEvents::ms_invalidEntryMarker)
824         {
825             // copy the _real_ parameter into this one
826             // NOTE: m_params stores the parameters in *reverse* order.
827             // Whyever, but this was the case in the original implementation of
828             // wxActiveXEvents::Invoke
829             // Keep this convention.
830             VARIANTARG& va = native->pDispParams->rgvarg[ native->pDispParams->cArgs - idx - 1 ];
831             wxConvertOleToVariant(va, vx);
832         }
833         return vx;
834     }
835     return m_params[idx];
836 }
837 
wxActiveXEventsInterface(wxActiveXEvents * self,REFIID iid,void ** _interface,const char * & desc)838 bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc)
839 {
840     if (self->m_haveCustomId && IsEqualIID(iid, self->m_customId))
841     {
842         *_interface = (IUnknown *) (IDispatch *) self;
843         desc = "Custom Dispatch Interface";
844         return true;
845     }
846 
847     return false;
848 }
849 
850 DEFINE_OLE_TABLE(wxActiveXEvents)
OLE_IINTERFACE(IUnknown)851     OLE_IINTERFACE(IUnknown)
852     OLE_INTERFACE(IID_IDispatch, IDispatch)
853     OLE_INTERFACE_CUSTOM(wxActiveXEventsInterface)
854 END_OLE_TABLE
855 
856 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
857 //
858 // wxActiveXContainer
859 //
860 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
861 
862 //---------------------------------------------------------------------------
863 // wxActiveXContainer Constructor
864 //
865 // Initializes members and creates the native ActiveX container
866 //---------------------------------------------------------------------------
867 wxActiveXContainer::wxActiveXContainer(wxWindow * parent,
868                                        REFIID iid, IUnknown* pUnk)
869     : m_realparent(parent)
870 {
871     m_bAmbientUserMode = true;
872     m_docAdviseCookie = 0;
873     CreateActiveX(iid, pUnk);
874 }
875 
876 //---------------------------------------------------------------------------
877 // wxActiveXContainer Destructor
878 //
879 // Destroys members (the FrameSite et al. are destroyed implicitly
880 // through COM ref counting)
881 //---------------------------------------------------------------------------
~wxActiveXContainer()882 wxActiveXContainer::~wxActiveXContainer()
883 {
884     // disconnect connection points
885     if (m_oleInPlaceObject.IsOk())
886     {
887         m_oleInPlaceObject->InPlaceDeactivate();
888         m_oleInPlaceObject->UIDeactivate();
889     }
890 
891     if (m_oleObject.IsOk())
892     {
893         if (m_docAdviseCookie != 0)
894             m_oleObject->Unadvise(m_docAdviseCookie);
895 
896         m_oleObject->DoVerb(
897             OLEIVERB_HIDE, NULL, m_clientSite, 0, (HWND) GetHWND(), NULL);
898         m_oleObject->Close(OLECLOSE_NOSAVE);
899         m_oleObject->SetClientSite(NULL);
900     }
901 
902     // m_clientSite uses m_frameSite so destroy it first
903     m_clientSite.Free();
904     delete m_frameSite;
905 
906     // our window doesn't belong to us, don't destroy it
907     m_hWnd = NULL;
908 }
909 
910 // VZ: we might want to really report an error instead of just asserting here
911 #if wxDEBUG_LEVEL
912     #define CHECK_HR(hr) \
913         wxASSERT_LEVEL_2_MSG( SUCCEEDED(hr), \
914                 wxString::Format("HRESULT = %X", (unsigned)(hr)) )
915 #else
916     #define CHECK_HR(hr) wxUnusedVar(hr)
917 #endif
918 
919 //---------------------------------------------------------------------------
920 // wxActiveXContainer::CreateActiveX
921 //
922 // Actually creates the ActiveX container through the FrameSite
923 // and sets up ActiveX events
924 //
925 // TODO: Document this more
926 //---------------------------------------------------------------------------
CreateActiveX(REFIID iid,IUnknown * pUnk)927 void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
928 {
929     HRESULT hret;
930     hret = m_ActiveX.QueryInterface(iid, pUnk);
931     CHECK_HR(hret);
932 
933     // FrameSite
934     m_frameSite = new FrameSite(m_realparent, this);
935     // oleClientSite
936     hret = m_clientSite.QueryInterface(
937         IID_IOleClientSite, (IDispatch *) m_frameSite);
938     CHECK_HR(hret);
939     // adviseSink
940     wxAutoIAdviseSink adviseSink(IID_IAdviseSink, (IDispatch *) m_frameSite);
941     wxASSERT(adviseSink.IsOk());
942 
943     // Get Dispatch interface
944     hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX);
945     CHECK_HR(hret);
946 
947     //
948     // SETUP TYPEINFO AND ACTIVEX EVENTS
949     //
950 
951     // get type info via class info
952     wxAutoIProvideClassInfo classInfo(IID_IProvideClassInfo, m_ActiveX);
953     wxASSERT(classInfo.IsOk());
954 
955     // type info
956     wxAutoITypeInfo typeInfo;
957     hret = classInfo->GetClassInfo(typeInfo.GetRef());
958     CHECK_HR(hret);
959     wxASSERT(typeInfo.IsOk());
960 
961     // TYPEATTR
962     TYPEATTR *ta = NULL;
963     hret = typeInfo->GetTypeAttr(&ta);
964     CHECK_HR(hret);
965 
966     // this should be a TKIND_COCLASS
967     wxASSERT(ta->typekind == TKIND_COCLASS);
968 
969     // iterate contained interfaces
970     for (int i = 0; i < ta->cImplTypes; i++)
971     {
972         HREFTYPE rt = 0;
973 
974         // get dispatch type info handle
975         hret = typeInfo->GetRefTypeOfImplType(i, &rt);
976         if (! SUCCEEDED(hret))
977             continue;
978 
979         // get dispatch type info interface
980         wxAutoITypeInfo  ti;
981         hret = typeInfo->GetRefTypeInfo(rt, ti.GetRef());
982         if (! ti.IsOk())
983             continue;
984 
985         CHECK_HR(hret);
986 
987         // check if default event sink
988         bool defEventSink = false;
989         int impTypeFlags = 0;
990         typeInfo->GetImplTypeFlags(i, &impTypeFlags);
991 
992         if (impTypeFlags & IMPLTYPEFLAG_FDEFAULT)
993         {
994             if (impTypeFlags & IMPLTYPEFLAG_FSOURCE)
995             {
996                 // WXOLE_TRACEOUT("Default Event Sink");
997                 defEventSink = true;
998                 if (impTypeFlags & IMPLTYPEFLAG_FDEFAULTVTABLE)
999                 {
1000                     // WXOLE_TRACEOUT("*ERROR* - Default Event Sink is via vTable");
1001                     defEventSink = false;
1002                     wxFAIL_MSG(wxT("Default event sink is in vtable!"));
1003                 }
1004             }
1005         }
1006 
1007 
1008         // wxAutoOleInterface<> assumes a ref has already been added
1009         // TYPEATTR
1010         TYPEATTR *ta2 = NULL;
1011         hret = ti->GetTypeAttr(&ta2);
1012         CHECK_HR(hret);
1013 
1014         if (ta2->typekind == TKIND_DISPATCH)
1015         {
1016             // WXOLE_TRACEOUT("GUID = " << GetIIDName(ta2->guid).c_str());
1017             if (defEventSink)
1018             {
1019                 wxAutoIConnectionPoint    cp;
1020                 DWORD                    adviseCookie = 0;
1021 
1022                 wxAutoIConnectionPointContainer cpContainer(IID_IConnectionPointContainer, m_ActiveX);
1023                 wxASSERT( cpContainer.IsOk());
1024 
1025                 hret = cpContainer->FindConnectionPoint(ta2->guid, cp.GetRef());
1026 
1027                 // Notice that the return value of CONNECT_E_NOCONNECTION is
1028                 // expected if the interface doesn't support connection points.
1029                 if ( hret != CONNECT_E_NOCONNECTION )
1030                 {
1031                     CHECK_HR(hret);
1032                 }
1033 
1034                 if ( cp )
1035                 {
1036                     wxActiveXEvents * const
1037                         events = new wxActiveXEvents(this, ta2->guid);
1038                     hret = cp->Advise(events, &adviseCookie);
1039 
1040                     // We don't need this object any more and cp will keep a
1041                     // reference to it if it needs it, i.e. if Advise()
1042                     // succeeded.
1043                     events->Release();
1044 
1045                     CHECK_HR(hret);
1046                 }
1047             }
1048         }
1049 
1050         ti->ReleaseTypeAttr(ta2);
1051     }
1052 
1053     // free
1054     typeInfo->ReleaseTypeAttr(ta);
1055 
1056     //
1057     // END
1058     //
1059 
1060     // Get IOleObject interface
1061     hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX);
1062     CHECK_HR(hret);
1063 
1064     // get IViewObject Interface
1065     hret = m_viewObject.QueryInterface(IID_IViewObject, m_ActiveX);
1066     CHECK_HR(hret);
1067 
1068     // document advise
1069     m_docAdviseCookie = 0;
1070     hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie);
1071     CHECK_HR(hret);
1072 
1073     // TODO:Needed?
1074 //    hret = m_viewObject->SetAdvise(DVASPECT_CONTENT, 0, adviseSink);
1075     m_oleObject->SetHostNames(L"wxActiveXContainer", NULL);
1076     OleSetContainedObject(m_oleObject, TRUE);
1077     OleRun(m_oleObject);
1078 
1079 
1080     // Get IOleInPlaceObject interface
1081     hret = m_oleInPlaceObject.QueryInterface(
1082         IID_IOleInPlaceObject, m_ActiveX);
1083     CHECK_HR(hret);
1084 
1085     // status
1086     DWORD dwMiscStatus;
1087     m_oleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
1088     CHECK_HR(hret);
1089 
1090     // set client site first ?
1091     if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
1092         m_oleObject->SetClientSite(m_clientSite);
1093 
1094 
1095     // stream init
1096     wxAutoIPersistStreamInit
1097         pPersistStreamInit(IID_IPersistStreamInit, m_oleObject);
1098 
1099     if (pPersistStreamInit.IsOk())
1100     {
1101         hret = pPersistStreamInit->InitNew();
1102         CHECK_HR(hret);
1103     }
1104 
1105     if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
1106         m_oleObject->SetClientSite(m_clientSite);
1107 
1108 
1109     m_oleObjectHWND = 0;
1110 
1111 
1112     if (! (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME))
1113     {
1114         RECT posRect;
1115         wxCopyRectToRECT(m_realparent->GetClientSize(), posRect);
1116 
1117         hret = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL,
1118             m_clientSite, 0, (HWND)m_realparent->GetHWND(), &posRect);
1119         CHECK_HR(hret);
1120 
1121         if (m_oleInPlaceObject.IsOk())
1122         {
1123             hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
1124             CHECK_HR(hret);
1125             ::SetActiveWindow(m_oleObjectHWND);
1126         }
1127 
1128         if (posRect.right > 0 && posRect.bottom > 0 &&
1129             m_oleInPlaceObject.IsOk())
1130         {
1131             m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
1132         }
1133 
1134         hret = m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0,
1135             (HWND)m_realparent->GetHWND(), &posRect);
1136         CHECK_HR(hret);
1137     }
1138 
1139     if (! m_oleObjectHWND && m_oleInPlaceObject.IsOk())
1140     {
1141         hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
1142         CHECK_HR(hret);
1143     }
1144 
1145     if (m_oleObjectHWND)
1146     {
1147         ::SetActiveWindow(m_oleObjectHWND);
1148         ::ShowWindow(m_oleObjectHWND, SW_SHOW);
1149 
1150         this->AssociateHandle(m_oleObjectHWND);
1151         this->Reparent(m_realparent);
1152 
1153         wxWindow* pWnd = m_realparent;
1154         int id = m_realparent->GetId();
1155 
1156         pWnd->Connect(id, wxEVT_SIZE,
1157             wxSizeEventHandler(wxActiveXContainer::OnSize), 0, this);
1158 //        this->Connect(GetId(), wxEVT_PAINT,
1159 //            wxPaintEventHandler(wxActiveXContainer::OnPaint), 0, this);
1160         pWnd->Connect(id, wxEVT_SET_FOCUS,
1161             wxFocusEventHandler(wxActiveXContainer::OnSetFocus), 0, this);
1162         pWnd->Connect(id, wxEVT_KILL_FOCUS,
1163             wxFocusEventHandler(wxActiveXContainer::OnKillFocus), 0, this);
1164     }
1165 }
1166 
1167 //---------------------------------------------------------------------------
1168 // wxActiveXContainer::OnSize
1169 //
1170 // Called when the parent is resized - we need to do this to actually
1171 // move the ActiveX control to where the parent is
1172 //---------------------------------------------------------------------------
OnSize(wxSizeEvent & event)1173 void wxActiveXContainer::OnSize(wxSizeEvent& event)
1174 {
1175     int w, h;
1176     GetParent()->GetClientSize(&w, &h);
1177 
1178     RECT posRect;
1179     posRect.left = 0;
1180     posRect.top = 0;
1181     posRect.right = w;
1182     posRect.bottom = h;
1183 
1184     if (w <= 0 || h <= 0)
1185         return;
1186 
1187     // extents are in HIMETRIC units
1188     if (m_oleObject.IsOk())
1189     {
1190 
1191         SIZEL sz = {w, h};
1192         PixelsToHimetric(sz);
1193 
1194         SIZEL sz2;
1195 
1196         m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2);
1197         if (sz2.cx !=  sz.cx || sz.cy != sz2.cy)
1198             m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
1199 
1200     }
1201 
1202     if (m_oleInPlaceObject.IsOk())
1203         m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
1204 
1205     event.Skip();
1206 }
1207 
1208 //---------------------------------------------------------------------------
1209 // wxActiveXContainer::OnPaint
1210 //
1211 // Called when the parent is resized - repaints the ActiveX control
1212 //---------------------------------------------------------------------------
OnPaint(wxPaintEvent & WXUNUSED (event))1213 void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
1214 {
1215     wxPaintDC dc(this);
1216     // Draw only when control is windowless or deactivated
1217     if (m_viewObject)
1218     {
1219         int w, h;
1220         GetParent()->GetSize(&w, &h);
1221         RECT posRect;
1222         posRect.left = 0;
1223         posRect.top = 0;
1224         posRect.right = w;
1225         posRect.bottom = h;
1226 
1227 #if !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
1228         ::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
1229 #else
1230         ::InvalidateRect(m_oleObjectHWND, NULL, false);
1231 #endif
1232         RECTL *prcBounds = (RECTL *) &posRect;
1233         wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl );
1234         m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
1235             (HDC)msw->GetHDC(), prcBounds, NULL, NULL, 0);
1236     }
1237 }
1238 
1239 //---------------------------------------------------------------------------
1240 // wxActiveXContainer::OnSetFocus
1241 //
1242 // Called when the focus is set on the parent - activates the activex control
1243 //---------------------------------------------------------------------------
OnSetFocus(wxFocusEvent & event)1244 void wxActiveXContainer::OnSetFocus(wxFocusEvent& event)
1245 {
1246     if (m_oleInPlaceActiveObject.IsOk())
1247         m_oleInPlaceActiveObject->OnFrameWindowActivate(TRUE);
1248 
1249     event.Skip();
1250 }
1251 
1252 //---------------------------------------------------------------------------
1253 // wxActiveXContainer::OnKillFocus
1254 //
1255 // Called when the focus is killed on the parent -
1256 // deactivates the activex control
1257 //---------------------------------------------------------------------------
OnKillFocus(wxFocusEvent & event)1258 void wxActiveXContainer::OnKillFocus(wxFocusEvent& event)
1259 {
1260     if (m_oleInPlaceActiveObject.IsOk())
1261         m_oleInPlaceActiveObject->OnFrameWindowActivate(FALSE);
1262 
1263     event.Skip();
1264 }
1265 
1266 //---------------------------------------------------------------------------
1267 // wxActiveXContainer::MSWTranslateMessage
1268 //
1269 // Called for every message that needs to be translated.
1270 // Some controls might need more keyboard keys to process (CTRL-C, CTRL-A etc),
1271 // In that case TranslateAccelerator should always be called first.
1272 //---------------------------------------------------------------------------
MSWTranslateMessage(WXMSG * pMsg)1273 bool wxActiveXContainer::MSWTranslateMessage(WXMSG* pMsg)
1274 {
1275     if(m_oleInPlaceActiveObject.IsOk() && m_oleInPlaceActiveObject->TranslateAccelerator(pMsg) == S_OK)
1276     {
1277         return true;
1278     }
1279     return wxWindow::MSWTranslateMessage(pMsg);
1280 }
1281 
1282 //---------------------------------------------------------------------------
1283 // wxActiveXContainer::QueryClientSiteInterface
1284 //
1285 // Called in the host's site's query method for other interfaces.
1286 //---------------------------------------------------------------------------
QueryClientSiteInterface(REFIID iid,void ** _interface,const char * & desc)1287 bool wxActiveXContainer::QueryClientSiteInterface(REFIID iid, void **_interface, const char *&desc)
1288 {
1289     wxUnusedVar(iid);
1290     wxUnusedVar(_interface);
1291     wxUnusedVar(desc);
1292     return false;
1293 }
1294 
1295 #endif // wxUSE_ACTIVEX
1296