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