2 wxActiveX Library Licence, Version 3
3 ====================================
5 Copyright (C) 2003 Lindsay Mathieson [, ...]
7 Everyone is permitted to copy and distribute verbatim copies
8 of this licence document, but changing it is not allowed.
10 wxActiveX LIBRARY LICENCE
11 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
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.
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.
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.
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
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
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
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.
56 \brief implements wxActiveX window class and OLE tools
61 #pragma warning( disable : 4101 4786)
62 #pragma warning( disable : 4786)
67 #include <wx/variant.h>
68 #include <wx/datetime.h>
77 /// \brief wxActiveX Namespace for stuff I want to keep out of other tools way.
78 namespace NS_wxActiveX
81 /// specific to wxActiveX, for creating
82 /// case insenstive maps etc
85 bool operator()(const wxString
& x
, const wxString
& y
) const
87 return x
.CmpNoCase(y
) < 0;
93 //////////////////////////////////////////
94 /// Template class for smart interface handling.
95 /// - Automatically dereferences ole interfaces
96 /// - Smart Copy Semantics
97 /// - Can Create Interfaces
98 /// - Can query for other interfaces
99 template <class I
> class wxAutoOleInterface
105 /// takes ownership of an existing interface
106 /// Assumed to already have a AddRef() applied
107 explicit wxAutoOleInterface(I
*pInterface
= NULL
) : m_interface(pInterface
) {}
109 /// queries for an interface
110 wxAutoOleInterface(REFIID riid
, IUnknown
*pUnk
) : m_interface(NULL
)
112 QueryInterface(riid
, pUnk
);
114 /// queries for an interface
115 wxAutoOleInterface(REFIID riid
, IDispatch
*pDispatch
) : m_interface(NULL
)
117 QueryInterface(riid
, pDispatch
);
120 /// Creates an Interface
121 wxAutoOleInterface(REFCLSID clsid
, REFIID riid
) : m_interface(NULL
)
123 CreateInstance(clsid
, riid
);
127 wxAutoOleInterface(const wxAutoOleInterface
<I
>& ti
) : m_interface(NULL
)
132 /// assignment operator
133 wxAutoOleInterface
<I
>& operator = (const wxAutoOleInterface
<I
>& ti
)
136 ti
.m_interface
->AddRef();
138 m_interface
= ti
.m_interface
;
142 /// takes ownership of an existing interface
143 /// Assumed to already have a AddRef() applied
144 wxAutoOleInterface
<I
>& operator = (I
*&ti
)
152 ~wxAutoOleInterface()
158 /// Releases interface (i.e decrements refCount)
162 m_interface
->Release();
166 /// queries for an interface
167 HRESULT
QueryInterface(REFIID riid
, IUnknown
*pUnk
)
170 wxCHECK(pUnk
!= NULL
, -1);
171 return pUnk
->QueryInterface(riid
, (void **) &m_interface
);
174 /// Create a Interface instance
175 HRESULT
CreateInstance(REFCLSID clsid
, REFIID riid
)
178 return CoCreateInstance(clsid
, NULL
, CLSCTX_ALL
, riid
, (void **) &m_interface
);
182 /// returns the interface pointer
183 inline operator I
*() const {return m_interface
;}
185 /// returns the dereferenced interface pointer
186 inline I
* operator ->() {return m_interface
;}
187 /// returns a pointer to the interface pointer
188 inline I
** GetRef() {return &m_interface
;}
189 /// returns true if we have a valid interface pointer
190 inline bool Ok() const {return m_interface
!= NULL
;}
194 /// \brief Converts a std HRESULT to its error code.
195 /// Hardcoded, by no means a definitive list.
196 wxString
OLEHResultToString(HRESULT hr
);
197 /// \brief Returns the string description of a IID.
198 /// Hardcoded, by no means a definitive list.
199 wxString
GetIIDName(REFIID riid
);
201 //#define __WXOLEDEBUG
205 #define WXOLE_TRACE(str) {OutputDebugString(str);OutputDebugString("\r\n");}
206 #define WXOLE_TRACEOUT(stuff)\
209 os << stuff << "\r\n";\
210 WXOLE_TRACE(os.mb_str());\
213 #define WXOLE_WARN(__hr,msg)\
217 wxString s = "*** ";\
219 s += " : "+ OLEHResultToString(__hr);\
220 WXOLE_TRACE(s.c_str());\
224 #define WXOLE_TRACE(str)
225 #define WXOLE_TRACEOUT(stuff)
226 #define WXOLE_WARN(_proc,msg) {_proc;}
232 static IMalloc
*GetIMalloc();
238 #define DECLARE_OLE_UNKNOWN(cls)\
244 TAutoInitInt() : l(0) {}\
246 TAutoInitInt refCount, lockCount;\
248 static void _GetInterface(cls *self, REFIID iid, void **_interface, const char *&desc);\
251 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject);\
252 ULONG STDMETHODCALLTYPE AddRef();\
253 ULONG STDMETHODCALLTYPE Release();\
254 ULONG STDMETHODCALLTYPE AddLock();\
255 ULONG STDMETHODCALLTYPE ReleaseLock()
257 #define DEFINE_OLE_TABLE(cls)\
258 LONG cls::GetRefCount() {return refCount.l;}\
259 HRESULT STDMETHODCALLTYPE cls::QueryInterface(REFIID iid, void ** ppvObject)\
263 WXOLE_TRACE("*** NULL POINTER ***");\
266 const char *desc = NULL;\
267 cls::_GetInterface(this, iid, ppvObject, desc);\
270 WXOLE_TRACEOUT("<" << GetIIDName(iid).c_str() << "> Not Found");\
271 return E_NOINTERFACE;\
273 WXOLE_TRACEOUT("QI : <" << desc <<">");\
274 ((IUnknown * )(*ppvObject))->AddRef();\
277 ULONG STDMETHODCALLTYPE cls::AddRef()\
279 WXOLE_TRACEOUT(# cls << "::Add ref(" << refCount.l << ")");\
280 InterlockedIncrement(&refCount.l);\
283 ULONG STDMETHODCALLTYPE cls::Release()\
287 InterlockedDecrement(&refCount.l);\
288 WXOLE_TRACEOUT(# cls << "::Del ref(" << refCount.l << ")");\
289 if (refCount.l == 0)\
299 ULONG STDMETHODCALLTYPE cls::AddLock()\
301 WXOLE_TRACEOUT(# cls << "::Add Lock(" << lockCount.l << ")");\
302 InterlockedIncrement(&lockCount.l);\
305 ULONG STDMETHODCALLTYPE cls::ReleaseLock()\
307 if (lockCount.l > 0)\
309 InterlockedDecrement(&lockCount.l);\
310 WXOLE_TRACEOUT(# cls << "::Del Lock(" << lockCount.l << ")");\
318 #define DEFINE_OLE_BASE(cls)\
319 void cls::_GetInterface(cls *self, REFIID iid, void **_interface, const char *&desc)\
324 #define OLE_INTERFACE(_iid, _type)\
325 if (IsEqualIID(iid, _iid))\
327 WXOLE_TRACE("Found Interface <" # _type ">");\
328 *_interface = (IUnknown *) (_type *) self;\
333 #define OLE_IINTERFACE(_face) OLE_INTERFACE(IID_##_face, _face)
335 #define OLE_INTERFACE_CUSTOM(func)\
336 if (func(self, iid, _interface, desc))\
341 #define END_OLE_TABLE\
345 /// Main class for embedding a ActiveX control.
346 /// Use by itself or derive from it
347 /// \note The utility program (wxie) can generate a list of events, methods & properties
349 /// First display the control (File|Display),
350 /// then get the type info (ActiveX|Get Type Info) - these are copied to the clipboard.
351 /// Eventually this will be expanded to autogenerate
352 /// wxWindows source files for a control with all methods etc encapsulated.
354 /// construct using a ProgId or class id
355 /// \code new wxActiveX(parent, CLSID_WebBrowser, id, pos, size, style, name)\endcode
356 /// \code new wxActiveX(parent, "ShockwaveFlash.ShockwaveFlash", id, pos, size, style, name)\endcode
358 /// Properties can be set using \c SetProp() and set/retrieved using \c Prop()
359 /// \code SetProp(name, wxVariant(x)) \endcode or
360 /// \code wxString Prop("<name>") = x\endcode
361 /// \code wxString result = Prop("<name>")\endcode
362 /// \code flash_ctl.Prop("movie") = "file:///movies/test.swf";\endcode
363 /// \code flash_ctl.Prop("Playing") = false;\endcode
364 /// \code wxString current_movie = flash_ctl.Prop("movie");\endcode
366 /// Methods are invoked with \c CallMethod()
367 /// \code wxVariant result = CallMethod("<name>", args, nargs = -1)\endcode
368 /// \code wxVariant args[] = {0L, "file:///e:/dev/wxie/bug-zap.swf"};
369 /// wxVariant result = X->CallMethod("LoadMovie", args);\endcode
371 /// respond to events with the
372 /// \c EVT_ACTIVEX(controlId, eventName, handler) &
373 /// \c EVT_ACTIVEX_DISPID(controlId, eventDispId, handler) macros
375 /// BEGIN_EVENT_TABLE(wxIEFrame, wxFrame)
376 /// EVT_ACTIVEX_DISPID(ID_MSHTML, DISPID_STATUSTEXTCHANGE, OnMSHTMLStatusTextChangeX)
377 /// EVT_ACTIVEX(ID_MSHTML, "BeforeNavigate2", OnMSHTMLBeforeNavigate2X)
378 /// EVT_ACTIVEX(ID_MSHTML, "TitleChange", OnMSHTMLTitleChangeX)
379 /// EVT_ACTIVEX(ID_MSHTML, "NewWindow2", OnMSHTMLNewWindow2X)
380 /// EVT_ACTIVEX(ID_MSHTML, "ProgressChange", OnMSHTMLProgressChangeX)
381 /// END_EVENT_TABLE()\endcode
382 class wxActiveX
: public wxWindow
{
384 /// General parameter and return type infoformation for Events, Properties and Methods.
385 /// refer to ELEMDESC, IDLDESC in MSDN
396 ParamX() : isOptional(false), vt(VT_EMPTY
) {}
397 inline bool IsIn() const {return (flags
& IDLFLAG_FIN
) != 0;}
398 inline bool IsOut() const {return (flags
& IDLFLAG_FOUT
) != 0;}
399 inline bool IsRetVal() const {return (flags
& IDLFLAG_FRETVAL
) != 0;}
401 typedef vector
<ParamX
> ParamXArray
;
404 /// Type & Parameter info for Events and Methods.
405 /// refer to FUNCDESC in MSDN
416 typedef vector
<FuncX
> FuncXArray
;
419 /// Type info for properties.
429 PropX() : putByRef (false) {}
430 inline bool CanGet() const {return type
.vt
!= VT_EMPTY
;}
431 inline bool CanSet() const {return arg
.vt
!= VT_EMPTY
;}
433 typedef vector
<PropX
> PropXArray
;
436 /// Create using clsid.
437 wxActiveX(wxWindow
* parent
, REFCLSID clsid
, wxWindowID id
= -1,
438 const wxPoint
& pos
= wxDefaultPosition
,
439 const wxSize
& size
= wxDefaultSize
,
441 const wxString
& name
= wxPanelNameStr
);
442 /// create using progid.
443 wxActiveX(wxWindow
* parent
, const wxString
& progId
, wxWindowID id
= -1,
444 const wxPoint
& pos
= wxDefaultPosition
,
445 const wxSize
& size
= wxDefaultSize
,
447 const wxString
& name
= wxPanelNameStr
);
448 virtual ~wxActiveX();
450 /// Number of events defined for this control.
451 inline int GetEventCount() const {return m_events
.size();}
452 /// returns event description by index.
453 /// throws exception for invalid index
454 const FuncX
& GetEventDesc(int idx
) const;
456 /// Number of properties defined for this control.
457 inline int GetPropCount() const {return m_props
.size();}
458 /// returns property description by index.
459 /// throws exception for invalid index
460 const PropX
& GetPropDesc(int idx
) const;
461 /// returns property description by name.
462 /// throws exception for invalid name
463 const PropX
& GetPropDesc(const wxString
& name
) const;
465 /// Number of methods defined for this control.
466 inline int GetMethodCount() const {return m_methods
.size();}
467 /// returns method description by name.
468 /// throws exception for invalid index
469 const FuncX
& GetMethodDesc(int idx
) const;
470 /// returns method description by name.
471 /// throws exception for invalid name
472 const FuncX
& GetMethodDesc(const wxString
& name
) const;
474 /// Set property VARIANTARG value by MEMBERID.
475 void SetProp(MEMBERID name
, VARIANTARG
& value
);
476 /// Set property using wxVariant by name.
477 void SetProp(const wxString
&name
, const wxVariant
&value
);
479 class wxPropertySetter
485 wxPropertySetter(wxActiveX
*ctl
, const wxString
& propName
) :
486 m_ctl(ctl
), m_propName(propName
) {}
488 inline const wxPropertySetter
& operator = (wxVariant v
) const
490 m_ctl
->SetProp(m_propName
, v
);
494 inline operator wxVariant() const {return m_ctl
->GetPropAsWxVariant(m_propName
);};
495 inline operator wxString() const {return m_ctl
->GetPropAsString(m_propName
);};
496 inline operator char() const {return m_ctl
->GetPropAsChar(m_propName
);};
497 inline operator long() const {return m_ctl
->GetPropAsLong(m_propName
);};
498 inline operator bool() const {return m_ctl
->GetPropAsBool(m_propName
);};
499 inline operator double() const {return m_ctl
->GetPropAsDouble(m_propName
);};
500 inline operator wxDateTime() const {return m_ctl
->GetPropAsDateTime(m_propName
);};
501 inline operator void *() const {return m_ctl
->GetPropAsPointer(m_propName
);};
504 /// \fn inline wxPropertySetter Prop(wxString name) {return wxPropertySetter(this, name);}
505 /// \param name Property name to read/set
506 /// \return wxPropertySetter, which has overloads for setting/getting the property
507 /// \brief Generic Get/Set Property by name.
508 /// Automatically handles most types
510 /// - Prop("\<name\>") = \<value\>
511 /// - var = Prop("\<name\>")
513 /// - \code flash_ctl.Prop("movie") = "file:///movies/test.swf";\endcode
514 /// - \code flash_ctl.Prop("Playing") = false;\endcode
515 /// - \code wxString current_movie = flash_ctl.Prop("movie");\endcode
516 /// \exception raises exception if \<name\> is invalid
517 /// \note Have to add a few more type conversions yet ...
518 inline wxPropertySetter
Prop(wxString name
) {return wxPropertySetter(this, name
);}
520 VARIANT
GetPropAsVariant(MEMBERID name
);
521 VARIANT
GetPropAsVariant(const wxString
& name
);
522 wxVariant
GetPropAsWxVariant(const wxString
& name
);
523 wxString
GetPropAsString(const wxString
& name
);
524 char GetPropAsChar(const wxString
& name
);
525 long GetPropAsLong(const wxString
& name
);
526 bool GetPropAsBool(const wxString
& name
);
527 double GetPropAsDouble(const wxString
& name
);
528 wxDateTime
GetPropAsDateTime(const wxString
& name
);
529 void *GetPropAsPointer(const wxString
& name
);
532 // VARIANTARG form is passed straight to Invoke,
533 // so args in *REVERSE* order
534 VARIANT
CallMethod(MEMBERID name
, VARIANTARG args
[], int argc
);
535 VARIANT
CallMethod(const wxString
& name
, VARIANTARG args
[] = NULL
, int argc
= -1);
536 // args are in *NORMAL* order
537 // args can be a single wxVariant or an array
538 /// \fn wxVariant CallMethod(wxString name, wxVariant args[], int nargs = -1);
539 /// \param name name of method to call
540 /// \param args array of wxVariant's, defaults to NULL (no args)
541 /// \param nargs number of arguments passed via args. Defaults to actual number of args for the method
542 /// \return wxVariant
543 /// \brief Call a method of the ActiveX control.
544 /// Automatically handles most types
546 /// - result = CallMethod("\<name\>", args, nargs)
549 /// wxVariant args[] = {0L, "file:///e:/dev/wxie/bug-zap.swf"};
550 /// wxVariant result = X->CallMethod("LoadMovie", args);\endcode
551 /// \exception raises exception if \<name\> is invalid
552 /// \note Since wxVariant has built in type conversion, most the std types can be passed easily
553 wxVariant
CallMethod(const wxString
& name
, wxVariant args
[], int nargs
= -1);
555 HRESULT
ConnectAdvise(REFIID riid
, IUnknown
*eventSink
);
557 void OnSize(wxSizeEvent
&);
558 void OnPaint(wxPaintEvent
& event
);
559 void OnMouse(wxMouseEvent
& event
);
560 void OnSetFocus(wxFocusEvent
&);
561 void OnKillFocus(wxFocusEvent
&);
563 DECLARE_EVENT_TABLE();
566 friend class FrameSite
;
567 friend class wxActiveXEvents
;
569 unsigned long m_pdwRegister
;
571 typedef map
<MEMBERID
, int> MemberIdMap
;
572 typedef map
<wxString
, int, NS_wxActiveX::less_wxStringI
> NameMap
;
574 typedef wxAutoOleInterface
<IConnectionPoint
> wxOleConnectionPoint
;
575 typedef pair
<wxOleConnectionPoint
, DWORD
> wxOleConnection
;
576 typedef vector
<wxOleConnection
> wxOleConnectionArray
;
578 wxAutoOleInterface
<IDispatch
> m_Dispatch
;
579 wxAutoOleInterface
<IOleClientSite
> m_clientSite
;
580 wxAutoOleInterface
<IUnknown
> m_ActiveX
;
581 wxAutoOleInterface
<IOleObject
> m_oleObject
;
582 wxAutoOleInterface
<IOleInPlaceObject
> m_oleInPlaceObject
;
583 wxAutoOleInterface
<IOleInPlaceActiveObject
>
585 m_oleInPlaceActiveObject
;
586 wxAutoOleInterface
<IOleDocumentView
> m_docView
;
587 wxAutoOleInterface
<IViewObject
> m_viewObject
;
588 HWND m_oleObjectHWND
;
589 bool m_bAmbientUserMode
;
590 DWORD m_docAdviseCookie
;
591 wxOleConnectionArray m_connections
;
593 void CreateActiveX(REFCLSID clsid
);
594 void CreateActiveX(LPOLESTR progId
);
595 HRESULT
AmbientPropertyChanged(DISPID dispid
);
598 void GetTypeInfo(ITypeInfo
*ti
, bool defInterface
, bool defEventSink
);
603 MemberIdMap m_eventMemberIds
;
610 FuncXArray m_methods
;
611 NameMap m_methodNames
;
613 virtual bool MSWTranslateMessage(WXMSG
* pMsg
);
614 long MSWWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
);
616 DECLARE_CLASS(wxActiveX
)
620 class wxActiveXEvent
: public wxCommandEvent
623 friend class wxActiveXEvents
;
629 virtual wxEvent
*Clone() const { return new wxActiveXEvent(*this); }
631 wxString
EventName();
632 int ParamCount() const;
633 wxString
ParamType(int idx
);
634 wxString
ParamName(int idx
);
635 wxVariant
& operator[] (int idx
);
636 wxVariant
& operator[] (wxString name
);
639 DECLARE_CLASS(wxActiveXEvent
)
642 const wxEventType
& RegisterActiveXEvent(const wxChar
*eventName
);
643 const wxEventType
& RegisterActiveXEvent(DISPID event
);
645 typedef void (wxEvtHandler::*wxActiveXEventFunction
)(wxActiveXEvent
&);
647 /// \def EVT_ACTIVEX(id, eventName, fn)
648 /// \brief Event handle for events by name
649 #define EVT_ACTIVEX(id, eventName, fn) DECLARE_EVENT_TABLE_ENTRY(RegisterActiveXEvent(wxT(eventName)), id, -1, (wxObjectEventFunction) (wxEventFunction) (wxActiveXEventFunction) & fn, (wxObject *) NULL ),
650 /// \def EVT_ACTIVEX_DISPID(id, eventDispId, fn)
651 /// \brief Event handle for events by DISPID (dispath id)
652 #define EVT_ACTIVEX_DISPID(id, eventDispId, fn) DECLARE_EVENT_TABLE_ENTRY(RegisterActiveXEvent(eventDispId), id, -1, (wxObjectEventFunction) (wxEventFunction) (wxActiveXEventFunction) & fn, (wxObject *) NULL ),
655 bool wxDateTimeToVariant(wxDateTime dt
, VARIANTARG
& va
);
656 bool VariantToWxDateTime(VARIANTARG va
, wxDateTime
& dt
);
657 /// \relates wxActiveX
658 /// \fn bool MSWVariantToVariant(VARIANTARG& va, wxVariant& vx);
659 /// \param va VARAIANTARG to convert from
660 /// \param vx Destination wxVariant
661 /// \return success/failure (true/false)
662 /// \brief Convert MSW VARIANTARG to wxVariant.
663 /// Handles basic types, need to add:
664 /// - VT_ARRAY | VT_*
665 /// - better support for VT_UNKNOWN (currently treated as void *)
666 /// - better support for VT_DISPATCH (currently treated as void *)
667 bool MSWVariantToVariant(VARIANTARG
& va
, wxVariant
& vx
);
668 /// \relates wxActiveX
669 /// \fn bool VariantToMSWVariant(const wxVariant& vx, VARIANTARG& va);
670 /// \param vx wxVariant to convert from
671 /// \param va Destination VARIANTARG
672 /// \return success/failure (true/false)
673 /// \brief Convert wxVariant to MSW VARIANTARG.
674 /// Handles basic types, need to add:
675 /// - VT_ARRAY | VT_*
676 /// - better support for VT_UNKNOWN (currently treated as void *)
677 /// - better support for VT_DISPATCH (currently treated as void *)
678 bool VariantToMSWVariant(const wxVariant
& vx
, VARIANTARG
& va
);
680 #endif /* _IEHTMLWIN_H_ */