Wednesday, March 16, 2016

HTML display on a dialog (MFC)

There is a serious disconnect in the MFC with HTML formatted strings and displaying them on anything *other* than a pure HTMLedit control or HTML Doc/View based full frame windows.  I have no idea how they got to that point, but the lack is extreme.  Of course, people will point out that moving to Qt, wx, or .NET would address this, but the realities of legacy code make this a tough bite to chew.

So here is a solution, imperfect, but workable:  Subclass an existing dialog control (I use a picture control in this example) as a HTMLView.  The idea and following implementation is an amalgam of a number of things I found searching for solutions and altered based on failures in use.  The major contribution was Jean-Claude Lanz.


  • Add a picture control to your dialog in the area you want the view to appear (IDC_HTML in this example).
  • Add afxhtml.h to your stdafx.h:
#include <afxhtml.h>

  • Add a member variable to the dialog class for holding the view:

CView* m_pView;

  • Add the following construction function (swiped from ) to the top of your cpp file for your dialog:

 CWnd* CreateNewView(CCreateContext* pContext, CWnd *pParent, CRect& rect, int wID)
{
  CWnd* pWnd = NULL;

 if (pContext != NULL)
  {
    if (pContext->m_pNewViewClass != NULL)
    {
      pWnd = (CWnd*)pContext->m_pNewViewClass->CreateObject();
      if (pWnd == NULL)
      {
        TRACE1("Error: Dynamic create of view %Fs failed\n", pContext->m_pNewViewClass->m_lpszClassName);
        return NULL;
      }
      ASSERT(pWnd->IsKindOf(RUNTIME_CLASS(CWnd)));

     if (!pWnd->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, rect, pParent, wID, pContext))
      {
        TRACE0("Error: couldn't create view \n");
        return NULL;
      }
      // send initial notification message
      pWnd->SendMessage(WM_INITIALUPDATE);
    }
  }
  return pWnd;
}


  • In your OnInit() create a context:

 CCreateContext cc;
  cc.m_pNewViewClass = RUNTIME_CLASS(CHtmlView);
  cc.m_pCurrentDoc = NULL;
  cc.m_pNewDocTemplate = NULL;
  cc.m_pLastView = NULL;
  cc.m_pCurrentFrame = NULL;

  • ...Create the View

 m_pView = (CHtmlView*)CreateNewView(&cc, this, CRect(0, 0, 0, 0), 0);
  if (m_pView == NULL)
    EndDialog(IDCANCEL);

  •  ...place the View in the view rectangle from the picture control:

  CRect rect;
  GetDlgItem(IDC_HTML)->GetWindowRect(&rect);
  ScreenToClient(rect);
  m_pView->MoveWindow(&rect);


  • Wherever you want to display the HTML:

std::ofstream myfile;
myfile.open ("/blah/blah/v.html");
myfile << *html text string from memory here*;
myfile.close();
((CHtmlView*)m_pView)->Navigate2("file:///blah/blah/v.html");



Of course any number of changes on the views properties can be set to change appearance.

No comments:

Post a Comment