WTL 程序中显示 HTML

在 MFC 程序中有专门封装的 CHTMLView 来显示 HTML 文件,如果在对话框中显示网页可以使用 CDHTMLDialog ,甚至多页 HTML 向导风格的对话框都可以使用实现,但是在 WTL 中却没有单独封装 HTML 的对应控件,这是因为 COM 组件的使用和编写本来就是 ATL 的强项,WTL扩展的是 ATL 欠缺的桌面应用的功能部分,所以即使不使用 WTL 也可以使用 ATL 的基本功能来显示 HTML ,首先来看如何显示一个 HTML:

struct CWelcomePage : public CWindowImpl< CWelcomePage , CAxWindow >
{
    DECLARE_WND_SUPERCLASS( TEXT(
"WelcomePage") ,  CAxWindow::GetWndClassName( ) )
    BEGIN_MSG_MAP_EX( CWelcomePage )

    END_MSG_MAP( )
};
在上面的类声明中,可以看到和普通的每一什么差别,唯一不同的就是基类使用 CAxWindow 而不是 CWindow
然后创建窗口的使用将窗口标题指定为对应的网址就可以了,如下所示:
CWelComePage WelcomePage;

WelcomePage.Create( m_hWnd , rcDefault , TEXT(
"http://www.microsoft.com"), dwStyle);
现在该窗口将自动通过 Internet 加载并显示微软网站的首页,这一切太简单了吧!就像是魔术一般不是吗?
现在我们要搞明白为什么会如此,否则职业病(  C++ 程序员的职业病就是一切都要搞明白原理才肯罢休 )发作会寝室不安的;
首先我们来看当我们声明了一个从 CAxWindow 集成类的实例时 ATL 干了什么:在 CAxWindow 的构造函数中调用了 AtlAxWinInit 函数,这个函数注册了两个特定的消息用来实现 CAxWindow 对宿主和内部包含的COM控件的获取,更重要的是注册了一个叫做 ATLAXWIN_CLASS 的窗口类(ATLAXWIN_CLASS 是一个宏,在 VS2008 附带的 ATL 中被定义为 “AtlAxWin90” ),这个窗口类的窗口函数不是普通的窗口那样使用一个起始函数,然后内部去初始化 chunk,而是使用了一个全局静态函数:AtlAxWindowProc , 我们来看看该函数的实现:
哦,看到了 WM_CREATE 消息的处理,在这个消息处理中,如果窗口的标题不是空的, 那么使用窗口标题最为首参数调用 AtlAxCreateControlLic , 该函数内部直接调用 AtlAxCreateControlLicEx ,函数 AtlAxCreateControlLicEx  内部创建一个 CAxHostWindow ,然后调用该实例的 CreateControlLicEx 函数,哦,好累啊,怎么这么多层次啊,插一插汗继续,恩, 继续跟踪到 CreateNormalizedObject 函数内部,啊哦,终于找到了,在该函数内部根据传入的字符串来决定创建什么:如果是 "MSHTML:"(不区分大小写)那么创建 HTMLDocument 对象;否则如果发现包含“:”,那么创建 WebBrowser 对象;否则检查是否为 CLSID 的字符串格式(即第一个字符是‘{’),并转换为 CLSID,如果转换成功那么使用该 CLSID 创建对象;
恩,对象创建出来了,那网页是什么时候加载并显示的呢?继续.......
CreateNormalizedObject 函数创建完了控件返回到 CreateControlLicEx,继续向下代码实现是,如果是 “MSHTML:” ,那么获取 IPersistStreamInit 接口掉哟个 Load ,否则尝试获取 IWebBrowser2 接口,如果包含该接口则调用 Navigate2 ,至此魔术的外衣已经掀开,一切都明朗了;
posted @ 2009-07-17 08:37  王志科  阅读(2341)  评论(0编辑  收藏  举报