HTML Editor for VC++ 6.0

Introduction

Today, applications often need a rich user interface. One of them is ability to compose or edit HTML documents in an easy, effective, and reliable way. This article and source code attached give you a nice control to perform this task. And now, the best part: This control works fine with Microsoft VC++ 6.0!

Background

I'm author of the Tray Helper application. For a long time, I wanted to add a feature to send colorful HTML mail. After some research, I found that Microsoft did a nice thing implementing IHTMLDocument2 interface (and a few others related to it), but working with raw COM interfaces is not very easy, effective, or programmer-friendly. I think someone from Microsoft also realized that and in MFC 7.0 there is a very nice wrapper for COM: CHtmlEditCtrlBase class. After examining code from this class, I decided to port it to MFC 4.0 and VC++ 6.0.

Using the Code

The CHtmlEditCtrl2 class I want to introduce there is not only ported from CHtmlEditCtrlBase—I did some other improvements and changes to the orginal code—so it not only compiles under VC++ 6.0 but also has some new features and is even easier to use in existing projects. The main change was that CHtmlEditCtrl2 class derives from CWebBrowser2. It means that if your projects already use a standard Web browser control to display a HTML documents, adding editing capabilities would be trivial (read below for full instructions).

Adding HTML Editor to Your Projects

Step 1: Adding an ordinary Web browser control to your project

If you already use a Web browser control in your project, skip this paragraph and start reading from "Step 2."

Let's assume that you want add a HTML edit control to your dialog-based application. First, you need to add a Web browser control that will contain your HTML documents.

  • Go to the dialog template editor of Visual Studio and click on "Project / Add to project / Components and controls". From the resulting pop-up dialog, select "Registered active X controls" and finally find a select "Web Browser control" (the name of the control depends on language of your PC; for example, on my Polish version of Windows it is "Przegladarka Przeglądarka sieci Web firmy Microsoft"). To be sure that you're selecting a correct control, check the description below the file list; it should be "WebBrowser control".
  • After selecting a control, a dialog box with the CWebBrowser2 class to be created should appear. Click "OK" without any modifications.
  • Note that the new position should be added to the toolbar with a list of controls available to insert into the dialog. So, select it and just add a Web browser!
  • Finally, use a class wizard (Ctrl+W) to add a member variable of type CWebBrowser2 to the newly addeded item.
  • Next, you can add an OnInitdialog method to your dialog and request a browser to load a HTML document using the Navigate method of the CWebBrowser2 class.

Step 2: Adding edit capabilities to the Web browser

It's VERY easy. Just follow those few steps:

  • Copy the HtmlEditCtrl2.H and HtmlEditCtrl2.cpp directories with your source files and add them to your project.
  • Modify the header file where you have a member variable of CWebBrowser2 declared and change it to CHtmlEditCtrl2.
  • Change #include "WebBrowser2.H" to #include "HtmlEditCtrl2.H".
  • After loading an HTML document (using, for example, the Navigate method) call the SetDesignMode(TRUE) method to enable edit mode.
  • If, after editing is complete, you want to get a source of the HTML document, call the GetDocumentHTML function.

Highlights of the Most Important Methods of the Control
(Most Likely You Will Need to Use Them)

void Navigate(LPCTSTR URL, VARIANT* Flags, VARIANT* TargetFrameName,
              VARIANT* PostData, VARIANT* Headers)

Use this function to load an HTML document. Pass as an URL a string with a path to the file to open. It could be a remote site or a local file. The rest of the parameters could be null.

Examples:

Navigate("http://www.codeguru.com/", NULL, NULL, NULL, NULL);
Navigate("C:\\my_file.html", NULL, NULL, NULL, NULL);
BOOL SetDesignMode(BOOL bMode);

Enables or disables edit mode. In versions of Internet Explorer prior to 6.0, the document must be loaded in the first place to enter a design mode.

HRESULT GetDocumentHTML(CString& szHTML,
                        BOOL a_bClearDirtyFlag = FALSE);

Gets a content of HTML document.

HRESULT SetDocumentHTML(LPCTSTR szHTML);

Sets new contents of the HTML document. Please note that you can't call this function on an empty control. You need to load a document first (for example, by calling the Navigate method).

Complete List of Public Member Functions of the CHtmlEditCtrl2 Class

BOOL    SetDesignMode(BOOL bMode);
HRESULT ExecCommand(const GUID *pGuid, long cmdID, long cmdExecOpt,
        VARIANT* pInVar=NULL, VARIANT* pOutVar=NULL);
HRESULT ExecCommand(long cmdID, long cmdExecOpt,
        VARIANT* pInVar=NULL, VARIANT* pOutVar=NULL);
        long QueryStatus(long cmdID);
HRESULT GetEvent(IHTMLEventObj **ppEventObj);
HRESULT GetEventSrcElement(IHTMLElement **ppSrcElement);
HRESULT GetDocument(IHTMLDocument2** ppDoc);
HRESULT NewDocument();
HRESULT GetDocumentHTML(CString& szHTML,
                        BOOL a_bClearDirtyFlag = FALSE);
HRESULT SetDocumentHTML(LPCTSTR szHTML);
HRESULT GetIsDirty();
HRESULT GetDocumentTitle(CString& szTitle);
HRESULT GetBlockFormatNames(CStringArray &sa);
HRESULT SetForeColor(LPCTSTR szColor);
HRESULT SetForeColor(int nColor);
HRESULT GetForeColor(int &nColor);
HRESULT GetBackColor(int& nColor);
HRESULT SetBackColor(LPCTSTR szColor);
HRESULT SetBackColor(int nColor);

HRESULT SetDefaultComposeSettings(LPCSTR szFontName=NULL,
                  unsigned short nFontSize=3,
                  COLORREF crFontColor=0xFF000000,
                  COLORREF crFontBgColor=0xFF000000,
                  bool bBold = false,
                  bool bItalic = false,
                  bool bUnderline = false);

HRESULT GetBlockFormat(CString& strFormat);
HRESULT SetBlockFormat(LPCTSTR szFormat);
HRESULT GetFontFace(CString& strFace);
HRESULT SetFontFace(LPCTSTR szFace);
HRESULT IE50Paste(LPCTSTR szData);
HRESULT GetBookMark(CString& strAnchor);
HRESULT SetBookMark(LPCTSTR szAnchorName);
HRESULT SetOverwriteMode(bool bMode);
HRESULT Is1DElement(bool& bValue);
HRESULT Is2DElement(bool& bValue);
HRESULT GetFontSize(short& nSize);
HRESULT SetFontSize(unsigned short size);
HRESULT GetFrameZone(short& nZone);
HRESULT SetCSSEditingLevel(short nLevel);
HRESULT HyperLink(LPCTSTR szUrl = NULL);
HRESULT Image(LPCTSTR szUrl = NULL);
HRESULT OrderList(LPCTSTR szId = NULL);
HRESULT UnorderList(LPCTSTR szId = NULL);

HRESULT AddToGlyphTable(LPCTSTR szTag,
            LPCTSTR szImgUrl,
            unsigned short nTagType,
            unsigned short nAlignment,
            unsigned short nPosInfo,
            unsigned short nDirection,
            unsigned int nImgWidth,
            unsigned int nImgHeight);

HRESULT EmptyGlyphTable();
HRESULT Button(LPCTSTR szId = NULL);
HRESULT CheckBox(LPCTSTR szId = NULL);
HRESULT DropDownBox(LPCTSTR szId = NULL);
HRESULT HorizontalLine(LPCTSTR szId = NULL);
HRESULT Iframe(LPCTSTR szId = NULL);
HRESULT InsFieldSet(LPCTSTR szId = NULL);
HRESULT InsInputButton(LPCTSTR szId = NULL);
HRESULT InsInputHidden(LPCTSTR szId = NULL);
HRESULT InsInputImage(LPCTSTR szId = NULL);
HRESULT InsInputPassword(LPCTSTR szId = NULL);
HRESULT InsInputReset(LPCTSTR szId = NULL);
HRESULT InsInputSubmit(LPCTSTR szId = NULL);
HRESULT InsInputUpload(LPCTSTR szId = NULL);
HRESULT ListBox(LPCTSTR szId = NULL);
HRESULT Marquee(LPCTSTR szId = NULL);
HRESULT Paragraph(LPCTSTR szId = NULL);
HRESULT RadioButton(LPCTSTR szId = NULL);
HRESULT SaveAs(LPCTSTR szPath = NULL);
HRESULT TextArea(LPCTSTR szId = NULL);
HRESULT TextBox(LPCTSTR szId = NULL);
HRESULT GetAbsolutePosition(bool &bCurValue);
HRESULT SetAbsolutePosition(bool bNewValue);
HRESULT Set2DPosition(bool bNewValue);
HRESULT SetAtomicSelection(bool bNewValue);
HRESULT SetAutoURLDetectMode(bool bNewValue);
HRESULT SetDisableEditFocusUI(bool bNewValue);
HRESULT SetIE5PasteMode(bool bNewValue);
HRESULT SetLiveResize(bool bNewValue);
HRESULT SetMultiSelect(bool bNewValue);
HRESULT SetOverrideCursor(bool bNewValue);
HRESULT SetRespectVisInDesign(bool bNewValue);
HRESULT GetShowAlignedSiteTags(bool &bCurValue);
HRESULT SetShowAlignedSiteTags(bool bNewValue);
HRESULT GetShowAllTags(bool &bCurValue);
HRESULT SetShowAllTags(bool bNewValue);
HRESULT GetShowAreaTags(bool &bCurValue);
HRESULT SetShowAreaTags(bool bNewValue);
HRESULT GetShowCommentTags(bool &bCurValue);
HRESULT SetShowCommentTags(bool bNewValue);
HRESULT GetShowMiscTags(bool &bCurValue);
HRESULT SetShowMiscTags(bool bNewValue);
HRESULT GetShowScriptTags(bool &bCurValue);
HRESULT SetShowScriptTags(bool bNewValue);
HRESULT GetShowStyleTags(bool &bCurValue);
HRESULT SetShowStyleTags(bool bNewValue);
HRESULT GetShowUnknownTags(bool &bCurValue);
HRESULT SetShowUnknownTags(bool bNewValue);
HRESULT GetShowBRTags(bool &bCurValue);
HRESULT SetShowBRTags(bool bNewValue);
HRESULT PrintDocument();
HRESULT PrintDocument(LPCTSTR szPrintTemplate);
HRESULT PrintDocument(bool bShowPrintDialog);
HRESULT PrintPreview();
HRESULT PrintPreview(LPCTSTR szPrintTemplate);
HRESULT Bold();
HRESULT Copy();
HRESULT Cut();
HRESULT Delete();
HRESULT Indent();
HRESULT Italic();
HRESULT JustifyCenter();
HRESULT JustifyLeft();
HRESULT JustifyRight();
HRESULT Outdent();
HRESULT Paste();
HRESULT RemoveFormat();
HRESULT SelectAll();
HRESULT Underline();
HRESULT Unlink();
HRESULT ClearSelection();
HRESULT Font();
HRESULT RefreshDocument();
HRESULT UnBookmark();

//IZ: Added by Irek Zielinski: /////////////////////////////////
BOOL IsBold();
BOOL IsUnderline();
BOOL IsStrikeOut();
BOOL IsItalic();
BOOL CanPaste();

HRESULT LineBreakNormal();
BOOL    IsDesignMode();
HRESULT StrikeOut();
HRESULT GetURLsOfAllImages(CStringArray& a_arrImages);
HRESULT ReplaceImageURL(const CString& a_sUrlToReplace,
                        const CString& a_sUrlToReplaceWith);
HRESULT GetDocumentBody(CString& a_sBody, BOOL a_bTextInsteadHTML);
HRESULT Undo();
HRESULT Redo();
HRESULT Find();
HRESULT SubScriptSelectedText();
HRESULT SuperScriptSelectedText();
HRESULT SetDocumentCharset(const CString& a_sCharsetEncoding);
HRESULT GetDocumentCharset(CString& a_sCharsetEncoding);
HRESULT ShowSource();
HRESULT ShowIEOptionsDialog();

HRESULT GetBodyBackgroundImage(CString& a_sImage);
HRESULT SetBodyBackgroundImage(const CString& a_sImage);
HRESULT GetBodyProperties(CString& a_sTag);
HRESULT GetBodyBackgroundColor(CString& a_sColor);
HRESULT GetBodyTextColor(CString& a_sColor);
HRESULT GetBodyBackgroundCSSText(CString& a_sStyleText);
HRESULT PasteHTMLAtCurrentSelection(const CString& a_sHTMLText,
                   BOOL a_bSetCursorAtBeginingOfInsertedText);

The meaning and usage of nearly all of those functions is very easy to comprehend. Most of those functions are simple wrappers over COM calls; so, in case of any problems, check which COM function is being called and read about it in MSDN. The ultimate MSDN resource is a description of CHtmlEditCtrlBase class. Because my class is 80% only a port of CHtmlEditCtrlBase, I recommend that you read this page first (in case of any questions).

Here are some tips that could save you some time:

  1. Call the SetDesignerMode(TRUE) function when the document is loaded into the control. Doing it just after calling Navigate(url...) could be too early. (The function will fail on a machine where a version of Internet Explorer prior to 6.0 is installed.)
  2. If you create an empty HTML document and start editing it, you will quickly realize that pressing the Enter key inserts a paragraph, not a line break. This default behavior is pretty irritating and could be solved in two ways: First, you could press SHIFT + ENTER instead, or load into the HTML control such an HTML document as this:
  3. <HTML>
    <BODY>
    <DIV>&nbsp;</DIV>
    </BODY>
    </HTML>

At this point of the article, I would like to wish you good luck in creating a killer applications. Sorry for my English; it's not my native language.

Points of Interest

MSDN pages about CHtmlEditCtrlBase class.

MSDN pages about IHTMLDocument2 interface.

MSDN Programming and Reusing the Browser Overviews and Tutorials



Downloads

Comments

  • Can you tell me how to set the font color? the function SetForeColor doesn't work,Thank you.

    Posted by Sanhan on 08/08/2004 09:03am

    I tried for many times,but the SetForeColor function doesn't work,can you help me?Thank you very much,your code helped me a lot

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • 10 Rules that Make or Break Enterprise App Development Projects In today's app-driven world, application development is a top priority. Even so, 68% of enterprise application delivery projects fail. Designing and building applications that pay for themselves and adapt to future needs is incredibly difficult. Executing one successful project is lucky, but making it a repeatable process and strategic advantage? That's where the money is. With help from our most experienced project leads and software engineers, …

  • IT decision support impacts all aspects of technology management, from governance and strategy to budgets and resource planning. IT decision support effectiveness often falls prey to data-driven challenges that make it difficult to understand the data in context. These challenges: overwhelming data volumes, heterogeneous data types, and growing data complexity. This Forrester Consulting Paper reports the three key findings from their study conducted, on behalf of BDNA, to test the hypothesis that data …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds