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