BUG: Error Accessing Window.external in ATL DHTML Control
ID: Q202009
|
The information in this article applies to:
-
Microsoft Internet Explorer (Programming) version 5
SYMPTOMS
A DHTML control created with the ATL Object Wizard fails with the following script error when accessing window.external from Internet Explorer 5.0:
'Object doesn't support this property or method'
CAUSE
A DHTML control contains two IDispatch interfaces, a default interface for scripting and another for the window.external methods. The WebBrowser control incorrectly uses the default IDispatch interface when invoking window.external methods.
RESOLUTION
Implement the window.external IDispatch method in a separate COM object.
Use the following steps to implement a sub-object for a default ATL DHTML control project:
- Add HTML Control to project (Ctrl).
- Add Simple Object to project, use default of "dual interface" (UIObj).
- Remove original UI dispatch interface (ICtrlUI) from ctrl.h:
From class derivation list:
public IDispatchImpl<ICtrlUI, &IID_ICtrlUI, &LIBID_DHTMLCONTROLLib>,
From COM_MAP, replace the following two lines:
COM_INTERFACE_ENTRY(ICtrlUI)
COM_INTERFACE_ENTRY2(IDispatch, ICtrl)
with
)
COM_INTERFACE_ENTRY(IDispatch)
- Move the example OnClick method from ctrl.h to uiobj.h:
// ICtrlUI
public:
// Example method called by the HTML to change the <BODY> background color
STDMETHOD(OnClick)(IDispatch* pdispBody, VARIANT varColor)
{
CComQIPtr<IHTMLBodyElement> spBody(pdispBody);
if (spBody != NULL)
spBody->put_bgColor(varColor);
return S_OK;
}
- Modify dhtmlcontrol.idl to reflect above changes:
Move OnClick method from ICtrlUI to IUIObj interface definition:
// Example method that will be called by the HTML
HRESULT OnClick([in]IDispatch* pdispBody, [in]VARIANT varColor);
Remove original ICtrlUI interface from interface definition:
[
object, dual,
uuid(C3920EDB-BAD6-11D2-AFA1-00A0C9C9E6C5),
helpstring("ICtrlUI Interface"),
pointer_default(unique)
]
interface ICtrlUI : IDispatch
{
};
Remove original ICtrlUI interface from Ctrl coclass:
interface ICtrlUI;
- Modify OnCreate method in Ctrl.h:
#include "uiobj.h"
...
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CAxWindow wnd(m_hWnd);
HRESULT hr = wnd.CreateControl(IDH_CTRL);
if (SUCCEEDED(hr))
{
// Create sub-object - this implements our window.external methods to be called from HTML
hr = CComObject<CUIObj>::CreateInstance( &m_pUI );
if ( SUCCEEDED(hr) )
{
CComQIPtr<IDispatch> pDisp(m_pUI);
hr = wnd.SetExternalDispatch(pDisp);
}
}
if (SUCCEEDED(hr))
hr = wnd.QueryControl(IID_IWebBrowser2, (void**)&m_spBrowser);
return SUCCEEDED(hr) ? 0 : -1;
}
CComObject<CUIObj>* m_pUI;
- In addition, you can specify that this simple object should not be creatable with CoCreateInstance by marking the object as non-creatable.
STATUSMicrosoft has confirmed this to be a bug in the Microsoft products listed
at the beginning of this article.
MORE INFORMATION
Microsoft Active Template Library (ATL), Version 3.0, allows developers to write Dynamic HTML (DHTML) controls. A DHTML control is an ActiveX control which hosts the Internet Explorer WebBrowser control to display an HTML file. The HTML file is stored in the control as a resource and can contain DHTML and script to create an interactive user interface.
One additional feature of the DHTML control is that it's methods can be invoked from the HTML page by means of the DHTML window.external object. When any method is invoked from script using window.external, the WebBrowser control obtains the IDispatch for these methods by calling the host implementation of IDocHostUIHandler::GetExternal(). The correct IDispatch interface is set by a call to CAxWindow::SetExternalDispatch() in the control's OnCreate message handler.
The problem occurs because the WebBrowser control uses the IDispatch interface to query for IDispatchEx. If this fails, the host is queried for the default IDispatch instead of using the original interface.
Steps to Reproduce Behavior
- From Microsoft Visual C++ 6.0, From the File menu select New to create a new ATL project with default settings
- From the Insert menu select New ATL Object to insert an object of type HTML Control or Lite HTML Control. Use the default settings.
- Build the control and open the generated HTML file which contains the OBJECT tag for this control.
- The default DHTML control implements an OnClick() method which is invoked by clicking one of the three HTML buttons on the page.
REFERENCESFor more information, please see the MSDN Web Workshop:
http://msdn.microsoft.com/workshop/default.asp
For more information about ATL DHTML controls, please refer to the Microsoft Visual C++ 6.0 online documentation.
For additional information, please refer to the following article in the
Microsoft Knowledge Base:
Q188015 TITLE: HOWTO: Access Methods/Properties of Container from Script
(c) Microsoft Corporation 1999, All Rights Reserved. Contributions by Mark Davis, Microsoft Corporation.
Additional query words:
kbDSupport kbbeta
Keywords : kbDHTML kbMSHTML kbWebBrowser kbATL300 kbIE500dp1bug kbGrpInet kbDSupport
Version : WINDOWS:5
Platform : WINDOWS
Issue type : kbbug
|