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