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