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