]> git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/activex.cpp
- Rewrite wxHeaderCtrl to be virtual-like: even if we don't need an infinite
[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 // VZ: we might want to really report an error instead of just asserting here
835 #ifdef __WXDEBUG__
836 #define CHECK_HR(hr) \
837 wxASSERT_MSG( SUCCEEDED(hr), \
838 wxString::Format("HRESULT = %X", (unsigned)(hr)) )
839 #else
840 #define CHECK_HR(hr) wxUnusedVar(hr)
841 #endif
842
843 //---------------------------------------------------------------------------
844 // wxActiveXContainer::CreateActiveX
845 //
846 // Actually creates the ActiveX container through the FrameSite
847 // and sets up ActiveX events
848 //
849 // TODO: Document this more
850 //---------------------------------------------------------------------------
851 void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
852 {
853 HRESULT hret;
854 hret = m_ActiveX.QueryInterface(iid, pUnk);
855 CHECK_HR(hret);
856
857 // FrameSite
858 FrameSite *frame = new FrameSite(m_realparent, this);
859 // oleClientSite
860 hret = m_clientSite.QueryInterface(
861 IID_IOleClientSite, (IDispatch *) frame);
862 CHECK_HR(hret);
863 // adviseSink
864 wxAutoIAdviseSink adviseSink(IID_IAdviseSink, (IDispatch *) frame);
865 wxASSERT(adviseSink.Ok());
866
867 // Get Dispatch interface
868 hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX);
869 CHECK_HR(hret);
870
871 //
872 // SETUP TYPEINFO AND ACTIVEX EVENTS
873 //
874
875 // get type info via class info
876 wxAutoIProvideClassInfo classInfo(IID_IProvideClassInfo, m_ActiveX);
877 wxASSERT(classInfo.Ok());
878
879 // type info
880 wxAutoITypeInfo typeInfo;
881 hret = classInfo->GetClassInfo(typeInfo.GetRef());
882 CHECK_HR(hret);
883 wxASSERT(typeInfo.Ok());
884
885 // TYPEATTR
886 TYPEATTR *ta = NULL;
887 hret = typeInfo->GetTypeAttr(&ta);
888 CHECK_HR(hret);
889
890 // this should be a TKIND_COCLASS
891 wxASSERT(ta->typekind == TKIND_COCLASS);
892
893 // iterate contained interfaces
894 for (int i = 0; i < ta->cImplTypes; i++)
895 {
896 HREFTYPE rt = 0;
897
898 // get dispatch type info handle
899 hret = typeInfo->GetRefTypeOfImplType(i, &rt);
900 if (! SUCCEEDED(hret))
901 continue;
902
903 // get dispatch type info interface
904 wxAutoITypeInfo ti;
905 hret = typeInfo->GetRefTypeInfo(rt, ti.GetRef());
906 if (! ti.Ok())
907 continue;
908
909 CHECK_HR(hret);
910
911 // check if default event sink
912 bool defEventSink = false;
913 int impTypeFlags = 0;
914 typeInfo->GetImplTypeFlags(i, &impTypeFlags);
915
916 if (impTypeFlags & IMPLTYPEFLAG_FDEFAULT)
917 {
918 if (impTypeFlags & IMPLTYPEFLAG_FSOURCE)
919 {
920 // WXOLE_TRACEOUT("Default Event Sink");
921 defEventSink = true;
922 if (impTypeFlags & IMPLTYPEFLAG_FDEFAULTVTABLE)
923 {
924 // WXOLE_TRACEOUT("*ERROR* - Default Event Sink is via vTable");
925 defEventSink = false;
926 wxFAIL_MSG(wxT("Default event sink is in vtable!"));
927 }
928 }
929 }
930
931
932 // wxAutoOleInterface<> assumes a ref has already been added
933 // TYPEATTR
934 TYPEATTR *ta = NULL;
935 hret = ti->GetTypeAttr(&ta);
936 CHECK_HR(hret);
937
938 if (ta->typekind == TKIND_DISPATCH)
939 {
940 // WXOLE_TRACEOUT("GUID = " << GetIIDName(ta->guid).c_str());
941 if (defEventSink)
942 {
943 wxAutoIConnectionPoint cp;
944 DWORD adviseCookie = 0;
945
946 wxAutoIConnectionPointContainer cpContainer(IID_IConnectionPointContainer, m_ActiveX);
947 wxASSERT( cpContainer.Ok());
948
949 HRESULT hret =
950 cpContainer->FindConnectionPoint(ta->guid, cp.GetRef());
951 CHECK_HR(hret);
952
953 IDispatch* disp;
954 frame->QueryInterface(IID_IDispatch, (void**)&disp);
955 hret = cp->Advise(new wxActiveXEvents(this, ta->guid),
956 &adviseCookie);
957 CHECK_HR(hret);
958 }
959 }
960
961 ti->ReleaseTypeAttr(ta);
962 }
963
964 // free
965 typeInfo->ReleaseTypeAttr(ta);
966
967 //
968 // END
969 //
970
971 // Get IOleObject interface
972 hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX);
973 CHECK_HR(hret);
974
975 // get IViewObject Interface
976 hret = m_viewObject.QueryInterface(IID_IViewObject, m_ActiveX);
977 CHECK_HR(hret);
978
979 // document advise
980 m_docAdviseCookie = 0;
981 hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie);
982 CHECK_HR(hret);
983
984 // TODO:Needed?
985 // hret = m_viewObject->SetAdvise(DVASPECT_CONTENT, 0, adviseSink);
986 m_oleObject->SetHostNames(L"wxActiveXContainer", NULL);
987 OleSetContainedObject(m_oleObject, TRUE);
988 OleRun(m_oleObject);
989
990
991 // Get IOleInPlaceObject interface
992 hret = m_oleInPlaceObject.QueryInterface(
993 IID_IOleInPlaceObject, m_ActiveX);
994 CHECK_HR(hret);
995
996 // status
997 DWORD dwMiscStatus;
998 m_oleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
999 CHECK_HR(hret);
1000
1001 // set client site first ?
1002 if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
1003 m_oleObject->SetClientSite(m_clientSite);
1004
1005
1006 // stream init
1007 wxAutoIPersistStreamInit
1008 pPersistStreamInit(IID_IPersistStreamInit, m_oleObject);
1009
1010 if (pPersistStreamInit.Ok())
1011 {
1012 hret = pPersistStreamInit->InitNew();
1013 CHECK_HR(hret);
1014 }
1015
1016 if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
1017 m_oleObject->SetClientSite(m_clientSite);
1018
1019
1020 RECT posRect;
1021 ::GetClientRect((HWND)m_realparent->GetHWND(), &posRect);
1022
1023 m_oleObjectHWND = 0;
1024
1025 if (m_oleInPlaceObject.Ok())
1026 {
1027 hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
1028 if (SUCCEEDED(hret))
1029 ::SetActiveWindow(m_oleObjectHWND);
1030 }
1031
1032
1033 if (! (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME))
1034 {
1035 if (posRect.right > 0 && posRect.bottom > 0 &&
1036 m_oleInPlaceObject.Ok())
1037 m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
1038
1039 hret = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL,
1040 m_clientSite, 0, (HWND)m_realparent->GetHWND(), &posRect);
1041 CHECK_HR(hret);
1042
1043 hret = m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0,
1044 (HWND)m_realparent->GetHWND(), &posRect);
1045 CHECK_HR(hret);
1046 }
1047
1048 if (! m_oleObjectHWND && m_oleInPlaceObject.Ok())
1049 {
1050 hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
1051 CHECK_HR(hret);
1052 }
1053
1054 if (m_oleObjectHWND)
1055 {
1056 ::SetActiveWindow(m_oleObjectHWND);
1057 ::ShowWindow(m_oleObjectHWND, SW_SHOW);
1058
1059 this->AssociateHandle(m_oleObjectHWND);
1060 this->Reparent(m_realparent);
1061
1062 wxWindow* pWnd = m_realparent;
1063 int id = m_realparent->GetId();
1064
1065 pWnd->Connect(id, wxEVT_SIZE,
1066 wxSizeEventHandler(wxActiveXContainer::OnSize), 0, this);
1067 // this->Connect(GetId(), wxEVT_PAINT,
1068 // wxPaintEventHandler(wxActiveXContainer::OnPaint), 0, this);
1069 pWnd->Connect(id, wxEVT_SET_FOCUS,
1070 wxFocusEventHandler(wxActiveXContainer::OnSetFocus), 0, this);
1071 pWnd->Connect(id, wxEVT_KILL_FOCUS,
1072 wxFocusEventHandler(wxActiveXContainer::OnKillFocus), 0, this);
1073 }
1074 }
1075
1076 //---------------------------------------------------------------------------
1077 // wxActiveXContainer::OnSize
1078 //
1079 // Called when the parent is resized - we need to do this to actually
1080 // move the ActiveX control to where the parent is
1081 //---------------------------------------------------------------------------
1082 void wxActiveXContainer::OnSize(wxSizeEvent& event)
1083 {
1084 int w, h;
1085 GetParent()->GetClientSize(&w, &h);
1086
1087 RECT posRect;
1088 posRect.left = 0;
1089 posRect.top = 0;
1090 posRect.right = w;
1091 posRect.bottom = h;
1092
1093 if (w <= 0 && h <= 0)
1094 return;
1095
1096 // extents are in HIMETRIC units
1097 if (m_oleObject.Ok())
1098 {
1099 m_oleObject->DoVerb(OLEIVERB_HIDE, 0, m_clientSite, 0,
1100 (HWND)m_realparent->GetHWND(), &posRect);
1101
1102 SIZEL sz = {w, h};
1103 PixelsToHimetric(sz);
1104
1105 SIZEL sz2;
1106
1107 m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2);
1108 if (sz2.cx != sz.cx || sz.cy != sz2.cy)
1109 m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
1110
1111 m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0,
1112 (HWND)m_realparent->GetHWND(), &posRect);
1113 }
1114
1115 if (m_oleInPlaceObject.Ok())
1116 m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
1117
1118 event.Skip();
1119 }
1120
1121 //---------------------------------------------------------------------------
1122 // wxActiveXContainer::OnPaint
1123 //
1124 // Called when the parent is resized - repaints the ActiveX control
1125 //---------------------------------------------------------------------------
1126 void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
1127 {
1128 wxPaintDC dc(this);
1129 // Draw only when control is windowless or deactivated
1130 if (m_viewObject)
1131 {
1132 int w, h;
1133 GetParent()->GetSize(&w, &h);
1134 RECT posRect;
1135 posRect.left = 0;
1136 posRect.top = 0;
1137 posRect.right = w;
1138 posRect.bottom = h;
1139
1140 #if !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
1141 ::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
1142 #else
1143 ::InvalidateRect(m_oleObjectHWND, NULL, false);
1144 #endif
1145 RECTL *prcBounds = (RECTL *) &posRect;
1146 wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl );
1147 m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
1148 (HDC)msw->GetHDC(), prcBounds, NULL, NULL, 0);
1149 }
1150 }
1151
1152 //---------------------------------------------------------------------------
1153 // wxActiveXContainer::OnSetFocus
1154 //
1155 // Called when the focus is set on the parent - activates the activex control
1156 //---------------------------------------------------------------------------
1157 void wxActiveXContainer::OnSetFocus(wxFocusEvent& event)
1158 {
1159 if (m_oleInPlaceActiveObject.Ok())
1160 m_oleInPlaceActiveObject->OnFrameWindowActivate(TRUE);
1161
1162 event.Skip();
1163 }
1164
1165 //---------------------------------------------------------------------------
1166 // wxActiveXContainer::OnKillFocus
1167 //
1168 // Called when the focus is killed on the parent -
1169 // deactivates the activex control
1170 //---------------------------------------------------------------------------
1171 void wxActiveXContainer::OnKillFocus(wxFocusEvent& event)
1172 {
1173 if (m_oleInPlaceActiveObject.Ok())
1174 m_oleInPlaceActiveObject->OnFrameWindowActivate(FALSE);
1175
1176 event.Skip();
1177 }
1178
1179 #endif // wxUSE_ACTIVEX