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