Figure 1   CHtmlCtrl

HtmlCtrl.h


 // Microsoft Systems Journal -- January 2000
 // If this code works, it was written by Paul DiLascia.
 // If not, I don't know who wrote it.
 // Compiles with Visual C++ 6.0, runs on Windows 98 and probably Windows NT too.
 //
 class CHtmlCtrl : public CHtmlView {
 public:
    CHtmlCtrl() { }
    ~CHtmlCtrl() { }
 
    BOOL CreateFromStatic(UINT nID, CWnd* pParent);
 
    // Normally, CHtmlView destroys itself in PostNcDestroy,
    // but we don't want to do that for a control since a control
    // is usually implemented as a stack object in a dialog.
    //
    virtual void PostNcDestroy() {  }
 
    // overrides to bypass MFC doc/view frame dependencies
    afx_msg void OnDestroy();
    afx_msg int  OnMouseActivate(CWnd* pDesktopWnd,UINT nHitTest,UINT message);
 
    // override to trap "app:" pseudo protocol
    virtual void OnBeforeNavigate2( LPCTSTR lpszURL,
       DWORD nFlags,
       LPCTSTR lpszTargetFrameName,
       CByteArray& baPostedData,
       LPCTSTR lpszHeaders,
       BOOL* pbCancel );
 
    // override to handle links to "app:mumble...". lpszWhere will be "mumble"
    virtual void OnAppCmd(LPCTSTR lpszWhere);
 
    DECLARE_MESSAGE_MAP();
    DECLARE_DYNAMIC(CHtmlCtrl)
 };
HtmlCtrl.cpp

 // Microsoft Systems Journal -- January 2000
 // If this code works, it was written by Paul DiLascia.
 // If not, I don't know who wrote it.
 // Compiles with Visual C++ 6.0, runs on Windows 98 and probably Windows NT too.
 //
 #include "StdAfx.h"
 #include "HtmlCtrl.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
 #undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
 #endif
 
 IMPLEMENT_DYNAMIC(CHtmlCtrl, CHtmlView)
 BEGIN_MESSAGE_MAP(CHtmlCtrl, CHtmlView)
    ON_WM_DESTROY()
    ON_WM_MOUSEACTIVATE()
 END_MESSAGE_MAP()
 
 //////////////////
 // Create control in same position as an existing static control with
 // the same ID (could be any kind of control, really)
 //
 BOOL CHtmlCtrl::CreateFromStatic(UINT nID, CWnd* pParent)
 {
    CStatic wndStatic;
    if (!wndStatic.SubclassDlgItem(nID, pParent))
       return FALSE;
 
    // Get static control rect, convert to parent's client coords.
    CRect rc;
    wndStatic.GetWindowRect(&rc);
    pParent->ScreenToClient(&rc);
    wndStatic.DestroyWindow();
 
    // create HTML control (CHtmlView)
    return Create(NULL,                  // class name
       NULL,                             // title
       (WS_CHILD | WS_VISIBLE ),         // style
       rc,                               // rectangle
       pParent,                          // parent
       nID,                              // control ID
       NULL);                            // frame/doc context not used
 }
 
 ////////////////
 // Override to avoid CView stuff that assumes a frame.
 //
 void CHtmlCtrl::OnDestroy()
 {
    // This is probably unecessary since ~CHtmlView does it, but
    // safer to mimic CHtmlView::OnDestroy.
    if (m_pBrowserApp) {
       m_pBrowserApp->Release();
       m_pBrowserApp = NULL;
    }
    CWnd::OnDestroy(); // bypass CView doc/frame stuff
 }
 
 ////////////////
 // Override to avoid CView stuff that assumes a frame.
 //
 int CHtmlCtrl::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT msg)
 {
    // bypass CView doc/frame stuff
    return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, msg);
 }
 
 //////////////////
 // Override navigation handler to pass to "app:" links to virtual handler.
 // Cancels the navigation in the browser, since app: is a pseudo-protocol.
 //
 void CHtmlCtrl::OnBeforeNavigate2( LPCTSTR lpszURL,
    DWORD nFlags,
    LPCTSTR lpszTargetFrameName,
    CByteArray& baPostedData,
    LPCTSTR lpszHeaders,
    BOOL* pbCancel )
 {
    const char APP_PROTOCOL[] = "app:";
    int len = _tcslen(APP_PROTOCOL);
    if (_tcsnicmp(lpszURL, APP_PROTOCOL, len)==0) {
       OnAppCmd(lpszURL + len);
       *pbCancel = TRUE;
    }
 }
 
 void CHtmlCtrl::OnAppCmd(LPCTSTR lpszWhere)
 {
    // default: do nothing
}

Figure 2   AboutHtml


 <HTML>
 
 <HEAD>
 <BASE url="res://AboutHtml.exe/about.htm">
 <TITLE>CHtmlCtrl About Page</TITLE>
 <META http-equiv="Page-Enter" content="blendTrans(Duration=1.0)">
 <BGSOUND loop="1" src="mozart.wav">
 </HEAD>
 
 <STYLE>A:hover { color:#FF00C0 }</STYLE>
 
 <SCRIPT LANGUAGE="JavaScript">
     var okImages = new Array(2);
     okImages[0]  = new Image();
     okImages[1]  = new Image();
     okImages[0].src = "okup.gif";
     okImages[1].src = "okdn.gif";
     function OnClickOK(bDown) {
         okImage.src = okImages[bDown].src;    
     }
 </SCRIPT>
 
 <BODY scroll=no link="#02B7B7" vlink="#02B7B7">
 
 <TABLE border="0" width="100%" cellspacing="0" cellpadding="0">
 
 <TR><TD width="15%" valign="top">
 <a target="newwin" href="http://pobox.com/~askpd">
 <img src="pd.jpg" border="0" alt="Yours Truly" width="83" height="90">
 </a></TD>
 <TD width="85%" valign="top">
 <p align=right><FONT size=1><B>HTMLCTRL</b>Copyright 1999<br>
 <a target="newwin" href="http://microsoft.com/msj">Microsoft 
 Systems Journal</a><br>
 Written by <a target="newwin" href="http://pobox.com/~askpd">Paul DiLascia</a>
 </FONT></TD>
 </TR>
 
 <TR>
 <TD width="100%" colspan="2"><br>
 <FONT size=1>This program shows how to implement a new class,
 <b>CHtmlCtrl</b>, derived from <b>CHtmlView</b> with minor modifications, to
 implement web pages you can embed in dialogs such as this About box. It also
 shows how to embed HTML files as resources within your EXE or DLL. You can
 read all about it in my C++ Q&amp;A column in the January 2000 issue of
 <a href="http://microsoft.com/msj" target="newwin">MSJ</a>.
 <P>
 You might think this is frivolous, but actually it's way cool! You can even
 write some <b>JavaScript</b> or <b>DHTML</b> to do animations--HTML is just
 the ticket for implementing late-nite EXE easter eggs.
 </FONT>
 </TD>
 </TR>
 
 <TR>
 <TD width="100%" colspan="2"><br>
 <b><SMALL><a target="newwin" href="http://www.webpagesthatsuck.com"><marquee
 border="2" style="color: rgb(2,183,183); text-decoration: none; font-family:
 Tahoma" bgcolor="#E2FCFC" scrollamount="3" scrolldelay="60" width="100%"
 height="13">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Marquees
 like this are really grody....&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Click to find out why...
 </marquee></a></SMALL></b>
 </TD>
 
 </TR>
 <TR>
 <TD width="28%"></TD>
 
 <TD width="72%">&nbsp;<p>
 <a onMouseDown="OnClickOK(1);"
     onMouseUp="OnClickOK(0);" 
     onMouseOut="OnClickOK(0);" href="app:ok">
 <img name="okImage" src="okup.gif" align="right" border="0" width="80"
 height="20"></a>
 </TD>
 </TR>
 
 </TABLE>
 </BODY>
 </HTML>