]> git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/activex.cpp
don't crash when destroying a not initialized socket (patch 1489095)
[wxWidgets.git] / src / msw / ole / activex.cpp
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 // RCS-ID: $Id$
8 // Copyright: (c) 2003 Lindsay Mathieson, (c) 2005 Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #ifndef WX_PRECOMP
27 #include "wx/dcclient.h"
28 #endif
29
30 #include "wx/math.h"
31
32 // I don't know why members of tagVARIANT aren't found when compiling
33 // with Wine
34 #ifndef __WINE__
35
36 #include "wx/msw/ole/activex.h"
37 // autointerfaces that we only use here
38 WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceSite, IOleInPlaceSite)
39 WX_DECLARE_AUTOOLE(wxAutoIOleDocument, IOleDocument)
40 WX_DECLARE_AUTOOLE(wxAutoIPersistStreamInit, IPersistStreamInit)
41 WX_DECLARE_AUTOOLE(wxAutoIAdviseSink, IAdviseSink)
42 WX_DECLARE_AUTOOLE(wxAutoIProvideClassInfo, IProvideClassInfo)
43 WX_DECLARE_AUTOOLE(wxAutoITypeInfo, ITypeInfo)
44 WX_DECLARE_AUTOOLE(wxAutoIConnectionPoint, IConnectionPoint)
45 WX_DECLARE_AUTOOLE(wxAutoIConnectionPointContainer, IConnectionPointContainer)
46
47 DEFINE_EVENT_TYPE(wxEVT_ACTIVEX)
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(0) {}\
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
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:
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 }
227 virtual ~FrameSite(){}
228 //***************************IDispatch*****************************
229 HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID, OLECHAR ** ,
230 unsigned int , LCID ,
231 DISPID * )
232 { return E_NOTIMPL; }
233 STDMETHOD(GetTypeInfo)(unsigned int, LCID, ITypeInfo **)
234 { return E_NOTIMPL; }
235 HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int *)
236 { return E_NOTIMPL; }
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)= FALSE;
255 return S_OK;
256
257 case DISPID_AMBIENT_DISPLAYASDEFAULT:
258 V_BOOL(pVarResult)= TRUE;
259 return S_OK;
260
261 case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
262 V_BOOL(pVarResult) = TRUE;
263 return S_OK;
264
265 case DISPID_AMBIENT_SILENT:
266 V_BOOL(pVarResult)= TRUE;
267 return S_OK;
268
269 case DISPID_AMBIENT_APPEARANCE:
270 pVarResult->vt = VT_BOOL;
271 pVarResult->boolVal = m_bAmbientAppearance;
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;
292 break;
293
294 case DISPID_AMBIENT_SHOWGRABHANDLES:
295 pVarResult->vt = VT_BOOL;
296 pVarResult->boolVal = m_bAmbientShowGrabHandles;
297 break;
298
299 case DISPID_AMBIENT_SHOWHATCHING:
300 pVarResult->vt = VT_BOOL;
301 pVarResult->boolVal = m_bAmbientShowHatching;
302 break;
303
304 default:
305 return DISP_E_MEMBERNOTFOUND;
306 }
307
308 return S_OK;
309 }
310
311 //**************************IOleWindow***************************
312 HRESULT STDMETHODCALLTYPE GetWindow(HWND * phwnd)
313 {
314 if (phwnd == NULL)
315 return E_INVALIDARG;
316 (*phwnd) = m_hWndParent;
317 return S_OK;
318 }
319 HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL)
320 {return S_OK;}
321 //**************************IOleInPlaceUIWindow*****************
322 HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprectBorder)
323 {
324 if (lprectBorder == NULL)
325 return E_INVALIDARG;
326 return INPLACE_E_NOTOOLSPACE;
327 }
328 HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
329 {
330 if (pborderwidths == NULL)
331 return E_INVALIDARG;
332 return INPLACE_E_NOTOOLSPACE;
333 }
334 HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS)
335 {return S_OK;}
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
348 STDMETHOD(InsertMenus)(HMENU, LPOLEMENUGROUPWIDTHS){return S_OK;}
349 STDMETHOD(SetMenu)(HMENU, HOLEMENU, HWND){ return S_OK;}
350 STDMETHOD(RemoveMenus)(HMENU){return S_OK;}
351 STDMETHOD(SetStatusText)(LPCOLESTR){ return S_OK;}
352 HRESULT STDMETHODCALLTYPE EnableModeless(BOOL){return S_OK;}
353 HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD)
354 {
355 // TODO: send an event with this id
356 if (m_window->m_oleInPlaceActiveObject.Ok())
357 m_window->m_oleInPlaceActiveObject->TranslateAccelerator(lpmsg);
358 return S_FALSE;
359 }
360
361 //*******************IOleInPlaceSite**************************
362 HRESULT STDMETHODCALLTYPE CanInPlaceActivate(){return S_OK;}
363 HRESULT STDMETHODCALLTYPE OnInPlaceActivate()
364 { m_bInPlaceActive = true; return S_OK; }
365 HRESULT STDMETHODCALLTYPE OnUIActivate()
366 { m_bUIActive = true; return S_OK; }
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 }
418 HRESULT STDMETHODCALLTYPE Scroll(SIZE){return S_OK;}
419 HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL)
420 { m_bUIActive = false; return S_OK; }
421 HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate()
422 { m_bInPlaceActive = false; return S_OK; }
423 HRESULT STDMETHODCALLTYPE DiscardUndoState(){return S_OK;}
424 HRESULT STDMETHODCALLTYPE DeactivateAndUndo(){return S_OK; }
425 HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect)
426 {
427 if (m_window->m_oleInPlaceObject.Ok() && 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***********************
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
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 }
478 STDMETHOD(RequestUIActivate)(){ return S_OK;}
479 //*************************IOleClientSite**************************
480 HRESULT STDMETHODCALLTYPE SaveObject(){return S_OK;}
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
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 }
503 STDMETHOD(GetMoniker)(DWORD, DWORD, IMoniker **){return E_FAIL;}
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 }
513 HRESULT STDMETHODCALLTYPE ShowObject()
514 {
515 if (m_window->m_oleObjectHWND)
516 ::ShowWindow(m_window->m_oleObjectHWND, SW_SHOW);
517 return S_OK;
518 }
519 STDMETHOD(OnShowWindow)(BOOL){return S_OK;}
520 STDMETHOD(RequestNewObjectLayout)(){return E_NOTIMPL;}
521 //********************IParseDisplayName***************************
522 HRESULT STDMETHODCALLTYPE ParseDisplayName(
523 IBindCtx *, LPOLESTR, ULONG *, IMoniker **){return E_NOTIMPL;}
524 //********************IOleContainer*******************************
525 STDMETHOD(EnumObjects)(DWORD, IEnumUnknown **){return E_NOTIMPL;}
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
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 }
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 }
551 HRESULT STDMETHODCALLTYPE IsRunning(LPOLESTR pszItem)
552 {
553 if (pszItem == NULL)
554 return E_INVALIDARG;
555 return MK_E_NOOBJECT;
556 }
557 //***********************IOleControlSite*****************************
558 HRESULT STDMETHODCALLTYPE OnControlInfoChanged()
559 {return S_OK;}
560 HRESULT STDMETHODCALLTYPE LockInPlaceActive(BOOL fLock)
561 {
562 m_bInPlaceLocked = (fLock) ? true : false;
563 return S_OK;
564 }
565 HRESULT STDMETHODCALLTYPE GetExtendedControl(IDispatch **)
566 {return E_NOTIMPL;}
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 }
574 HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG, DWORD)
575 {return E_NOTIMPL;}
576 HRESULT STDMETHODCALLTYPE OnFocus(BOOL){return S_OK;}
577 HRESULT STDMETHODCALLTYPE ShowPropertyFrame(){return E_NOTIMPL;}
578 //**************************IOleCommandTarget***********************
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
591 HRESULT STDMETHODCALLTYPE Exec(const GUID *, DWORD,
592 DWORD, VARIANTARG *, VARIANTARG *)
593 {return OLECMDERR_E_NOTSUPPORTED;}
594
595 //**********************IAdviseSink************************************
596 void STDMETHODCALLTYPE OnDataChange(FORMATETC *, STGMEDIUM *) {}
597 void STDMETHODCALLTYPE OnViewChange(DWORD, LONG) {}
598 void STDMETHODCALLTYPE OnRename(IMoniker *){}
599 void STDMETHODCALLTYPE OnSave(){}
600 void STDMETHODCALLTYPE OnClose(){}
601
602 //**********************IOleDocumentSite***************************
603 HRESULT STDMETHODCALLTYPE ActivateMe(
604 IOleDocumentView __RPC_FAR *pViewToActivate)
605 {
606 wxAutoIOleInPlaceSite inPlaceSite(
607 IID_IOleInPlaceSite, (IDispatch *) this);
608 if (!inPlaceSite.Ok())
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.Ok())
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
635
636 protected:
637 wxActiveXContainer * m_window;
638
639 HDC m_hDCBuffer;
640 HWND m_hWndParent;
641
642 bool m_bSupportsWindowlessActivation;
643 bool m_bInPlaceLocked;
644 bool m_bInPlaceActive;
645 bool m_bUIActive;
646 bool m_bWindowless;
647
648 LCID m_nAmbientLocale;
649 COLORREF m_clrAmbientForeColor;
650 COLORREF m_clrAmbientBackColor;
651 bool m_bAmbientShowHatching;
652 bool m_bAmbientShowGrabHandles;
653 bool m_bAmbientAppearance;
654 };
655
656 DEFINE_OLE_TABLE(FrameSite)
657 OLE_INTERFACE(IID_IUnknown, IOleClientSite)
658 OLE_IINTERFACE(IOleClientSite)
659 OLE_INTERFACE(IID_IOleWindow, IOleInPlaceSite)
660 OLE_IINTERFACE(IOleInPlaceSite)
661 OLE_IINTERFACE(IOleInPlaceSiteEx)
662 OLE_IINTERFACE(IOleInPlaceUIWindow)
663 OLE_IINTERFACE(IOleInPlaceFrame)
664 OLE_IINTERFACE(IParseDisplayName)
665 OLE_IINTERFACE(IOleContainer)
666 OLE_IINTERFACE(IOleItemContainer)
667 OLE_IINTERFACE(IDispatch)
668 OLE_IINTERFACE(IOleCommandTarget)
669 OLE_IINTERFACE(IOleDocumentSite)
670 OLE_IINTERFACE(IAdviseSink)
671 OLE_IINTERFACE(IOleControlSite)
672 END_OLE_TABLE
673
674
675 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
676 //
677 // wxActiveXEvents
678 //
679 // Handles and sends activex events received from the ActiveX control
680 // to the appropriate wxEvtHandler
681 //
682 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
683 class wxActiveXEvents : public IDispatch
684 {
685 private:
686 DECLARE_OLE_UNKNOWN(wxActiveXEvents);
687
688
689 wxActiveXContainer *m_activeX;
690 IID m_customId;
691 bool m_haveCustomId;
692
693 friend bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc);
694
695 public:
696 wxActiveXEvents(wxActiveXContainer *ax) : m_activeX(ax), m_haveCustomId(false) {}
697 wxActiveXEvents(wxActiveXContainer *ax, REFIID iid) : m_activeX(ax), m_customId(iid), m_haveCustomId(true) {}
698 virtual ~wxActiveXEvents()
699 {
700 }
701
702 // IDispatch
703 STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR**, unsigned int, LCID, DISPID*)
704 {
705 return E_NOTIMPL;
706 }
707
708 STDMETHODIMP GetTypeInfo(unsigned int, LCID, ITypeInfo**)
709 {
710 return E_NOTIMPL;
711 }
712
713 STDMETHODIMP GetTypeInfoCount(unsigned int*)
714 {
715 return E_NOTIMPL;
716 }
717
718
719 STDMETHODIMP Invoke(DISPID dispIdMember, REFIID WXUNUSED(riid),
720 LCID WXUNUSED(lcid),
721 WORD wFlags, DISPPARAMS * pDispParams,
722 VARIANT * WXUNUSED(pVarResult), EXCEPINFO * WXUNUSED(pExcepInfo),
723 unsigned int * WXUNUSED(puArgErr))
724 {
725 if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
726 return E_NOTIMPL;
727
728 wxASSERT(m_activeX);
729
730 // ActiveX Event
731
732 // Dispatch Event
733 wxActiveXEvent event;
734 event.SetEventType(wxEVT_ACTIVEX);
735 event.m_params.NullList();
736 event.m_dispid = dispIdMember;
737
738 // arguments
739 if (pDispParams)
740 {
741 for (DWORD i = pDispParams->cArgs; i > 0; i--)
742 {
743 VARIANTARG& va = pDispParams->rgvarg[i-1];
744 wxVariant vx;
745
746 // vx.SetName(px.name);
747 wxConvertOleToVariant(va, vx);
748 event.m_params.Append(vx);
749 }
750 }
751
752 // process the events from the activex method
753 m_activeX->ProcessEvent(event);
754 for (DWORD i = 0; i < pDispParams->cArgs; i++)
755 {
756 VARIANTARG& va = pDispParams->rgvarg[i];
757 wxVariant& vx =
758 event.m_params[pDispParams->cArgs - i - 1];
759 wxConvertVariantToOle(vx, va);
760 }
761
762 if(event.GetSkipped())
763 return DISP_E_MEMBERNOTFOUND;
764
765 return S_OK;
766 }
767 };
768
769 bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc)
770 {
771 if (self->m_haveCustomId && IsEqualIID(iid, self->m_customId))
772 {
773 // WXOLE_TRACE("Found Custom Dispatch Interface");
774 *_interface = (IUnknown *) (IDispatch *) self;
775 desc = "Custom Dispatch Interface";
776 return true;
777 }
778
779 return false;
780 }
781
782 DEFINE_OLE_TABLE(wxActiveXEvents)
783 OLE_IINTERFACE(IUnknown)
784 OLE_INTERFACE(IID_IDispatch, IDispatch)
785 OLE_INTERFACE_CUSTOM(wxActiveXEventsInterface)
786 END_OLE_TABLE
787
788 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
789 //
790 // wxActiveXContainer
791 //
792 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
793
794 //---------------------------------------------------------------------------
795 // wxActiveXContainer Constructor
796 //
797 // Initializes members and creates the native ActiveX container
798 //---------------------------------------------------------------------------
799 wxActiveXContainer::wxActiveXContainer(wxWindow * parent,
800 REFIID iid, IUnknown* pUnk)
801 : m_realparent(parent)
802 {
803 m_bAmbientUserMode = true;
804 m_docAdviseCookie = 0;
805 CreateActiveX(iid, pUnk);
806 }
807
808 //---------------------------------------------------------------------------
809 // wxActiveXContainer Destructor
810 //
811 // Destroys members (the FrameSite et al. are destroyed implicitly
812 // through COM ref counting)
813 //---------------------------------------------------------------------------
814 wxActiveXContainer::~wxActiveXContainer()
815 {
816 // disconnect connection points
817 if (m_oleInPlaceObject.Ok())
818 {
819 m_oleInPlaceObject->InPlaceDeactivate();
820 m_oleInPlaceObject->UIDeactivate();
821 }
822
823 if (m_oleObject.Ok())
824 {
825 if (m_docAdviseCookie != 0)
826 m_oleObject->Unadvise(m_docAdviseCookie);
827
828 m_oleObject->DoVerb(
829 OLEIVERB_HIDE, NULL, m_clientSite, 0, (HWND) GetHWND(), NULL);
830 m_oleObject->Close(OLECLOSE_NOSAVE);
831 m_oleObject->SetClientSite(NULL);
832 }
833 }
834
835 //---------------------------------------------------------------------------
836 // wxActiveXContainer::CreateActiveX
837 //
838 // Actually creates the ActiveX container through the FrameSite
839 // and sets up ActiveX events
840 //
841 // TODO: Document this more
842 //---------------------------------------------------------------------------
843 void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
844 {
845 HRESULT hret;
846 hret = m_ActiveX.QueryInterface(iid, pUnk);
847 wxASSERT(SUCCEEDED(hret));
848
849 // FrameSite
850 FrameSite *frame = new FrameSite(m_realparent, this);
851 // oleClientSite
852 hret = m_clientSite.QueryInterface(
853 IID_IOleClientSite, (IDispatch *) frame);
854 wxASSERT(SUCCEEDED(hret));
855 // adviseSink
856 wxAutoIAdviseSink adviseSink(IID_IAdviseSink, (IDispatch *) frame);
857 wxASSERT(adviseSink.Ok());
858
859 // Get Dispatch interface
860 hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX);
861
862 //
863 // SETUP TYPEINFO AND ACTIVEX EVENTS
864 //
865
866 // get type info via class info
867 wxAutoIProvideClassInfo classInfo(IID_IProvideClassInfo, m_ActiveX);
868 wxASSERT(classInfo.Ok());
869
870 // type info
871 wxAutoITypeInfo typeInfo;
872 hret = classInfo->GetClassInfo(typeInfo.GetRef());
873 wxASSERT(typeInfo.Ok());
874
875 // TYPEATTR
876 TYPEATTR *ta = NULL;
877 hret = typeInfo->GetTypeAttr(&ta);
878 wxASSERT(ta);
879
880 // this should be a TKIND_COCLASS
881 wxASSERT(ta->typekind == TKIND_COCLASS);
882
883 // iterate contained interfaces
884 for (int i = 0; i < ta->cImplTypes; i++)
885 {
886 HREFTYPE rt = 0;
887
888 // get dispatch type info handle
889 hret = typeInfo->GetRefTypeOfImplType(i, &rt);
890 if (! SUCCEEDED(hret))
891 continue;
892
893 // get dispatch type info interface
894 wxAutoITypeInfo ti;
895 hret = typeInfo->GetRefTypeInfo(rt, ti.GetRef());
896 if (! ti.Ok())
897 continue;
898
899 // check if default event sink
900 bool defInterface = false;
901 bool defEventSink = false;
902 int impTypeFlags = 0;
903 typeInfo->GetImplTypeFlags(i, &impTypeFlags);
904
905 if (impTypeFlags & IMPLTYPEFLAG_FDEFAULT)
906 {
907 if (impTypeFlags & IMPLTYPEFLAG_FSOURCE)
908 {
909 // WXOLE_TRACEOUT("Default Event Sink");
910 defEventSink = true;
911 if (impTypeFlags & IMPLTYPEFLAG_FDEFAULTVTABLE)
912 {
913 // WXOLE_TRACEOUT("*ERROR* - Default Event Sink is via vTable");
914 defEventSink = false;
915 wxFAIL_MSG(wxT("Default event sink is in vtable!"));
916 }
917 }
918 else
919 {
920 // WXOLE_TRACEOUT("Default Interface");
921 defInterface = true;
922 }
923 }
924
925
926 // wxAutoOleInterface<> assumes a ref has already been added
927 // TYPEATTR
928 TYPEATTR *ta = NULL;
929 hret = ti->GetTypeAttr(&ta);
930 wxASSERT(ta);
931
932 if (ta->typekind == TKIND_DISPATCH)
933 {
934 // WXOLE_TRACEOUT("GUID = " << GetIIDName(ta->guid).c_str());
935 if (defEventSink)
936 {
937 wxAutoIConnectionPoint cp;
938 DWORD adviseCookie = 0;
939
940 wxAutoIConnectionPointContainer cpContainer(IID_IConnectionPointContainer, m_ActiveX);
941 wxASSERT( cpContainer.Ok());
942
943 HRESULT hret =
944 cpContainer->FindConnectionPoint(ta->guid, cp.GetRef());
945 wxASSERT ( SUCCEEDED(hret));
946
947 IDispatch* disp;
948 frame->QueryInterface(IID_IDispatch, (void**)&disp);
949 hret = cp->Advise(new wxActiveXEvents(this, ta->guid),
950 &adviseCookie);
951 wxASSERT_MSG( SUCCEEDED(hret),
952 wxString::Format(wxT("Cannot connect!\nHRESULT:%X"), (unsigned int)hret)
953 );
954 }
955 }
956
957 ti->ReleaseTypeAttr(ta);
958 }
959
960 // free
961 typeInfo->ReleaseTypeAttr(ta);
962
963 //
964 // END
965 //
966
967 // Get IOleObject interface
968 hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX);
969 wxASSERT(SUCCEEDED(hret));
970
971 // get IViewObject Interface
972 hret = m_viewObject.QueryInterface(IID_IViewObject, m_ActiveX);
973 wxASSERT(SUCCEEDED(hret));
974
975 // document advise
976 m_docAdviseCookie = 0;
977 hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie);
978 // TODO:Needed?
979 // hret = m_viewObject->SetAdvise(DVASPECT_CONTENT, 0, adviseSink);
980 m_oleObject->SetHostNames(L"wxActiveXContainer", NULL);
981 OleSetContainedObject(m_oleObject, TRUE);
982 OleRun(m_oleObject);
983
984
985 // Get IOleInPlaceObject interface
986 hret = m_oleInPlaceObject.QueryInterface(
987 IID_IOleInPlaceObject, m_ActiveX);
988 wxASSERT(SUCCEEDED(hret));
989
990 // status
991 DWORD dwMiscStatus;
992 m_oleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
993 wxASSERT(SUCCEEDED(hret));
994
995 // set client site first ?
996 if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
997 m_oleObject->SetClientSite(m_clientSite);
998
999
1000 // stream init
1001 wxAutoIPersistStreamInit
1002 pPersistStreamInit(IID_IPersistStreamInit, m_oleObject);
1003
1004 if (pPersistStreamInit.Ok())
1005 {
1006 hret = pPersistStreamInit->InitNew();
1007 }
1008
1009 if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
1010 m_oleObject->SetClientSite(m_clientSite);
1011
1012
1013 RECT posRect;
1014 ::GetClientRect((HWND)m_realparent->GetHWND(), &posRect);
1015
1016 m_oleObjectHWND = 0;
1017
1018 if (m_oleInPlaceObject.Ok())
1019 {
1020 hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
1021 if (SUCCEEDED(hret))
1022 ::SetActiveWindow(m_oleObjectHWND);
1023 }
1024
1025
1026 if (! (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME))
1027 {
1028 if (posRect.right > 0 && posRect.bottom > 0 &&
1029 m_oleInPlaceObject.Ok())
1030 m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
1031
1032 hret = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL,
1033 m_clientSite, 0, (HWND)m_realparent->GetHWND(), &posRect);
1034 hret = m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0,
1035 (HWND)m_realparent->GetHWND(), &posRect);
1036 }
1037
1038 if (! m_oleObjectHWND && m_oleInPlaceObject.Ok())
1039 {
1040 hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
1041 }
1042
1043 if (m_oleObjectHWND)
1044 {
1045 ::SetActiveWindow(m_oleObjectHWND);
1046 ::ShowWindow(m_oleObjectHWND, SW_SHOW);
1047
1048 this->AssociateHandle(m_oleObjectHWND);
1049 this->Reparent(m_realparent);
1050
1051 wxWindow* pWnd = m_realparent;
1052 int id = m_realparent->GetId();
1053
1054 pWnd->Connect(id, wxEVT_SIZE,
1055 wxSizeEventHandler(wxActiveXContainer::OnSize), 0, this);
1056 // this->Connect(GetId(), wxEVT_PAINT,
1057 // wxPaintEventHandler(wxActiveXContainer::OnPaint), 0, this);
1058 pWnd->Connect(id, wxEVT_SET_FOCUS,
1059 wxFocusEventHandler(wxActiveXContainer::OnSetFocus), 0, this);
1060 pWnd->Connect(id, wxEVT_KILL_FOCUS,
1061 wxFocusEventHandler(wxActiveXContainer::OnKillFocus), 0, this);
1062 }
1063 }
1064
1065 //---------------------------------------------------------------------------
1066 // wxActiveXContainer::OnSize
1067 //
1068 // Called when the parent is resized - we need to do this to actually
1069 // move the ActiveX control to where the parent is
1070 //---------------------------------------------------------------------------
1071 void wxActiveXContainer::OnSize(wxSizeEvent& event)
1072 {
1073 int w, h;
1074 GetParent()->GetClientSize(&w, &h);
1075
1076 RECT posRect;
1077 posRect.left = 0;
1078 posRect.top = 0;
1079 posRect.right = w;
1080 posRect.bottom = h;
1081
1082 if (w <= 0 && h <= 0)
1083 return;
1084
1085 // extents are in HIMETRIC units
1086 if (m_oleObject.Ok())
1087 {
1088 m_oleObject->DoVerb(OLEIVERB_HIDE, 0, m_clientSite, 0,
1089 (HWND)m_realparent->GetHWND(), &posRect);
1090
1091 SIZEL sz = {w, h};
1092 PixelsToHimetric(sz);
1093
1094 SIZEL sz2;
1095
1096 m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2);
1097 if (sz2.cx != sz.cx || sz.cy != sz2.cy)
1098 m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
1099
1100 m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0,
1101 (HWND)m_realparent->GetHWND(), &posRect);
1102 }
1103
1104 if (m_oleInPlaceObject.Ok())
1105 m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
1106
1107 event.Skip();
1108 }
1109
1110 //---------------------------------------------------------------------------
1111 // wxActiveXContainer::OnPaint
1112 //
1113 // Called when the parent is resized - repaints the ActiveX control
1114 //---------------------------------------------------------------------------
1115 void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
1116 {
1117 wxPaintDC dc(this);
1118 // Draw only when control is windowless or deactivated
1119 if (m_viewObject)
1120 {
1121 int w, h;
1122 GetParent()->GetSize(&w, &h);
1123 RECT posRect;
1124 posRect.left = 0;
1125 posRect.top = 0;
1126 posRect.right = w;
1127 posRect.bottom = h;
1128
1129 #if !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
1130 ::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
1131 #else
1132 ::InvalidateRect(m_oleObjectHWND, NULL, false);
1133 #endif
1134 RECTL *prcBounds = (RECTL *) &posRect;
1135 m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
1136 (HDC)dc.GetHDC(), prcBounds, NULL, NULL, 0);
1137 }
1138 }
1139
1140 //---------------------------------------------------------------------------
1141 // wxActiveXContainer::OnSetFocus
1142 //
1143 // Called when the focus is set on the parent - activates the activex control
1144 //---------------------------------------------------------------------------
1145 void wxActiveXContainer::OnSetFocus(wxFocusEvent& event)
1146 {
1147 if (m_oleInPlaceActiveObject.Ok())
1148 m_oleInPlaceActiveObject->OnFrameWindowActivate(TRUE);
1149
1150 event.Skip();
1151 }
1152
1153 //---------------------------------------------------------------------------
1154 // wxActiveXContainer::OnKillFocus
1155 //
1156 // Called when the focus is killed on the parent -
1157 // deactivates the activex control
1158 //---------------------------------------------------------------------------
1159 void wxActiveXContainer::OnKillFocus(wxFocusEvent& event)
1160 {
1161 if (m_oleInPlaceActiveObject.Ok())
1162 m_oleInPlaceActiveObject->OnFrameWindowActivate(FALSE);
1163
1164 event.Skip();
1165 }
1166
1167 #endif
1168 // __WINE__