티스토리 툴바


BUG: Error Accessing Window.external in ATL DHTML Control

Posted 2008/09/18 15:00 by Dave Aitch

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'

Back to the top

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.

Back to the top

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:
1. Add HTML Control to project (Ctrl).
2. Add Simple Object to project, use default of "dual interface" (UIObj).
3. 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)
						
4. 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;
   }
						
5. 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;
						
6. 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;
						
7. In addition, you can specify that this simple object should not be creatable with CoCreateInstance by marking the object as non-creatable.
Add the [noncreatable] attribute in the IDL file for the simple object's coclass. Don't forget the comma after the help string attribute
 [
    uuid(....),
    help string("UIObj class"),
    noncreatable
  ]
  coclass UIObj
  {
    ...
  }
								
Change OBJECT_ENTRY(CLSID_UIObj, CUIObj)macro in the object map to OBJECT_ENTRY_NON_CREATEABLE(CUIObj) for the simple object.



출처 : http://support.microsoft.com/kb/202009

« PREV : 1 : ... 31 : 32 : 33 : 34 : 35 : 36 : 37 : 38 : 39 : ... 200 : NEXT »