解释Duilib_旗舰版官方代码中的浏览器嵌入关于IE内核

30 篇文章 9 订阅

文章目录

解释Duilib_旗舰版官方代码中的浏览器嵌入关于IE内核

2.1、CWebBrowserUI类的接口声明

  • CWebBrowserUI类在DuiLib框架中的作用是提供一个封装了Web浏览器控件的UI组件,使得开发者可以在基于DuiLib的应用程序中嵌入和使用Web浏览器功能。这个类通过继承和实现多个COM接口,实现了对Web浏览器控件的复杂控制和管理,包括但不限于导航、刷新、前进、后退以及处理浏览器事件等。
    • 具体来说,CWebBrowserUI类的主要作用包括:
      1. 嵌入Web浏览器:允许在DuiLib UI库构建的应用程序中直接嵌入Web浏览器控件,为用户提供Web浏览能力。
      2. 导航控制:提供了一系列方法(如Navigate2RefreshGoBackGoForward等)来控制Web页面的导航和浏览。
      3. 事件处理:通过实现事件处理接口(如DWebBrowserEvents2事件和IDocHostUIHandler接口),CWebBrowserUI可以响应和处理来自Web浏览器控件的各种事件,如导航完成、导航错误、新窗口打开等。
      4. UI自定义:通过IDocHostUIHandler接口的实现,它允许开发者自定义浏览器控件的用户界面元素,如上下文菜单、工具栏等。
      5. 安全管理:实现IInternetSecurityManager接口,提供了一种机制来管理和控制与Internet安全相关的策略和设置,提高嵌入式浏览器的安全性。
      6. 接口访问:通过实现IUnknownIDispatch接口,CWebBrowserUI提供了对内部Web浏览器控件的底层访问能力,允许开发者进行更深入的定制和控制。
      7. COM兼容性:通过COM接口的实现,CWebBrowserUI确保了与其他COM组件的良好兼容性,使得它可以在广泛的Windows环境下运行,并利用Windows提供的丰富的Web浏览器功能。
    • 总的来说,CWebBrowserUI类为基于DuiLib的应用程序提供了一个功能丰富的Web浏览器UI组件,极大地扩展了应用程序的功能和用途,允许开发者在其应用程序中直接嵌入和利用Web内容和资源。
#ifndef __UIWEBBROWSER_H__
#define __UIWEBBROWSER_H__

#pragma once

#include <MsHTML.h>
#include "Utils/WebBrowserEventHandler.h"
#include <ExDisp.h>

namespace DuiLib
{
	class UILIB_API CWebBrowserUI
		: public CActiveXUI
		, public IDocHostUIHandler
		, public IServiceProvider
		, public IOleCommandTarget
		, public IDispatch
		, public ITranslateAccelerator
		, public IInternetSecurityManager 
	{
		DECLARE_DUICONTROL(CWebBrowserUI)
	public:
		/// 构造函数
		CWebBrowserUI();
		virtual ~CWebBrowserUI();

		void SetHomePage(LPCTSTR lpszUrl);
		LPCTSTR GetHomePage();

		void SetAutoNavigation(bool bAuto = TRUE);
		bool IsAutoNavigation();

		void SetWebBrowserEventHandler(CWebBrowserEventHandler* pEventHandler);
		void Navigate2(LPCTSTR lpszUrl);
		void Refresh();
		void Refresh2(int Level);
		void GoBack();
		void GoForward();
		void NavigateHomePage();
		void NavigateUrl(LPCTSTR lpszUrl);
		virtual bool DoCreateControl();
		IWebBrowser2* GetWebBrowser2(void);
		IDispatch*		   GetHtmlWindow();
		static DISPID FindId(IDispatch *pObj, LPOLESTR pName);
		static HRESULT InvokeMethod(IDispatch *pObj, LPOLESTR pMehtod, VARIANT *pVarResult, VARIANT *ps, int cArgs);
		static HRESULT GetProperty(IDispatch *pObj, LPOLESTR pName, VARIANT *pValue);
		static HRESULT SetProperty(IDispatch *pObj, LPOLESTR pName, VARIANT *pValue);

	protected:
		IWebBrowser2*			m_pWebBrowser2; //浏览器指针
		IHTMLWindow2*		_pHtmlWnd2;
		LONG m_dwRef;
		DWORD m_dwCookie;
		virtual void ReleaseControl();
		HRESULT RegisterEventHandler(BOOL inAdvise);
		virtual void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);
		CDuiString m_sHomePage;	// 默认页面
		bool m_bAutoNavi;	// 是否启动时打开默认页面
		CWebBrowserEventHandler* m_pWebBrowserEventHandler;	//浏览器事件处理

		// DWebBrowserEvents2
		void BeforeNavigate2( IDispatch *pDisp,VARIANT *&url,VARIANT *&Flags,VARIANT *&TargetFrameName,VARIANT *&PostData,VARIANT *&Headers,VARIANT_BOOL *&Cancel );
		void NavigateError(IDispatch *pDisp,VARIANT * &url,VARIANT *&TargetFrameName,VARIANT *&StatusCode,VARIANT_BOOL *&Cancel);
		void NavigateComplete2(IDispatch *pDisp,VARIANT *&url);
		void ProgressChange(LONG nProgress, LONG nProgressMax);
		void NewWindow3(IDispatch **pDisp, VARIANT_BOOL *&Cancel, DWORD dwFlags, BSTR bstrUrlContext, BSTR bstrUrl);
		void CommandStateChange(long Command,VARIANT_BOOL Enable);
		void TitleChange(BSTR bstrTitle);
		void DocumentComplete(IDispatch *pDisp,VARIANT *&url);

	public:
		virtual LPCTSTR GetClass() const;
		virtual LPVOID GetInterface( LPCTSTR pstrName );

		// IUnknown
		STDMETHOD_(ULONG,AddRef)();
		STDMETHOD_(ULONG,Release)();
		STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObject);

		// IDispatch
		virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount( __RPC__out UINT *pctinfo );
		virtual HRESULT STDMETHODCALLTYPE GetTypeInfo( UINT iTInfo, LCID lcid, __RPC__deref_out_opt ITypeInfo **ppTInfo );
		virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames( __RPC__in REFIID riid, __RPC__in_ecount_full(cNames ) LPOLESTR *rgszNames, UINT cNames, LCID lcid, __RPC__out_ecount_full(cNames) DISPID *rgDispId);
		virtual HRESULT STDMETHODCALLTYPE Invoke( DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr );

		// IDocHostUIHandler
		STDMETHOD(ShowContextMenu)(DWORD dwID, POINT* pptPosition, IUnknown* pCommandTarget, IDispatch* pDispatchObjectHit);
		STDMETHOD(GetHostInfo)(DOCHOSTUIINFO* pInfo);
		STDMETHOD(ShowUI)(DWORD dwID, IOleInPlaceActiveObject* pActiveObject, IOleCommandTarget* pCommandTarget, IOleInPlaceFrame* pFrame, IOleInPlaceUIWindow* pDoc);
		STDMETHOD(HideUI)();
		STDMETHOD(UpdateUI)();
		STDMETHOD(EnableModeless)(BOOL fEnable);
		STDMETHOD(OnDocWindowActivate)(BOOL fActivate);
		STDMETHOD(OnFrameWindowActivate)(BOOL fActivate);
		STDMETHOD(ResizeBorder)(LPCRECT prcBorder, IOleInPlaceUIWindow* pUIWindow, BOOL fFrameWindow);
		STDMETHOD(TranslateAccelerator)(LPMSG lpMsg, const GUID* pguidCmdGroup, DWORD nCmdID);	//浏览器消息过滤
		STDMETHOD(GetOptionKeyPath)(LPOLESTR* pchKey, DWORD dwReserved);
		STDMETHOD(GetDropTarget)(IDropTarget* pDropTarget, IDropTarget** ppDropTarget);
		STDMETHOD(GetExternal)(IDispatch** ppDispatch);
		STDMETHOD(TranslateUrl)(DWORD dwTranslate, OLECHAR* pchURLIn, OLECHAR** ppchURLOut);
		STDMETHOD(FilterDataObject)(IDataObject* pDO, IDataObject** ppDORet);

		// IServiceProvider
		STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void** ppvObject);

		// IOleCommandTarget
		virtual HRESULT STDMETHODCALLTYPE QueryStatus( __RPC__in_opt const GUID *pguidCmdGroup, ULONG cCmds, __RPC__inout_ecount_full(cCmds ) OLECMD prgCmds[ ], __RPC__inout_opt OLECMDTEXT *pCmdText);
		virtual HRESULT STDMETHODCALLTYPE Exec( __RPC__in_opt const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, __RPC__in_opt VARIANT *pvaIn, __RPC__inout_opt VARIANT *pvaOut );

		// IDownloadManager
		STDMETHOD(Download)( 
			/* [in] */ IMoniker *pmk,
			/* [in] */ IBindCtx *pbc,
			/* [in] */ DWORD dwBindVerb,
			/* [in] */ LONG grfBINDF,
			/* [in] */ BINDINFO *pBindInfo,
			/* [in] */ LPCOLESTR pszHeaders,
			/* [in] */ LPCOLESTR pszRedir,
			/* [in] */ UINT uiCP);

		virtual HRESULT STDMETHODCALLTYPE SetSecuritySite( 
            /* [unique][in] */ __RPC__in_opt IInternetSecurityMgrSite *pSite){return S_OK;}
        
        virtual HRESULT STDMETHODCALLTYPE GetSecuritySite( 
            /* [out] */ __RPC__deref_out_opt IInternetSecurityMgrSite **ppSite){return S_OK;}
        
        virtual HRESULT STDMETHODCALLTYPE MapUrlToZone( 
            /* [in] */ __RPC__in LPCWSTR pwszUrl,
            /* [out] */ __RPC__out DWORD *pdwZone,
			/* [in] */ DWORD dwFlags) {return S_OK;}
        
        virtual HRESULT STDMETHODCALLTYPE GetSecurityId( 
            /* [in] */ __RPC__in LPCWSTR pwszUrl,
            /* [size_is][out] */ __RPC__out_ecount_full(*pcbSecurityId) BYTE *pbSecurityId,
            /* [out][in] */ __RPC__inout DWORD *pcbSecurityId,
            /* [in] */ DWORD_PTR dwReserved) {return S_OK;}
        
        virtual HRESULT STDMETHODCALLTYPE ProcessUrlAction( 
            /* [in] */ __RPC__in LPCWSTR pwszUrl,
            /* [in] */ DWORD dwAction,
            /* [size_is][out] */ __RPC__out_ecount_full(cbPolicy) BYTE *pPolicy,
            /* [in] */ DWORD cbPolicy,
            /* [unique][in] */ __RPC__in_opt BYTE *pContext,
            /* [in] */ DWORD cbContext,
            /* [in] */ DWORD dwFlags,
			/* [in] */ DWORD dwReserved)
		{
			return S_OK;
		}
        
        virtual HRESULT STDMETHODCALLTYPE QueryCustomPolicy( 
            /* [in] */ __RPC__in LPCWSTR pwszUrl,
            /* [in] */ __RPC__in REFGUID guidKey,
            /* [size_is][size_is][out] */ __RPC__deref_out_ecount_full_opt(*pcbPolicy) BYTE **ppPolicy,
            /* [out] */ __RPC__out DWORD *pcbPolicy,
            /* [in] */ __RPC__in BYTE *pContext,
            /* [in] */ DWORD cbContext,
            /* [in] */ DWORD dwReserved) {return S_OK;}
        
        virtual HRESULT STDMETHODCALLTYPE SetZoneMapping( 
            /* [in] */ DWORD dwZone,
            /* [in] */ __RPC__in LPCWSTR lpszPattern,
            /* [in] */ DWORD dwFlags) {return S_OK;}
        
        virtual HRESULT STDMETHODCALLTYPE GetZoneMappings( 
            /* [in] */ DWORD dwZone,
            /* [out] */ __RPC__deref_out_opt IEnumString **ppenumString,
            /* [in] */ DWORD dwFlags) {return S_OK;}
		// ITranslateAccelerator
		// Duilib消息分发给WebBrowser
		virtual LRESULT TranslateAccelerator( MSG *pMsg );
	};
} // namespace DuiLib
#endif // __UIWEBBROWSER_H__
  • 代码解释:

    • CWebBrowserUI()

      构造函数,用于初始化CWebBrowserUI类的实例。

      virtual ~CWebBrowserUI()

      析构函数,用于在类的实例被销毁时进行清理工作。

      SetHomePage(LPCTSTR lpszUrl)

      设置浏览器控件的首页URL。

      GetHomePage()

      获取当前设置的首页URL。

      SetAutoNavigation(bool bAuto = TRUE)

      设置是否在控件初始化时自动导航到首页。

      IsAutoNavigation()

      查询是否启用了在初始化时自动导航到首页的功能。

      SetWebBrowserEventHandler(CWebBrowserEventHandler* pEventHandler)

      设置一个事件处理器以处理浏览器控件的事件。

      Navigate2(LPCTSTR lpszUrl)

      导航到一个新的URL。

      Refresh()

      刷新当前显示的网页。

      Refresh2(int Level)

      以指定的刷新级别刷新当前页面。

      GoBack()

      导航到浏览器的上一个页面。

      GoForward()

      导航到浏览器的下一个页面。

      NavigateHomePage()

      导航到设置的首页URL。

      NavigateUrl(LPCTSTR lpszUrl)

      导航到指定的URL。

      DoCreateControl()

      在内部创建和初始化Web浏览器控件。

      GetWebBrowser2()

      获取IWebBrowser2接口的指针,允许直接访问底层浏览器控件。

      GetHtmlWindow()

      获取IDispatch接口的指针,用于访问HTML窗口对象。

      FindId(IDispatch *pObj, LPOLESTR pName)

      在给定的IDispatch对象中查找一个具有指定名称的成员的ID。

      InvokeMethod(IDispatch *pObj, LPOLESTR pMethod, VARIANT *pVarResult, VARIANT *ps, int cArgs)

      调用IDispatch对象上的一个方法。

      GetProperty(IDispatch *pObj, LPOLESTR pName, VARIANT *pValue)

      获取IDispatch对象的一个属性值。

      SetProperty(IDispatch *pObj, LPOLESTR pName, VARIANT *pValue)

      设置IDispatch对象的一个属性值。

      ReleaseControl()

      释放浏览器控件和相关资源。

      RegisterEventHandler(BOOL inAdvise)

      注册或注销浏览器事件处理器。

      SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)

      设置控件的一个属性。

      接下来的方法都是接口方法,主要用于提供浏览器控件的各种行为和功能的定制:

      AddRef(), Release(), QueryInterface()

      这些是COM对象的标准方法,用于管理对象的生命周期和接口查询。

      GetTypeInfoCount(), GetTypeInfo(), GetIDsOfNames(), Invoke()

      这些方法是IDispatch接口的一部分,用于提供动态类型信息和调用功能。

      ShowContextMenu(), GetHostInfo(), ShowUI(), HideUI(), UpdateUI(), EnableModeless(), OnDocWindowActivate(), OnFrameWindowActivate(), ResizeBorder(), TranslateAccelerator(), GetOptionKeyPath(), GetDropTarget(), GetExternal(), TranslateUrl(), FilterDataObject()

      这些方法属于IDocHostUIHandler接口,用于自定义和控制浏览器UI和行为。

      QueryService()

      属于IServiceProvider接口,用于查询特定的服务。

      QueryStatus(), Exec()

      这些方法属于IOleCommandTarget接口,用于执行和查询命令状态。

      安全管理接口方法 (SetSecuritySite(), GetSecuritySite(), MapUrlToZone(), GetSecurityId(), ProcessUrlAction(), QueryCustomPolicy(), SetZoneMapping(), GetZoneMappings())

      这些属于IInternetSecurityManager接口。

    • 成员变量

      • m_pWebBrowser2: 指向IWebBrowser2的指针,这是COM接口提供的Web浏览器控件接口,允许对浏览器进行各种操作,如导航、刷新等。
      • _pHtmlWnd2: 指向IHTMLWindow2的指针,这是HTML文档的窗口对象,提供对文档窗口的操作,如执行脚本等。
      • m_dwRef: 对象的引用计数。
      • m_dwCookie: 事件处理程序注册时返回的cookie,用于之后注销事件处理程序。
      • m_sHomePage: 存储浏览器的首页URL。
      • m_bAutoNavi: 指示是否在控件初始化时自动导航到首页。
      • m_pWebBrowserEventHandler: 指向CWebBrowserEventHandler的指针,这是自定义的事件处理器,用于处理浏览器事件。
    • 方法和接口解释

      • 构造函数和析构函数: 初始化和清理类实例时调用。
      • SetHomePage / GetHomePage: 设置和获取浏览器的首页URL。
      • SetAutoNavigation / IsAutoNavigation: 控制浏览器是否自动导航到首页。
      • SetWebBrowserEventHandler: 设置处理浏览器事件的自定义事件处理器。
      • Navigate2: 导航到指定的URL。
      • Refresh / Refresh2: 刷新当前页面。
      • GoBack / GoForward: 浏览器后退和前进。
      • NavigateHomePage / NavigateUrl: 导航到首页或指定URL。
      • DoCreateControl: 创建ActiveX控件实例。
      • GetWebBrowser2: 获取IWebBrowser2接口的指针。
      • GetHtmlWindow: 获取IDispatch接口的指针,通常用于执行JavaScript代码。
      • FindId / InvokeMethod / GetProperty / SetProperty: 用于通过IDispatch接口与ActiveX控件交互,包括查找方法或属性的ID、调用方法、获取或设置属性。
    • 事件处理方法

      • BeforeNavigate2 / NavigateError / NavigateComplete2: 在导航过程中的不同阶段触发。
      • ProgressChange: 在页面加载进度变化时触发。
      • NewWindow3: 在尝试打开新窗口时触发。
      • CommandStateChange / TitleChange / DocumentComplete: 分别在浏览器命令状态改变、标题变化和文档加载完成时触发。
    • 接口实现

      • IDocHostUIHandler: 提供一组方法用于托管UI,包括处理上下文菜单、获取主机信息、显示或隐藏UI等。
      • IServiceProvider: 允许请求额外的接口服务。
      • IOleCommandTarget: 提供执行命令的能力。
      • IDispatch: 提供对对象的方法和属性的访问。
      • ITranslateAccelerator: 处理键盘消息,如快捷键。
    • 特殊接口和方法

      • virtual LRESULT TranslateAccelerator(MSG *pMsg): 这是一个重载方法,用于处理传递给Web浏览器控件的键盘消息。它允许开发者自定义快捷键或其他键盘操作的处理逻辑。
      • IInternetSecurityManager: 通过实现此接口,CWebBrowserUI可以自定义安全策略,包括如何处理URL的安全区域映射、安全ID的获取、URL动作的处理等。这些方法通常返回S_OK,表示采用默认行为,但开发者可以重写这些方法以提供定制的安全。
    • 接口实现

      1. virtual LPCTSTR GetClass() const;

      此方法返回当前控件的类名。它是一个虚拟方法,意味着派生类可以重写它以提供特定的类名。这个方法通常用于反射或类型检查,帮助确定对象的具体类型。

      2. virtual LPVOID GetInterface(LPCTSTR pstrName);

      这个方法用于查询对象支持的接口。给定一个接口名称pstrName,如果该对象实现了相应的接口,则返回指向接口的指针;否则返回nullptr。这是一种动态查询接口的机制,允许在运行时根据名称获取对象的特定接口。

      IUnknown接口

      IUnknown是所有COM接口的基础,提供了对象生命周期管理(引用计数)和接口查询的基本方法。CWebBrowserUI作为一个COM对象,实现了以下IUnknown方法:

      3. STDMETHOD_(ULONG,AddRef)();

      这个方法用于增加对象的引用计数。每当有新的持有者(如指针或引用)时,都应该调用AddRef以表明对象被额外引用,这有助于管理对象的生命周期。

      4. STDMETHOD_(ULONG,Release)();

      AddRef相对,这个方法用于减少对象的引用计数。当持有对象的代码不再需要对象时,应该调用Release。如果引用计数达到0,对象将自我销毁。

      5. STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObject);

      这是COM的接口查询方法,用于获取对象支持的接口。给定一个接口IDriid,如果对象实现了该接口,则ppvObject返回指向接口的指针,并返回成功的HRESULT值;否则返回失败。

      IDispatch接口

      IDispatch接口使得对象能够通过名字或ID动态调用其方法,这是ActiveX控件和脚本语言交互的基础。

      6. virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(__RPC__out UINT *pctinfo);

      这个方法用于获取对象提供的类型信息数量。对于大多数实现,如果对象支持自我描述(type info),这个值通常是1。

      7. virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, __RPC__deref_out_opt ITypeInfo **ppTInfo);

      提供对象的类型信息,允许调用者获取有关对象的接口和属性的详细信息。iTInfo是索引值(对于只有一个类型信息的对象,此值为0),lcid指定了本地化信息,ppTInfo是返回的类型信息对象。

      8. virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(__RPC__in REFIID riid, __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames, UINT cNames, LCID lcid, __RPC__out_ecount_full(cNames) DISPID *rgDispId);

      将一组名称转换为它们对应的DISPID(标识符)。这使得可以通过名称动态调用方法或访问属性。

      9. virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);

      执行由dispIdMember指定的方法或访问属性。riid通常是IID_NULLlcid用于指定本地化信息,wFlags指定是调用方法还是访问属性,pDispParams包含方法参数,pVarResult返回结果,pExcepInfo在发生异常时返回异常

      1. IDocHostUIHandler

      这个接口为ActiveX控件宿主提供了一组方法,使宿主能够影响或控制浏览器控件的UI元素。具体来说,包括:

      • ShowContextMenu: 控制是否显示上下文菜单,以及如何显示。
      • GetHostInfo: 获取宿主UI的特性和偏好设置。
      • ShowUI: 在显示浏览器UI(如对话框)时由宿主处理。
      • HideUI: 要求宿主隐藏其用户界面。
      • UpdateUI: 通知宿主更新其用户界面。
      • EnableModeless: 启用或禁用模式对话框。
      • OnDocWindowActivate / OnFrameWindowActivate: 文档或框架窗口激活时的处理。
      • ResizeBorder: 在浏览器控件周围调整边框大小。
      • TranslateAccelerator: 处理键盘快捷键消息。
      • GetOptionKeyPath: 获取注册表中用于存储用户选项的路径。
      • GetDropTarget: 自定义拖放操作。
      • GetExternal: 允许访问宿主的对象模型。
      • TranslateUrl: 转换URL。
      • FilterDataObject: 过滤传递给浏览器控件的数据对象。
      2. IServiceProvider

      这个接口允许对象声明它能提供哪些服务。具体来说,它使得控件可以请求额外的接口服务,如:

      • QueryService: 请求一个服务(接口),如获取浏览器的其他接口引用。
      3. IOleCommandTarget

      这个接口用于处理命令消息,允许执行命令或查询命令的状态。主要方法包括:

      • QueryStatus: 查询特定命令的状态。
      • Exec: 执行一个命令。
      4. IDispatch

      这个接口提供了一种机制,允许从外部调用对象的方法或访问其属性。主要用于自动化和脚本语言。具体方法包括:

      • GetTypeInfoCount / GetTypeInfo: 获取类型信息。
      • GetIDsOfNames: 将方法名或属性名映射到其对应的ID。
      • Invoke: 调用方法或访问属性。
      5. ITranslateAccelerator

      这个接口处理传递给控件的键盘消息,如快捷键或命令键。它提供了:

      • TranslateAccelerator: 方法允许开发者自定义快捷键或其他键盘操作的处理逻辑。
    • 特殊接口和方法

      virtual LRESULT TranslateAccelerator(MSG *pMsg)

      这是一个虚拟方法,用于处理传递给Web浏览器控件的键盘消息。它允许开发者在浏览器控件接收到键盘消息前拦截这些消息,并根据需要进行处理,比如实现特定的快捷键功能。

      IInternetSecurityManager

      通过实现此接口,CWebBrowserUI可以自定义与安全相关的策略和行为,这些方法通常包括:

      • SetSecuritySite / GetSecuritySite: 设置或获取安全站点。
      • MapUrlToZone: 将URL映射到一个安全区域。
      • GetSecurityId: 获取URL的安全ID。
      • ProcessUrlAction: 处理对特定URL的操作请求,如运行脚本、下载文件等。
      • QueryCustomPolicy: 查询特定URL的自定义安全策略。
      • SetZoneMapping / GetZoneMappings:

    2.2、CWebBrowserUI类的接口定义

定义了CWebBrowserUI类,一个基于DuiLib框架的组件,旨在为基于DuiLib开发的应用程序提供内嵌Web浏览器功能。这个类通过继承和实现多个COM接口与ActiveX控件(特别是Web浏览器控件)交互,实现了Web内容的显示和管理。

#include "StdAfx.h"
#include "UIWebBrowser.h"
#include <atlconv.h>
#include <atlcomcli.h>
#include "../Utils/downloadmgr.h"
#include <mshtml.h>

namespace DuiLib
{
	
	//
	IMPLEMENT_DUICONTROL(CWebBrowserUI)

		CWebBrowserUI::CWebBrowserUI()
		: m_pWebBrowser2(NULL)
		, _pHtmlWnd2(NULL)
		, m_pWebBrowserEventHandler(NULL)
		, m_bAutoNavi(false)
		, m_dwRef(0)
		, m_dwCookie(0)
	{
		m_clsid=CLSID_WebBrowser;
		m_sHomePage.Empty();
	}

	bool CWebBrowserUI::DoCreateControl()
	{
		if (!CActiveXUI::DoCreateControl())
			return false;
		GetManager()->AddTranslateAccelerator(this);
		GetControl(IID_IWebBrowser2,(LPVOID*)&m_pWebBrowser2);
		if ( m_bAutoNavi && !m_sHomePage.IsEmpty())
		{
			this->Navigate2(m_sHomePage);
		}
		RegisterEventHandler(TRUE);
		return true;
	}

	void CWebBrowserUI::ReleaseControl()
	{
		m_bCreated=false;
		GetManager()->RemoveTranslateAccelerator(this);
		RegisterEventHandler(FALSE);
	}

	CWebBrowserUI::~CWebBrowserUI()
	{
		ReleaseControl();
	}

	STDMETHODIMP CWebBrowserUI::GetTypeInfoCount( UINT *iTInfo )
	{
		*iTInfo = 0;
		return E_NOTIMPL;
	}

	STDMETHODIMP CWebBrowserUI::GetTypeInfo( UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo )
	{
		return E_NOTIMPL;
	}

	STDMETHODIMP CWebBrowserUI::GetIDsOfNames( REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid,DISPID *rgDispId )
	{
		return E_NOTIMPL;
	}

	STDMETHODIMP CWebBrowserUI::Invoke( DISPID dispIdMember, REFIID riid, LCID lcid,WORD wFlags, DISPPARAMS* pDispParams,VARIANT* pVarResult, EXCEPINFO* pExcepInfo,UINT* puArgErr )
	{
		if ((riid != IID_NULL))
			return E_INVALIDARG;

		switch(dispIdMember)
		{
		case DISPID_BEFORENAVIGATE2:
			BeforeNavigate2(
				pDispParams->rgvarg[6].pdispVal,
				pDispParams->rgvarg[5].pvarVal,
				pDispParams->rgvarg[4].pvarVal,
				pDispParams->rgvarg[3].pvarVal,
				pDispParams->rgvarg[2].pvarVal,
				pDispParams->rgvarg[1].pvarVal,
				pDispParams->rgvarg[0].pboolVal);
			break;
		case DISPID_COMMANDSTATECHANGE:
			CommandStateChange(
				pDispParams->rgvarg[1].lVal,
				pDispParams->rgvarg[0].boolVal);
			break;
		case DISPID_NAVIGATECOMPLETE2:
			NavigateComplete2(
				pDispParams->rgvarg[1].pdispVal,
				pDispParams->rgvarg[0].pvarVal);
			break;
		case DISPID_NAVIGATEERROR:
			NavigateError(
				pDispParams->rgvarg[4].pdispVal,
				pDispParams->rgvarg[3].pvarVal,
				pDispParams->rgvarg[2].pvarVal,
				pDispParams->rgvarg[1].pvarVal,
				pDispParams->rgvarg[0].pboolVal);
			break;
		case DISPID_STATUSTEXTCHANGE:
			break;
			//  	case DISPID_NEWWINDOW2:
			//  		break;
		case DISPID_NEWWINDOW3:
			NewWindow3(
				pDispParams->rgvarg[4].ppdispVal,
				pDispParams->rgvarg[3].pboolVal,
				pDispParams->rgvarg[2].uintVal,
				pDispParams->rgvarg[1].bstrVal,
				pDispParams->rgvarg[0].bstrVal);
			break;
		case DISPID_TITLECHANGE:
			{
				TitleChange(pDispParams->rgvarg[0].bstrVal);
				break;
			}
		case DISPID_DOCUMENTCOMPLETE:
			{
				DocumentComplete(
					pDispParams->rgvarg[1].pdispVal,
					pDispParams->rgvarg[0].pvarVal);

				break;
			}
		default:
			return DISP_E_MEMBERNOTFOUND;
		}
		return S_OK;
	}

	STDMETHODIMP CWebBrowserUI::QueryInterface( REFIID riid, LPVOID *ppvObject )
	{
		*ppvObject = NULL;

		if( riid == IID_IDocHostUIHandler)
			*ppvObject = static_cast<IDocHostUIHandler*>(this);
		else if( riid == IID_IDispatch)
			*ppvObject = static_cast<IDispatch*>(this);
		else if( riid == IID_IServiceProvider)
			*ppvObject = static_cast<IServiceProvider*>(this);
		else if(riid == IID_IInternetSecurityManager ) {
			*ppvObject = static_cast<IInternetSecurityManager*>(this);
		}
		else if (riid == IID_IOleCommandTarget)
			*ppvObject = static_cast<IOleCommandTarget*>(this);

		if( *ppvObject != NULL )
			AddRef();
		return *ppvObject == NULL ? E_NOINTERFACE : S_OK;
	}

	STDMETHODIMP_(ULONG) CWebBrowserUI::AddRef()
	{
		InterlockedIncrement(&m_dwRef); 
		return m_dwRef;
	}

	STDMETHODIMP_(ULONG) CWebBrowserUI::Release()
	{
		ULONG ulRefCount = InterlockedDecrement(&m_dwRef);
		return ulRefCount; 
	}

	void CWebBrowserUI::Navigate2( LPCTSTR lpszUrl )
	{
		if (lpszUrl == NULL)
			return;

		if (m_pWebBrowser2)
		{
			CDuiVariant url;
			url.vt=VT_BSTR;
			url.bstrVal=T2BSTR(lpszUrl);
			HRESULT hr = m_pWebBrowser2->Navigate2(&url, NULL, NULL, NULL, NULL);
		}
	}

	void CWebBrowserUI::Refresh()
	{
		if (m_pWebBrowser2)
		{
			m_pWebBrowser2->Refresh();
		}
	}
	void CWebBrowserUI::GoBack()
	{
		if (m_pWebBrowser2)
		{
			m_pWebBrowser2->GoBack();
		}
	}
	void CWebBrowserUI::GoForward()
	{
		if (m_pWebBrowser2)
		{
			m_pWebBrowser2->GoForward();
		}
	}
	/// DWebBrowserEvents2
	void CWebBrowserUI::BeforeNavigate2( IDispatch *pDisp,VARIANT *&url,VARIANT *&Flags,VARIANT *&TargetFrameName,VARIANT *&PostData,VARIANT *&Headers,VARIANT_BOOL *&Cancel )
	{
		if (m_pWebBrowserEventHandler)
		{
			m_pWebBrowserEventHandler->BeforeNavigate2(this, pDisp,url,Flags,TargetFrameName,PostData,Headers,Cancel);
		}
	}

	void CWebBrowserUI::NavigateError( IDispatch *pDisp,VARIANT * &url,VARIANT *&TargetFrameName,VARIANT *&StatusCode,VARIANT_BOOL *&Cancel )
	{
		if (m_pWebBrowserEventHandler)
		{
			m_pWebBrowserEventHandler->NavigateError(this, pDisp,url,TargetFrameName,StatusCode,Cancel);
		}
	}

	void CWebBrowserUI::NavigateComplete2( IDispatch *pDisp,VARIANT *&url )
	{
		CComPtr<IDispatch> spDoc;   
		m_pWebBrowser2->get_Document(&spDoc);   

		if (spDoc)
		{   
			CComQIPtr<ICustomDoc, &IID_ICustomDoc> spCustomDoc(spDoc);   
			if (spCustomDoc)   
				spCustomDoc->SetUIHandler(this);   
		}

		if (m_pWebBrowserEventHandler)
		{
			m_pWebBrowserEventHandler->NavigateComplete2(this, pDisp,url);
		}
	}

	void CWebBrowserUI::ProgressChange( LONG nProgress, LONG nProgressMax )
	{
		if (m_pWebBrowserEventHandler)
		{
			m_pWebBrowserEventHandler->ProgressChange(this, nProgress,nProgressMax);
		}
	}

	void CWebBrowserUI::NewWindow3( IDispatch **pDisp, VARIANT_BOOL *&Cancel, DWORD dwFlags, BSTR bstrUrlContext, BSTR bstrUrl )
	{
		if (m_pWebBrowserEventHandler)
		{
			m_pWebBrowserEventHandler->NewWindow3(this, pDisp,Cancel,dwFlags,bstrUrlContext,bstrUrl);
		}
	}
	void CWebBrowserUI::CommandStateChange(long Command,VARIANT_BOOL Enable)
	{
		if (m_pWebBrowserEventHandler)
		{
			m_pWebBrowserEventHandler->CommandStateChange(this, Command,Enable);
		}
	}

	void CWebBrowserUI::TitleChange(BSTR bstrTitle)
	{
		if (m_pWebBrowserEventHandler)
		{
			m_pWebBrowserEventHandler->TitleChange(this, bstrTitle);
		}
	}

	void CWebBrowserUI::DocumentComplete(IDispatch *pDisp, VARIANT *&url)
	{
		if (m_pWebBrowserEventHandler)
		{
			m_pWebBrowserEventHandler->DocumentComplete(this, pDisp, url);
		}
	}

	// IDownloadManager
	STDMETHODIMP CWebBrowserUI::Download( /* [in] */ IMoniker *pmk, /* [in] */ IBindCtx *pbc, /* [in] */ DWORD dwBindVerb, /* [in] */ LONG grfBINDF, /* [in] */ BINDINFO *pBindInfo, /* [in] */ LPCOLESTR pszHeaders, /* [in] */ LPCOLESTR pszRedir, /* [in] */ UINT uiCP )
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->Download(this, pmk,pbc,dwBindVerb,grfBINDF,pBindInfo,pszHeaders,pszRedir,uiCP);
		}
		return S_OK;
	}

	// IDocHostUIHandler
	STDMETHODIMP CWebBrowserUI::ShowContextMenu( DWORD dwID, POINT* pptPosition, IUnknown* pCommandTarget, IDispatch* pDispatchObjectHit )
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->ShowContextMenu(this, dwID,pptPosition,pCommandTarget,pDispatchObjectHit);
		}
		return S_FALSE;
	}

	STDMETHODIMP CWebBrowserUI::GetHostInfo( DOCHOSTUIINFO* pInfo )
	{
		if (pInfo != NULL) {
			pInfo->dwFlags |= DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_NO3DOUTERBORDER;
		}
		if (m_pWebBrowserEventHandler) {
			return m_pWebBrowserEventHandler->GetHostInfo(this, pInfo);
		}
		return S_OK;
	}

	STDMETHODIMP CWebBrowserUI::ShowUI( DWORD dwID, IOleInPlaceActiveObject* pActiveObject, IOleCommandTarget* pCommandTarget, IOleInPlaceFrame* pFrame, IOleInPlaceUIWindow* pDoc )
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->ShowUI(this, dwID,pActiveObject,pCommandTarget,pFrame,pDoc);
		}
		return S_OK;
	}

	STDMETHODIMP CWebBrowserUI::HideUI()
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->HideUI(this);
		}
		return S_OK;
	}

	STDMETHODIMP CWebBrowserUI::UpdateUI()
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->UpdateUI(this);
		}
		return S_OK;
	}

	STDMETHODIMP CWebBrowserUI::EnableModeless( BOOL fEnable )
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->EnableModeless(this, fEnable);
		}
		return E_NOTIMPL;
	}

	STDMETHODIMP CWebBrowserUI::OnDocWindowActivate( BOOL fActivate )
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->OnDocWindowActivate(this, fActivate);
		}
		return E_NOTIMPL;
	}

	STDMETHODIMP CWebBrowserUI::OnFrameWindowActivate( BOOL fActivate )
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->OnFrameWindowActivate(this, fActivate);
		}
		return E_NOTIMPL;
	}

	STDMETHODIMP CWebBrowserUI::ResizeBorder( LPCRECT prcBorder, IOleInPlaceUIWindow* pUIWindow, BOOL fFrameWindow )
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->ResizeBorder(this, prcBorder,pUIWindow,fFrameWindow);
		}
		return E_NOTIMPL;
	}

	STDMETHODIMP CWebBrowserUI::TranslateAccelerator( LPMSG lpMsg, const GUID* pguidCmdGroup, DWORD nCmdID )
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->TranslateAccelerator(this, lpMsg,pguidCmdGroup,nCmdID);
		}
		return S_FALSE;
	}

	LRESULT CWebBrowserUI::TranslateAccelerator( MSG *pMsg )
	{
		if(pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST)
			return S_FALSE;

		if( m_pWebBrowser2 == NULL )
			return E_NOTIMPL;

		// 当前Web窗口不是焦点,不处理加速键
		BOOL bIsChild = FALSE;
		HWND hTempWnd = NULL;
		HWND hWndFocus = ::GetFocus();

		hTempWnd = hWndFocus;
		while(hTempWnd != NULL)
		{
			if(hTempWnd == m_hwndHost)
			{
				bIsChild = TRUE;
				break;
			}
			hTempWnd = ::GetParent(hTempWnd);
		}
		if(!bIsChild)
			return S_FALSE;

		IOleInPlaceActiveObject *pObj;
		if (FAILED(m_pWebBrowser2->QueryInterface(IID_IOleInPlaceActiveObject, (LPVOID *)&pObj)))
			return S_FALSE;

		HRESULT hResult = pObj->TranslateAccelerator(pMsg);
		pObj->Release();
		return hResult;
	}

	STDMETHODIMP CWebBrowserUI::GetOptionKeyPath( LPOLESTR* pchKey, DWORD dwReserved )
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->GetOptionKeyPath(this, pchKey,dwReserved);
		}
		return E_NOTIMPL;
	}

	STDMETHODIMP CWebBrowserUI::GetDropTarget( IDropTarget* pDropTarget, IDropTarget** ppDropTarget )
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->GetDropTarget(this, pDropTarget,ppDropTarget);
		}
		return S_FALSE;	// 使用系统拖拽
	}

	STDMETHODIMP CWebBrowserUI::GetExternal( IDispatch** ppDispatch )
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->GetExternal(this, ppDispatch);
		}
		return S_FALSE;
	}

	STDMETHODIMP CWebBrowserUI::TranslateUrl( DWORD dwTranslate, OLECHAR* pchURLIn, OLECHAR** ppchURLOut )
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->TranslateUrl(this, dwTranslate,pchURLIn,ppchURLOut);
		}
		else
		{
			*ppchURLOut = 0;
			return E_NOTIMPL;
		}
	}

	STDMETHODIMP CWebBrowserUI::FilterDataObject( IDataObject* pDO, IDataObject** ppDORet )
	{
		if (m_pWebBrowserEventHandler)
		{
			return m_pWebBrowserEventHandler->FilterDataObject(this, pDO,ppDORet);
		}
		else
		{
			*ppDORet = 0;
			return E_NOTIMPL;
		}
	}

	void CWebBrowserUI::SetWebBrowserEventHandler( CWebBrowserEventHandler* pEventHandler )
	{
		if ( pEventHandler!=NULL && m_pWebBrowserEventHandler!=pEventHandler)
			m_pWebBrowserEventHandler=pEventHandler;
	}

	void CWebBrowserUI::Refresh2( int Level )
	{
		CDuiVariant vLevel;
		vLevel.vt=VT_I4;
		vLevel.intVal=Level;
		m_pWebBrowser2->Refresh2(&vLevel);
	}

	void CWebBrowserUI::SetAttribute( LPCTSTR pstrName, LPCTSTR pstrValue )
	{
		if (_tcsicmp(pstrName, _T("homepage")) == 0)
		{
			m_sHomePage = pstrValue;
		}
		else if (_tcsicmp(pstrName, _T("autonavi"))==0)
		{
			m_bAutoNavi = (_tcsicmp(pstrValue, _T("true")) == 0);
		}
		else
			CActiveXUI::SetAttribute(pstrName, pstrValue);
	}

	void CWebBrowserUI::NavigateHomePage()
	{
		if (!m_sHomePage.IsEmpty())
			this->NavigateUrl(m_sHomePage);
	}

	void CWebBrowserUI::NavigateUrl( LPCTSTR lpszUrl )
	{
		if (m_pWebBrowser2 && lpszUrl)
		{
			m_pWebBrowser2->Navigate((BSTR)SysAllocString(T2BSTR(lpszUrl)),NULL,NULL,NULL,NULL);
		}
	}

	LPCTSTR CWebBrowserUI::GetClass() const
	{
		return _T("WebBrowserUI");
	}

	LPVOID CWebBrowserUI::GetInterface( LPCTSTR pstrName )
	{
		if( _tcsicmp(pstrName, DUI_CTR_WEBBROWSER) == 0 ) return static_cast<CWebBrowserUI*>(this);
		return CActiveXUI::GetInterface(pstrName);
	}

	void CWebBrowserUI::SetHomePage( LPCTSTR lpszUrl )
	{
		m_sHomePage.Format(_T("%s"),lpszUrl);
	}

	LPCTSTR CWebBrowserUI::GetHomePage()
	{
		return m_sHomePage;
	}

	void CWebBrowserUI::SetAutoNavigation( bool bAuto /*= TRUE*/ )
	{
		if (m_bAutoNavi==bAuto)	return;

		m_bAutoNavi=bAuto;
	}

	bool CWebBrowserUI::IsAutoNavigation()
	{
		return m_bAutoNavi;
	}

	STDMETHODIMP CWebBrowserUI::QueryService( REFGUID guidService, REFIID riid, void** ppvObject )
	{
		HRESULT hr = E_NOINTERFACE;
		*ppvObject = NULL;

		if ( guidService == SID_SDownloadManager && riid == IID_IDownloadManager)
		{
			*ppvObject = this;
			return S_OK;
		}
		if(guidService == SID_SInternetSecurityManager && riid == IID_IInternetSecurityManager) {
			*ppvObject = this;
			return S_OK;
		}
		return hr;
	}

	HRESULT CWebBrowserUI::RegisterEventHandler( BOOL inAdvise )
	{
		CComPtr<IWebBrowser2> pWebBrowser;
		CComPtr<IConnectionPointContainer>  pCPC;
		CComPtr<IConnectionPoint> pCP;
		HRESULT hr = GetControl(IID_IWebBrowser2, (void**)&pWebBrowser);
		if (FAILED(hr))
			return hr;
		hr=pWebBrowser->QueryInterface(IID_IConnectionPointContainer,(void **)&pCPC);
		if (FAILED(hr))
			return hr;
		hr=pCPC->FindConnectionPoint(DIID_DWebBrowserEvents2,&pCP);
		if (FAILED(hr))
			return hr;

		if (inAdvise)
		{
			hr = pCP->Advise((IDispatch*)this, &m_dwCookie);
		}
		else
		{
			hr = pCP->Unadvise(m_dwCookie);
		}
		return hr; 
	}

	DISPID CWebBrowserUI::FindId( IDispatch *pObj, LPOLESTR pName )
	{
		DISPID id = 0;
		if(FAILED(pObj->GetIDsOfNames(IID_NULL,&pName,1,LOCALE_SYSTEM_DEFAULT,&id))) id = -1;
		return id;
	}

	HRESULT CWebBrowserUI::InvokeMethod( IDispatch *pObj, LPOLESTR pMehtod, VARIANT *pVarResult, VARIANT *ps, int cArgs )
	{
		DISPID dispid = FindId(pObj, pMehtod);
		if(dispid == -1) return E_FAIL;

		DISPPARAMS dispparams;
		dispparams.cArgs = cArgs;
		dispparams.rgvarg = ps;
		dispparams.cNamedArgs = 0;
		dispparams.rgdispidNamedArgs = NULL;

		return pObj->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispparams, pVarResult, NULL, NULL);
	}

	HRESULT CWebBrowserUI::GetProperty( IDispatch *pObj, LPOLESTR pName, VARIANT *pValue )
	{
		DISPID dispid = FindId(pObj, pName);
		if(dispid == -1) return E_FAIL;

		DISPPARAMS ps;
		ps.cArgs = 0;
		ps.rgvarg = NULL;
		ps.cNamedArgs = 0;
		ps.rgdispidNamedArgs = NULL;

		return pObj->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &ps, pValue, NULL, NULL);
	}

	HRESULT CWebBrowserUI::SetProperty( IDispatch *pObj, LPOLESTR pName, VARIANT *pValue )
	{
		DISPID dispid = FindId(pObj, pName);
		if(dispid == -1) return E_FAIL;

		DISPPARAMS ps;
		ps.cArgs = 1;
		ps.rgvarg = pValue;
		ps.cNamedArgs = 0;
		ps.rgdispidNamedArgs = NULL;

		return pObj->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &ps, NULL, NULL, NULL);
	}

	IDispatch* CWebBrowserUI::GetHtmlWindow()
	{
		IDispatch* pDp =  NULL;
		HRESULT hr;
		if (m_pWebBrowser2)
			hr=m_pWebBrowser2->get_Document(&pDp);

		if (FAILED(hr))
			return NULL;

		CComQIPtr<IHTMLDocument2> pHtmlDoc2 = pDp;

		if (pHtmlDoc2 == NULL)
			return NULL;

		hr=pHtmlDoc2->get_parentWindow(&_pHtmlWnd2);

		if (FAILED(hr))
			return NULL;

		IDispatch *pHtmlWindown = NULL;
		hr=_pHtmlWnd2->QueryInterface(IID_IDispatch, (void**)&pHtmlWindown);
		if (FAILED(hr))
			return NULL;

		return pHtmlWindown;
	}

	IWebBrowser2* CWebBrowserUI::GetWebBrowser2( void )
	{
		return m_pWebBrowser2;
	}

	HRESULT STDMETHODCALLTYPE CWebBrowserUI::QueryStatus( __RPC__in_opt const GUID *pguidCmdGroup, ULONG cCmds, __RPC__inout_ecount_full(cCmds ) OLECMD prgCmds[ ], __RPC__inout_opt OLECMDTEXT *pCmdText )
	{
		HRESULT hr = OLECMDERR_E_NOTSUPPORTED;
		return hr;
	}

	HRESULT STDMETHODCALLTYPE CWebBrowserUI::Exec( __RPC__in_opt const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, __RPC__in_opt VARIANT *pvaIn, __RPC__inout_opt VARIANT *pvaOut )
	{
		HRESULT hr = S_OK;

		if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup, CGID_DocHostCommandHandler))
		{

			switch (nCmdID) 
			{

			case OLECMDID_SHOWSCRIPTERROR:
				{
					IHTMLDocument2*             pDoc = NULL;
					IHTMLWindow2*               pWindow = NULL;
					IHTMLEventObj*              pEventObj = NULL;
					BSTR                        rgwszNames[5] = 
					{ 
						SysAllocString(L"errorLine"),
						SysAllocString(L"errorCharacter"),
						SysAllocString(L"errorCode"),
						SysAllocString(L"errorMessage"),
						SysAllocString(L"errorUrl")
					};
					DISPID                      rgDispIDs[5];
					VARIANT                     rgvaEventInfo[5];
					DISPPARAMS                  params;
					BOOL                        fContinueRunningScripts = true;
					int                         i;

					params.cArgs = 0;
					params.cNamedArgs = 0;

					// Get the document that is currently being viewed.
					hr = pvaIn->punkVal->QueryInterface(IID_IHTMLDocument2, (void **) &pDoc);    
					// Get document.parentWindow.
					hr = pDoc->get_parentWindow(&pWindow);
					pDoc->Release();
					// Get the window.event object.
					hr = pWindow->get_event(&pEventObj);
					// Get the error info from the window.event object.
					for (i = 0; i < 5; i++) 
					{  
						// Get the property's dispID.
						hr = pEventObj->GetIDsOfNames(IID_NULL, &rgwszNames[i], 1, 
							LOCALE_SYSTEM_DEFAULT, &rgDispIDs[i]);
						// Get the value of the property.
						hr = pEventObj->Invoke(rgDispIDs[i], IID_NULL,
							LOCALE_SYSTEM_DEFAULT,
							DISPATCH_PROPERTYGET, &params, &rgvaEventInfo[i],
							NULL, NULL);
						SysFreeString(rgwszNames[i]);
					}

					// At this point, you would normally alert the user with 
					// the information about the error, which is now contained
					// in rgvaEventInfo[]. Or, you could just exit silently.

					(*pvaOut).vt = VT_BOOL;
					if (fContinueRunningScripts)
					{
						// Continue running scripts on the page.
						(*pvaOut).boolVal = VARIANT_TRUE;
					}
					else
					{
						// Stop running scripts on the page.
						(*pvaOut).boolVal = VARIANT_FALSE;   
					} 
					break;
				}
			default:
				hr = OLECMDERR_E_NOTSUPPORTED;
				break;
			}
		}
		else
		{
			hr = OLECMDERR_E_UNKNOWNGROUP;
		}
		return (hr);
	}
}
  • 类成员变量

    • m_pWebBrowser2: 指向IWebBrowser2的指针,控制和管理Web浏览器。
    • _pHtmlWnd2: 指向IHTMLWindow2的指针,代表HTML文档的窗口。
    • m_pWebBrowserEventHandler: 自定义的事件处理器,处理浏览器事件。
    • m_bAutoNavi: 指示是否在控件初始化时自动导航到首页。
    • m_dwRef: 对象的引用计数,用于实现COM的引用计数机制。
    • m_dwCookie: 事件处理注册的cookie,用于后续事件处理注销。
    • m_sHomePage: 存储浏览器的首页URL。

    类方法

    • 构造函数和析构函数:初始化和释放类实例时调用。
    • DoCreateControl:创建并初始化Web浏览器控件。
    • ReleaseControl:释放Web浏览器控件资源。
    • Navigate2RefreshGoBackGoForwardNavigateUrl:提供基本的浏览器导航功能。
    • 事件处理方法(如BeforeNavigate2NavigateErrorNavigateComplete2等):处理来自Web浏览器控件的事件。
    • IDocHostUIHandler、IServiceProvider、IInternetSecurityManager等接口实现:自定义浏览器UI和行为、提供服务、管理安全策略等。
    • QueryInterface、AddRef、Release:实现COM接口的标准方法,用于接口查询和引用计数管理。

    COM接口实现

    类实现了多个COM接口,如IDocHostUIHandlerIServiceProviderIInternetSecurityManager等,以及IUnknownIDispatch的基本方法,允许它在COM环境中正常工作,同时提供了Web浏览器的高级控制和定制能力。

    特性和功能

    • 内嵌Web浏览:允许DuiLib应用程序内嵌Web页面,提供丰富的内容展示能力。
    • 自定义事件处理:通过设置事件处理器,开发者可以自定义对浏览器事件的响应。
    • 自定义UI和安全策略:实现相关接口可以自定义浏览器UI组件和安全策略,如禁用上下文菜单、管理安全区域等。
    • COM兼容:通过实现IUnknownIDispatch等接口,CWebBrowserUI可以作为COM组件使用,确保与其他COM对象的兼容性。
  • 这个类通过提供对Web浏览器控件的封装和控制,极大地扩展了基于DuiLib的应用程序的功能,允许开发者轻松集成Web内容和功能到自己的应用中。

2.3、CActiveXUI类的接口声明

CActiveXUI类是DuiLib框架的一部分,设计用于在DuiLib基于DirectUI的用户界面中嵌入和管理ActiveX控件。这个类提供了一个通用的接口来创建和操作任何ActiveX控件,使得它们可以被集成到DuiLib UI元素中,从而扩展应用程序的功能。

#ifndef __UIACTIVEX_H__
#define __UIACTIVEX_H__

#pragma once

struct IOleObject;


namespace DuiLib {
	/
	//

	class CActiveXCtrl;

	template< class T >
	class CSafeRelease
	{
	public:
		CSafeRelease(T* p) : m_p(p) { };
		~CSafeRelease() { if( m_p != NULL ) m_p->Release(); };
		T* Detach() { T* t = m_p; m_p = NULL; return t; };
		T* m_p;
	};

	/
	//

	class UILIB_API CActiveXUI : public CControlUI, public IMessageFilterUI
	{
		DECLARE_DUICONTROL(CActiveXUI)

		friend class CActiveXCtrl;
	public:
		CActiveXUI();
		virtual ~CActiveXUI();

		LPCTSTR GetClass() const;
		LPVOID GetInterface(LPCTSTR pstrName);

		HWND GetHostWindow() const;

		virtual bool IsDelayCreate() const;
		virtual void SetDelayCreate(bool bDelayCreate = true);
		virtual bool IsMFC() const;
		virtual void SetMFC(bool bMFC = false);

		bool CreateControl(const CLSID clsid);
		bool CreateControl(LPCTSTR pstrCLSID);
		HRESULT GetControl(const IID iid, LPVOID* ppRet);
		CLSID GetClisd() const;
		CDuiString GetModuleName() const;
		void SetModuleName(LPCTSTR pstrText);

		void SetVisible(bool bVisible = true);
		void SetInternVisible(bool bVisible = true);
		void SetPos(RECT rc, bool bNeedInvalidate = true);
		void Move(SIZE szOffset, bool bNeedInvalidate = true);
		bool DoPaint(HDC hDC, const RECT& rcPaint, CControlUI* pStopControl);

		void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);

		LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled);

	protected:
		virtual void ReleaseControl();
		virtual bool DoCreateControl();

	protected:
		CLSID m_clsid;
		CDuiString m_sModuleName;
		bool m_bCreated;
		bool m_bDelayCreate;
		bool m_bMFC;
		IOleObject* m_pUnk;
		CActiveXCtrl* m_pControl;
		HWND m_hwndHost;
	};

} // namespace DuiLib

#endif // __UIACTIVEX_H__

  • 类成员变量

    • m_clsid:存储ActiveX控件的CLSID(类标识符),用于创建控件实例。
    • m_sModuleName:控件所在的模块名,如果控件不是从标准位置加载,则需要此信息。
    • m_bCreated:标志位,指示控件是否已经创建。
    • m_bDelayCreate:标志位,指示控件是否延迟创建,直到需要显示时。
    • m_bMFC:标志位,指示是否在MFC环境中使用控件。
    • m_pUnk:指向控件的IOleObject接口的指针,用于控件的基本操作。
    • m_pControl:指向CActiveXCtrl的指针,这是一个辅助类,用于管理ActiveX控件的具体实现细节。
    • m_hwndHost:宿主窗口的句柄,ActiveX控件在此窗口中显示。

    类方法

    • 构造函数和析构函数:初始化类成员变量,释放资源。
    • CreateControl:通过CLSID或控件的ProgID创建ActiveX控件。
    • GetControl:获取指向已创建控件的特定接口的指针,例如IWebBrowser2
    • SetVisible/SetInternVisible:控制控件的可见性。
    • SetPos/Move:设置控件的位置和大小。
    • DoPaint:在指定的HDC上绘制控件。
    • SetAttribute:设置控件的属性,如模块名、延迟创建等。
    • MessageHandler:处理窗口消息。

    特点和功能

    • 通用ActiveX控件集成:提供了一个标准化的方法来在DuiLib应用程序中集成任何ActiveX控件。
    • 延迟创建:支持控件的延迟创建,有助于提高应用程序启动速度和响应性。
    • 消息过滤和事件处理:通过实现IMessageFilterUI接口,CActiveXUI能够处理和转发窗口消息给ActiveX控件,实现复杂的事件处理逻辑。
    • 灵活的控件管理:提供了丰富的接口来管理ActiveX控件的生命周期、可见性、位置和绘制等,使得控件的集成和操作更加灵活。
  • 总的来说,CActiveXUI类极大地简化了在DuiLib应用程序中使用ActiveX控件的复杂性,为开发者提供了一个强大、灵活的工具来扩展其应用程序的功能。通过这个类,开发者可以轻松地将各种ActiveX控件集成到基于DirectUI的用户界面中,从而提升用户体验和应用能力。

2.4、CActiveXUI类的接口定义

这段代码定义了几个与ActiveX控件集成相关的类:CActiveXWndCActiveXEnumCActiveXFrameWnd以及CActiveXCtrl。这些类共同作用于CActiveXUI类,以便在DuiLib框架中嵌入和管理ActiveX控件。下面详细解释每个类的接口和作用:

#include "StdAfx.h"

namespace DuiLib {

	/
	//
	//

	class CActiveXCtrl;


	/
	//
	//

	class CActiveXWnd : public CWindowWnd
	{
	public:
		CActiveXWnd() : m_iLayeredTick(0), m_bDrawCaret(false) {}
		HWND Init(CActiveXCtrl* pOwner, HWND hWndParent);

		LPCTSTR GetWindowClassName() const;
		void OnFinalMessage(HWND hWnd);

		LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);

	protected:
		void DoVerb(LONG iVerb);

		LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		LRESULT OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		LRESULT OnPrint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

	protected:
		enum { 
			DEFAULT_TIMERID = 20,
		};

		CActiveXCtrl* m_pOwner;
		int m_iLayeredTick;
		bool m_bDrawCaret;
	};


	/
	//
	//

	class CActiveXEnum : public IEnumUnknown
	{
	public:
		CActiveXEnum(IUnknown* pUnk) : m_pUnk(pUnk), m_dwRef(1), m_iPos(0)
		{
			m_pUnk->AddRef();
		}
		~CActiveXEnum()
		{
			m_pUnk->Release();
		}

		LONG m_iPos;
		ULONG m_dwRef;
		IUnknown* m_pUnk;

		STDMETHOD_(ULONG,AddRef)()
		{
			return ++m_dwRef;
		}
		STDMETHOD_(ULONG,Release)()
		{
			LONG lRef = --m_dwRef;
			if( lRef == 0 ) delete this;
			return lRef;
		}
		STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObject)
		{
			*ppvObject = NULL;
			if( riid == IID_IUnknown ) *ppvObject = static_cast<IEnumUnknown*>(this);
			else if( riid == IID_IEnumUnknown ) *ppvObject = static_cast<IEnumUnknown*>(this);
			if( *ppvObject != NULL ) AddRef();
			return *ppvObject == NULL ? E_NOINTERFACE : S_OK;
		}
		STDMETHOD(Next)(ULONG celt, IUnknown **rgelt, ULONG *pceltFetched)
		{
			if( pceltFetched != NULL ) *pceltFetched = 0;
			if( ++m_iPos > 1 ) return S_FALSE;
			*rgelt = m_pUnk;
			(*rgelt)->AddRef();
			if( pceltFetched != NULL ) *pceltFetched = 1;
			return S_OK;
		}
		STDMETHOD(Skip)(ULONG celt)
		{
			m_iPos += celt;
			return S_OK;
		}
		STDMETHOD(Reset)(void)
		{
			m_iPos = 0;
			return S_OK;
		}
		STDMETHOD(Clone)(IEnumUnknown **ppenum)
		{
			return E_NOTIMPL;
		}
	};


	/
	//
	//

	class CActiveXFrameWnd : public IOleInPlaceFrame
	{
	public:
		CActiveXFrameWnd(CActiveXUI* pOwner) : m_dwRef(1), m_pOwner(pOwner), m_pActiveObject(NULL)
		{
		}
		~CActiveXFrameWnd()
		{
			if( m_pActiveObject != NULL ) m_pActiveObject->Release();
		}

		ULONG m_dwRef;
		CActiveXUI* m_pOwner;
		IOleInPlaceActiveObject* m_pActiveObject;

		// IUnknown
		STDMETHOD_(ULONG,AddRef)()
		{
			return ++m_dwRef;
		}
		STDMETHOD_(ULONG,Release)()
		{
			ULONG lRef = --m_dwRef;
			if( lRef == 0 ) delete this;
			return lRef;
		}
		STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObject)
		{
			*ppvObject = NULL;
			if( riid == IID_IUnknown ) *ppvObject = static_cast<IOleInPlaceFrame*>(this);
			else if( riid == IID_IOleWindow ) *ppvObject = static_cast<IOleWindow*>(this);
			else if( riid == IID_IOleInPlaceFrame ) *ppvObject = static_cast<IOleInPlaceFrame*>(this);
			else if( riid == IID_IOleInPlaceUIWindow ) *ppvObject = static_cast<IOleInPlaceUIWindow*>(this);
			if( *ppvObject != NULL ) AddRef();
			return *ppvObject == NULL ? E_NOINTERFACE : S_OK;
		}  
		// IOleInPlaceFrameWindow
		STDMETHOD(InsertMenus)(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/)
		{
			return S_OK;
		}
		STDMETHOD(SetMenu)(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/)
		{
			return S_OK;
		}
		STDMETHOD(RemoveMenus)(HMENU /*hmenuShared*/)
		{
			return S_OK;
		}
		STDMETHOD(SetStatusText)(LPCOLESTR /*pszStatusText*/)
		{
			return S_OK;
		}
		STDMETHOD(EnableModeless)(BOOL /*fEnable*/)
		{
			return S_OK;
		}
		STDMETHOD(TranslateAccelerator)(LPMSG /*lpMsg*/, WORD /*wID*/)
		{
			return S_FALSE;
		}
		// IOleWindow
		STDMETHOD(GetWindow)(HWND* phwnd)
		{
			if( m_pOwner == NULL ) return E_UNEXPECTED;
			*phwnd = m_pOwner->GetManager()->GetPaintWindow();
			return S_OK;
		}
		STDMETHOD(ContextSensitiveHelp)(BOOL /*fEnterMode*/)
		{
			return S_OK;
		}
		// IOleInPlaceUIWindow
		STDMETHOD(GetBorder)(LPRECT /*lprectBorder*/)
		{
			return S_OK;
		}
		STDMETHOD(RequestBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/)
		{
			return INPLACE_E_NOTOOLSPACE;
		}
		STDMETHOD(SetBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/)
		{
			return S_OK;
		}
		STDMETHOD(SetActiveObject)(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR /*pszObjName*/)
		{
			if( pActiveObject != NULL ) pActiveObject->AddRef();
			if( m_pActiveObject != NULL ) m_pActiveObject->Release();
			m_pActiveObject = pActiveObject;
			return S_OK;
		}
	};

	/
	//

	class CActiveXCtrl :
		public IOleClientSite,
		public IOleInPlaceSiteWindowless,
		public IOleControlSite,
		public IObjectWithSite,
		public IOleContainer
	{
		friend class CActiveXUI;
		friend class CActiveXWnd;
	public:
		CActiveXCtrl();
		~CActiveXCtrl();

		// IUnknown
		STDMETHOD_(ULONG,AddRef)();
		STDMETHOD_(ULONG,Release)();
		STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObject);

		// IObjectWithSite
		STDMETHOD(SetSite)(IUnknown *pUnkSite);
		STDMETHOD(GetSite)(REFIID riid, LPVOID* ppvSite);

		// IOleClientSite
		STDMETHOD(SaveObject)(void);       
		STDMETHOD(GetMoniker)(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk);
		STDMETHOD(GetContainer)(IOleContainer** ppContainer);        
		STDMETHOD(ShowObject)(void);        
		STDMETHOD(OnShowWindow)(BOOL fShow);        
		STDMETHOD(RequestNewObjectLayout)(void);

		// IOleInPlaceSiteWindowless
		STDMETHOD(CanWindowlessActivate)(void);
		STDMETHOD(GetCapture)(void);
		STDMETHOD(SetCapture)(BOOL fCapture);
		STDMETHOD(GetFocus)(void);
		STDMETHOD(SetFocus)(BOOL fFocus);
		STDMETHOD(GetDC)(LPCRECT pRect, DWORD grfFlags, HDC* phDC);
		STDMETHOD(ReleaseDC)(HDC hDC);
		STDMETHOD(InvalidateRect)(LPCRECT pRect, BOOL fErase);
		STDMETHOD(InvalidateRgn)(HRGN hRGN, BOOL fErase);
		STDMETHOD(ScrollRect)(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip);
		STDMETHOD(AdjustRect)(LPRECT prc);
		STDMETHOD(OnDefWindowMessage)(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult);

		// IOleInPlaceSiteEx
		STDMETHOD(OnInPlaceActivateEx)(BOOL *pfNoRedraw, DWORD dwFlags);        
		STDMETHOD(OnInPlaceDeactivateEx)(BOOL fNoRedraw);       
		STDMETHOD(RequestUIActivate)(void);

		// IOleInPlaceSite
		STDMETHOD(CanInPlaceActivate)(void);       
		STDMETHOD(OnInPlaceActivate)(void);        
		STDMETHOD(OnUIActivate)(void);
		STDMETHOD(GetWindowContext)(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo);
		STDMETHOD(Scroll)(SIZE scrollExtant);
		STDMETHOD(OnUIDeactivate)(BOOL fUndoable);
		STDMETHOD(OnInPlaceDeactivate)(void);
		STDMETHOD(DiscardUndoState)( void);
		STDMETHOD(DeactivateAndUndo)( void);
		STDMETHOD(OnPosRectChange)(LPCRECT lprcPosRect);

		// IOleWindow
		STDMETHOD(GetWindow)(HWND* phwnd);
		STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode);

		// IOleControlSite
		STDMETHOD(OnControlInfoChanged)(void);      
		STDMETHOD(LockInPlaceActive)(BOOL fLock);       
		STDMETHOD(GetExtendedControl)(IDispatch** ppDisp);        
		STDMETHOD(TransformCoords)(POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags);       
		STDMETHOD(TranslateAccelerator)(MSG* pMsg, DWORD grfModifiers);
		STDMETHOD(OnFocus)(BOOL fGotFocus);
		STDMETHOD(ShowPropertyFrame)(void);

		// IOleContainer
		STDMETHOD(EnumObjects)(DWORD grfFlags, IEnumUnknown** ppenum);
		STDMETHOD(LockContainer)(BOOL fLock);

		// IParseDisplayName
		STDMETHOD(ParseDisplayName)(IBindCtx* pbc, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);

	protected:
		HRESULT CreateActiveXWnd();

	protected:
		LONG m_dwRef;
		CActiveXUI* m_pOwner;
		CActiveXWnd* m_pWindow;
		IUnknown* m_pUnkSite;
		IViewObject* m_pViewObject;
		IOleInPlaceObjectWindowless* m_pInPlaceObject;
		bool m_bLocked;
		bool m_bFocused;
		bool m_bCaptured;
		bool m_bUIActivated;
		bool m_bInPlaceActive;
		bool m_bWindowless;
	};

	CActiveXCtrl::CActiveXCtrl() : 
	m_dwRef(1), 
		m_pOwner(NULL), 
		m_pWindow(NULL),
		m_pUnkSite(NULL), 
		m_pViewObject(NULL),
		m_pInPlaceObject(NULL),
		m_bLocked(false), 
		m_bFocused(false),
		m_bCaptured(false),
		m_bWindowless(true),
		m_bUIActivated(false),
		m_bInPlaceActive(false)
	{
	}

	CActiveXCtrl::~CActiveXCtrl()
	{
		if( m_pWindow != NULL ) {
			::DestroyWindow(*m_pWindow);
			delete m_pWindow;
		}
		if( m_pUnkSite != NULL ) m_pUnkSite->Release();
		if( m_pViewObject != NULL ) m_pViewObject->Release();
		if( m_pInPlaceObject != NULL ) m_pInPlaceObject->Release();
	}

	STDMETHODIMP CActiveXCtrl::QueryInterface(REFIID riid, LPVOID *ppvObject)
	{
		*ppvObject = NULL;
		if( riid == IID_IUnknown )                       *ppvObject = static_cast<IOleWindow*>(this);
		else if( riid == IID_IOleClientSite )            *ppvObject = static_cast<IOleClientSite*>(this);
		else if( riid == IID_IOleInPlaceSiteWindowless ) *ppvObject = static_cast<IOleInPlaceSiteWindowless*>(this);
		else if( riid == IID_IOleInPlaceSiteEx )         *ppvObject = static_cast<IOleInPlaceSiteEx*>(this);
		else if( riid == IID_IOleInPlaceSite )           *ppvObject = static_cast<IOleInPlaceSite*>(this);
		else if( riid == IID_IOleWindow )                *ppvObject = static_cast<IOleWindow*>(this);
		else if( riid == IID_IOleControlSite )           *ppvObject = static_cast<IOleControlSite*>(this);
		else if( riid == IID_IOleContainer )             *ppvObject = static_cast<IOleContainer*>(this);
		else if( riid == IID_IObjectWithSite )           *ppvObject = static_cast<IObjectWithSite*>(this);
		if( *ppvObject != NULL ) AddRef();
		return *ppvObject == NULL ? E_NOINTERFACE : S_OK;
	}

	STDMETHODIMP_(ULONG) CActiveXCtrl::AddRef()
	{
		return ++m_dwRef;
	}

	STDMETHODIMP_(ULONG) CActiveXCtrl::Release()
	{
		LONG lRef = --m_dwRef;
		if( lRef == 0 ) delete this;
		return lRef;
	}

	STDMETHODIMP CActiveXCtrl::SetSite(IUnknown *pUnkSite)
	{
		DUITRACE(_T("AX: CActiveXCtrl::SetSite"));
		if( m_pUnkSite != NULL ) {
			m_pUnkSite->Release();
			m_pUnkSite = NULL;
		}
		if( pUnkSite != NULL ) {
			m_pUnkSite = pUnkSite;
			m_pUnkSite->AddRef();
		}
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::GetSite(REFIID riid, LPVOID* ppvSite)
	{
		DUITRACE(_T("AX: CActiveXCtrl::GetSite"));
		if( ppvSite == NULL ) return E_POINTER;
		*ppvSite = NULL;
		if( m_pUnkSite == NULL ) return E_FAIL;
		return m_pUnkSite->QueryInterface(riid, ppvSite);
	}

	STDMETHODIMP CActiveXCtrl::SaveObject(void)
	{
		DUITRACE(_T("AX: CActiveXCtrl::SaveObject"));
		return E_NOTIMPL;
	}

	STDMETHODIMP CActiveXCtrl::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk)
	{
		DUITRACE(_T("AX: CActiveXCtrl::GetMoniker"));
		if( ppmk != NULL ) *ppmk = NULL;
		return E_NOTIMPL;
	}

	STDMETHODIMP CActiveXCtrl::GetContainer(IOleContainer** ppContainer)
	{
		DUITRACE(_T("AX: CActiveXCtrl::GetContainer"));
		if( ppContainer == NULL ) return E_POINTER;
		*ppContainer = NULL;
		HRESULT Hr = E_NOTIMPL;
		if( m_pUnkSite != NULL ) Hr = m_pUnkSite->QueryInterface(IID_IOleContainer, (LPVOID*) ppContainer);
		if( FAILED(Hr) ) Hr = QueryInterface(IID_IOleContainer, (LPVOID*) ppContainer);
		return Hr;
	}

	STDMETHODIMP CActiveXCtrl::ShowObject(void)
	{
		DUITRACE(_T("AX: CActiveXCtrl::ShowObject"));
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		HDC hDC = ::GetDC(m_pOwner->m_hwndHost);
		if( hDC == NULL ) return E_FAIL;
		if( m_pViewObject != NULL ) m_pViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hDC, (RECTL*) &m_pOwner->m_rcItem, (RECTL*) &m_pOwner->m_rcItem, NULL, NULL);
		::ReleaseDC(m_pOwner->m_hwndHost, hDC);
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::OnShowWindow(BOOL fShow)
	{
		DUITRACE(_T("AX: CActiveXCtrl::OnShowWindow"));
		return E_NOTIMPL;
	}

	STDMETHODIMP CActiveXCtrl::RequestNewObjectLayout(void)
	{
		DUITRACE(_T("AX: CActiveXCtrl::RequestNewObjectLayout"));
		return E_NOTIMPL;
	}

	STDMETHODIMP CActiveXCtrl::CanWindowlessActivate(void)
	{
		DUITRACE(_T("AX: CActiveXCtrl::CanWindowlessActivate"));
		return S_OK;  // Yes, we can!!
	}

	STDMETHODIMP CActiveXCtrl::GetCapture(void)
	{
		DUITRACE(_T("AX: CActiveXCtrl::GetCapture"));
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		return m_bCaptured ? S_OK : S_FALSE;
	}

	STDMETHODIMP CActiveXCtrl::SetCapture(BOOL fCapture)
	{
		DUITRACE(_T("AX: CActiveXCtrl::SetCapture"));
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		m_bCaptured = (fCapture == TRUE);
		if( fCapture ) ::SetCapture(m_pOwner->m_hwndHost); else ::ReleaseCapture();
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::GetFocus(void)
	{
		DUITRACE(_T("AX: CActiveXCtrl::GetFocus"));
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		return m_bFocused ? S_OK : S_FALSE;
	}

	STDMETHODIMP CActiveXCtrl::SetFocus(BOOL fFocus)
	{
		DUITRACE(_T("AX: CActiveXCtrl::SetFocus"));
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		if( fFocus ) m_pOwner->SetFocus();
		m_bFocused = (fFocus == TRUE);
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::GetDC(LPCRECT pRect, DWORD grfFlags, HDC* phDC)
	{
		DUITRACE(_T("AX: CActiveXCtrl::GetDC"));
		if( phDC == NULL ) return E_POINTER;
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		if( m_bWindowless ) return S_FALSE;
		*phDC = ::GetDC(m_pOwner->m_hwndHost);
		if( (grfFlags & OLEDC_PAINTBKGND) != 0 ) {
			CDuiRect rcItem = m_pOwner->GetPos();
			if( !m_bWindowless ) rcItem.ResetOffset();
			::FillRect(*phDC, &rcItem, (HBRUSH) (COLOR_WINDOW + 1));
		}
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::ReleaseDC(HDC hDC)
	{
		DUITRACE(_T("AX: CActiveXCtrl::ReleaseDC"));
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		::ReleaseDC(m_pOwner->m_hwndHost, hDC);
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::InvalidateRect(LPCRECT pRect, BOOL fErase)
	{
		DUITRACE(_T("AX: CActiveXCtrl::InvalidateRect"));
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		if( m_pOwner->m_hwndHost == NULL ) return E_FAIL;
		return ::InvalidateRect(m_pOwner->m_hwndHost, pRect, fErase) ? S_OK : E_FAIL;
	}

	STDMETHODIMP CActiveXCtrl::InvalidateRgn(HRGN hRGN, BOOL fErase)
	{
		DUITRACE(_T("AX: CActiveXCtrl::InvalidateRgn"));
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		return ::InvalidateRgn(m_pOwner->m_hwndHost, hRGN, fErase) ? S_OK : E_FAIL;
	}

	STDMETHODIMP CActiveXCtrl::ScrollRect(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip)
	{
		DUITRACE(_T("AX: CActiveXCtrl::ScrollRect"));
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::AdjustRect(LPRECT prc)
	{
		DUITRACE(_T("AX: CActiveXCtrl::AdjustRect"));
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::OnDefWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
	{
		DUITRACE(_T("AX: CActiveXCtrl::OnDefWindowMessage"));
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		*plResult = ::DefWindowProc(m_pOwner->m_hwndHost, msg, wParam, lParam);
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::OnInPlaceActivateEx(BOOL* pfNoRedraw, DWORD dwFlags)        
	{
		DUITRACE(_T("AX: CActiveXCtrl::OnInPlaceActivateEx"));
		ASSERT(m_pInPlaceObject==NULL);
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		if( m_pOwner->m_pUnk == NULL ) return E_UNEXPECTED;
		::OleLockRunning(m_pOwner->m_pUnk, TRUE, FALSE);
		HWND hWndFrame = m_pOwner->GetManager()->GetPaintWindow();
		HRESULT Hr = E_FAIL;
		if( (dwFlags & ACTIVATE_WINDOWLESS) != 0 ) {
			m_bWindowless = true;
			Hr = m_pOwner->m_pUnk->QueryInterface(IID_IOleInPlaceObjectWindowless, (LPVOID*) &m_pInPlaceObject);
			m_pOwner->m_hwndHost = hWndFrame;
			m_pOwner->GetManager()->AddMessageFilter(m_pOwner);
		}
		if( FAILED(Hr) ) {
			m_bWindowless = false;
			Hr = CreateActiveXWnd();
			if( FAILED(Hr) ) return Hr;
			Hr = m_pOwner->m_pUnk->QueryInterface(IID_IOleInPlaceObject, (LPVOID*) &m_pInPlaceObject);
		}
		if( m_pInPlaceObject != NULL && !m_pOwner->IsMFC() ) {
			CDuiRect rcItem = m_pOwner->m_rcItem;
			if( !m_bWindowless ) rcItem.ResetOffset();
			m_pInPlaceObject->SetObjectRects(&rcItem, &rcItem);
		}
		m_bInPlaceActive = SUCCEEDED(Hr);
		return Hr;
	}

	STDMETHODIMP CActiveXCtrl::OnInPlaceDeactivateEx(BOOL fNoRedraw)       
	{
		DUITRACE(_T("AX: CActiveXCtrl::OnInPlaceDeactivateEx"));
		m_bInPlaceActive = false;
		if( m_pInPlaceObject != NULL ) {
			m_pInPlaceObject->Release();
			m_pInPlaceObject = NULL;
		}
		if( m_pWindow != NULL ) {
			::DestroyWindow(*m_pWindow);
			delete m_pWindow;
			m_pWindow = NULL;
		}
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::RequestUIActivate(void)
	{
		DUITRACE(_T("AX: CActiveXCtrl::RequestUIActivate"));
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::CanInPlaceActivate(void)       
	{
		DUITRACE(_T("AX: CActiveXCtrl::CanInPlaceActivate"));
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::OnInPlaceActivate(void)
	{
		DUITRACE(_T("AX: CActiveXCtrl::OnInPlaceActivate"));
		BOOL bDummy = FALSE;
		return OnInPlaceActivateEx(&bDummy, 0);
	}

	STDMETHODIMP CActiveXCtrl::OnUIActivate(void)
	{
		DUITRACE(_T("AX: CActiveXCtrl::OnUIActivate"));
		m_bUIActivated = true;
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::GetWindowContext(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
	{
		DUITRACE(_T("AX: CActiveXCtrl::GetWindowContext"));
		if( ppDoc == NULL ) return E_POINTER;
		if( ppFrame == NULL ) return E_POINTER;
		if( lprcPosRect == NULL ) return E_POINTER;
		if( lprcClipRect == NULL ) return E_POINTER;
		if (m_pWindow)
		{
			::GetClientRect(m_pWindow->GetHWND(),lprcPosRect);
			::GetClientRect(m_pWindow->GetHWND(),lprcClipRect);
		}
		*ppFrame = new CActiveXFrameWnd(m_pOwner);
		*ppDoc = NULL;
		ACCEL ac = { 0 };
		HACCEL hac = ::CreateAcceleratorTable(&ac, 1);
		lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
		lpFrameInfo->fMDIApp = FALSE;
		lpFrameInfo->hwndFrame = m_pOwner->GetManager()->GetPaintWindow();
		lpFrameInfo->haccel = hac;
		lpFrameInfo->cAccelEntries = 1;
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::Scroll(SIZE scrollExtant)
	{
		DUITRACE(_T("AX: CActiveXCtrl::Scroll"));
		return E_NOTIMPL;
	}

	STDMETHODIMP CActiveXCtrl::OnUIDeactivate(BOOL fUndoable)
	{
		DUITRACE(_T("AX: CActiveXCtrl::OnUIDeactivate"));
		m_bUIActivated = false;
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::OnInPlaceDeactivate(void)
	{
		DUITRACE(_T("AX: CActiveXCtrl::OnInPlaceDeactivate"));
		return OnInPlaceDeactivateEx(TRUE);
	}

	STDMETHODIMP CActiveXCtrl::DiscardUndoState(void)
	{
		DUITRACE(_T("AX: CActiveXCtrl::DiscardUndoState"));
		return E_NOTIMPL;
	}

	STDMETHODIMP CActiveXCtrl::DeactivateAndUndo(void)
	{
		DUITRACE(_T("AX: CActiveXCtrl::DeactivateAndUndo"));
		return E_NOTIMPL;
	}

	STDMETHODIMP CActiveXCtrl::OnPosRectChange(LPCRECT lprcPosRect)
	{
		DUITRACE(_T("AX: CActiveXCtrl::OnPosRectChange"));
		return E_NOTIMPL;
	}

	STDMETHODIMP CActiveXCtrl::GetWindow(HWND* phwnd)
	{
		DUITRACE(_T("AX: CActiveXCtrl::GetWindow"));
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		if( m_pOwner->m_hwndHost == NULL ) CreateActiveXWnd();
		if( m_pOwner->m_hwndHost == NULL ) return E_FAIL;
		*phwnd = m_pOwner->m_hwndHost;
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::ContextSensitiveHelp(BOOL fEnterMode)
	{
		DUITRACE(_T("AX: CActiveXCtrl::ContextSensitiveHelp"));
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::OnControlInfoChanged(void)      
	{
		DUITRACE(_T("AX: CActiveXCtrl::OnControlInfoChanged"));
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::LockInPlaceActive(BOOL fLock)       
	{
		DUITRACE(_T("AX: CActiveXCtrl::LockInPlaceActive"));
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::GetExtendedControl(IDispatch** ppDisp)        
	{
		DUITRACE(_T("AX: CActiveXCtrl::GetExtendedControl"));
		if( ppDisp == NULL ) return E_POINTER;   
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		if( m_pOwner->m_pUnk == NULL ) return E_UNEXPECTED;
		return m_pOwner->m_pUnk->QueryInterface(IID_IDispatch, (LPVOID*) ppDisp);
	}

	STDMETHODIMP CActiveXCtrl::TransformCoords(POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags)       
	{
		DUITRACE(_T("AX: CActiveXCtrl::TransformCoords"));
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::TranslateAccelerator(MSG *pMsg, DWORD grfModifiers)
	{
		DUITRACE(_T("AX: CActiveXCtrl::TranslateAccelerator"));
		return S_FALSE;
	}

	STDMETHODIMP CActiveXCtrl::OnFocus(BOOL fGotFocus)
	{
		DUITRACE(_T("AX: CActiveXCtrl::OnFocus"));
		m_bFocused = (fGotFocus == TRUE);
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::ShowPropertyFrame(void)
	{
		DUITRACE(_T("AX: CActiveXCtrl::ShowPropertyFrame"));
		return E_NOTIMPL;
	}

	STDMETHODIMP CActiveXCtrl::EnumObjects(DWORD grfFlags, IEnumUnknown** ppenum)
	{
		DUITRACE(_T("AX: CActiveXCtrl::EnumObjects"));
		if( ppenum == NULL ) return E_POINTER;
		if( m_pOwner == NULL ) return E_UNEXPECTED;
		*ppenum = new CActiveXEnum(m_pOwner->m_pUnk);
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::LockContainer(BOOL fLock)
	{
		DUITRACE(_T("AX: CActiveXCtrl::LockContainer"));
		m_bLocked = fLock != FALSE;
		return S_OK;
	}

	STDMETHODIMP CActiveXCtrl::ParseDisplayName(IBindCtx *pbc, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
	{
		DUITRACE(_T("AX: CActiveXCtrl::ParseDisplayName"));
		return E_NOTIMPL;
	}

	HRESULT CActiveXCtrl::CreateActiveXWnd()
	{
		if( m_pWindow != NULL ) return S_OK;
		m_pWindow = new CActiveXWnd;
		if( m_pWindow == NULL ) return E_OUTOFMEMORY;
		m_pOwner->m_hwndHost = m_pWindow->Init(this, m_pOwner->GetManager()->GetPaintWindow());
		return S_OK;
	}


	/
	//
	//

	HWND CActiveXWnd::Init(CActiveXCtrl* pOwner, HWND hWndParent)
	{
		m_pOwner = pOwner;
		UINT uStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
		Create(hWndParent, _T("UIActiveX"), uStyle, 0L, 0,0,0,0, NULL);
		return m_hWnd;
	}

	LPCTSTR CActiveXWnd::GetWindowClassName() const
	{
		return _T("ActiveXWnd");
	}

	void CActiveXWnd::OnFinalMessage(HWND hWnd)
	{
		if( m_pOwner->m_pOwner->GetManager()->IsLayered() ) {
			m_pOwner->m_pOwner->GetManager()->RemoveNativeWindow(hWnd);
		}
	}

	void CActiveXWnd::DoVerb(LONG iVerb)
	{
		if( m_pOwner == NULL ) return;
		if( m_pOwner->m_pOwner == NULL ) return;
		IOleObject* pUnk = NULL;
		m_pOwner->m_pOwner->GetControl(IID_IOleObject, (LPVOID*) &pUnk);
		if( pUnk == NULL ) return;
		CSafeRelease<IOleObject> RefOleObject = pUnk;
		IOleClientSite* pOleClientSite = NULL;
		m_pOwner->QueryInterface(IID_IOleClientSite, (LPVOID*) &pOleClientSite);
		CSafeRelease<IOleClientSite> RefOleClientSite = pOleClientSite;
		pUnk->DoVerb(iVerb, NULL, pOleClientSite, 0, m_hWnd, &m_pOwner->m_pOwner->GetPos());
	}

	LRESULT CActiveXWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
	{
		LRESULT lRes=0;
		BOOL bHandled = TRUE;
		switch( uMsg ) {
		case WM_CREATE:        lRes = OnCreate(uMsg, wParam, lParam, bHandled); break;
		case WM_TIMER:         lRes = OnTimer(uMsg, wParam, lParam, bHandled); break;
		case WM_PAINT:         lRes = OnPaint(uMsg, wParam, lParam, bHandled); break;
		case WM_PRINT:		   lRes = OnPrint(uMsg, wParam, lParam, bHandled); break;
		case WM_SETFOCUS:      lRes = OnSetFocus(uMsg, wParam, lParam, bHandled); break;
		case WM_KILLFOCUS:     lRes = OnKillFocus(uMsg, wParam, lParam, bHandled); break;
		case WM_ERASEBKGND:    lRes = OnEraseBkgnd(uMsg, wParam, lParam, bHandled); break;
		case WM_MOUSEACTIVATE: lRes = OnMouseActivate(uMsg, wParam, lParam, bHandled); break;
		case WM_MOUSEWHEEL: break;
		default:
			bHandled = FALSE;
		}
		if( !bHandled ) return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
		return lRes;
	}

	LRESULT CActiveXWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		if( m_pOwner->m_pOwner->GetManager()->IsLayered() ) {
			::SetTimer(m_hWnd, CARET_TIMERID, ::GetCaretBlinkTime(), NULL);
		}
		return 0;
	}

	LRESULT CActiveXWnd::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		if (wParam == DEFAULT_TIMERID) {
			if (m_pOwner->m_pOwner->GetManager()->IsLayered()) {
				//m_pOwner->m_pOwner->GetManager()->AddNativeWindow(m_pOwner->m_pOwner, m_hWnd);
				m_iLayeredTick += 1;
				if (m_iLayeredTick >= 10) {
					m_iLayeredTick = 0;
					m_bDrawCaret = !m_bDrawCaret;
				}
			}
			return 0;
		}
		bHandled = FALSE;
		return 0;
	}

	LRESULT CActiveXWnd::OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		if( m_pOwner->m_pViewObject == NULL ) bHandled = FALSE;
		return 1;
	}

	LRESULT CActiveXWnd::OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		IOleObject* pUnk = NULL;
		m_pOwner->m_pOwner->GetControl(IID_IOleObject, (LPVOID*) &pUnk);
		if( pUnk == NULL ) return 0;
		CSafeRelease<IOleObject> RefOleObject = pUnk;
		DWORD dwMiscStatus = 0;
		pUnk->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
		if( (dwMiscStatus & OLEMISC_NOUIACTIVATE) != 0 ) return 0;
		if( !m_pOwner->m_bInPlaceActive ) DoVerb(OLEIVERB_INPLACEACTIVATE);
		bHandled = FALSE;
		return 0;
	}

	LRESULT CActiveXWnd::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		bHandled = FALSE;
		m_pOwner->m_bFocused = true;
		if( !m_pOwner->m_bUIActivated ) DoVerb(OLEIVERB_UIACTIVATE);
		return 0;
	}

	LRESULT CActiveXWnd::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		bHandled = FALSE;
		m_pOwner->m_bFocused = false;
		return 0;
	}

	LRESULT CActiveXWnd::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		PAINTSTRUCT ps = { 0 };
		::BeginPaint(m_hWnd, &ps);
		::EndPaint(m_hWnd, &ps);
		return 1;
	}

	LRESULT CActiveXWnd::OnPrint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		RECT rcClient;
		::GetClientRect(m_hWnd, &rcClient);
		m_pOwner->m_pViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, (HDC)wParam, (RECTL*) &rcClient, NULL, NULL, NULL); 

		if (m_bDrawCaret ) {
			RECT rcPos = m_pOwner->m_pOwner->GetPos();
			GUITHREADINFO guiThreadInfo;
			guiThreadInfo.cbSize = sizeof(GUITHREADINFO);
			::GetGUIThreadInfo(NULL, &guiThreadInfo);
			if (guiThreadInfo.hwndCaret) {
				POINT ptCaret;
				ptCaret.x = guiThreadInfo.rcCaret.left;
				ptCaret.y = guiThreadInfo.rcCaret.top;
				::ClientToScreen(guiThreadInfo.hwndCaret, &ptCaret);
				::ScreenToClient(m_pOwner->m_pOwner->GetManager()->GetPaintWindow(), &ptCaret);
				if( ::PtInRect(&rcPos, ptCaret) ) {
					RECT rcCaret;
					rcCaret = guiThreadInfo.rcCaret;
					rcCaret.right = rcCaret.left;
					CRenderEngine::DrawLine((HDC)wParam, rcCaret, 1, 0xFF000000);
				}
			}
		}

		return 1;
	}

	/
	//
	//
	IMPLEMENT_DUICONTROL(CActiveXUI)

	CActiveXUI::CActiveXUI() : m_pUnk(NULL), m_pControl(NULL), m_hwndHost(NULL), m_bCreated(false), m_bDelayCreate(true), m_bMFC(false)
	{
		m_clsid = IID_NULL;
	}

	CActiveXUI::~CActiveXUI()
	{
		ReleaseControl();
	}

	LPCTSTR CActiveXUI::GetClass() const
	{
		return _T("ActiveXUI");
	}

	LPVOID CActiveXUI::GetInterface(LPCTSTR pstrName)
	{
		if( _tcscmp(pstrName, DUI_CTR_ACTIVEX) == 0 ) return static_cast<CActiveXUI*>(this);
		return CControlUI::GetInterface(pstrName);
	}

	HWND CActiveXUI::GetHostWindow() const
	{
		return m_hwndHost;
	}

	static void PixelToHiMetric(const SIZEL* lpSizeInPix, LPSIZEL lpSizeInHiMetric)
	{
#define HIMETRIC_PER_INCH   2540
#define MAP_PIX_TO_LOGHIM(x,ppli)   MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
#define MAP_LOGHIM_TO_PIX(x,ppli)   MulDiv((ppli), (x), HIMETRIC_PER_INCH)
		int nPixelsPerInchX;    // Pixels per logical inch along width
		int nPixelsPerInchY;    // Pixels per logical inch along height
		HDC hDCScreen = ::GetDC(NULL);
		nPixelsPerInchX = ::GetDeviceCaps(hDCScreen, LOGPIXELSX);
		nPixelsPerInchY = ::GetDeviceCaps(hDCScreen, LOGPIXELSY);
		::ReleaseDC(NULL, hDCScreen);
		lpSizeInHiMetric->cx = MAP_PIX_TO_LOGHIM(lpSizeInPix->cx, nPixelsPerInchX);
		lpSizeInHiMetric->cy = MAP_PIX_TO_LOGHIM(lpSizeInPix->cy, nPixelsPerInchY);
	}

	void CActiveXUI::SetVisible(bool bVisible)
	{
		CControlUI::SetVisible(bVisible);
		if( m_hwndHost != NULL && !m_pControl->m_bWindowless ) 
			::ShowWindow(m_hwndHost, IsVisible() ? SW_SHOW : SW_HIDE);
	}

	void CActiveXUI::SetInternVisible(bool bVisible)
	{
		CControlUI::SetInternVisible(bVisible);
		if( m_hwndHost != NULL && !m_pControl->m_bWindowless ) 
			::ShowWindow(m_hwndHost, IsVisible() ? SW_SHOW : SW_HIDE);
	}

	void CActiveXUI::SetPos(RECT rc, bool bNeedInvalidate)
	{
		CControlUI::SetPos(rc, bNeedInvalidate);

		if( !m_bCreated ) DoCreateControl();

		if( m_pUnk == NULL ) return;
		if( m_pControl == NULL ) return;

		SIZEL hmSize = { 0 };
		SIZEL pxSize = { 0 };
		pxSize.cx = m_rcItem.right - m_rcItem.left;
		pxSize.cy = m_rcItem.bottom - m_rcItem.top;
		PixelToHiMetric(&pxSize, &hmSize);

		if( m_pUnk != NULL ) {
			m_pUnk->SetExtent(DVASPECT_CONTENT, &hmSize);
		}
		if( m_pControl->m_pInPlaceObject != NULL ) {
			CDuiRect rcItem = m_rcItem;
			if( !m_pControl->m_bWindowless ) rcItem.ResetOffset();
			m_pControl->m_pInPlaceObject->SetObjectRects(&rcItem, &rcItem);
		}
		if( !m_pControl->m_bWindowless ) {
			ASSERT(m_pControl->m_pWindow);
			::MoveWindow(*m_pControl->m_pWindow, m_rcItem.left, m_rcItem.top, m_rcItem.right - m_rcItem.left, m_rcItem.bottom - m_rcItem.top, TRUE);
		}
	}

	void CActiveXUI::Move(SIZE szOffset, bool bNeedInvalidate)
	{
		CControlUI::Move(szOffset, bNeedInvalidate);
		if( !m_pControl->m_bWindowless ) {
			ASSERT(m_pControl->m_pWindow);
			::MoveWindow(*m_pControl->m_pWindow, m_rcItem.left, m_rcItem.top, m_rcItem.right - m_rcItem.left, m_rcItem.bottom - m_rcItem.top, TRUE);
		}
	}

	bool CActiveXUI::DoPaint(HDC hDC, const RECT& rcPaint, CControlUI* pStopControl)
	{
		if( m_pControl != NULL && m_pControl->m_bWindowless && m_pControl->m_pViewObject != NULL )
		{
			m_pControl->m_pViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hDC, (RECTL*) &m_rcItem, (RECTL*) &m_rcItem, NULL, NULL); 
		}
		return true;
	}

	void CActiveXUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
	{
		if( _tcscmp(pstrName, _T("clsid")) == 0 ) CreateControl(pstrValue);
		else if( _tcscmp(pstrName, _T("modulename")) == 0 ) SetModuleName(pstrValue);
		else if( _tcscmp(pstrName, _T("delaycreate")) == 0 ) SetDelayCreate(_tcscmp(pstrValue, _T("true")) == 0);
		else CControlUI::SetAttribute(pstrName, pstrValue);
	}

	LRESULT CActiveXUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
	{
		if( m_pControl == NULL ) return 0;
		ASSERT(m_pControl->m_bWindowless);
		if( !m_pControl->m_bInPlaceActive ) return 0;
		if( m_pControl->m_pInPlaceObject == NULL ) return 0;
		if( !IsMouseEnabled() && uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST ) return 0;
		bool bWasHandled = true;
		if( (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST) || uMsg == WM_SETCURSOR ) {
			// Mouse message only go when captured or inside rect
			DWORD dwHitResult = m_pControl->m_bCaptured ? HITRESULT_HIT : HITRESULT_OUTSIDE;
			if( dwHitResult == HITRESULT_OUTSIDE && m_pControl->m_pViewObject != NULL ) {
				IViewObjectEx* pViewEx = NULL;
				m_pControl->m_pViewObject->QueryInterface(IID_IViewObjectEx, (LPVOID*) &pViewEx);
				if( pViewEx != NULL ) {
					POINT ptMouse = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
					pViewEx->QueryHitPoint(DVASPECT_CONTENT, &m_rcItem, ptMouse, 0, &dwHitResult);
					pViewEx->Release();
				}
			}
			if( dwHitResult != HITRESULT_HIT ) return 0;
			if( uMsg == WM_SETCURSOR ) bWasHandled = false;
		}
		else if( uMsg >= WM_KEYFIRST && uMsg <= WM_KEYLAST ) {
			// Keyboard messages just go when we have focus
			if( !IsFocused() ) return 0;
		}
		else {
			switch( uMsg ) {
			case WM_HELP:
			case WM_CONTEXTMENU:
				bWasHandled = false;
				break;
			default:
				return 0;
			}
		}
		LRESULT lResult = 0;
		HRESULT Hr = m_pControl->m_pInPlaceObject->OnWindowMessage(uMsg, wParam, lParam, &lResult);
		if( Hr == S_OK ) bHandled = bWasHandled;
		return lResult;
	}

	bool CActiveXUI::IsDelayCreate() const
	{
		return m_bDelayCreate;
	}

	void CActiveXUI::SetDelayCreate(bool bDelayCreate)
	{
		if( m_bDelayCreate == bDelayCreate ) return;
		if( bDelayCreate == false ) {
			if( m_bCreated == false && m_clsid != IID_NULL ) DoCreateControl();
		}
		m_bDelayCreate = bDelayCreate;
	}
	
	bool CActiveXUI::IsMFC() const
	{
		return m_bMFC;
	}

	void CActiveXUI::SetMFC(bool bMFC/* = false*/)
	{
		if( m_bMFC == bMFC ) return;
		m_bMFC = bMFC;
	}

	bool CActiveXUI::CreateControl(LPCTSTR pstrCLSID)
	{
		CLSID clsid = { 0 };
		OLECHAR szCLSID[100] = { 0 };
#ifndef _UNICODE
		::MultiByteToWideChar(::GetACP(), 0, pstrCLSID, -1, szCLSID, lengthof(szCLSID) - 1);
#else
		_tcsncpy(szCLSID, pstrCLSID, lengthof(szCLSID) - 1);
#endif
		if( pstrCLSID[0] == '{' ) ::CLSIDFromString(szCLSID, &clsid);
		else ::CLSIDFromProgID(szCLSID, &clsid);
		return CreateControl(clsid);
	}

	bool CActiveXUI::CreateControl(const CLSID clsid)
	{
		ASSERT(clsid!=IID_NULL);
		if( clsid == IID_NULL ) return false;
		m_bCreated = false;
		m_clsid = clsid;
		if( !m_bDelayCreate ) DoCreateControl();
		return true;
	}

	void CActiveXUI::ReleaseControl()
	{
		// 移除消息链
		if(m_pManager != NULL) m_pManager->RemoveMessageFilter(this);

		if( m_pUnk != NULL ) {
			IObjectWithSite* pSite = NULL;
			m_pUnk->QueryInterface(IID_IObjectWithSite, (LPVOID*) &pSite);
			if( pSite != NULL ) {
				pSite->SetSite(NULL);
				pSite->Release();
			}
			if(!IsMFC()) {
				m_pUnk->Close(OLECLOSE_NOSAVE);
			}
			m_pUnk->SetClientSite(NULL);
			m_pUnk->Release(); 
			m_pUnk = NULL;
		}		
		// 销毁CActiveXCtrl
		if( m_pControl != NULL ) {
			m_pControl->m_pOwner = NULL;
			m_pControl->Release();
			m_pControl = NULL;
		}

		m_hwndHost = NULL;
	}

	typedef HRESULT (__stdcall *DllGetClassObjectFunc)(REFCLSID rclsid, REFIID riid, LPVOID* ppv); 

	bool CActiveXUI::DoCreateControl()
	{
		ReleaseControl();
		// At this point we'll create the ActiveX control
		m_bCreated = true;
		IOleControl* pOleControl = NULL;

		HRESULT Hr = -1;
		if( !m_sModuleName.IsEmpty() ) {
			HMODULE hModule = ::LoadLibrary((LPCTSTR)m_sModuleName);
			if( hModule != NULL ) {
				IClassFactory* aClassFactory = NULL;
				DllGetClassObjectFunc aDllGetClassObjectFunc = (DllGetClassObjectFunc)::GetProcAddress(hModule, "DllGetClassObject");
				Hr = aDllGetClassObjectFunc(m_clsid, IID_IClassFactory, (LPVOID*)&aClassFactory);
				if( SUCCEEDED(Hr) ) {
					Hr = aClassFactory->CreateInstance(NULL, IID_IOleObject, (LPVOID*)&pOleControl);
				}
				aClassFactory->Release();
			}
		}
		if( FAILED(Hr) ) {
			Hr = ::CoCreateInstance(m_clsid, NULL, CLSCTX_ALL, IID_IOleControl, (LPVOID*)&pOleControl);
		}
		ASSERT(SUCCEEDED(Hr));
		if( FAILED(Hr) ) return false;
		pOleControl->QueryInterface(IID_IOleObject, (LPVOID*) &m_pUnk);
		pOleControl->Release();
		if( m_pUnk == NULL ) return false;
		// Create the host too
		m_pControl = new CActiveXCtrl();
		m_pControl->m_pOwner = this;
		// More control creation stuff
		DWORD dwMiscStatus = 0;
		m_pUnk->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
		IOleClientSite* pOleClientSite = NULL;
		m_pControl->QueryInterface(IID_IOleClientSite, (LPVOID*) &pOleClientSite);
		CSafeRelease<IOleClientSite> RefOleClientSite = pOleClientSite;
		// Initialize control
		if( (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) != 0 ) m_pUnk->SetClientSite(pOleClientSite);
		IPersistStreamInit* pPersistStreamInit = NULL;
		m_pUnk->QueryInterface(IID_IPersistStreamInit, (LPVOID*) &pPersistStreamInit);
		if( pPersistStreamInit != NULL ) {
			Hr = pPersistStreamInit->InitNew();
			pPersistStreamInit->Release();
		}
		if( FAILED(Hr) ) return false;
		if( (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) == 0 ) m_pUnk->SetClientSite(pOleClientSite);
		// Grab the view...
		Hr = m_pUnk->QueryInterface(IID_IViewObjectEx, (LPVOID*) &m_pControl->m_pViewObject);
		if( FAILED(Hr) ) Hr = m_pUnk->QueryInterface(IID_IViewObject2, (LPVOID*) &m_pControl->m_pViewObject);
		if( FAILED(Hr) ) Hr = m_pUnk->QueryInterface(IID_IViewObject, (LPVOID*) &m_pControl->m_pViewObject);
		// Activate and done...
		m_pUnk->SetHostNames(OLESTR("UIActiveX"), NULL);
		if( m_pManager != NULL ) m_pManager->SendNotify((CControlUI*)this, DUI_MSGTYPE_SHOWACTIVEX, 0, 0, false);
		if( (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME) == 0 ) {
			try
			{
				if(m_pManager != NULL) Hr = m_pUnk->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, pOleClientSite, 0, m_pManager->GetPaintWindow(), &m_rcItem);
			}
			catch (...)
			{
			}
		}
		IObjectWithSite* pSite = NULL;
		m_pUnk->QueryInterface(IID_IObjectWithSite, (LPVOID*) &pSite);
		if( pSite != NULL ) {
			pSite->SetSite(static_cast<IOleClientSite*>(m_pControl));
			pSite->Release();
		}
		return SUCCEEDED(Hr);
	}

	HRESULT CActiveXUI::GetControl(const IID iid, LPVOID* ppRet)
	{
		ASSERT(ppRet!=NULL);
		ASSERT(*ppRet==NULL);
		if( ppRet == NULL ) return E_POINTER;
		if( m_pUnk == NULL ) return E_PENDING;
		return m_pUnk->QueryInterface(iid, (LPVOID*) ppRet);
	}

	CLSID CActiveXUI::GetClisd() const
	{
		return m_clsid;
	}

	CDuiString CActiveXUI::GetModuleName() const
	{
		return m_sModuleName;
	}

	void CActiveXUI::SetModuleName(LPCTSTR pstrText)
	{
		m_sModuleName = pstrText;
	}

} // namespace DuiLib

  • CActiveXWnd

    CActiveXWnd类继承自CWindowWnd,用于创建和管理ActiveX控件的窗口。它处理与ActiveX控件相关的窗口消息,并将某些操作委托给ActiveX控件。

    • Init: 初始化ActiveX控件窗口,设置控件所有者和父窗口。
    • GetWindowClassName: 返回窗口类名。
    • OnFinalMessage: 窗口销毁时调用,进行资源清理。
    • HandleMessage: 处理窗口消息,如创建、定时器、激活等。
    • DoVerb: 执行OLE动作,如激活、显示等。

    CActiveXEnum

    CActiveXEnum类实现了IEnumUnknown接口,用于枚举ActiveX控件的对象。此类主要用于实现ActiveX控件容器的枚举功能。

    • AddRefReleaseQueryInterface: 实现COM对象的引用计数和接口查询。
    • NextSkipResetClone: 实现枚举器的基本操作,如获取下一个元素、跳过元素、重置枚举器、克隆枚举器。

    CActiveXFrameWnd

    CActiveXFrameWnd类实现了IOleInPlaceFrame接口,作为ActiveX控件的“就地”激活框架。它提供了ActiveX控件在就地激活时所需的窗口环境。

    • AddRefReleaseQueryInterface: 实现COM对象的基本管理。
    • InsertMenusSetMenuRemoveMenusSetStatusTextEnableModelessTranslateAccelerator: 实现激活时所需的框架操作。
    • GetWindowContextSensitiveHelp: 提供框架的窗口句柄和帮助支持。

    CActiveXCtrl

    CActiveXCtrl类是ActiveX控件的核心管理类,实现了多个接口,包括IOleClientSiteIOleInPlaceSiteWindowlessIOleControlSite等,提供了ActiveX控件所需的环境和服务。

    • AddRefReleaseQueryInterface: 实现COM对象的引用计数和接口查询。
    • SetSiteGetSite: 设置或获取控件的站点。
    • SaveObjectGetMonikerGetContainerShowObjectOnShowWindowRequestNewObjectLayout: 实现客户端站点的基本操作。
    • CanWindowlessActivateGetCaptureSetCaptureGetFocusSetFocus等: 实现无窗口激活和焦点管理。
    • TranslateAcceleratorOnFocusShowPropertyFrame等: 处理键盘事件和焦点事件。
    • GetWindowContextCanInPlaceActivateOnInPlaceActivateOnUIActivate等: 管理就地激活和用户界面激活。
    • EnumObjectsLockContainer: 实现容器的枚举和锁定。

    这些类共同为DuiLib框架中的CActiveXUI控件提供支持,允许开发者将ActiveX控件集成到基于DuiLib的应用程序中,扩展应用程序的功能。通过实现相关COM接口,这些类为ActiveX控件提供了所需的站点、

2.5、CWebBrowserEventHandler类的声明

这个CWebBrowserEventHandler类在DuiLib框架中用于为CWebBrowserUI(一个基于ActiveX技术实现的Web浏览器控件封装)提供一个事件处理的机制。通过继承并重写这个事件处理类的方法,开发者可以自定义对Web浏览器事件的响应。以下是各个接口的作用说明:

#pragma once
#include <ExDisp.h>
#include <ExDispid.h>
#include <mshtmhst.h>

namespace DuiLib
{
	class CWebBrowserUI;
	class CWebBrowserEventHandler
	{
	public:
		CWebBrowserEventHandler() {}
		~CWebBrowserEventHandler() {}

		virtual void BeforeNavigate2(CWebBrowserUI* pWeb, IDispatch *pDisp,VARIANT *&url,VARIANT *&Flags,VARIANT *&TargetFrameName,VARIANT *&PostData,VARIANT *&Headers,VARIANT_BOOL *&Cancel ) {}
		virtual void NavigateError(CWebBrowserUI* pWeb, IDispatch *pDisp,VARIANT * &url,VARIANT *&TargetFrameName,VARIANT *&StatusCode,VARIANT_BOOL *&Cancel) {}
		virtual void NavigateComplete2(CWebBrowserUI* pWeb, IDispatch *pDisp,VARIANT *&url){}
		virtual void ProgressChange(CWebBrowserUI* pWeb, LONG nProgress, LONG nProgressMax){}
		virtual void NewWindow3(CWebBrowserUI* pWeb, IDispatch **pDisp, VARIANT_BOOL *&Cancel, DWORD dwFlags, BSTR bstrUrlContext, BSTR bstrUrl){}
		virtual void CommandStateChange(CWebBrowserUI* pWeb, long Command,VARIANT_BOOL Enable){};
		virtual void TitleChange(CWebBrowserUI* pWeb, BSTR bstrTitle){};
		virtual void DocumentComplete(CWebBrowserUI* pWeb, IDispatch *pDisp,VARIANT *&url){}

		// interface IDocHostUIHandler
		virtual HRESULT STDMETHODCALLTYPE ShowContextMenu(CWebBrowserUI* pWeb, 
			/* [in] */ DWORD dwID,
			/* [in] */ POINT __RPC_FAR *ppt,
			/* [in] */ IUnknown __RPC_FAR *pcmdtReserved,
			/* [in] */ IDispatch __RPC_FAR *pdispReserved)
		{
			//return E_NOTIMPL;
			//返回 E_NOTIMPL 正常弹出系统右键菜单
			return S_OK;
			//返回S_OK 则可屏蔽系统右键菜单
		}

		virtual HRESULT STDMETHODCALLTYPE GetHostInfo(CWebBrowserUI* pWeb, 
			/* [out][in] */ DOCHOSTUIINFO __RPC_FAR *pInfo)
		{
			return E_NOTIMPL;
		}

		virtual HRESULT STDMETHODCALLTYPE ShowUI(CWebBrowserUI* pWeb, 
			/* [in] */ DWORD dwID,
			/* [in] */ IOleInPlaceActiveObject __RPC_FAR *pActiveObject,
			/* [in] */ IOleCommandTarget __RPC_FAR *pCommandTarget,
			/* [in] */ IOleInPlaceFrame __RPC_FAR *pFrame,
			/* [in] */ IOleInPlaceUIWindow __RPC_FAR *pDoc)
		{
			return S_FALSE;
		}

		virtual HRESULT STDMETHODCALLTYPE HideUI( CWebBrowserUI* pWeb)
		{
			return S_OK;
		}

		virtual HRESULT STDMETHODCALLTYPE UpdateUI( CWebBrowserUI* pWeb)
		{
			return S_OK;
		}

		virtual HRESULT STDMETHODCALLTYPE EnableModeless(CWebBrowserUI* pWeb, 
			/* [in] */ BOOL fEnable)
		{
			return S_OK;
		}

		virtual HRESULT STDMETHODCALLTYPE OnDocWindowActivate(CWebBrowserUI* pWeb, 
			/* [in] */ BOOL fActivate)
		{
			return S_OK;
		}

		virtual HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(CWebBrowserUI* pWeb, 
			/* [in] */ BOOL fActivate)
		{
			return S_OK;
		}

		virtual HRESULT STDMETHODCALLTYPE ResizeBorder(CWebBrowserUI* pWeb, 
			/* [in] */ LPCRECT prcBorder,
			/* [in] */ IOleInPlaceUIWindow __RPC_FAR *pUIWindow,
			/* [in] */ BOOL fRameWindow)
		{
			return S_OK;
		}

		virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(CWebBrowserUI* pWeb, 
			/* [in] */ LPMSG lpMsg,
			/* [in] */ const GUID __RPC_FAR *pguidCmdGroup,
			/* [in] */ DWORD nCmdID)
		{
			return S_FALSE;
		}

		virtual HRESULT STDMETHODCALLTYPE GetOptionKeyPath(CWebBrowserUI* pWeb, 
			/* [out] */ LPOLESTR __RPC_FAR *pchKey,
			/* [in] */ DWORD dw)
		{
			return S_OK;
		}

		virtual HRESULT STDMETHODCALLTYPE GetDropTarget(CWebBrowserUI* pWeb, 
			/* [in] */ IDropTarget __RPC_FAR *pDropTarget,
			/* [out] */ IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget)
		{
			return E_NOTIMPL;
		}

		virtual HRESULT STDMETHODCALLTYPE GetExternal(CWebBrowserUI* pWeb, 
			/* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDispatch)
		{
			return E_NOTIMPL;
		}

		virtual HRESULT STDMETHODCALLTYPE TranslateUrl(CWebBrowserUI* pWeb, 
			/* [in] */ DWORD dwTranslate,
			/* [in] */ OLECHAR __RPC_FAR *pchURLIn,
			/* [out] */ OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut)
		{
			return S_OK;
		}

		virtual HRESULT STDMETHODCALLTYPE FilterDataObject(CWebBrowserUI* pWeb, 
			/* [in] */ IDataObject __RPC_FAR *pDO,
			/* [out] */ IDataObject __RPC_FAR *__RPC_FAR *ppDORet)
		{
			return S_OK;
		}

		// 	virtual HRESULT STDMETHODCALLTYPE GetOverrideKeyPath( 
		// 		/* [annotation][out] */ 
		// 		__deref_out  LPOLESTR *pchKey,
		// 		/* [in] */ DWORD dw)
		// 	{
		// 		return E_NOTIMPL;
		// 	}

		// IDownloadManager
		virtual HRESULT STDMETHODCALLTYPE Download( CWebBrowserUI* pWeb, 
			/* [in] */ IMoniker *pmk,
			/* [in] */ IBindCtx *pbc,
			/* [in] */ DWORD dwBindVerb,
			/* [in] */ LONG grfBINDF,
			/* [in] */ BINDINFO *pBindInfo,
			/* [in] */ LPCOLESTR pszHeaders,
			/* [in] */ LPCOLESTR pszRedir,
			/* [in] */ UINT uiCP)
		{
			return S_OK;
		}
	};
}

  • 浏览器事件处理方法

    • BeforeNavigate2: 在导航到新页面之前调用。可以用来修改请求或取消导航。
    • NavigateError: 导航错误时调用,例如无法加载页面。
    • NavigateComplete2: 页面加载完成时调用。
    • ProgressChange: 在导航过程中,下载进度改变时调用。
    • NewWindow3: 在尝试打开新窗口时调用,可以用来阻止新窗口的打开或改变打开新窗口的方式。
    • CommandStateChange: 当浏览器命令状态改变时调用,例如前进或后退按钮的可用状态改变。
    • TitleChange: 页面标题改变时调用。
    • DocumentComplete: 页面完全加载完成时调用,包括所有相关资源如图片等。

    IDocHostUIHandler接口方法

    • ShowContextMenu: 当用户尝试显示上下文菜单时调用,可以用来自定义菜单。
    • GetHostInfo: 获取宿主信息,如UI能力标志。
    • ShowUI: 当浏览器控件显示其UI时调用。
    • HideUI: 当浏览器控件隐藏其UI时调用。
    • UpdateUI: 当浏览器控件更新其UI时调用。
    • EnableModeless: 启用或禁用无模式对话框。
    • OnDocWindowActivate: 当文档窗口被激活或停用时调用。
    • OnFrameWindowActivate: 当框架窗口被激活或停用时调用。
    • ResizeBorder: 在调整浏览器控件边框时调用。
    • TranslateAccelerator: 在处理键盘消息前调用,可用于拦截快捷键。
    • GetOptionKeyPath: 获取注册表中选项的键路径。
    • GetDropTarget: 获取自定义的拖放目标。
    • GetExternal: 允许提供外部对象给Web页面脚本。
    • TranslateUrl: 在导航之前修改URL。
    • FilterDataObject: 在将数据对象提供给脚本之前进行过滤。

    IDownloadManager接口方法

    • Download: 处理下载任务,可以用来拦截或自定义处理文件下载。
  • 通过实现CWebBrowserEventHandler类,开发者可以对Web浏览器控件的行为进行详细的控制和定制,比如自定义上下文菜单、处理页面导航和下载、修改用户界面等。这为嵌入Web内容提供了强大的灵活性和控制能力。

2.6、嵌入一个浏览器窗口总结

  • 通过上述描述的CActiveXUI类以及相关支持类(如CActiveXCtrlCActiveXWnd等),你可以在基于DuiLib框架的应用程序中创建并嵌入一个浏览器窗口。这主要是通过嵌入一个Web浏览器控件(通常是基于Internet Explorer的WebBrowser控件,即IWebBrowser2接口)来实现的。

    创建浏览器窗口的大致步骤如下:

    1. 实例化CActiveXUI对象:这个对象是ActiveX控件的容器,它提供了嵌入ActiveX控件所需的所有功能和接口实现。
    2. 调用CreateControl方法:通过传递Web浏览器控件的CLSID(或ProgID,如"Shell.Explorer")给CreateControl方法,来创建浏览器控件的实例。这个方法会处理控件的初始化和激活过程。
    3. 配置浏览器控件:一旦控件被创建,你可以通过GetControl方法获取到IWebBrowser2接口的指针,然后通过这个接口来控制和配置浏览器窗口,比如导航到特定的URL。
    4. 将控件添加到UI中:最后,将CActiveXUI对象添加到你的DuiLib应用程序的界面中。这通常涉及到将它添加到某个容器控件中,并设置适当的大小和位置。

    这样,你就在基于DuiLib的应用程序中嵌入了一个完全功能的浏览器窗口,可以用来显示网页和其他基于Web的内容。

  • 需要注意的是,由于这种方法依赖于COM和ActiveX技术,它主要适用于Windows平台。此外,随着Internet Explorer逐渐被淘汰,以及现代Windows应用开发中越来越多地采用Edge WebView2(基于Chromium的Edge浏览器控件)等更现代的Web渲染技术,使用基于IE的WebBrowser控件的方案可能面临兼容性和安全性的挑战。因此,对于新的项目,建议考虑使用更现代的Web渲染解决方案。

  • 提到的CWebBrowserUI及其事件处理CWebBrowserEventHandler类是基于ActiveX技术和IE(Internet Explorer)内核的。这种方法利用了Windows系统中预装的IE组件,通过ActiveX控件(特别是WebBrowser控件)来嵌入和使用Web浏览器功能。

    使用IE内核的主要优点是它的普遍可用性(几乎所有的Windows系统都预装了IE浏览器)和对老旧网站的兼容性。然而,随着时间的推移,这种方法面临着越来越多的限制和挑战:

    1. 安全性和现代Web标准支持: IE浏览器已经多年没有更新,不支持许多现代Web技术和标准,而且已知存在安全漏洞。
    2. Microsoft的支持策略: 微软已经明确表示将停止支持IE浏览器,转而推广基于Chromium的新Edge浏览器,并且在新版本的Windows系统中逐步淘汰IE。
    3. 开发和维护成本: 随着Web技术的快速发展,继续使用基于IE内核的解决方案可能会导致额外的开发和维护成本,特别是在兼容性和性能优化方面。

    为了应对这些挑战,推荐使用基于更现代浏览器内核的解决方案,如:

    • WebView2控件: 微软推出的WebView2控件基于Chromium内核,支持最新的Web技术和标准,提供了与IE基于ActiveX的WebBrowser控件类似的嵌入浏览器功能,但具有更好的性能、安全性和兼容性。
    • 其他嵌入式浏览器解决方案: 如使用CEF(Chromium Embedded Framework)或Electron等框架,它们提供了更灵活的Web内容嵌入和应用程序开发选项,尽管这可能意味着更高的复杂性和资源需求。
  • 项目或应用程序仍然需要支持基于IE内核的Web浏览器功能,使用上述提到的CWebBrowserUICWebBrowserEventHandler类是一种可行的方法。但是,考虑到长期的技术趋势和支持策略,评估和迁移到基于更现代浏览器内核的解决方案会是一个更好的选择。

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

森明帮大于黑虎帮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值