Introduction
WTL is the best library for Win32 Programming I have seen, simple and powerful. But sometimes during a period of time I have to change my mind and work with other libraries and tools, and then I forget some basic ATL/WTL concepts like:
- Event Sink implementations
- ActiveX instancing
- Other basic hard-to-forget concepts
For this reason I'm developing a little library in a WTL like fashion that will help me, (and maybe someone out there), to make my life easier with WTL.
CWTLAxControl
This class and other related classes in this article will help you to make your job with ActiveX controls easier.
CWTLAxControl
is a class that implements :
- SmartPointer (
CComPtr<>
).
CWindowImpl<>
( CAxWindow
).
IDispEventImpl<>
.
Maybe it seems to be a hard class to use , but wait a minute and take a look at the next IExplorer
implementation, using this class you will have access to the IWebBrowser2
methods interface via "->" ( smart pointer ), window messages handling (Host window) and Sink Events events fired from ActiveX hosted to your own event handlers.
#define EVENTFN void __stdcall
class CWTLIExplorer : public CWTLAxControl<CWTLIExplorer,IWebBrowser2>
{
public:
BEGIN_MSG_MAP( CWTLIExplorer )
MESSAGE_HANDLER(WM_CREATE,OnCreate)
END_MSG_MAP()
LRESULT OnCreate(UINT uMsg, WPARAM wParam , LPARAM lParam,
BOOL& bHandled)
{
return CWTLAxControl<CWTLIExplorer,IWebBrowser2,>::OnCreate(
uMsg, wParam, lParam, bHandled );
}
BEGIN_SINK_MAP( CWTLIExplorer )
SINK_ENTRY(0, DISPID_NAVIGATECOMPLETE2, OnNavigateComplete2 )
END_SINK_MAP()
EVENTFN OnNavigateComplete2( IDispatch* pDisp, VARIANT* URL )
{
MessageBox( "OnNavigateComplete2" );
}
};
Inside CWTLAxControl
Well, if you like the above implementation then it is time to get a more detailed view of how it works.
The first step is to take a look into the main parent class CWTLAxControl
that looks like:
template <class T, class Interface>
class CWTLAxControl : public CComPtr<Interface>,
public CWindowImpl<CWTLAxControl,CAxWindow>,
public CWTLDispEventHelper<T,Interface>
{
public:
BEGIN_MSG_MAP(CWTLAxControl)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
END_MSG_MAP()
LRESULT OnCreate( UINT uMsg, WPARAM wParam , LPARAM lParam,
BOOL & bHandled )
{
LRESULT lRet;
lRet = DefWindowProc( uMsg, wParam,lParam );
AttachControl(true);
return lRet;
}
HRESULT AttachControl( BOOL bWithEvents = false )
{
HRESULT hr = S_OK;
CComPtr<IUnknown> spUnk;
hr |= AtlAxGetControl( m_hWnd, &spUnk);
if (SUCCEEDED(hr))
hr |= spUnk->QueryInterface( __uuidof(Interface),
(void**) (CComPtr<Interface>*)this);
if ( bWithEvents && ! FAILED(hr) )
hr|= EasyAdvise( spUnk );
return hr;
};
};
This class helps us to attach our CComPtr
to the ActiveX control using the AttachControl
method when it receives the WM_CREATE
message. Furthermore this class is derived from CWindowImpl
that give us the chance to handle all the windows messages that we'll need.
The last class CWTLDispEventHelper
will help us to setup the correct IDispEventImpl
implementation.
Inside CWTLDispEventHelper
This class will help us to setup the Event Sink for our control and looks like:
template <class T,class Interface>
class CWTLDispEventHelper : public IDispEventImpl<0,T>
{
public:
CComPtr<IUnknown> m_pUnk;
HRESULT EasyAdvise(IUnknown* pUnk)
{
m_pUnk = pUnk;
AtlGetObjectSourceInterface(pUnk,&m_libid, &m_iid,
&m_wMajorVerNum, &m_wMinorVerNum);
return DispEventAdvise(pUnk, &m_iid);
}
HRESULT EasyUnadvise()
{
AtlGetObjectSourceInterface(m_pUnk,&m_libid,
&m_iid, &m_wMajorVerNum, &m_wMinorVerNum);
return DispEventUnadvise(pUnk, &m_iid);
}
};
It has only two methods
EasyAdvise
to setup the Event Sink handler and
EasyUnadvise
to deactivate it.
How to create the Control
Well, this is the easiest thing, the normal way we use to create any window in WTL:
[...]
CWTLIExplorer m_pBrowser;
[...]
m_pBrowser.Create( m_hWnd, rcDefault, _T("about:blank"),
WS_HSCROLL| WS_VSCROLL| WS_CHILD | WS_VISIBLE |
WS_CLIPSIBLINGS | WS_CLIPCHILDREN );
m_pBrowser->Navigate(_bstr_t("http://www.codeproject.com"),NULL,
NULL,NULL,NULL);
We can change the _T("about:blank")
by the CLSID of the control we want to create "{XXXXX-XXXXX-XXXXX...}"
.
Closing Words
Well, I expect you will find this article useful and helpful for you, if this is the case and you find anything wrong here, please, send me an email and I will be very happy to solve the mistake and re-upload this article. Bye!