I'm using WTL to implement an event sink object which tries to handle
FileDownload event.
(WTL 7.5 with VC.Net 2003, ATL 7.1)
While handling DocumentComplete event, there's no problem. As to
FileDownload event, however, an ATL assertion is triggered
(In function IDispEventImpl<>::InvokeFromFuncInfo)
ATLASSERT(pdispparams->cArgs == (UINT)info.nParams);
I trace the program a little and found that the _ATL_FUNC_INFO got inside
ATL framework preferred a FileDownload() event handler like
void __stdcall OnFileDownload(VARAIANT_BOOL*)
However, the QueryInterface() shows that there should be 2 params, thus the
assertion is triggered.
Is there any way to get around this problem?
Thanks in advance,
Arthur
PS. my code is attached below
===== BEGIN CODE ====
// WtlExt.h : WTL Extensions/Helpers
// Copyright: Jes? Salas 2002 ( jesus...@hotmail.com )
// License : none, feel free to use it.
////////////////////////////////////////////////////////////////////////////
/
// ahsu: I modified the event sink to intercept DocumentComplete
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);
}
};
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;
// We must call DefWindowProc before we can attach to the control.
lRet = DefWindowProc(uMsg, wParam,lParam);
// Get the Pointer to the control with Events (true)
AttachControl(true);
return lRet;
}
HRESULT AttachControl(BOOL bWithEvents = false)
{
HRESULT hr = S_OK;
CComPtr<IUnknown> spUnk;
// Get the IUnknown interface of control
hr |= AtlAxGetControl(m_hWnd, &spUnk);
if (SUCCEEDED(hr))
// Query our interface
hr |= spUnk->QueryInterface(__uuidof(Interface),
(void**)(CComPtr<Interface>*)this);
if (bWithEvents && !FAILED(hr))
// Start events
hr |= EasyAdvise(spUnk);
return hr;
};
};
public:
// BEGIN_MSG_MAP is optional, you don't need to define or use it if you
don't want
BEGIN_MSG_MAP( CWTLIExplorer )
MESSAGE_HANDLER(WM_CREATE, OnCreate)
END_MSG_MAP()
LRESULT OnCreate(UINT uMsg, WPARAM wParam , LPARAM lParam, BOOL& bHandled)
{
// First you must CWTLAxControl<...,...>::OnCreate ( it set this message
Handled )
return CWTLAxControl<CWTLIExplorer,IWebBrowser2>::OnCreate(uMsg, wParam,
lParam, bHandled);
}
BEGIN_SINK_MAP(CWTLIExplorer)
SINK_ENTRY(0, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
SINK_ENTRY(0, DISPID_FILEDOWNLOAD, OnFileDownload)
END_SINK_MAP()
void __stdcall OnDocumentComplete(IDispatch* pDisp, VARIANT* URL)
{
// some code here
}
void __stdcall OnFileDownload(VARIANT_BOOL *&ActiveDocument, VARIANT_BOOL
*&Cancel)
{
// some code here
}
===== END CODE =====
It's a known problem. The type library says that FileDownload has just
one parameter, but the browser fires it with two parameters,
VARIANT_BOOL and VARIANT_BOOL*. The assertion is caused by this
mismatch.
The workaround is to use SINK_ENTRY_INFO with a hand-built
_ATL_FUNC_INFO structure:
static const _ATL_FUNC_INFO FileDownloadInfo;
SINK_ENTRY_INFO(0, IID_DWebBrowserEvents2, DISPID_FILEDOWNLOAD,
OnFileDownload, &FileDownloadInfo)
void STDMETHODCALLTYPE OnFileDownload(VARIANT_BOOL, VARIANT_BOOL*
pCancel);
// In .cpp file
const _ATL_FUNC_INFO CYourClass::FileDownloadInfo =
{
CC_STDCALL, VT_EMPTY, 2, {VT_BOOL, VT_BOOL | VT_BYREF}
};
--
With best wishes,
Igor Tandetnik
"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken
I still have some compilation errors that don't know how to solve.
The compiler first complained that IID_DWebBrowserEvents2 is undefined. I
tried to use DIID_DWebBrowserEvents2 instead, this time some more weird
message occurs:
d:\ahsu\WebSnap2\WtlExt.h(291) : error C2440: 'static_cast' : cannot convert
from '_atl_event_classtype *' to 'ATL::_IDispEventLocator<nID,piid> *'
with
[
nID=0,
piid=& DIID_DWebBrowserEvents2
]
Types pointed to are unrelated; conversion requires
reinterpret_cast, C-style cast or function-style cast
d:\ahsu\WebSnap2\WtlExt.h(291) : error C2440: 'initializing' : cannot
convert from 'void (__stdcall CWTLIExplorer::* )(void)' to 'DISPID'
There is no context in which this conversion is possible
d:\ahsu\WebSnap2\WtlExt.h(291) : error C2440: 'initializing' : cannot
convert from 'const ATL::_ATL_FUNC_INFO *' to 'void (__stdcall
CWTLIExplorer::* )(void)'
There is no context in which this conversion is possible
Any clues?
-Arthur
"Igor Tandetnik" <itand...@mvps.org> wrote in message
news:%23NHbepv...@TK2MSFTNGP11.phx.gbl...
Right. That was my typo, sorry.
>, this time
> some more weird message occurs:
>
> d:\ahsu\WebSnap2\WtlExt.h(291) : error C2440: 'static_cast' : cannot
> convert from '_atl_event_classtype *' to
> 'ATL::_IDispEventLocator<nID,piid> *' with
> [
> nID=0,
> piid=& DIID_DWebBrowserEvents2
> ]
In your derivation, change IDispEventImpl<0,T> to IDispEventImpl<0,T,
&DIID_DWebBrowserEvents2>
-Arthur
"Igor Tandetnik" <itand...@mvps.org> wrote in message
news:OcIMxG3X...@TK2MSFTNGP11.phx.gbl...