]> git.saurik.com Git - wxWidgets.git/blob - wxPython/contrib/activex/wxie/wxactivex.cpp
Patch from Ole André, call RegisterActiveObject() so the objects can
[wxWidgets.git] / wxPython / contrib / activex / wxie / wxactivex.cpp
1 /*
2 wxActiveX Library Licence, Version 3
3 ====================================
4
5 Copyright (C) 2003 Lindsay Mathieson [, ...]
6
7 Everyone is permitted to copy and distribute verbatim copies
8 of this licence document, but changing it is not allowed.
9
10 wxActiveX LIBRARY LICENCE
11 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12
13 This library is free software; you can redistribute it and/or modify it
14 under the terms of the GNU Library General Public Licence as published by
15 the Free Software Foundation; either version 2 of the Licence, or (at
16 your option) any later version.
17
18 This library is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
21 General Public Licence for more details.
22
23 You should have received a copy of the GNU Library General Public Licence
24 along with this software, usually in a file named COPYING.LIB. If not,
25 write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
26 Boston, MA 02111-1307 USA.
27
28 EXCEPTION NOTICE
29
30 1. As a special exception, the copyright holders of this library give
31 permission for additional uses of the text contained in this release of
32 the library as licenced under the wxActiveX Library Licence, applying
33 either version 3 of the Licence, or (at your option) any later version of
34 the Licence as published by the copyright holders of version 3 of the
35 Licence document.
36
37 2. The exception is that you may use, copy, link, modify and distribute
38 under the user's own terms, binary object code versions of works based
39 on the Library.
40
41 3. If you copy code from files distributed under the terms of the GNU
42 General Public Licence or the GNU Library General Public Licence into a
43 copy of this library, as this licence permits, the exception does not
44 apply to the code that you add in this way. To avoid misleading anyone as
45 to the status of such modified files, you must delete this exception
46 notice from such code and/or adjust the licensing conditions notice
47 accordingly.
48
49 4. If you write modifications of your own for this library, it is your
50 choice whether to permit this exception to apply to your modifications.
51 If you do not wish that, you must delete the exception notice from such
52 code and/or adjust the licensing conditions notice accordingly.
53 */
54
55 #include "wxActiveX.h"
56 #include <wx/strconv.h>
57 #include <wx/event.h>
58 #include <wx/string.h>
59 #include <wx/datetime.h>
60 #include <wx/log.h>
61 #include <oleidl.h>
62 #include <winerror.h>
63 #include <idispids.h>
64 #include <olectl.h>
65 using namespace std;
66
67 // Depending on compilation mode, the wx headers may have undef'd
68 // this, but in this case we need it so the virtual method in
69 // FrameSite will match what is in oleidl.h.
70 #ifndef GetObject
71 #ifdef _UNICODE
72 #define GetObject GetObjectW
73 #else
74 #define GetObject GetObjectA
75 #endif
76 #endif
77
78
79 //////////////////////////////////////////////////////////////////////
80 BEGIN_EVENT_TABLE(wxActiveX, wxWindow)
81 EVT_SIZE(wxActiveX::OnSize)
82 EVT_PAINT(wxActiveX::OnPaint)
83 EVT_MOUSE_EVENTS(wxActiveX::OnMouse)
84 EVT_SET_FOCUS(wxActiveX::OnSetFocus)
85 EVT_KILL_FOCUS(wxActiveX::OnKillFocus)
86 END_EVENT_TABLE()
87
88 IMPLEMENT_CLASS(wxActiveX, wxWindow)
89
90 class wxActiveX;
91
92 class FrameSite :
93 public IOleClientSite,
94 public IOleInPlaceSiteEx,
95 public IOleInPlaceFrame,
96 public IOleItemContainer,
97 public IDispatch,
98 public IOleCommandTarget,
99 public IOleDocumentSite,
100 public IAdviseSink,
101 public IOleControlSite
102 {
103 private:
104 DECLARE_OLE_UNKNOWN(FrameSite);
105
106 public:
107 FrameSite(wxActiveX * win);
108 virtual ~FrameSite();
109
110 //IOleWindow
111 STDMETHODIMP GetWindow(HWND*);
112 STDMETHODIMP ContextSensitiveHelp(BOOL);
113
114 //IOleInPlaceUIWindow
115 STDMETHODIMP GetBorder(LPRECT);
116 STDMETHODIMP RequestBorderSpace(LPCBORDERWIDTHS);
117 STDMETHODIMP SetBorderSpace(LPCBORDERWIDTHS);
118 STDMETHODIMP SetActiveObject(IOleInPlaceActiveObject*, LPCOLESTR);
119
120 //IOleInPlaceFrame
121 STDMETHODIMP InsertMenus(HMENU, LPOLEMENUGROUPWIDTHS);
122 STDMETHODIMP SetMenu(HMENU, HOLEMENU, HWND);
123 STDMETHODIMP RemoveMenus(HMENU);
124 STDMETHODIMP SetStatusText(LPCOLESTR);
125 STDMETHODIMP EnableModeless(BOOL);
126 STDMETHODIMP TranslateAccelerator(LPMSG, WORD);
127
128 //IOleInPlaceSite
129 STDMETHODIMP CanInPlaceActivate();
130 STDMETHODIMP OnInPlaceActivate();
131 STDMETHODIMP OnUIActivate();
132 STDMETHODIMP GetWindowContext(IOleInPlaceFrame**, IOleInPlaceUIWindow**,
133 LPRECT, LPRECT, LPOLEINPLACEFRAMEINFO);
134 STDMETHODIMP Scroll(SIZE);
135 STDMETHODIMP OnUIDeactivate(BOOL);
136 STDMETHODIMP OnInPlaceDeactivate();
137 STDMETHODIMP DiscardUndoState();
138 STDMETHODIMP DeactivateAndUndo();
139 STDMETHODIMP OnPosRectChange(LPCRECT);
140
141 //IOleInPlaceSiteEx
142 STDMETHODIMP OnInPlaceActivateEx(BOOL*, DWORD);
143 STDMETHODIMP OnInPlaceDeactivateEx(BOOL);
144 STDMETHODIMP RequestUIActivate();
145
146 //IOleClientSite
147 STDMETHODIMP SaveObject();
148 STDMETHODIMP GetMoniker(DWORD, DWORD, IMoniker**);
149 STDMETHODIMP GetContainer(LPOLECONTAINER FAR*);
150 STDMETHODIMP ShowObject();
151 STDMETHODIMP OnShowWindow(BOOL);
152 STDMETHODIMP RequestNewObjectLayout();
153
154 //IOleControlSite
155 STDMETHODIMP OnControlInfoChanged();
156 STDMETHODIMP LockInPlaceActive(BOOL);
157 STDMETHODIMP GetExtendedControl(IDispatch**);
158 STDMETHODIMP TransformCoords(POINTL*, POINTF*, DWORD);
159 STDMETHODIMP TranslateAccelerator(LPMSG, DWORD);
160 STDMETHODIMP OnFocus(BOOL);
161 STDMETHODIMP ShowPropertyFrame();
162
163 //IOleCommandTarget
164 STDMETHODIMP QueryStatus(const GUID*, ULONG, OLECMD[], OLECMDTEXT*);
165 STDMETHODIMP Exec(const GUID*, DWORD, DWORD, VARIANTARG*, VARIANTARG*);
166
167 //IParseDisplayName
168 STDMETHODIMP ParseDisplayName(IBindCtx*, LPOLESTR, ULONG*, IMoniker**);
169
170 //IOleContainer
171 STDMETHODIMP EnumObjects(DWORD, IEnumUnknown**);
172 STDMETHODIMP LockContainer(BOOL);
173
174 //IOleItemContainer
175 STDMETHODIMP GetObject(LPOLESTR, DWORD, IBindCtx*, REFIID, void**);
176 STDMETHODIMP GetObjectStorage(LPOLESTR, IBindCtx*, REFIID, void**);
177 STDMETHODIMP IsRunning(LPOLESTR);
178
179 //IDispatch
180 STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR**, unsigned int, LCID, DISPID*);
181 STDMETHODIMP GetTypeInfo(unsigned int, LCID, ITypeInfo**);
182 STDMETHODIMP GetTypeInfoCount(unsigned int*);
183 STDMETHODIMP Invoke(DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);
184
185 //IAdviseSink
186 void STDMETHODCALLTYPE OnDataChange(FORMATETC*, STGMEDIUM*);
187 void STDMETHODCALLTYPE OnViewChange(DWORD, LONG);
188 void STDMETHODCALLTYPE OnRename(IMoniker*);
189 void STDMETHODCALLTYPE OnSave();
190 void STDMETHODCALLTYPE OnClose();
191
192 // IOleDocumentSite
193 HRESULT STDMETHODCALLTYPE ActivateMe(IOleDocumentView __RPC_FAR *pViewToActivate);
194
195 protected:
196
197 wxActiveX * m_window;
198
199 HDC m_hDCBuffer;
200 HWND m_hWndParent;
201
202 bool m_bSupportsWindowlessActivation;
203 bool m_bInPlaceLocked;
204 bool m_bInPlaceActive;
205 bool m_bUIActive;
206 bool m_bWindowless;
207
208
209
210 LCID m_nAmbientLocale;
211 COLORREF m_clrAmbientForeColor;
212 COLORREF m_clrAmbientBackColor;
213 bool m_bAmbientShowHatching;
214 bool m_bAmbientShowGrabHandles;
215 bool m_bAmbientAppearance;
216 };
217
218 DEFINE_OLE_TABLE(FrameSite)
219 OLE_INTERFACE(IID_IUnknown, IOleClientSite)
220
221 OLE_IINTERFACE(IOleClientSite)
222
223 OLE_INTERFACE(IID_IOleWindow, IOleInPlaceSite)
224 OLE_IINTERFACE(IOleInPlaceSite)
225 OLE_IINTERFACE(IOleInPlaceSiteEx)
226
227 //OLE_IINTERFACE(IOleWindow)
228 OLE_IINTERFACE(IOleInPlaceUIWindow)
229 OLE_IINTERFACE(IOleInPlaceFrame)
230
231 OLE_IINTERFACE(IParseDisplayName)
232 OLE_IINTERFACE(IOleContainer)
233 OLE_IINTERFACE(IOleItemContainer)
234
235 OLE_IINTERFACE(IDispatch)
236
237 OLE_IINTERFACE(IOleCommandTarget)
238
239 OLE_IINTERFACE(IOleDocumentSite)
240
241 OLE_IINTERFACE(IAdviseSink)
242
243 OLE_IINTERFACE(IOleControlSite)
244
245 END_OLE_TABLE;
246
247
248 wxActiveX::wxActiveX(wxWindow * parent, REFCLSID clsid, wxWindowID id,
249 const wxPoint& pos,
250 const wxSize& size,
251 long style,
252 const wxString& name) :
253 wxWindow(parent, id, pos, size, style, name)
254 {
255 m_bAmbientUserMode = true;
256 m_docAdviseCookie = 0;
257 CreateActiveX(clsid);
258 }
259
260 wxActiveX::wxActiveX(wxWindow * parent, const wxString& progId, wxWindowID id,
261 const wxPoint& pos,
262 const wxSize& size,
263 long style,
264 const wxString& name) :
265 wxWindow(parent, id, pos, size, style, name)
266 {
267 m_bAmbientUserMode = true;
268 m_docAdviseCookie = 0;
269 CreateActiveX((LPOLESTR) (const wchar_t *) progId.wc_str(wxConvUTF8));
270 }
271
272 wxActiveX::~wxActiveX()
273 {
274 // disconnect connection points
275 wxOleConnectionArray::iterator it = m_connections.begin();
276 while (it != m_connections.end())
277 {
278 wxOleConnectionPoint& cp = it->first;
279 cp->Unadvise(it->second);
280
281 it++;
282 };
283 m_connections.clear();
284
285 if (m_oleInPlaceObject.Ok())
286 {
287 m_oleInPlaceObject->InPlaceDeactivate();
288 m_oleInPlaceObject->UIDeactivate();
289 }
290
291
292 if (m_oleObject.Ok())
293 {
294 if (m_docAdviseCookie != 0)
295 m_oleObject->Unadvise(m_docAdviseCookie);
296
297 m_oleObject->DoVerb(OLEIVERB_HIDE, NULL, m_clientSite, 0, (HWND) GetHWND(), NULL);
298 m_oleObject->Close(OLECLOSE_NOSAVE);
299 m_oleObject->SetClientSite(NULL);
300 }
301 }
302
303 void wxActiveX::CreateActiveX(REFCLSID clsid)
304 {
305 SetTransparent();
306
307 HRESULT hret;
308
309 ////////////////////////////////////////////////////////
310 // FrameSite
311 FrameSite *frame = new FrameSite(this);
312 // oleClientSite
313 hret = m_clientSite.QueryInterface(IID_IOleClientSite, (IDispatch *) frame);
314 wxCHECK_RET(SUCCEEDED(hret), _T("m_clientSite.QueryInterface failed"));
315 // adviseSink
316 wxAutoOleInterface<IAdviseSink> adviseSink(IID_IAdviseSink, (IDispatch *) frame);
317 wxCHECK_RET(adviseSink.Ok(), _T("adviseSink not Ok"));
318
319
320 // Create Object, get IUnknown interface
321 m_ActiveX.CreateInstance(clsid, IID_IUnknown);
322 wxCHECK_RET(m_ActiveX.Ok(), _T("m_ActiveX.CreateInstance failed"));
323
324 // Register object as active
325 unsigned long pdwRegister;
326 hret = RegisterActiveObject(m_ActiveX, clsid, ACTIVEOBJECT_WEAK, &pdwRegister);
327 WXOLE_WARN(hret, "Unable to register object as active");
328
329 // Get Dispatch interface
330 hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX);
331 WXOLE_WARN(hret, "Unable to get dispatch interface");
332
333 // Type Info
334 GetTypeInfo();
335
336 // Get IOleObject interface
337 hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX);
338 wxCHECK_RET(SUCCEEDED(hret), _("Unable to get IOleObject interface"));
339
340 // get IViewObject Interface
341 hret = m_viewObject.QueryInterface(IID_IViewObject, m_ActiveX);
342 wxCHECK_RET(SUCCEEDED(hret), _T("Unable to get IViewObject Interface"));
343
344 // document advise
345 m_docAdviseCookie = 0;
346 hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie);
347 WXOLE_WARN(hret, "m_oleObject->Advise(adviseSink, &m_docAdviseCookie),\"Advise\")");
348 m_oleObject->SetHostNames(L"wxActiveXContainer", NULL);
349 OleSetContainedObject(m_oleObject, TRUE);
350 OleRun(m_oleObject);
351
352
353 // Get IOleInPlaceObject interface
354 hret = m_oleInPlaceObject.QueryInterface(IID_IOleInPlaceObject, m_ActiveX);
355 wxCHECK_RET(SUCCEEDED(hret), _T("Unable to get IOleInPlaceObject interface"));
356
357 // status
358 DWORD dwMiscStatus;
359 m_oleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
360 wxCHECK_RET(SUCCEEDED(hret), _T("Unable to get oleObject status"));
361
362 // set client site first ?
363 if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
364 m_oleObject->SetClientSite(m_clientSite);
365
366
367 // stream init
368 wxAutoOleInterface<IPersistStreamInit>
369 pPersistStreamInit(IID_IPersistStreamInit, m_oleObject);
370
371 if (pPersistStreamInit.Ok())
372 {
373 hret = pPersistStreamInit->InitNew();
374 WXOLE_WARN(hret, "CreateActiveX::pPersistStreamInit->InitNew()");
375 };
376
377 if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
378 m_oleObject->SetClientSite(m_clientSite);
379
380
381 int w, h;
382 GetClientSize(&w, &h);
383 RECT posRect;
384 posRect.left = 0;
385 posRect.top = 0;
386 posRect.right = w;
387 posRect.bottom = h;
388
389 m_oleObjectHWND = 0;
390
391 if (m_oleInPlaceObject.Ok())
392 {
393 hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
394 WXOLE_WARN(hret, "m_oleInPlaceObject->GetWindow(&m_oleObjectHWND)");
395 if (SUCCEEDED(hret))
396 ::SetActiveWindow(m_oleObjectHWND);
397 };
398
399
400 if (! (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME))
401 {
402 if (w > 0 && h > 0 && m_oleInPlaceObject.Ok())
403 m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
404
405 hret = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, m_clientSite, 0, (HWND)GetHWND(), &posRect);
406 hret = m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0, (HWND)GetHWND(), &posRect);
407 };
408
409 if (! m_oleObjectHWND && m_oleInPlaceObject.Ok())
410 {
411 hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
412 WXOLE_WARN(hret, "m_oleInPlaceObject->GetWindow(&m_oleObjectHWND)");
413 };
414
415 if (m_oleObjectHWND)
416 {
417 ::SetActiveWindow(m_oleObjectHWND);
418 ::ShowWindow(m_oleObjectHWND, SW_SHOW);
419
420 // Update by GBR to resize older controls
421 wxSizeEvent szEvent;
422 szEvent.m_size = wxSize(w, h) ;
423 GetEventHandler()->AddPendingEvent(szEvent);
424 };
425 }
426
427 void wxActiveX::CreateActiveX(LPOLESTR progId)
428 {
429 CLSID clsid;
430 if (CLSIDFromProgID(progId, &clsid) != S_OK)
431 return;
432
433 CreateActiveX(clsid);
434 };
435
436 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
437 // Case Insensitive Map of Event names to eventTypes
438 // created dynamically at run time in:
439 // EVT_ACTIVEX(eventName, id, fn)
440 // we map the pointer to them so that:
441 // const wxEventType& RegisterActiveXEvent(wxString eventName);
442 // can return a const reference, which is neccessary for event tables
443 // probably should use a wxWindows hash table here, but I'm lazy ...
444 typedef map<wxString, wxEventType *, NS_wxActiveX::less_wxStringI> ActiveXNamedEventMap;
445 static ActiveXNamedEventMap sg_NamedEventMap;
446
447 const wxEventType& RegisterActiveXEvent(const wxChar *eventName)
448 {
449 wxString ev = eventName;
450 ActiveXNamedEventMap::iterator it = sg_NamedEventMap.find(ev);
451 if (it == sg_NamedEventMap.end())
452 {
453 wxEventType *et = new wxEventType(wxNewEventType());
454 sg_NamedEventMap[ev] = et;
455
456 return *et;
457 };
458
459 return *(it->second);
460 };
461
462
463 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
464 // Map of Event DISPID's to eventTypes
465 // created dynamically at run time in:
466 // EVT_ACTIVEX(eventName, id, fn)
467 // we map the pointer to them so that:
468 // const wxEventType& RegisterActiveXEvent(wxString eventName);
469 // can return a const reference, which is neccessary for event tables
470
471 typedef map<DISPID, wxEventType *> ActiveXDISPIDEventMap;
472 static ActiveXDISPIDEventMap sg_dispIdEventMap;
473
474 const wxEventType& RegisterActiveXEvent(DISPID event)
475 {
476 ActiveXDISPIDEventMap::iterator it = sg_dispIdEventMap.find(event);
477 if (it == sg_dispIdEventMap.end())
478 {
479 wxEventType *et = new wxEventType(wxNewEventType());
480 sg_dispIdEventMap[event] = et;
481
482 return *et;
483 };
484
485 return *(it->second);
486 };
487
488 // one off class for automatic freeing of activeX eventtypes
489 class ActiveXEventMapFlusher
490 {
491 public:
492 ~ActiveXEventMapFlusher()
493 {
494 // Named events
495 ActiveXNamedEventMap::iterator it = sg_NamedEventMap.end();
496 while (it != sg_NamedEventMap.end())
497 {
498 delete it->second;
499 it++;
500 };
501 sg_NamedEventMap.clear();
502
503 // DISPID events
504 ActiveXDISPIDEventMap::iterator dit = sg_dispIdEventMap.end();
505 while (dit != sg_dispIdEventMap.end())
506 {
507 delete dit->second;
508 dit++;
509 };
510 sg_dispIdEventMap.clear();
511 };
512 };
513
514 static ActiveXEventMapFlusher s_dummyActiveXEventMapFlusher;
515
516
517 //////////////////////////////////////////////////////
518 VARTYPE wxTypeToVType(const wxVariant& v)
519 {
520 wxString type = v.GetType();
521 if (type == wxT("bool"))
522 return VT_BOOL;
523 else if (type == wxT("char"))
524 return VT_I1;
525 else if (type == wxT("datetime"))
526 return VT_DATE;
527 else if (type == wxT("double"))
528 return VT_R8;
529 else if (type == wxT("list"))
530 return VT_ARRAY;
531 else if (type == wxT("long"))
532 return VT_I4;
533 else if (type == wxT("string"))
534 return VT_BSTR;
535 else if (type == wxT("stringlist"))
536 return VT_ARRAY;
537 else if (type == wxT("date"))
538 return VT_DATE;
539 else if (type == wxT("time"))
540 return VT_DATE;
541 else if (type == wxT("void*"))
542 return VT_VOID | VT_BYREF;
543 else
544 return VT_NULL;
545 };
546
547 bool wxDateTimeToDATE(wxDateTime dt, DATE& d)
548 {
549 SYSTEMTIME st;
550 memset(&st, 0, sizeof(st));
551
552 st.wYear = dt.GetYear();
553 st.wMonth = dt.GetMonth() + 1;
554 st.wDay = dt.GetDay();
555 st.wHour = dt.GetHour();
556 st.wMinute = dt.GetMinute();
557 st.wSecond = dt.GetSecond();
558 st.wMilliseconds = dt.GetMillisecond();
559 return SystemTimeToVariantTime(&st, &d) != FALSE;
560 };
561
562 bool wxDateTimeToVariant(wxDateTime dt, VARIANTARG& va)
563 {
564 return wxDateTimeToDATE(dt, va.date);
565 };
566
567 bool DATEToWxDateTime(DATE date, wxDateTime& dt)
568 {
569 SYSTEMTIME st;
570 if (! VariantTimeToSystemTime(date, &st))
571 return false;
572
573 dt = wxDateTime(
574 st.wDay,
575 wxDateTime::Month(int(wxDateTime::Jan) + st.wMonth - 1),
576 st.wYear,
577 st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
578
579 return true;
580 };
581
582 bool VariantToWxDateTime(VARIANTARG va, wxDateTime& dt)
583 {
584 HRESULT hr = VariantChangeType(&va, &va, 0, VT_DATE);
585 if (! SUCCEEDED(hr))
586 return false;
587
588 return DATEToWxDateTime(va.date, dt);
589 };
590
591 bool MSWVariantToVariant(VARIANTARG& va, wxVariant& vx)
592 {
593 bool byRef = false;
594 VARTYPE vt = va.vt;
595
596 if (vt & VT_ARRAY)
597 return false; // don't support arrays yet
598
599 if (vt & VT_BYREF)
600 {
601 byRef = true;
602 vt &= ~(VT_BYREF);
603 };
604
605
606 switch(vt)
607 {
608 case VT_VARIANT:
609 if (byRef)
610 return MSWVariantToVariant(*va.pvarVal, vx);
611 else
612 {
613 VARIANT tmp = va;
614 VariantChangeType(&tmp, &tmp, 0, wxTypeToVType(vx));
615 bool rc = MSWVariantToVariant(tmp, vx);
616 VariantClear(&tmp);
617 return rc;
618 };
619
620 // 1 byte chars
621 case VT_I1:
622 case VT_UI1:
623 if (byRef)
624 vx = (char) *va.pbVal;
625 else
626 vx = (char) va.bVal;
627 return true;
628
629 // 2 byte shorts
630 case VT_I2:
631 case VT_UI2:
632 if (byRef)
633 vx = (long) *va.puiVal;
634 else
635 vx = (long) va.uiVal;
636 return true;
637
638 // 4 bytes longs
639 case VT_I4:
640 case VT_UI4:
641 case VT_INT:
642 case VT_UINT:
643 case VT_ERROR:
644 if (byRef)
645 vx = (long) *va.pulVal;
646 else
647 vx = (long) va.ulVal;
648 return true;
649
650
651 // 4 byte floats
652 case VT_R4:
653 if (byRef)
654 vx = *va.pfltVal;
655 else
656 vx = va.fltVal;
657 return true;
658
659 // 8 byte doubles
660 case VT_R8:
661 if (byRef)
662 vx = *va.pdblVal;
663 else
664 vx = va.dblVal;
665 return true;
666
667 case VT_BOOL:
668 if (byRef)
669 vx = (*va.pboolVal ? true : false);
670 else
671 vx = (va.boolVal ? true : false);
672 return true;
673
674 case VT_CY:
675 vx.MakeNull();
676 return false; // what the hell is a CY ?
677
678 case VT_DECIMAL:
679 {
680 double d = 0;
681 HRESULT hr;
682 if (byRef)
683 hr = VarR8FromDec(va.pdecVal, &d);
684 else
685 hr = VarR8FromDec(&va.decVal, &d);
686
687 vx = d;
688 return SUCCEEDED(hr);
689 };
690
691 case VT_DATE:
692 {
693 wxDateTime dt;
694 bool rc = false;
695 if (byRef)
696 rc = DATEToWxDateTime(*va.pdate, dt);
697 else
698 rc = VariantToWxDateTime(va, dt);
699 vx = dt;
700 return rc;
701 };
702
703 case VT_BSTR:
704 if (byRef)
705 vx = wxString(*va.pbstrVal);
706 else
707 vx = wxString(va.bstrVal);
708 return true;
709
710 case VT_UNKNOWN: // should do a custom wxVariantData for this
711 if (byRef)
712 vx = (void *) *va.ppunkVal;
713 else
714 vx = (void *) va.punkVal;
715 return false;
716
717 case VT_DISPATCH: // should do a custom wxVariantData for this
718 if (byRef)
719 vx = (void *) *va.ppdispVal;
720 else
721 vx = (void *) va.pdispVal;
722 return false;
723
724 default:
725 vx.MakeNull();
726 return false;
727 };
728 };
729
730 bool VariantToMSWVariant(const wxVariant& vx, VARIANTARG& va)
731 {
732 bool byRef = false;
733 VARTYPE vt = va.vt;
734
735 if (vt & VT_ARRAY)
736 return false; // don't support arrays yet
737
738 if (vt & VT_BYREF)
739 {
740 byRef = true;
741 vt &= ~(VT_BYREF);
742 };
743
744 switch(vt)
745 {
746 case VT_VARIANT:
747 if (byRef)
748 return VariantToMSWVariant(vx, *va.pvarVal);
749 else
750 {
751 va.vt = wxTypeToVType(vx);
752 return VariantToMSWVariant(vx, va);
753 };
754
755 // 1 byte chars
756 case VT_I1:
757 case VT_UI1:
758 if (byRef)
759 *va.pbVal = (char) vx;
760 else
761 va.bVal = (char) vx;
762 return true;
763
764 // 2 byte shorts
765 case VT_I2:
766 case VT_UI2:
767 if (byRef)
768 *va.puiVal = (long) vx;
769 else
770 va.uiVal = (long) vx;
771 return true;
772
773 // 4 bytes longs
774 case VT_I4:
775 case VT_UI4:
776 case VT_INT:
777 case VT_UINT:
778 case VT_ERROR:
779 if (byRef)
780 *va.pulVal = (long) vx;
781 else
782 va.ulVal = (long) vx;
783 return true;
784
785
786 // 4 byte floats
787 case VT_R4:
788 if (byRef)
789 *va.pfltVal = (double) vx;
790 else
791 va.fltVal = (double) vx;
792 return true;
793
794 // 8 byte doubles
795 case VT_R8:
796 if (byRef)
797 *va.pdblVal = (double) vx;
798 else
799 va.dblVal = (double) vx;
800 return true;
801
802 case VT_BOOL:
803 if (byRef)
804 *va.pboolVal = ((bool) vx) ? TRUE : FALSE;
805 else
806 va.boolVal = ((bool) vx) ? TRUE : FALSE;
807 return true;
808
809 case VT_CY:
810 return false; // what the hell is a CY ?
811
812 case VT_DECIMAL:
813 if (byRef)
814 return SUCCEEDED(VarDecFromR8(vx, va.pdecVal));
815 else
816 return SUCCEEDED(VarDecFromR8(vx, &va.decVal));
817
818 case VT_DATE:
819 if (byRef)
820 return wxDateTimeToDATE(vx, *va.pdate);
821 else
822 return wxDateTimeToVariant(vx,va);
823
824 case VT_BSTR:
825 if (byRef)
826 *va.pbstrVal = SysAllocString(vx.GetString().wc_str(wxConvUTF8));
827 else
828 va.bstrVal = SysAllocString(vx.GetString().wc_str(wxConvUTF8));
829 return true;
830
831 case VT_UNKNOWN: // should do a custom wxVariantData for this
832 if (byRef)
833 *va.ppunkVal = (IUnknown *) (void *) vx;
834 else
835 va.punkVal = (IUnknown *) (void *) vx;
836 return false;
837
838 case VT_DISPATCH: // should do a custom wxVariantData for this
839 if (byRef)
840 *va.ppdispVal = (IDispatch *) (void *) vx;
841 else
842 va.pdispVal = (IDispatch *) (void *) vx;
843 return false;
844
845 default:
846 return false;
847 };
848 };
849
850 IMPLEMENT_CLASS(wxActiveXEvent, wxCommandEvent)
851
852 class wxActiveXEvents : public IDispatch
853 {
854 private:
855 DECLARE_OLE_UNKNOWN(wxActiveXEvents);
856
857
858 wxActiveX *m_activeX;
859 IID m_customId;
860 bool m_haveCustomId;
861
862 friend bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc);
863
864 public:
865 wxActiveXEvents(wxActiveX *ax) : m_activeX(ax), m_haveCustomId(false) {}
866 wxActiveXEvents(wxActiveX *ax, REFIID iid) : m_activeX(ax), m_haveCustomId(true), m_customId(iid) {}
867 virtual ~wxActiveXEvents()
868 {
869 }
870
871 //IDispatch
872 STDMETHODIMP GetIDsOfNames(REFIID r, OLECHAR** o, unsigned int i, LCID l, DISPID* d)
873 {
874 return E_NOTIMPL;
875 };
876
877 STDMETHODIMP GetTypeInfo(unsigned int i, LCID l, ITypeInfo** t)
878 {
879 return E_NOTIMPL;
880 };
881
882 STDMETHODIMP GetTypeInfoCount(unsigned int* i)
883 {
884 return E_NOTIMPL;
885 };
886
887
888 void DispatchEvent(wxActiveX::FuncX &func, const wxEventType& eventType, DISPPARAMS * pDispParams)
889 {
890 wxActiveXEvent event;
891 event.SetId(m_activeX->GetId());
892 event.SetEventType(eventType);
893 event.m_params.NullList();
894 event.m_params.SetName(func.name);
895
896 // arguments
897 if (pDispParams)
898 {
899 // cdecl call
900 // sometimes the pDispParams does not match the param info for a activex control
901 int nArg = wxMin(func.params.size(), pDispParams->cArgs);
902 for (int i = nArg - 1; i >= 0; i--)
903 {
904 VARIANTARG& va = pDispParams->rgvarg[i];
905 wxActiveX::ParamX &px = func.params[nArg - i - 1];
906 wxVariant vx;
907
908 vx.SetName(px.name);
909 MSWVariantToVariant(va, vx);
910 event.m_params.Append(vx);
911 };
912 };
913
914 if (func.hasOut)
915 {
916 int nArg = wxMin(func.params.size(), pDispParams->cArgs);
917 m_activeX->GetEventHandler()->ProcessEvent(event);
918 for (int i = 0; i < nArg; i++)
919 {
920 VARIANTARG& va = pDispParams->rgvarg[i];
921 wxActiveX::ParamX &px = func.params[nArg - i - 1];
922
923 if (px.IsOut())
924 {
925 wxVariant& vx = event.m_params[nArg - i - 1];
926
927 VariantToMSWVariant(vx, va);
928 };
929 };
930 }
931 else
932 m_activeX->GetEventHandler()->AddPendingEvent(event);
933
934 };
935
936 STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
937 WORD wFlags, DISPPARAMS * pDispParams,
938 VARIANT * pVarResult, EXCEPINFO * pExcepInfo,
939 unsigned int * puArgErr)
940 {
941 if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
942 return E_NOTIMPL;
943
944 wxASSERT(m_activeX);
945
946 // find event for dispid
947 wxActiveX::MemberIdMap::iterator mit = m_activeX->m_eventMemberIds.find((MEMBERID) dispIdMember);
948 if (mit == m_activeX->m_eventMemberIds.end())
949 return S_OK;
950
951 // sanity check
952 int midx = mit->second;
953 if (midx < 0 || midx >= m_activeX->GetEventCount())
954 return S_OK;
955
956 wxActiveX::FuncX &func = m_activeX->m_events[midx];
957
958
959 // try to find dispid event
960 ActiveXDISPIDEventMap::iterator dit = sg_dispIdEventMap.find(dispIdMember);
961 if (dit != sg_dispIdEventMap.end())
962 {
963 // Dispatch Event
964 DispatchEvent(func, *(dit->second), pDispParams);
965 return S_OK;
966 };
967
968 // try named event
969 ActiveXNamedEventMap::iterator nit = sg_NamedEventMap.find(func.name);
970 if (nit == sg_NamedEventMap.end())
971 return S_OK;
972
973 // Dispatch Event
974 DispatchEvent(func, *(nit->second), pDispParams);
975 return S_OK;
976 }
977 };
978
979 bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc)
980 {
981 if (self->m_haveCustomId && IsEqualIID(iid, self->m_customId))
982 {
983 WXOLE_TRACE("Found Custom Dispatch Interface");
984 *_interface = (IUnknown *) (IDispatch *) self;
985 desc = "Custom Dispatch Interface";
986 return true;
987 };
988
989 return false;
990 };
991
992 DEFINE_OLE_TABLE(wxActiveXEvents)
993 OLE_IINTERFACE(IUnknown)
994 OLE_INTERFACE(IID_IDispatch, IDispatch)
995 OLE_INTERFACE_CUSTOM(wxActiveXEventsInterface)
996 END_OLE_TABLE;
997
998 wxString wxActiveXEvent::EventName()
999 {
1000 return m_params.GetName();
1001 };
1002
1003 int wxActiveXEvent::ParamCount() const
1004 {
1005 return m_params.GetCount();
1006 };
1007
1008 wxString wxActiveXEvent::ParamType(int idx)
1009 {
1010 wxASSERT(idx >= 0 && idx < m_params.GetCount());
1011
1012 return m_params[idx].GetType();
1013 };
1014
1015 wxString wxActiveXEvent::ParamName(int idx)
1016 {
1017 wxASSERT(idx >= 0 && idx < m_params.GetCount());
1018
1019 return m_params[idx].GetName();
1020 };
1021
1022 static wxVariant nullVar;
1023
1024 wxVariant& wxActiveXEvent::operator[] (int idx)
1025 {
1026 wxASSERT(idx >= 0 && idx < ParamCount());
1027
1028 return m_params[idx];
1029 };
1030
1031 wxVariant& wxActiveXEvent::operator[] (wxString name)
1032 {
1033 for (int i = 0; i < m_params.GetCount(); i++)
1034 {
1035 if (name.CmpNoCase(m_params[i].GetName()) == 0)
1036 return m_params[i];
1037 };
1038
1039 wxString err = _T("wxActiveXEvent::operator[] invalid name <") + name + _T(">");
1040 err += _T("\r\nValid Names = :\r\n");
1041 for (i = 0; i < m_params.GetCount(); i++)
1042 {
1043 err += m_params[i].GetName();
1044 err += _T("\r\n");
1045 };
1046
1047 wxASSERT_MSG(false, err);
1048
1049 return nullVar;
1050 };
1051
1052 void wxActiveX::GetTypeInfo()
1053 {
1054 /*
1055 We are currently only interested in the IDispatch interface
1056 to the control. For dual interfaces (TypeKind = TKIND_INTERFACE)
1057 we should drill down through the inheritance
1058 (using TYPEATTR->cImplTypes) and GetRefTypeOfImplType(n)
1059 and retrieve all the func names etc that way, then generate a C++
1060 header file for it.
1061
1062 But we don't do this and probably never will, so if we have a DUAL
1063 interface then we query for the IDispatch
1064 via GetRefTypeOfImplType(-1).
1065 */
1066
1067 HRESULT hret = 0;
1068
1069 // get type info via class info
1070 wxAutoOleInterface<IProvideClassInfo> classInfo(IID_IProvideClassInfo, m_ActiveX);
1071 if (! classInfo.Ok())
1072 return;
1073
1074 // type info
1075 wxAutoOleInterface<ITypeInfo> typeInfo;
1076 hret = classInfo->GetClassInfo(typeInfo.GetRef());
1077 if (! typeInfo.Ok())
1078 return;
1079
1080 // TYPEATTR
1081 TYPEATTR *ta = NULL;
1082 hret = typeInfo->GetTypeAttr(&ta);
1083 if (! ta)
1084 return;
1085
1086 // this should be a TKIND_COCLASS
1087 wxASSERT(ta->typekind == TKIND_COCLASS);
1088
1089 // iterate contained interfaces
1090 for (int i = 0; i < ta->cImplTypes; i++)
1091 {
1092 HREFTYPE rt = 0;
1093
1094 // get dispatch type info handle
1095 hret = typeInfo->GetRefTypeOfImplType(i, &rt);
1096 if (! SUCCEEDED(hret))
1097 continue;
1098
1099 // get dispatch type info interface
1100 wxAutoOleInterface<ITypeInfo> ti;
1101 hret = typeInfo->GetRefTypeInfo(rt, ti.GetRef());
1102 if (! ti.Ok())
1103 continue;
1104
1105 // check if default event sink
1106 bool defInterface = false;
1107 bool defEventSink = false;
1108 int impTypeFlags = 0;
1109 typeInfo->GetImplTypeFlags(i, &impTypeFlags);
1110
1111 if (impTypeFlags & IMPLTYPEFLAG_FDEFAULT)
1112 {
1113 if (impTypeFlags & IMPLTYPEFLAG_FSOURCE)
1114 {
1115 WXOLE_TRACEOUT("Default Event Sink");
1116 defEventSink = true;
1117 if (impTypeFlags & IMPLTYPEFLAG_FDEFAULTVTABLE)
1118 {
1119 WXOLE_TRACEOUT("*ERROR* - Default Event Sink is via vTable");
1120 defEventSink = false;
1121 };
1122 }
1123 else
1124 {
1125 WXOLE_TRACEOUT("Default Interface");
1126 defInterface = true;
1127 }
1128 };
1129
1130
1131 // process
1132 GetTypeInfo(ti, defInterface, defEventSink);
1133 };
1134
1135
1136 // free
1137 typeInfo->ReleaseTypeAttr(ta);
1138 };
1139
1140 void ElemDescToParam(const ELEMDESC& ed, wxActiveX::ParamX& param)
1141 {
1142 param.flags = ed.idldesc.wIDLFlags;
1143 param.vt = ed.tdesc.vt;
1144 param.isPtr = (param.vt == VT_PTR);
1145 param.isSafeArray = (param.vt == VT_SAFEARRAY);
1146 if (param.isPtr || param.isSafeArray)
1147 param.vt = ed.tdesc.lptdesc->vt;
1148 };
1149
1150 void wxActiveX::GetTypeInfo(ITypeInfo *ti, bool defInterface, bool defEventSink)
1151 {
1152 // wxAutoOleInterface<> assumes a ref has already been added
1153 ti->AddRef();
1154 wxAutoOleInterface<ITypeInfo> typeInfo(ti);
1155
1156 // TYPEATTR
1157 TYPEATTR *ta = NULL;
1158 HRESULT hret = typeInfo->GetTypeAttr(&ta);
1159 if (! ta)
1160 return;
1161
1162 if (ta->typekind == TKIND_DISPATCH)
1163 {
1164 WXOLE_TRACEOUT("GUID = " << GetIIDName(ta->guid).c_str());
1165
1166 if (defEventSink)
1167 {
1168 wxActiveXEvents *disp = new wxActiveXEvents(this, ta->guid);
1169 ConnectAdvise(ta->guid, disp);
1170 };
1171
1172
1173 // Get Function Names
1174 for (int i = 0; i < ta->cFuncs; i++)
1175 {
1176 FUNCDESC FAR *fd = NULL;
1177
1178 hret = typeInfo->GetFuncDesc(i, &fd);
1179 if (! fd)
1180 continue;
1181
1182 BSTR anames[1] = {NULL};
1183 unsigned int n = 0;
1184
1185 hret = typeInfo->GetNames(fd->memid, anames, 1, &n);
1186
1187 if (anames[0])
1188 {
1189 wxString name = anames[0];
1190
1191 WXOLE_TRACEOUT("Name " << i << " = " << name.c_str());
1192 SysFreeString(anames[0]);
1193
1194 if (defInterface || defEventSink)
1195 {
1196 FuncX func;
1197 func.name = name;
1198 func.memid = fd->memid;
1199 func.hasOut = false;
1200
1201 // get Param Names
1202 unsigned int maxPNames = fd->cParams + 1;
1203 unsigned int nPNames = 0;
1204 BSTR *pnames = new BSTR[maxPNames];
1205
1206 hret = typeInfo->GetNames(fd->memid, pnames, maxPNames, &nPNames);
1207
1208 int pbase = 0;
1209 if (fd->cParams < int(nPNames))
1210 {
1211 pbase++;
1212 SysFreeString(pnames[0]);
1213 };
1214
1215 // params
1216 ElemDescToParam(fd->elemdescFunc, func.retType);
1217 for (int p = 0; p < fd->cParams; p++)
1218 {
1219 ParamX param;
1220
1221 ElemDescToParam(fd->lprgelemdescParam[p], param);
1222
1223 param.name = pnames[pbase + p];
1224 SysFreeString(pnames[pbase + p]);
1225
1226 param.isOptional = (p > fd->cParams - fd->cParamsOpt);
1227
1228 func.hasOut |= (param.IsOut() || param.isPtr);
1229 func.params.push_back(param);
1230 };
1231 delete [] pnames;
1232
1233 if (defEventSink)
1234 {
1235 m_events.push_back(func);
1236 m_eventMemberIds[fd->memid] = m_events.size() - 1;
1237 }
1238 else
1239 {
1240 if (fd->invkind == INVOKE_FUNC)
1241 {
1242 m_methods.push_back(func);
1243 m_methodNames[func.name] = m_methods.size() - 1;
1244 }
1245 else
1246 {
1247 NameMap::iterator it = m_propNames.find(func.name);
1248 int idx = -1;
1249 if (it == m_propNames.end())
1250 {
1251 m_props.push_back(PropX());
1252 idx = m_props.size() - 1;
1253 m_propNames[func.name] = idx;
1254 m_props[idx].name = func.name;
1255 m_props[idx].memid = func.memid;
1256
1257 }
1258 else
1259 idx = it->second;
1260
1261 if (fd->invkind == INVOKE_PROPERTYGET)
1262 m_props[idx].type = func.retType;
1263 else if (func.params.size() > 0)
1264 {
1265 m_props[idx].arg = func.params[0];
1266 m_props[idx].putByRef = (fd->invkind == INVOKE_PROPERTYPUTREF);
1267 };
1268 };
1269 };
1270 };
1271 };
1272
1273 typeInfo->ReleaseFuncDesc(fd);
1274 };
1275 }
1276
1277 typeInfo->ReleaseTypeAttr(ta);
1278 };
1279
1280 ///////////////////////////////////////////////
1281 // Type Info exposure
1282 const wxActiveX::FuncX& wxActiveX::GetEventDesc(int idx) const
1283 {
1284 wxASSERT(idx >= 0 && idx < GetEventCount());
1285
1286 return m_events[idx];
1287 };
1288
1289 const wxActiveX::PropX& wxActiveX::GetPropDesc(int idx) const
1290 {
1291 if (idx < 0 || idx >= GetPropCount())
1292 throw exception("Property index out of bounds");
1293
1294 return m_props[idx];
1295 };
1296
1297 const wxActiveX::PropX& wxActiveX::GetPropDesc(const wxString& name) const
1298 {
1299 NameMap::const_iterator it = m_propNames.find(name);
1300 if (it == m_propNames.end())
1301 {
1302 wxString s;
1303 s << _T("property <") << name << _T("> not found");
1304 throw exception(s.mb_str());
1305 };
1306
1307 return GetPropDesc(it->second);
1308 };
1309
1310 const wxActiveX::FuncX& wxActiveX::GetMethodDesc(int idx) const
1311 {
1312 if (idx < 0 || idx >= GetMethodCount())
1313 throw exception("Method index out of bounds");
1314
1315
1316 return m_methods[idx];
1317 };
1318
1319
1320 const wxActiveX::FuncX& wxActiveX::GetMethodDesc(const wxString& name) const
1321 {
1322 NameMap::const_iterator it = m_methodNames.find(name);
1323 if (it == m_methodNames.end())
1324 {
1325 wxString s;
1326 s << _T("method <") << name << _T("> not found");
1327 throw exception(s.mb_str());
1328 };
1329
1330 return GetMethodDesc(it->second);
1331 };
1332
1333
1334 void wxActiveX::SetProp(MEMBERID name, VARIANTARG& value)
1335 {
1336 DISPID pids[1] = {DISPID_PROPERTYPUT};
1337 DISPPARAMS params = {&value, pids, 1, 1};
1338
1339 EXCEPINFO x;
1340 memset(&x, 0, sizeof(x));
1341 unsigned int argErr = 0;
1342
1343 HRESULT hr = m_Dispatch->Invoke(
1344 name,
1345 IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
1346 &params, NULL, &x, &argErr);
1347
1348 WXOLE_WARN(hr, "Invoke Prop(...)");
1349 };
1350
1351 void wxActiveX::SetProp(const wxString &name, const wxVariant &value)
1352 {
1353 const PropX& prop = GetPropDesc(name);
1354 if (! prop.CanSet())
1355 {
1356 wxString s;
1357 s << _T("property <") << name << _T("> is readonly");
1358 throw exception(s.mb_str());
1359 };
1360
1361 VARIANT v = {prop.arg.vt};
1362 VariantToMSWVariant(value, v);
1363 SetProp(prop.memid, v);
1364 VariantClear(&v); // this releases any BSTR's etc
1365 };
1366
1367 VARIANT wxActiveX::GetPropAsVariant(MEMBERID name)
1368 {
1369 VARIANT v;
1370 VariantInit(&v);
1371
1372 DISPPARAMS params = {NULL, NULL, 0, 0};
1373
1374 EXCEPINFO x;
1375 memset(&x, 0, sizeof(x));
1376 unsigned int argErr = 0;
1377
1378 HRESULT hr = m_Dispatch->Invoke(
1379 name,
1380 IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
1381 &params, &v, &x, &argErr);
1382
1383 WXOLE_WARN(hr, "Invoke Prop(...)");
1384
1385 return v;
1386 };
1387
1388 VARIANT wxActiveX::GetPropAsVariant(const wxString& name)
1389 {
1390 const PropX& prop = GetPropDesc(name);
1391 if (! prop.CanGet())
1392 {
1393 wxString s;
1394 s << _T("property <") << name << _T("> is writeonly");
1395 throw exception(s.mb_str());
1396 };
1397
1398 return GetPropAsVariant(prop.memid);
1399 };
1400
1401 wxVariant wxActiveX::GetPropAsWxVariant(const wxString& name)
1402 {
1403 VARIANT v = GetPropAsVariant(name);
1404 HRESULT hr = VariantChangeType(&v, &v, 0, VT_BSTR);
1405 if (! SUCCEEDED(hr))
1406 throw exception("Unable to convert variant");
1407
1408 wxVariant wv;
1409 MSWVariantToVariant(v, wv);
1410
1411 VariantClear(&v);
1412
1413 return wv;
1414 };
1415
1416 wxString wxActiveX::GetPropAsString(const wxString& name)
1417 {
1418 VARIANT v = GetPropAsVariant(name);
1419 HRESULT hr = VariantChangeType(&v, &v, 0, VT_BSTR);
1420 if (! SUCCEEDED(hr))
1421 throw exception("Unable to convert variant");
1422
1423 wxString s = v.bstrVal;
1424 VariantClear(&v);
1425
1426 return s;
1427 };
1428
1429 char wxActiveX::GetPropAsChar(const wxString& name)
1430 {
1431 VARIANT v = GetPropAsVariant(name);
1432 HRESULT hr = VariantChangeType(&v, &v, 0, VT_I1);
1433 if (! SUCCEEDED(hr))
1434 throw exception("Unable to convert variant");
1435
1436 return v.cVal;
1437 };
1438
1439 long wxActiveX::GetPropAsLong(const wxString& name)
1440 {
1441 VARIANT v = GetPropAsVariant(name);
1442 HRESULT hr = VariantChangeType(&v, &v, 0, VT_I4);
1443 if (! SUCCEEDED(hr))
1444 throw exception("Unable to convert variant");
1445
1446 return v.iVal;
1447 };
1448
1449 bool wxActiveX::GetPropAsBool(const wxString& name)
1450 {
1451 VARIANT v = GetPropAsVariant(name);
1452 HRESULT hr = VariantChangeType(&v, &v, 0, VT_BOOL);
1453 if (! SUCCEEDED(hr))
1454 throw exception("Unable to convert variant");
1455
1456 return v.boolVal != 0;
1457 };
1458
1459 double wxActiveX::GetPropAsDouble(const wxString& name)
1460 {
1461 VARIANT v = GetPropAsVariant(name);
1462 HRESULT hr = VariantChangeType(&v, &v, 0, VT_R8);
1463 if (! SUCCEEDED(hr))
1464 throw exception("Unable to convert variant");
1465
1466 return v.dblVal;
1467 };
1468
1469 wxDateTime wxActiveX::GetPropAsDateTime(const wxString& name)
1470 {
1471 wxDateTime dt;
1472 VARIANT v = GetPropAsVariant(name);
1473
1474 if (! VariantToWxDateTime(v, dt))
1475 throw exception("Unable to convert variant to wxDateTime");
1476
1477 return dt;
1478 };
1479
1480 void *wxActiveX::GetPropAsPointer(const wxString& name)
1481 {
1482 VARIANT v = GetPropAsVariant(name);
1483 HRESULT hr = VariantChangeType(&v, &v, 0, VT_BYREF);
1484 if (! SUCCEEDED(hr))
1485 throw exception("Unable to convert variant");
1486
1487 return v.byref;
1488 };
1489
1490
1491
1492 // call methods
1493 VARIANT wxActiveX::CallMethod(MEMBERID name, VARIANTARG args[], int argc)
1494 {
1495 DISPPARAMS pargs = {args, NULL, argc, 0};
1496 VARIANT retVal;
1497 VariantInit(&retVal);
1498
1499 EXCEPINFO x;
1500 memset(&x, 0, sizeof(x));
1501 unsigned int argErr = 0;
1502
1503 HRESULT hr = m_Dispatch->Invoke(
1504 name,
1505 IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD,
1506 &pargs, &retVal, &x, &argErr);
1507
1508 WXOLE_WARN(hr, "Invoke Method(...)");
1509 return retVal;
1510 };
1511
1512 VARIANT wxActiveX::CallMethod(const wxString& name, VARIANTARG args[], int argc)
1513 {
1514 const FuncX& func = GetMethodDesc(name);
1515 if (argc < 0)
1516 argc = func.params.size();
1517
1518 return CallMethod(func.memid, args, argc);
1519 };
1520
1521
1522 wxVariant wxActiveX::CallMethod(const wxString& name, wxVariant args[], int nargs)
1523 {
1524 const FuncX& func = GetMethodDesc(name);
1525
1526 if (args == NULL)
1527 nargs = 0;
1528
1529 VARIANTARG *vargs = NULL;
1530 if (nargs < 0)
1531 nargs = func.params.size();
1532
1533 if (nargs > 0)
1534 vargs = new VARIANTARG[nargs];
1535
1536 if (vargs)
1537 {
1538 // init type of vargs
1539 for (int i = 0; i < nargs; i++)
1540 vargs[nargs - i - 1].vt = func.params[i].vt;
1541
1542 // put data
1543 for (i = 0; i < nargs; i++)
1544 VariantToMSWVariant(args[i], vargs[nargs - i - 1]);
1545 };
1546
1547 VARIANT rv = CallMethod(func.memid, vargs, nargs);
1548
1549 // process any by ref params
1550 if (func.hasOut)
1551 {
1552 for (int i = 0; i < nargs; i++)
1553 {
1554 VARIANTARG& va = vargs[nargs - i - 1];
1555 const wxActiveX::ParamX &px = func.params[i];
1556
1557 if (px.IsOut())
1558 {
1559 wxVariant& vx = args[i];
1560
1561 MSWVariantToVariant(va, vx);
1562 };
1563 };
1564 }
1565
1566 if (vargs)
1567 {
1568 for (int i = 0; i < nargs; i++)
1569 VariantClear(&vargs[i]);
1570 delete [] vargs;
1571 };
1572
1573 wxVariant ret;
1574
1575 MSWVariantToVariant(rv, ret);
1576 VariantClear(&rv);
1577
1578 return ret;
1579 };
1580
1581
1582 ///////////////////////////////////////////////
1583
1584 HRESULT wxActiveX::ConnectAdvise(REFIID riid, IUnknown *events)
1585 {
1586 wxOleConnectionPoint cp;
1587 DWORD adviseCookie = 0;
1588
1589 wxAutoOleInterface<IConnectionPointContainer> cpContainer(IID_IConnectionPointContainer, m_ActiveX);
1590 if (! cpContainer.Ok())
1591 return E_FAIL;
1592
1593 HRESULT hret = cpContainer->FindConnectionPoint(riid, cp.GetRef());
1594 if (! SUCCEEDED(hret))
1595 return hret;
1596
1597 hret = cp->Advise(events, &adviseCookie);
1598
1599 if (SUCCEEDED(hret))
1600 m_connections.push_back(wxOleConnection(cp, adviseCookie));
1601 else
1602 {
1603 WXOLE_WARN(hret, "ConnectAdvise");
1604 };
1605
1606 return hret;
1607 };
1608
1609 HRESULT wxActiveX::AmbientPropertyChanged(DISPID dispid)
1610 {
1611 wxAutoOleInterface<IOleControl> oleControl(IID_IOleControl, m_oleObject);
1612
1613 if (oleControl.Ok())
1614 return oleControl->OnAmbientPropertyChange(dispid);
1615 else
1616 return S_FALSE;
1617 };
1618
1619 #define HIMETRIC_PER_INCH 2540
1620 #define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
1621
1622 static void PixelsToHimetric(SIZEL &sz)
1623 {
1624 static int logX = 0;
1625 static int logY = 0;
1626
1627 if (logY == 0)
1628 {
1629 // initaliase
1630 HDC dc = GetDC(NULL);
1631 logX = GetDeviceCaps(dc, LOGPIXELSX);
1632 logY = GetDeviceCaps(dc, LOGPIXELSY);
1633 ReleaseDC(NULL, dc);
1634 };
1635
1636 #define HIMETRIC_INCH 2540
1637 #define CONVERT(x, logpixels) MulDiv(HIMETRIC_INCH, (x), (logpixels))
1638
1639 sz.cx = CONVERT(sz.cx, logX);
1640 sz.cy = CONVERT(sz.cy, logY);
1641
1642 #undef CONVERT
1643 #undef HIMETRIC_INCH
1644 }
1645
1646
1647 void wxActiveX::OnSize(wxSizeEvent& event)
1648 {
1649 int w, h;
1650 GetClientSize(&w, &h);
1651
1652 RECT posRect;
1653 posRect.left = 0;
1654 posRect.top = 0;
1655 posRect.right = w;
1656 posRect.bottom = h;
1657
1658 if (w <= 0 && h <= 0)
1659 return;
1660
1661 // extents are in HIMETRIC units
1662 if (m_oleObject.Ok())
1663 {
1664 SIZEL sz = {w, h};
1665 PixelsToHimetric(sz);
1666
1667 SIZEL sz2;
1668
1669 m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2);
1670 if (sz2.cx != sz.cx || sz.cy != sz2.cy)
1671 m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
1672 };
1673
1674 if (m_oleInPlaceObject.Ok())
1675 m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
1676 }
1677
1678 void wxActiveX::OnPaint(wxPaintEvent& event)
1679 {
1680 wxLogTrace(wxT(""),wxT("repainting activex win"));
1681 wxPaintDC dc(this);
1682 dc.BeginDrawing();
1683 int w, h;
1684 GetSize(&w, &h);
1685 RECT posRect;
1686 posRect.left = 0;
1687 posRect.top = 0;
1688 posRect.right = w;
1689 posRect.bottom = h;
1690
1691 // Draw only when control is windowless or deactivated
1692 if (m_viewObject)
1693 {
1694 ::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
1695 {
1696 RECTL *prcBounds = (RECTL *) &posRect;
1697 m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
1698 (HDC)dc.GetHDC(), prcBounds, NULL, NULL, 0);
1699 }
1700 }
1701 else
1702 {
1703 dc.SetBrush(*wxRED_BRUSH);
1704 dc.DrawRectangle(0, 0, w, h);
1705 dc.SetBrush(wxNullBrush);
1706 }
1707 dc.EndDrawing();
1708 }
1709
1710
1711 void wxActiveX::OnMouse(wxMouseEvent& event)
1712 {
1713 if (m_oleObjectHWND == NULL)
1714 {
1715 wxLogTrace(wxT(""),wxT("no oleInPlaceObject"));
1716 event.Skip();
1717 return;
1718 }
1719
1720 wxLogTrace(wxT(""),wxT("mouse event"));
1721 UINT msg = 0;
1722 WPARAM wParam = 0;
1723 LPARAM lParam = 0;
1724 LRESULT lResult = 0;
1725
1726 if (event.m_metaDown)
1727 wParam |= MK_CONTROL;
1728 if (event.m_shiftDown)
1729 wParam |= MK_SHIFT;
1730 if (event.m_leftDown)
1731 wParam |= MK_LBUTTON;
1732 if (event.m_middleDown)
1733 wParam |= MK_MBUTTON;
1734 if (event.m_rightDown)
1735 wParam |= MK_RBUTTON;
1736 lParam = event.m_x << 16;
1737 lParam |= event.m_y;
1738
1739 if (event.LeftDown())
1740 msg = WM_LBUTTONDOWN;
1741 else if (event.LeftDClick())
1742 msg = WM_LBUTTONDBLCLK;
1743 else if (event.LeftUp())
1744 msg = WM_LBUTTONUP;
1745 else if (event.MiddleDown())
1746 msg = WM_MBUTTONDOWN;
1747 else if (event.MiddleDClick())
1748 msg = WM_MBUTTONDBLCLK;
1749 else if (event.MiddleUp())
1750 msg = WM_MBUTTONUP;
1751 else if (event.RightDown())
1752 msg = WM_RBUTTONDOWN;
1753 else if (event.RightDClick())
1754 msg = WM_RBUTTONDBLCLK;
1755 else if (event.RightUp())
1756 msg = WM_RBUTTONUP;
1757 else if (event.Moving() || event.Dragging())
1758 msg = WM_MOUSEMOVE;
1759
1760 wxString log;
1761 if (msg == 0)
1762 {
1763 wxLogTrace(wxT(""),wxT("no message"));
1764 event.Skip(); return;
1765 };
1766
1767 if (!::SendMessage(m_oleObjectHWND, msg, wParam, lParam))
1768 {
1769 wxLogTrace(wxT(""),wxT("msg not delivered"));
1770 event.Skip();
1771 return;
1772 };
1773
1774 wxLogTrace(wxT(""),wxT("msg sent"));
1775 }
1776
1777 long wxActiveX::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
1778 {
1779 if (m_oleObjectHWND == NULL)
1780 return wxWindow::MSWWindowProc(nMsg, wParam, lParam);
1781
1782 switch(nMsg)
1783 {
1784 case WM_CHAR:
1785 case WM_DEADCHAR:
1786 case WM_KEYDOWN:
1787 case WM_KEYUP:
1788 case WM_SYSCHAR:
1789 case WM_SYSDEADCHAR:
1790 case WM_SYSKEYDOWN:
1791 case WM_SYSKEYUP:
1792 PostMessage(m_oleObjectHWND, nMsg, wParam, lParam);
1793
1794 default:
1795 return wxWindow::MSWWindowProc(nMsg, wParam, lParam);
1796 };
1797 };
1798
1799 void wxActiveX::OnSetFocus(wxFocusEvent& event)
1800 {
1801 if (m_oleInPlaceActiveObject.Ok())
1802 m_oleInPlaceActiveObject->OnFrameWindowActivate(TRUE);
1803 }
1804
1805 void wxActiveX::OnKillFocus(wxFocusEvent& event)
1806 {
1807 if (m_oleInPlaceActiveObject.Ok())
1808 m_oleInPlaceActiveObject->OnFrameWindowActivate(FALSE);
1809 }
1810
1811
1812 FrameSite::FrameSite(wxActiveX * win)
1813 {
1814 m_window = win;
1815 m_bSupportsWindowlessActivation = true;
1816 m_bInPlaceLocked = false;
1817 m_bUIActive = false;
1818 m_bInPlaceActive = false;
1819 m_bWindowless = false;
1820
1821 m_nAmbientLocale = 0;
1822 m_clrAmbientForeColor = ::GetSysColor(COLOR_WINDOWTEXT);
1823 m_clrAmbientBackColor = ::GetSysColor(COLOR_WINDOW);
1824 m_bAmbientShowHatching = true;
1825 m_bAmbientShowGrabHandles = true;
1826 m_bAmbientAppearance = true;
1827
1828 m_hDCBuffer = NULL;
1829 m_hWndParent = (HWND)m_window->GetHWND();
1830 }
1831
1832 FrameSite::~FrameSite()
1833 {
1834 }
1835
1836
1837 //IDispatch
1838
1839 HRESULT FrameSite::GetIDsOfNames(REFIID riid, OLECHAR ** rgszNames, unsigned int cNames,
1840 LCID lcid, DISPID * rgDispId)
1841 {
1842 WXOLE_TRACE("IDispatch::GetIDsOfNames");
1843 return E_NOTIMPL;
1844 }
1845
1846 HRESULT FrameSite::GetTypeInfo(unsigned int iTInfo, LCID lcid, ITypeInfo ** ppTInfo)
1847 {
1848 WXOLE_TRACE("IDispatch::GetTypeInfo");
1849 return E_NOTIMPL;
1850 }
1851
1852 HRESULT FrameSite::GetTypeInfoCount(unsigned int * pcTInfo)
1853 {
1854 WXOLE_TRACE("IDispatch::GetTypeInfoCount");
1855 return E_NOTIMPL;
1856 }
1857
1858 HRESULT FrameSite::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
1859 WORD wFlags, DISPPARAMS * pDispParams,
1860 VARIANT * pVarResult, EXCEPINFO * pExcepInfo,
1861 unsigned int * puArgErr)
1862 {
1863 WXOLE_TRACE("IDispatch::Invoke");
1864
1865 if (!(wFlags & DISPATCH_PROPERTYGET))
1866 return S_OK;
1867
1868 HRESULT hr;
1869
1870 if (pVarResult == NULL)
1871 return E_INVALIDARG;
1872
1873 //The most common case is boolean, use as an initial type
1874 V_VT(pVarResult) = VT_BOOL;
1875
1876 switch (dispIdMember)
1877 {
1878 case DISPID_AMBIENT_MESSAGEREFLECT:
1879 WXOLE_TRACE("Invoke::DISPID_AMBIENT_MESSAGEREFLECT");
1880 V_BOOL(pVarResult)= FALSE;
1881 return S_OK;
1882
1883 case DISPID_AMBIENT_DISPLAYASDEFAULT:
1884 WXOLE_TRACE("Invoke::DISPID_AMBIENT_DISPLAYASDEFAULT");
1885 V_BOOL(pVarResult)= TRUE;
1886 return S_OK;
1887
1888 case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
1889 WXOLE_TRACE("Invoke::DISPID_AMBIENT_OFFLINEIFNOTCONNECTED");
1890 V_BOOL(pVarResult) = TRUE;
1891 return S_OK;
1892
1893
1894 case DISPID_AMBIENT_SILENT:
1895 WXOLE_TRACE("Invoke::DISPID_AMBIENT_SILENT");
1896 V_BOOL(pVarResult)= TRUE;
1897 return S_OK;
1898
1899 case DISPID_AMBIENT_APPEARANCE:
1900 pVarResult->vt = VT_BOOL;
1901 pVarResult->boolVal = m_bAmbientAppearance;
1902 break;
1903
1904 case DISPID_AMBIENT_FORECOLOR:
1905 pVarResult->vt = VT_I4;
1906 pVarResult->lVal = (long) m_clrAmbientForeColor;
1907 break;
1908
1909 case DISPID_AMBIENT_BACKCOLOR:
1910 pVarResult->vt = VT_I4;
1911 pVarResult->lVal = (long) m_clrAmbientBackColor;
1912 break;
1913
1914 case DISPID_AMBIENT_LOCALEID:
1915 pVarResult->vt = VT_I4;
1916 pVarResult->lVal = (long) m_nAmbientLocale;
1917 break;
1918
1919 case DISPID_AMBIENT_USERMODE:
1920 pVarResult->vt = VT_BOOL;
1921 pVarResult->boolVal = m_window->m_bAmbientUserMode;
1922 break;
1923
1924 case DISPID_AMBIENT_SHOWGRABHANDLES:
1925 pVarResult->vt = VT_BOOL;
1926 pVarResult->boolVal = m_bAmbientShowGrabHandles;
1927 break;
1928
1929 case DISPID_AMBIENT_SHOWHATCHING:
1930 pVarResult->vt = VT_BOOL;
1931 pVarResult->boolVal = m_bAmbientShowHatching;
1932 break;
1933
1934 default:
1935 return DISP_E_MEMBERNOTFOUND;
1936 }
1937
1938 return S_OK;
1939 }
1940
1941 //IOleWindow
1942
1943 HRESULT FrameSite::GetWindow(HWND * phwnd)
1944 {
1945 WXOLE_TRACE("IOleWindow::GetWindow");
1946 if (phwnd == NULL)
1947 return E_INVALIDARG;
1948 (*phwnd) = m_hWndParent;
1949 return S_OK;
1950 }
1951
1952 HRESULT FrameSite::ContextSensitiveHelp(BOOL fEnterMode)
1953 {
1954 WXOLE_TRACE("IOleWindow::ContextSensitiveHelp");
1955 return S_OK;
1956 }
1957
1958 //IOleInPlaceUIWindow
1959
1960 HRESULT FrameSite::GetBorder(LPRECT lprectBorder)
1961 {
1962 WXOLE_TRACE("IOleInPlaceUIWindow::GetBorder");
1963 if (lprectBorder == NULL)
1964 return E_INVALIDARG;
1965 return INPLACE_E_NOTOOLSPACE;
1966 }
1967
1968 HRESULT FrameSite::RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
1969 {
1970 WXOLE_TRACE("IOleInPlaceUIWindow::RequestBorderSpace");
1971 if (pborderwidths == NULL)
1972 return E_INVALIDARG;
1973 return INPLACE_E_NOTOOLSPACE;
1974 }
1975
1976 HRESULT FrameSite::SetBorderSpace(LPCBORDERWIDTHS pborderwidths)
1977 {
1978 WXOLE_TRACE("IOleInPlaceUIWindow::SetBorderSpace");
1979 return S_OK;
1980 }
1981
1982 HRESULT FrameSite::SetActiveObject(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
1983 {
1984 WXOLE_TRACE("IOleInPlaceUIWindow::SetActiveObject");
1985
1986 if (pActiveObject)
1987 pActiveObject->AddRef();
1988
1989 m_window->m_oleInPlaceActiveObject = pActiveObject;
1990 return S_OK;
1991 }
1992
1993 //IOleInPlaceFrame
1994
1995 HRESULT FrameSite::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
1996 {
1997 WXOLE_TRACE("IOleInPlaceFrame::InsertMenus");
1998 return S_OK;
1999 }
2000
2001 HRESULT FrameSite::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
2002 {
2003 WXOLE_TRACE("IOleInPlaceFrame::SetMenu");
2004 return S_OK;
2005 }
2006
2007 HRESULT FrameSite::RemoveMenus(HMENU hmenuShared)
2008 {
2009 WXOLE_TRACE("IOleInPlaceFrame::RemoveMenus");
2010 return S_OK;
2011 }
2012
2013 HRESULT FrameSite::SetStatusText(LPCOLESTR pszStatusText)
2014 {
2015 WXOLE_TRACE("IOleInPlaceFrame::SetStatusText");
2016 //((wxFrame*)wxGetApp().GetTopWindow())->GetStatusBar()->SetStatusText(pszStatusText);
2017 return S_OK;
2018 }
2019
2020 HRESULT FrameSite::EnableModeless(BOOL fEnable)
2021 {
2022 WXOLE_TRACE("IOleInPlaceFrame::EnableModeless");
2023 return S_OK;
2024 }
2025
2026 HRESULT FrameSite::TranslateAccelerator(LPMSG lpmsg, WORD wID)
2027 {
2028 WXOLE_TRACE("IOleInPlaceFrame::TranslateAccelerator");
2029 // TODO: send an event with this id
2030 if (m_window->m_oleInPlaceActiveObject.Ok())
2031 m_window->m_oleInPlaceActiveObject->TranslateAccelerator(lpmsg);
2032
2033 return S_FALSE;
2034 }
2035
2036 //IOleInPlaceSite
2037
2038 HRESULT FrameSite::CanInPlaceActivate()
2039 {
2040 WXOLE_TRACE("IOleInPlaceSite::CanInPlaceActivate");
2041 return S_OK;
2042 }
2043
2044 HRESULT FrameSite::OnInPlaceActivate()
2045 {
2046 WXOLE_TRACE("IOleInPlaceSite::OnInPlaceActivate");
2047 m_bInPlaceActive = true;
2048 return S_OK;
2049 }
2050
2051 HRESULT FrameSite::OnUIActivate()
2052 {
2053 WXOLE_TRACE("IOleInPlaceSite::OnUIActivate");
2054 m_bUIActive = true;
2055 return S_OK;
2056 }
2057
2058 HRESULT FrameSite::GetWindowContext(IOleInPlaceFrame **ppFrame,
2059 IOleInPlaceUIWindow **ppDoc,
2060 LPRECT lprcPosRect,
2061 LPRECT lprcClipRect,
2062 LPOLEINPLACEFRAMEINFO lpFrameInfo)
2063 {
2064 WXOLE_TRACE("IOleInPlaceSite::GetWindowContext");
2065 if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL ||
2066 lprcClipRect == NULL || lpFrameInfo == NULL)
2067 {
2068 if (ppFrame != NULL)
2069 (*ppFrame) = NULL;
2070 if (ppDoc != NULL)
2071 (*ppDoc) = NULL;
2072 return E_INVALIDARG;
2073 }
2074
2075 HRESULT hr = QueryInterface(IID_IOleInPlaceFrame, (void **) ppFrame);
2076 if (! SUCCEEDED(hr))
2077 {
2078 WXOLE_TRACE("IOleInPlaceSite::IOleInPlaceFrame Error !");
2079 return E_UNEXPECTED;
2080 };
2081
2082 hr = QueryInterface(IID_IOleInPlaceUIWindow, (void **) ppDoc);
2083 if (! SUCCEEDED(hr))
2084 {
2085 WXOLE_TRACE("IOleInPlaceSite::IOleInPlaceUIWindow Error !");
2086 (*ppFrame)->Release();
2087 *ppFrame = NULL;
2088 return E_UNEXPECTED;
2089 };
2090
2091 int w, h;
2092 m_window->GetClientSize(&w, &h);
2093 if (lprcPosRect)
2094 {
2095 lprcPosRect->left = lprcPosRect->top = 0;
2096 lprcPosRect->right = w;
2097 lprcPosRect->bottom = h;
2098 };
2099 if (lprcClipRect)
2100 {
2101 lprcClipRect->left = lprcClipRect->top = 0;
2102 lprcClipRect->right = w;
2103 lprcClipRect->bottom = h;
2104 };
2105
2106 memset(lpFrameInfo, 0, sizeof(OLEINPLACEFRAMEINFO));
2107 lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
2108 lpFrameInfo->hwndFrame = m_hWndParent;
2109
2110 return S_OK;
2111 }
2112
2113 HRESULT FrameSite::Scroll(SIZE scrollExtent)
2114 {
2115 WXOLE_TRACE("IOleInPlaceSite::Scroll");
2116 return S_OK;
2117 }
2118
2119 HRESULT FrameSite::OnUIDeactivate(BOOL fUndoable)
2120 {
2121 WXOLE_TRACE("IOleInPlaceSite::OnUIDeactivate");
2122 m_bUIActive = false;
2123 return S_OK;
2124 }
2125
2126 HRESULT FrameSite::OnInPlaceDeactivate()
2127 {
2128 WXOLE_TRACE("IOleInPlaceSite::OnInPlaceDeactivate");
2129 m_bInPlaceActive = false;
2130 return S_OK;
2131 }
2132
2133 HRESULT FrameSite::DiscardUndoState()
2134 {
2135 WXOLE_TRACE("IOleInPlaceSite::DiscardUndoState");
2136 return S_OK;
2137 }
2138
2139 HRESULT FrameSite::DeactivateAndUndo()
2140 {
2141 WXOLE_TRACE("IOleInPlaceSite::DeactivateAndUndo");
2142 return S_OK;
2143 }
2144
2145 HRESULT FrameSite::OnPosRectChange(LPCRECT lprcPosRect)
2146 {
2147 WXOLE_TRACE("IOleInPlaceSite::OnPosRectChange");
2148 if (m_window->m_oleInPlaceObject.Ok() && lprcPosRect)
2149 m_window->m_oleInPlaceObject->SetObjectRects(lprcPosRect, lprcPosRect);
2150
2151 return S_OK;
2152 }
2153
2154 //IOleInPlaceSiteEx
2155
2156 HRESULT FrameSite::OnInPlaceActivateEx(BOOL * pfNoRedraw, DWORD dwFlags)
2157 {
2158 WXOLE_TRACE("IOleInPlaceSiteEx::OnInPlaceActivateEx");
2159 OleLockRunning(m_window->m_ActiveX, TRUE, FALSE);
2160 if (pfNoRedraw)
2161 (*pfNoRedraw) = FALSE;
2162 return S_OK;
2163 }
2164
2165 HRESULT FrameSite::OnInPlaceDeactivateEx(BOOL fNoRedraw)
2166 {
2167 WXOLE_TRACE("IOleInPlaceSiteEx::OnInPlaceDeactivateEx");
2168 OleLockRunning(m_window->m_ActiveX, FALSE, FALSE);
2169 return S_OK;
2170 }
2171
2172 HRESULT FrameSite::RequestUIActivate()
2173 {
2174 WXOLE_TRACE("IOleInPlaceSiteEx::RequestUIActivate");
2175 return S_OK;
2176 }
2177
2178
2179 //IOleClientSite
2180
2181 HRESULT FrameSite::SaveObject()
2182 {
2183 WXOLE_TRACE("IOleClientSite::SaveObject");
2184 return S_OK;
2185 }
2186
2187 const char *OleGetMonikerToStr(DWORD dwAssign)
2188 {
2189 switch (dwAssign)
2190 {
2191 case OLEGETMONIKER_ONLYIFTHERE : return "OLEGETMONIKER_ONLYIFTHERE";
2192 case OLEGETMONIKER_FORCEASSIGN : return "OLEGETMONIKER_FORCEASSIGN";
2193 case OLEGETMONIKER_UNASSIGN : return "OLEGETMONIKER_UNASSIGN";
2194 case OLEGETMONIKER_TEMPFORUSER : return "OLEGETMONIKER_TEMPFORUSER";
2195 default : return "Bad Enum";
2196 };
2197 };
2198
2199 const char *OleGetWhicMonikerStr(DWORD dwWhichMoniker)
2200 {
2201 switch(dwWhichMoniker)
2202 {
2203 case OLEWHICHMK_CONTAINER : return "OLEWHICHMK_CONTAINER";
2204 case OLEWHICHMK_OBJREL : return "OLEWHICHMK_OBJREL";
2205 case OLEWHICHMK_OBJFULL : return "OLEWHICHMK_OBJFULL";
2206 default : return "Bad Enum";
2207 };
2208 };
2209
2210 HRESULT FrameSite::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker,
2211 IMoniker ** ppmk)
2212 {
2213 WXOLE_TRACEOUT("IOleClientSite::GetMoniker(" << OleGetMonikerToStr(dwAssign) << ", " << OleGetWhicMonikerStr(dwWhichMoniker) << ")");
2214
2215
2216 if (! ppmk)
2217 return E_FAIL;
2218
2219 /*
2220 HRESULT hr = CreateFileMoniker(L"e:\\dev\\wxie\\bug-zap.swf", ppmk);
2221 if (SUCCEEDED(hr))
2222 return S_OK;
2223 */
2224 *ppmk = NULL;
2225
2226 return E_FAIL ;
2227 }
2228
2229 HRESULT FrameSite::GetContainer(LPOLECONTAINER * ppContainer)
2230 {
2231 WXOLE_TRACE("IOleClientSite::GetContainer");
2232 if (ppContainer == NULL)
2233 return E_INVALIDARG;
2234
2235 HRESULT hr = QueryInterface(IID_IOleContainer, (void**)(ppContainer));
2236 wxASSERT(SUCCEEDED(hr));
2237
2238 return hr;
2239 }
2240
2241 HRESULT FrameSite::ShowObject()
2242 {
2243 WXOLE_TRACE("IOleClientSite::ShowObject");
2244 if (m_window->m_oleObjectHWND)
2245 ::ShowWindow(m_window->m_oleObjectHWND, SW_SHOW);
2246 return S_OK;
2247 }
2248
2249 HRESULT FrameSite::OnShowWindow(BOOL fShow)
2250 {
2251 WXOLE_TRACE("IOleClientSite::OnShowWindow");
2252 return S_OK;
2253 }
2254
2255 HRESULT FrameSite::RequestNewObjectLayout()
2256 {
2257 WXOLE_TRACE("IOleClientSite::RequestNewObjectLayout");
2258 return E_NOTIMPL;
2259 }
2260
2261 // IParseDisplayName
2262
2263 HRESULT FrameSite::ParseDisplayName(IBindCtx *pbc, LPOLESTR pszDisplayName,
2264 ULONG *pchEaten, IMoniker **ppmkOut)
2265 {
2266 WXOLE_TRACE("IParseDisplayName::ParseDisplayName");
2267 return E_NOTIMPL;
2268 }
2269
2270 //IOleContainer
2271
2272 HRESULT FrameSite::EnumObjects(DWORD grfFlags, IEnumUnknown **ppenum)
2273 {
2274 WXOLE_TRACE("IOleContainer::EnumObjects");
2275 return E_NOTIMPL;
2276 }
2277
2278 HRESULT FrameSite::LockContainer(BOOL fLock)
2279 {
2280 WXOLE_TRACE("IOleContainer::LockContainer");
2281 // TODO
2282 return S_OK;
2283 }
2284
2285 //IOleItemContainer
2286
2287 HRESULT FrameSite::GetObject(LPOLESTR pszItem, DWORD dwSpeedNeeded,
2288 IBindCtx * pbc, REFIID riid, void ** ppvObject)
2289 {
2290 WXOLE_TRACE("IOleItemContainer::GetObject");
2291 if (pszItem == NULL)
2292 return E_INVALIDARG;
2293 if (ppvObject == NULL)
2294 return E_INVALIDARG;
2295
2296 *ppvObject = NULL;
2297 return MK_E_NOOBJECT;
2298 }
2299
2300 HRESULT FrameSite::GetObjectStorage(LPOLESTR pszItem, IBindCtx * pbc,
2301 REFIID riid, void ** ppvStorage)
2302 {
2303 WXOLE_TRACE("IOleItemContainer::GetObjectStorage");
2304 if (pszItem == NULL)
2305 return E_INVALIDARG;
2306 if (ppvStorage == NULL)
2307 return E_INVALIDARG;
2308
2309 *ppvStorage = NULL;
2310 return MK_E_NOOBJECT;
2311 }
2312
2313 HRESULT FrameSite::IsRunning(LPOLESTR pszItem)
2314 {
2315 WXOLE_TRACE("IOleItemContainer::IsRunning");
2316 if (pszItem == NULL)
2317 return E_INVALIDARG;
2318
2319 return MK_E_NOOBJECT;
2320 }
2321
2322
2323
2324 //IOleControlSite
2325
2326 HRESULT FrameSite::OnControlInfoChanged()
2327 {
2328 WXOLE_TRACE("IOleControlSite::OnControlInfoChanged");
2329 return S_OK;
2330 }
2331
2332 HRESULT FrameSite::LockInPlaceActive(BOOL fLock)
2333 {
2334 WXOLE_TRACE("IOleControlSite::LockInPlaceActive");
2335 m_bInPlaceLocked = (fLock) ? true : false;
2336 return S_OK;
2337 }
2338
2339 HRESULT FrameSite::GetExtendedControl(IDispatch ** ppDisp)
2340 {
2341 WXOLE_TRACE("IOleControlSite::GetExtendedControl");
2342 return E_NOTIMPL;
2343 }
2344
2345 HRESULT FrameSite::TransformCoords(POINTL * pPtlHimetric, POINTF * pPtfContainer, DWORD dwFlags)
2346 {
2347 WXOLE_TRACE("IOleControlSite::TransformCoords");
2348 HRESULT hr = S_OK;
2349
2350 if (pPtlHimetric == NULL)
2351 return E_INVALIDARG;
2352
2353 if (pPtfContainer == NULL)
2354 return E_INVALIDARG;
2355
2356 return E_NOTIMPL;
2357
2358 }
2359
2360 HRESULT FrameSite::TranslateAccelerator(LPMSG pMsg, DWORD grfModifiers)
2361 {
2362 WXOLE_TRACE("IOleControlSite::TranslateAccelerator");
2363 // TODO: send an event with this id
2364 return E_NOTIMPL;
2365 }
2366
2367 HRESULT FrameSite::OnFocus(BOOL fGotFocus)
2368 {
2369 WXOLE_TRACE("IOleControlSite::OnFocus");
2370 return S_OK;
2371 }
2372
2373 HRESULT FrameSite::ShowPropertyFrame()
2374 {
2375 WXOLE_TRACE("IOleControlSite::ShowPropertyFrame");
2376 return E_NOTIMPL;
2377 }
2378
2379 //IOleCommandTarget
2380
2381 HRESULT FrameSite::QueryStatus(const GUID * pguidCmdGroup, ULONG cCmds,
2382 OLECMD * prgCmds, OLECMDTEXT * pCmdTet)
2383 {
2384 WXOLE_TRACE("IOleCommandTarget::QueryStatus");
2385 if (prgCmds == NULL) return E_INVALIDARG;
2386 bool bCmdGroupFound = false;
2387
2388 for (ULONG nCmd = 0; nCmd < cCmds; nCmd++)
2389 {
2390 // unsupported by default
2391 prgCmds[nCmd].cmdf = 0;
2392
2393 // TODO
2394 }
2395
2396 if (!bCmdGroupFound) { OLECMDERR_E_UNKNOWNGROUP; }
2397 return S_OK;
2398 }
2399
2400 HRESULT FrameSite::Exec(const GUID * pguidCmdGroup, DWORD nCmdID,
2401 DWORD nCmdExecOpt, VARIANTARG * pVaIn,
2402 VARIANTARG * pVaOut)
2403 {
2404 WXOLE_TRACE("IOleCommandTarget::Exec");
2405 bool bCmdGroupFound = false;
2406
2407 if (!bCmdGroupFound) { OLECMDERR_E_UNKNOWNGROUP; }
2408 return OLECMDERR_E_NOTSUPPORTED;
2409 }
2410
2411 //IAdviseSink
2412
2413 void STDMETHODCALLTYPE FrameSite::OnDataChange(FORMATETC * pFormatEtc, STGMEDIUM * pgStgMed)
2414 {
2415 WXOLE_TRACE("IAdviseSink::OnDataChange");
2416 }
2417
2418 void STDMETHODCALLTYPE FrameSite::OnViewChange(DWORD dwAspect, LONG lIndex)
2419 {
2420 WXOLE_TRACE("IAdviseSink::OnViewChange");
2421 // redraw the control
2422 }
2423
2424 void STDMETHODCALLTYPE FrameSite::OnRename(IMoniker * pmk)
2425 {
2426 WXOLE_TRACE("IAdviseSink::OnRename");
2427 }
2428
2429 void STDMETHODCALLTYPE FrameSite::OnSave()
2430 {
2431 WXOLE_TRACE("IAdviseSink::OnSave");
2432 }
2433
2434 void STDMETHODCALLTYPE FrameSite::OnClose()
2435 {
2436 WXOLE_TRACE("IAdviseSink::OnClose");
2437 }
2438
2439 /////////////////////////////////////////////
2440 // IOleDocumentSite
2441 HRESULT STDMETHODCALLTYPE FrameSite::ActivateMe(
2442 /* [in] */ IOleDocumentView __RPC_FAR *pViewToActivate)
2443 {
2444 wxAutoOleInterface<IOleInPlaceSite> inPlaceSite(IID_IOleInPlaceSite, (IDispatch *) this);
2445 if (!inPlaceSite.Ok())
2446 return E_FAIL;
2447
2448 if (pViewToActivate)
2449 {
2450 m_window->m_docView = pViewToActivate;
2451 m_window->m_docView->SetInPlaceSite(inPlaceSite);
2452 }
2453 else
2454 {
2455 wxAutoOleInterface<IOleDocument> oleDoc(IID_IOleDocument, m_window->m_oleObject);
2456 if (! oleDoc.Ok())
2457 return E_FAIL;
2458
2459 HRESULT hr = oleDoc->CreateView(inPlaceSite, NULL, 0, m_window->m_docView.GetRef());
2460 if (hr != S_OK)
2461 return E_FAIL;
2462
2463 m_window->m_docView->SetInPlaceSite(inPlaceSite);
2464 };
2465
2466 m_window->m_docView->UIActivate(TRUE);
2467
2468 return S_OK;
2469 };
2470
2471
2472 static IMalloc *iMalloc = NULL;
2473
2474 IMalloc *wxOleInit::GetIMalloc()
2475 {
2476 assert(iMalloc);
2477 return iMalloc;
2478 };
2479
2480 wxOleInit::wxOleInit()
2481 {
2482 if (OleInitialize(NULL) == S_OK && iMalloc == NULL)
2483 CoGetMalloc(1, &iMalloc);
2484 else if (iMalloc)
2485 iMalloc->AddRef();
2486 };
2487
2488 wxOleInit::~wxOleInit()
2489 {
2490 if (iMalloc)
2491 {
2492 if (iMalloc->Release() == 0)
2493 iMalloc = NULL;
2494 };
2495
2496 OleUninitialize();
2497 }
2498
2499 bool GetSysErrMessage(int err, wxString& s)
2500 {
2501 wxChar buf[256];
2502 if (FormatMessage(
2503 FORMAT_MESSAGE_FROM_SYSTEM, NULL,
2504 err,0, buf, sizeof(buf), NULL) == 0)
2505 return false;
2506
2507 buf[sizeof(buf) - 1] = 0;
2508 s = buf;
2509 return true;
2510 };
2511
2512 wxString OLEHResultToString(HRESULT hr)
2513 {
2514 // try formatmessage
2515 wxString err;
2516 if (GetSysErrMessage(hr, err))
2517 return err;
2518
2519 switch (hr)
2520 {
2521 case S_OK:
2522 return wxEmptyString;
2523
2524 case CONNECT_E_CANNOTCONNECT:
2525 return _T("Cannot connect to event interface (maybe not there ?) - see MSDN");
2526
2527 case DISP_E_MEMBERNOTFOUND:
2528 return _T("The requested member does not exist, or the call to Invoke tried to set the value of a read-only property.");
2529
2530 case DISP_E_BADVARTYPE:
2531 return _T("One of the parameters in rgvarg is not a valid variant type.");
2532
2533 case DISP_E_BADPARAMCOUNT:
2534 return _T("The number of elements provided to DISPPARAMS is different from the number of parameters accepted by the method or property");
2535
2536 case DISP_E_EXCEPTION:
2537 return _T("The application needs to raise an exception. In this case, the structure passed in pExcepInfo should be filled in.");
2538
2539 case DISP_E_TYPEMISMATCH:
2540 return _T("One or more of the parameters could not be coerced. The index within rgvarg of the first parameter with the incorrect type is returned in the puArgErr parameter.");
2541
2542 case DISP_E_PARAMNOTOPTIONAL:
2543 return _T("A required parameter was omitted.");
2544
2545 case DISP_E_PARAMNOTFOUND:
2546 return _T("One of the parameter DISPIDs does not correspond to a parameter on the method. In this case, puArgErr should be set to the first parameter that contains the error.");
2547
2548 case OLECMDERR_E_UNKNOWNGROUP:
2549 return _T("The pguidCmdGroup parameter is not NULL but does not specify a recognized command group.");
2550
2551 case OLECMDERR_E_NOTSUPPORTED:
2552 return _T("The nCmdID parameter is not a valid command in the group identified by pguidCmdGroup.");
2553
2554 case OLECMDERR_E_DISABLED:
2555 return _T("The command identified by nCmdID is currently disabled and cannot be executed.");
2556
2557 case OLECMDERR_E_NOHELP:
2558 return _T("The caller has asked for help on the command identified by nCmdID, but no help is available.");
2559
2560 case OLECMDERR_E_CANCELED:
2561 return _T("The user canceled the execution of the command.");
2562
2563 case E_INVALIDARG:
2564 return _T("E_INVALIDARG");
2565
2566 case E_OUTOFMEMORY:
2567 return _T("E_OUTOFMEMORY");
2568
2569 case E_NOINTERFACE:
2570 return _T("E_NOINTERFACE");
2571
2572 case E_UNEXPECTED:
2573 return _T("E_UNEXPECTED");
2574
2575 case STG_E_INVALIDFLAG:
2576 return _T("STG_E_INVALIDFLAG");
2577
2578 case E_FAIL:
2579 return _T("E_FAIL");
2580
2581 case E_NOTIMPL:
2582 return _T("E_NOTIMPL");
2583
2584 default:
2585 {
2586 wxString buf;
2587 buf.Printf(_T("Unknown - 0x%X"), hr);
2588 return buf;
2589 }
2590 };
2591 };
2592
2593 // borrowed from src/msw/ole/oleutils.cpp
2594 wxString GetIIDName(REFIID riid)
2595 {
2596 // an association between symbolic name and numeric value of an IID
2597 struct KNOWN_IID
2598 {
2599 const IID *pIid;
2600 const wxChar *szName;
2601 };
2602
2603 // construct the table containing all known interfaces
2604 #define ADD_KNOWN_IID(name) { &IID_I##name, _T(#name) }
2605 #define ADD_KNOWN_GUID(name) { &name, _T(#name) }
2606
2607 static const KNOWN_IID aKnownIids[] =
2608 {
2609 ADD_KNOWN_IID(ServiceProvider),
2610 ADD_KNOWN_IID(AdviseSink),
2611 ADD_KNOWN_IID(AdviseSink2),
2612 ADD_KNOWN_IID(BindCtx),
2613 ADD_KNOWN_IID(ClassFactory),
2614 #if ( !defined( __VISUALC__) || (__VISUALC__!=1010) ) && !defined(__MWERKS__)
2615 ADD_KNOWN_IID(ContinueCallback),
2616 ADD_KNOWN_IID(EnumOleDocumentViews),
2617 ADD_KNOWN_IID(OleCommandTarget),
2618 ADD_KNOWN_IID(OleDocument),
2619 ADD_KNOWN_IID(OleDocumentSite),
2620 ADD_KNOWN_IID(OleDocumentView),
2621 ADD_KNOWN_IID(Print),
2622 #endif
2623 ADD_KNOWN_IID(DataAdviseHolder),
2624 ADD_KNOWN_IID(DataObject),
2625 ADD_KNOWN_IID(Debug),
2626 ADD_KNOWN_IID(DebugStream),
2627 ADD_KNOWN_IID(DfReserved1),
2628 ADD_KNOWN_IID(DfReserved2),
2629 ADD_KNOWN_IID(DfReserved3),
2630 ADD_KNOWN_IID(Dispatch),
2631 ADD_KNOWN_IID(DropSource),
2632 ADD_KNOWN_IID(DropTarget),
2633 ADD_KNOWN_IID(EnumCallback),
2634 ADD_KNOWN_IID(EnumFORMATETC),
2635 ADD_KNOWN_IID(EnumGeneric),
2636 ADD_KNOWN_IID(EnumHolder),
2637 ADD_KNOWN_IID(EnumMoniker),
2638 ADD_KNOWN_IID(EnumOLEVERB),
2639 ADD_KNOWN_IID(EnumSTATDATA),
2640 ADD_KNOWN_IID(EnumSTATSTG),
2641 ADD_KNOWN_IID(EnumString),
2642 ADD_KNOWN_IID(EnumUnknown),
2643 ADD_KNOWN_IID(EnumVARIANT),
2644 ADD_KNOWN_IID(ExternalConnection),
2645 ADD_KNOWN_IID(InternalMoniker),
2646 ADD_KNOWN_IID(LockBytes),
2647 ADD_KNOWN_IID(Malloc),
2648 ADD_KNOWN_IID(Marshal),
2649 ADD_KNOWN_IID(MessageFilter),
2650 ADD_KNOWN_IID(Moniker),
2651 ADD_KNOWN_IID(OleAdviseHolder),
2652 ADD_KNOWN_IID(OleCache),
2653 ADD_KNOWN_IID(OleCache2),
2654 ADD_KNOWN_IID(OleCacheControl),
2655 ADD_KNOWN_IID(OleClientSite),
2656 ADD_KNOWN_IID(OleContainer),
2657 ADD_KNOWN_IID(OleInPlaceActiveObject),
2658 ADD_KNOWN_IID(OleInPlaceFrame),
2659 ADD_KNOWN_IID(OleInPlaceObject),
2660 ADD_KNOWN_IID(OleInPlaceSite),
2661 ADD_KNOWN_IID(OleInPlaceUIWindow),
2662 ADD_KNOWN_IID(OleItemContainer),
2663 ADD_KNOWN_IID(OleLink),
2664 ADD_KNOWN_IID(OleManager),
2665 ADD_KNOWN_IID(OleObject),
2666 ADD_KNOWN_IID(OlePresObj),
2667 ADD_KNOWN_IID(OleWindow),
2668 ADD_KNOWN_IID(PSFactory),
2669 ADD_KNOWN_IID(ParseDisplayName),
2670 ADD_KNOWN_IID(Persist),
2671 ADD_KNOWN_IID(PersistFile),
2672 ADD_KNOWN_IID(PersistStorage),
2673 ADD_KNOWN_IID(PersistStream),
2674 ADD_KNOWN_IID(ProxyManager),
2675 ADD_KNOWN_IID(RootStorage),
2676 ADD_KNOWN_IID(RpcChannel),
2677 ADD_KNOWN_IID(RpcProxy),
2678 ADD_KNOWN_IID(RpcStub),
2679 ADD_KNOWN_IID(RunnableObject),
2680 ADD_KNOWN_IID(RunningObjectTable),
2681 ADD_KNOWN_IID(StdMarshalInfo),
2682 ADD_KNOWN_IID(Storage),
2683 ADD_KNOWN_IID(Stream),
2684 ADD_KNOWN_IID(StubManager),
2685 ADD_KNOWN_IID(Unknown),
2686 ADD_KNOWN_IID(ViewObject),
2687 ADD_KNOWN_IID(ViewObject2),
2688 ADD_KNOWN_GUID(IID_IDispatch),
2689 ADD_KNOWN_GUID(IID_IWebBrowser),
2690 ADD_KNOWN_GUID(IID_IWebBrowserApp),
2691 ADD_KNOWN_GUID(IID_IWebBrowser2),
2692 ADD_KNOWN_GUID(IID_IWebBrowser),
2693 ADD_KNOWN_GUID(DIID_DWebBrowserEvents2),
2694 ADD_KNOWN_GUID(DIID_DWebBrowserEvents),
2695 };
2696
2697 // don't clobber preprocessor name space
2698 #undef ADD_KNOWN_IID
2699 #undef ADD_KNOWN_GUID
2700
2701 // try to find the interface in the table
2702 for ( size_t ui = 0; ui < WXSIZEOF(aKnownIids); ui++ )
2703 {
2704 if ( riid == *aKnownIids[ui].pIid )
2705 {
2706 return aKnownIids[ui].szName;
2707 }
2708 }
2709
2710 // unknown IID, just transform to string
2711 LPOLESTR str = NULL;
2712 StringFromIID(riid, &str);
2713 if (str)
2714 {
2715 wxString s = str;
2716 CoTaskMemFree(str);
2717 return s;
2718 }
2719 else
2720 return _T("StringFromIID() error");
2721 }