]> git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/activex.cpp
avoid flicker when setting the text which is the same as the current status bar pane...
[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 defEventSink = false;
898 int impTypeFlags = 0;
899 typeInfo->GetImplTypeFlags(i, &impTypeFlags);
900
901 if (impTypeFlags & IMPLTYPEFLAG_FDEFAULT)
902 {
903 if (impTypeFlags & IMPLTYPEFLAG_FSOURCE)
904 {
905 // WXOLE_TRACEOUT("Default Event Sink");
906 defEventSink = true;
907 if (impTypeFlags & IMPLTYPEFLAG_FDEFAULTVTABLE)
908 {
909 // WXOLE_TRACEOUT("*ERROR* - Default Event Sink is via vTable");
910 defEventSink = false;
911 wxFAIL_MSG(wxT("Default event sink is in vtable!"));
912 }
913 }
914 }
915
916
917 // wxAutoOleInterface<> assumes a ref has already been added
918 // TYPEATTR
919 TYPEATTR *ta = NULL;
920 hret = ti->GetTypeAttr(&ta);
921 wxASSERT(ta);
922
923 if (ta->typekind == TKIND_DISPATCH)
924 {
925 // WXOLE_TRACEOUT("GUID = " << GetIIDName(ta->guid).c_str());
926 if (defEventSink)
927 {
928 wxAutoIConnectionPoint cp;
929 DWORD adviseCookie = 0;
930
931 wxAutoIConnectionPointContainer cpContainer(IID_IConnectionPointContainer, m_ActiveX);
932 wxASSERT( cpContainer.Ok());
933
934 HRESULT hret =
935 cpContainer->FindConnectionPoint(ta->guid, cp.GetRef());
936 wxASSERT ( SUCCEEDED(hret));
937
938 IDispatch* disp;
939 frame->QueryInterface(IID_IDispatch, (void**)&disp);
940 hret = cp->Advise(new wxActiveXEvents(this, ta->guid),
941 &adviseCookie);
942 wxASSERT_MSG( SUCCEEDED(hret),
943 wxString::Format(wxT("Cannot connect!\nHRESULT:%X"), (unsigned int)hret)
944 );
945 }
946 }
947
948 ti->ReleaseTypeAttr(ta);
949 }
950
951 // free
952 typeInfo->ReleaseTypeAttr(ta);
953
954 //
955 // END
956 //
957
958 // Get IOleObject interface
959 hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX);
960 wxASSERT(SUCCEEDED(hret));
961
962 // get IViewObject Interface
963 hret = m_viewObject.QueryInterface(IID_IViewObject, m_ActiveX);
964 wxASSERT(SUCCEEDED(hret));
965
966 // document advise
967 m_docAdviseCookie = 0;
968 hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie);
969 // TODO:Needed?
970 // hret = m_viewObject->SetAdvise(DVASPECT_CONTENT, 0, adviseSink);
971 m_oleObject->SetHostNames(L"wxActiveXContainer", NULL);
972 OleSetContainedObject(m_oleObject, TRUE);
973 OleRun(m_oleObject);
974
975
976 // Get IOleInPlaceObject interface
977 hret = m_oleInPlaceObject.QueryInterface(
978 IID_IOleInPlaceObject, m_ActiveX);
979 wxASSERT(SUCCEEDED(hret));
980
981 // status
982 DWORD dwMiscStatus;
983 m_oleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
984 wxASSERT(SUCCEEDED(hret));
985
986 // set client site first ?
987 if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
988 m_oleObject->SetClientSite(m_clientSite);
989
990
991 // stream init
992 wxAutoIPersistStreamInit
993 pPersistStreamInit(IID_IPersistStreamInit, m_oleObject);
994
995 if (pPersistStreamInit.Ok())
996 {
997 hret = pPersistStreamInit->InitNew();
998 }
999
1000 if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
1001 m_oleObject->SetClientSite(m_clientSite);
1002
1003
1004 RECT posRect;
1005 ::GetClientRect((HWND)m_realparent->GetHWND(), &posRect);
1006
1007 m_oleObjectHWND = 0;
1008
1009 if (m_oleInPlaceObject.Ok())
1010 {
1011 hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
1012 if (SUCCEEDED(hret))
1013 ::SetActiveWindow(m_oleObjectHWND);
1014 }
1015
1016
1017 if (! (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME))
1018 {
1019 if (posRect.right > 0 && posRect.bottom > 0 &&
1020 m_oleInPlaceObject.Ok())
1021 m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
1022
1023 hret = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL,
1024 m_clientSite, 0, (HWND)m_realparent->GetHWND(), &posRect);
1025 hret = m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0,
1026 (HWND)m_realparent->GetHWND(), &posRect);
1027 }
1028
1029 if (! m_oleObjectHWND && m_oleInPlaceObject.Ok())
1030 {
1031 hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
1032 }
1033
1034 if (m_oleObjectHWND)
1035 {
1036 ::SetActiveWindow(m_oleObjectHWND);
1037 ::ShowWindow(m_oleObjectHWND, SW_SHOW);
1038
1039 this->AssociateHandle(m_oleObjectHWND);
1040 this->Reparent(m_realparent);
1041
1042 wxWindow* pWnd = m_realparent;
1043 int id = m_realparent->GetId();
1044
1045 pWnd->Connect(id, wxEVT_SIZE,
1046 wxSizeEventHandler(wxActiveXContainer::OnSize), 0, this);
1047 // this->Connect(GetId(), wxEVT_PAINT,
1048 // wxPaintEventHandler(wxActiveXContainer::OnPaint), 0, this);
1049 pWnd->Connect(id, wxEVT_SET_FOCUS,
1050 wxFocusEventHandler(wxActiveXContainer::OnSetFocus), 0, this);
1051 pWnd->Connect(id, wxEVT_KILL_FOCUS,
1052 wxFocusEventHandler(wxActiveXContainer::OnKillFocus), 0, this);
1053 }
1054 }
1055
1056 //---------------------------------------------------------------------------
1057 // wxActiveXContainer::OnSize
1058 //
1059 // Called when the parent is resized - we need to do this to actually
1060 // move the ActiveX control to where the parent is
1061 //---------------------------------------------------------------------------
1062 void wxActiveXContainer::OnSize(wxSizeEvent& event)
1063 {
1064 int w, h;
1065 GetParent()->GetClientSize(&w, &h);
1066
1067 RECT posRect;
1068 posRect.left = 0;
1069 posRect.top = 0;
1070 posRect.right = w;
1071 posRect.bottom = h;
1072
1073 if (w <= 0 && h <= 0)
1074 return;
1075
1076 // extents are in HIMETRIC units
1077 if (m_oleObject.Ok())
1078 {
1079 m_oleObject->DoVerb(OLEIVERB_HIDE, 0, m_clientSite, 0,
1080 (HWND)m_realparent->GetHWND(), &posRect);
1081
1082 SIZEL sz = {w, h};
1083 PixelsToHimetric(sz);
1084
1085 SIZEL sz2;
1086
1087 m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2);
1088 if (sz2.cx != sz.cx || sz.cy != sz2.cy)
1089 m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
1090
1091 m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0,
1092 (HWND)m_realparent->GetHWND(), &posRect);
1093 }
1094
1095 if (m_oleInPlaceObject.Ok())
1096 m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
1097
1098 event.Skip();
1099 }
1100
1101 //---------------------------------------------------------------------------
1102 // wxActiveXContainer::OnPaint
1103 //
1104 // Called when the parent is resized - repaints the ActiveX control
1105 //---------------------------------------------------------------------------
1106 void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
1107 {
1108 wxPaintDC dc(this);
1109 // Draw only when control is windowless or deactivated
1110 if (m_viewObject)
1111 {
1112 int w, h;
1113 GetParent()->GetSize(&w, &h);
1114 RECT posRect;
1115 posRect.left = 0;
1116 posRect.top = 0;
1117 posRect.right = w;
1118 posRect.bottom = h;
1119
1120 #if !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
1121 ::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
1122 #else
1123 ::InvalidateRect(m_oleObjectHWND, NULL, false);
1124 #endif
1125 RECTL *prcBounds = (RECTL *) &posRect;
1126 m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
1127 (HDC)dc.GetHDC(), prcBounds, NULL, NULL, 0);
1128 }
1129 }
1130
1131 //---------------------------------------------------------------------------
1132 // wxActiveXContainer::OnSetFocus
1133 //
1134 // Called when the focus is set on the parent - activates the activex control
1135 //---------------------------------------------------------------------------
1136 void wxActiveXContainer::OnSetFocus(wxFocusEvent& event)
1137 {
1138 if (m_oleInPlaceActiveObject.Ok())
1139 m_oleInPlaceActiveObject->OnFrameWindowActivate(TRUE);
1140
1141 event.Skip();
1142 }
1143
1144 //---------------------------------------------------------------------------
1145 // wxActiveXContainer::OnKillFocus
1146 //
1147 // Called when the focus is killed on the parent -
1148 // deactivates the activex control
1149 //---------------------------------------------------------------------------
1150 void wxActiveXContainer::OnKillFocus(wxFocusEvent& event)
1151 {
1152 if (m_oleInPlaceActiveObject.Ok())
1153 m_oleInPlaceActiveObject->OnFrameWindowActivate(FALSE);
1154
1155 event.Skip();
1156 }
1157
1158 #endif // wxUSE_ACTIVEX