Click here to Skip to main content
Click here to Skip to main content

Using MSHTML Editing in VC6 Doc/View Applications

By , 25 Apr 2004
 
<!-- Download Links --> <!-- Article image -->

Sample Image - htmleditvc6.jpg

<!-- Add the rest of your HTML here -->

Introduction

I've recently published a couple of articles on CodeProject covering customisation of the MSHTML editor. Those articles are VC7 and MFC7 specific. Naturally there have been some posts asking how one can do the same things using VC6. This article will show you how you can use the MSHTML editor in a VC6 MFC document/view application.

Background

The version of MFC that ships with VC6 includes support for displaying HTML documents in a view. You derive your view class from the CHtmlView class, override a few virtual methods and voila, there's an embedded HTML display in your app.

MFC7, as shipped with VC7, extends this to include a CHtmlEditView class. See this [^] article for a quick overview of the class.

Scope of this article

I didn't set out to completely rewrite the CHtmlEditView class. Instead, I'll show you how to put the MSHTML control into edit mode and show how to implement the various commands it supports. You'll have to do most of the work yourself.

Structural differences between this implemenation and the MFC one

MFC adds HTML editing capability to CHtmlView by bolting on a class called CHtmlEditCtrlBase which actually implements the low level details. They did it that way so they could reuse the code in the CHtmlEditCtrl class (also new to MFC7). Being a lazy sod I chose to add the edit support into a direct derivative of CHtmlView called (so as not to conflict with MFC's naming) CHtmlEditorView.

Putting MSHTML into edit mode

is trivial. All you do is get an IHTMLDocument2 interface for the document being displayed and call the put_designMode(() function passing a case sensitive BSTR specifying edit mode as either On or Off. You can only do this once a document has been loaded into MSHTML and each time you navigate to a new document you need to repeat the process. I do it in the OnNavigateComplete2() event handler. In code it looks like this.
void CHTMLEditorView::OnNavigateComplete2(LPCTSTR strURL) 
{
    BSTR bs = SysAllocString(L"On");

    CHtmlView::OnNavigateComplete2(strURL);

    //  Get a pointer to our document
    m_pHTMLDoc = (IHTMLDocument2 *) GetHtmlDocument();
    
    if (m_pHTMLDoc != (IHTMLDocument2 *) NULL)
        m_pHTMLDoc->put_designMode(bs);

    SysFreeString(bs);
}
which will always force the document into edit mode. Once that's done you can click around on the document to your hearts content changing things, moving them around and generally messing up the page.

What about formatting the content?

That's the next step. The IHTMLDocument2 interface has an execCommand() method that lets you execute commands on the current selection in the MSHTML editor. For the purpose of this article I've only implemented the Bold command, which looks like this.
void CHTMLEditorView::Bold(BOOL bState)
{
    BSTR         bCmd = SysAllocString(L"Bold");
    VARIANT_BOOL vb;
    VARIANT      vValue;

    vValue.vt = VT_BOOL;
    vValue.boolVal = bState;

    if (m_pHTMLDoc != (IHTMLDocument2 *) NULL)
        m_pHTMLDoc->execCommand(bCmd, VARIANT_FALSE, vValue, &vb);

    SysFreeString(bCmd);
}
we set up a BSTR containing our command verb and a VARIANT containing the desired state. Then we call IHTMLDocument2::execCommand to actually execute the command. The second parameter in the call indicates that we don't want any user interface shown. In the case of the Bold command there isn't a user interface required but some other commands may support one. That second parameter gives us the chance to suppress the user interface if we wish. The fourth parameter is a pointer to a VARIANT_BOOL which recieves a value indicating the success of the operation.

All of the MSHTML commands follow this pattern however it should be clear that the variant type you assign to the variant depends on the datatype which in turn depends on the command. Setting the font face requires a string, setting the text colour requires a specially formatted string and so forth.

Querying the current state of a selection

is done using the IHTMLDocument2::QueryCommandState() or IHTMLDocument2::QueryCommandValue() methods. In each case you pass the name of the command you're querying (for example, is the selection bolded?) and a location to return the value. The demo project has a button on the toolbar to let you toggle Bold on selected text. Naturally it's expected that if the selection is already bold the button will be depressed indicating that fact. So whenever we change the selection we need to query the Bold state. The code to do this looks like
BOOL CHTMLEditorView::Bold()
{
    BSTR         bCmd = SysAllocString(L"Bold");
    VARIANT_BOOL vb = FALSE;

    if (m_pHTMLDoc != (IHTMLDocument2 *) NULL)
        m_pHTMLDoc->queryCommandState(bCmd, &vb);

    SysFreeString(bCmd);
    return vb;
}
which queries the document for the Bold state. This is returned in the VARIANT_BOOL which we simply return to the caller. The IHTMLDocument2::queryCommandState() method works only for BOOL properties. If we wanted to query the font name we'd do it like this
CString CHTMLEditorView::FontName()
{
    BSTR    bCmd = SysAllocString(L"FontName");
    VARIANT vb;
    CString csValue;

    if (m_pHTMLDoc != (IHTMLDocument2 *) NULL)
        m_pHTMLDoc->queryCommandValue(bCmd, &vb);

    SysFreeString(bCmd);
    
    if (vb.vt == VT_BSTR)
        csValue = CW2CT(vb.bstrVal);

    return csValue;
}
which receives the return value in a VARANT. Then it checks that the return value is indeed a string; if so it converts it from the BSTR returned in the VARIANT to a CString and returns the CString. If the return value isn't a string the conversion attempt doesn't take place and the empty CString is returned instead. Naturally the caller needs to allow for the case where an empty CString is returned, which might happen if one were to execute a font name query on an image, which leads to the next topic.

Determing if a command can be executed

This is done by calling the IHTMLDocument2::queryCommandEnabled() method. This takes the command name and a pointer to a VARIANT_BOOL which receives the return value. If the command is valid for the current selection you get back TRUE, otherwise you get back FALSE. The code that determines if the Bold command is valid for the current selection looks like this.
BOOL CHTMLEditorView::CanBold()
{
    BSTR         bCmd = SysAllocString(L"Bold");
    VARIANT_BOOL vb = FALSE;

    if (m_pHTMLDoc != (IHTMLDocument2 *) NULL)
        m_pHTMLDoc->queryCommandEnabled(bCmd, &vb);

    SysFreeString(bCmd);
    return vb;
}
which is almost identical to querying the current value.

Putting it all together

So now we have the code in place to set Bold on the current selection, determine if the current selection is Bold or not and determine if the current selection can be Bolded. We'd use that code in our toolbar Bold button command handler and UI state update handler like this.
void CHTMLEditorView::OnBold() 
{
    Bold(Bold() ? 1 : 0);
}

void CHTMLEditorView::OnUpdateBold(CCmdUI* pCmdUI) 
{
    pCmdUI->SetCheck(Bold() ? 1 : 0);
    pCmdUI->Enable(CanBold());
}
which is trivial in the extreme.

What commands are available?

I refer you to the IHTMLDocument2::execCommand() documentation available online at MSDN for the exhaustive list. I'm not providing a URL because MSDN sometimes change things around on their site and invalidate links.

Wich versions of Microsoft Internet Explorer will this work with?

According to the MSDN documentation the IHTMLDocument2 interface was added in version 4.0 of Microsoft Internet Explorer. It's probably safe to assume that almost every Windows machine you install your code on will have at least that version. You may run across the occasional command that requires a later version of Internet Explorer - if so the MSDN documentation will list version requirements.

Using the code

The source file download contains a copy of the CHtmlEditorView header and implementation files. As aforesaid I've only implemented the Bold command - it's up to you to add handlers for any other commands you're interested in. The class does include an override of OnNavigateComplete2() which puts the document into edit mode.

You derive your own class from this, or use the class directly if you wish.

History

26 April 2004 - Initial version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Rob Manderson

United States United States
I've been programming for 35 years - started in machine language on the National Semiconductor SC/MP chip, moved via the 8080 to the Z80 - graduated through HP Rocky Mountain Basic and HPL - then to C and C++ and now C#.
 
I used (30 or so years ago when I worked for Hewlett Packard) to repair HP Oscilloscopes and Spectrum Analysers - for a while there I was the one repairing DC to daylight SpecAns in the Asia Pacific area.
 
Afterward I was the fourth team member added to the Australia Post EPOS project at Unisys Australia. We grew to become an A$400 million project. I wrote a few device drivers for the project under Microsoft OS/2 v 1.3 - did hardware qualification and was part of the rollout team dealing directly with the customer.
 
Born and bred in Melbourne Australia, now living in Scottsdale Arizona USA, became a US Citizen on September 29th, 2006.
 
I work for a medical insurance broker, learning how to create ASP.NET websites in VB.Net and C#. It's all good.
 
Oh, I'm also a Kentucky Colonel. http://www.kycolonels.org

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalconverting text file to html filememberbohjkly14-Jun-09 19:42 
hello everybody,
I have a text file which includes information of employees I want to convert this text file in HTML file and display the content of file in browser.I have to do this using c++
 
Thanks in advance
GeneralMSHTML DOMmemberxgnitesh5-Jun-05 21:16 
Hi
Can I access Microsoft's HTML DOM using MFC. Are there any samples available for me to get started?
Any samples without MFC would also be helpful.
Thanks
Nitesh
GeneralContext MenumemberCrercio O. Silva7-Feb-05 2:15 
Hi,
 
Very nice article. I've been looking for that for something like that for quite a long time. Thanks.
How can we intercept the context menu and know that the options "properties" was clicked? Is it possible to know which element is selected and get other info from it?
 
Best Regards,
 

 
Crercio O. Silva / DBTools Software
http://www.dbtools.com.br
GeneralRe: Context Menumemberyuhaian9-Mar-05 13:31 
See IDocHostUIHandler interface at MSHTML in MSDN site.
 
to disable context menu, using:
 
<body contextmenu="return false">

 
---
Herbert Yu
Are you sure the speed of computer industry is proper? Are you sure the software you released is a bug free one?
GeneralExcellent ArticlememberSotiris Salloum31-Jan-05 8:39 
It was a pleasure reading it and even more developing one application with the article without the need to move to MFC7. Thank you.
GeneralRe: Excellent ArticleprotectorRob Manderson31-Jan-05 18:53 
Thanks for the kind words Smile | :)
 
Rob Manderson
 
I'm working on a version for Visual Lisp++
 
My (occasional) blog http://blogs.wdevs.com/ultramaroon/[^]

GeneralGetFont() function as coded does not work.memberErik Larson26-Aug-04 9:20 
I found that the GetFont() function presented above was always returning a blank string for me. I had to modify the function to set the VARIANT type to BSTR and initialize the vb.bstrVal before the call to queryCommandValue. This seems to have fixed the problem for me.
 
My additions to the code are in bold below.
 
CString CHTMLEditorView::FontName()
{
    BSTR    bCmd = SysAllocString(L"FontName");
    VARIANT vb;
    vb.vt = VT_BSTR;
    vb.bstrVal = SysAllocString(L"");

    CString csValue;
 
    if (m_pHTMLDoc != (IHTMLDocument2 *) NULL)
        m_pHTMLDoc->queryCommandValue(bCmd, &vb);
 
    SysFreeString(bCmd);
    
    if (vb.vt == VT_BSTR)
        csValue = CW2CT(vb.bstrVal);
 
    SysFreeString(vb.bstrVal);
    return csValue;
}

GeneralCheck if content goes outside visible areamembersanskypotov19-Aug-04 23:49 
Hi,
I am trying to restrict user from entering data that would exceed out of a fixed editable area.
Any ideas how can I put such restriction.
Thanks,
Big Grin | :-D
 
John 3:16

For God so loved the world,

that he gave his only begotten Son ( Jesus Christ ) ,

that whosoever believeth in him should not perish, but have everlasting life.

GeneralRe: Check if content goes outside visible areamemberLeonhardt Wille2-May-06 22:54 
Hi there,
I know this post is quite old - but I am also working on this for almost two years. I also needed a restricted editing area (about 350x400px of a 800x600 document) where the user has no chance to leave this area.
I have solved this problem by creating a HTML Edit View (with the size of the editable area) on top of a HTML View.
Between editing view and HTML view is a transparent window that just has the purpose to intercept mouse and keyboard input, so that the user can't click on the HtmlView below.
As the editable area is now a different window, I have to extract the text from the editable portion of the document and put it (together with formatting) into the editing window. I also copy the <style> tag and the opening <body> from the document to the editing window, so that formatting will also be applied to this window.
To make the editing area look transparent, I use a mod of Rob's code here[^] to render the document into an image, extract a portion from it and set it as the background image of the editing area...
 
I know this is quite a big effort for a relatively simple demand, but with this solution the user has no chance of getting out of the editable area.
If you need some further hints or code snippets, just drop a mail.
 
I want to thank Rob again for that he always uses to write an article when I run into some strange problems... I suspect him to be a secret employee at my company, spying at my projects all the time and, after figuring my problems out, posting an article at CP Big Grin | :-D
GeneralXML Editing in ViewmemberVikram Kashyap30-Jul-04 19:24 
Hi Rob,
 
Can u please help me doing the same thing using XML, as I've trying to do it using CHTMLEditView in Visual C++ .Net programming. It would be a great help to me from your side. My only motive is that I should be able to edit the XML file while in the preview mode (i,e. in WEB view or wat we call it as WYSIWYG). Currently I am having a SDI application with Doc/View architechture using CHTMLEditView as the base class, addition to it I've added CRichEditView where the user can view the source of the currently opened XML file and edit the same. It is working file, as I'm just opening the file using CFile pointers, saving it after editing and again Navigating the same using its path in the CHTMLEditView. Kindly help in the same...
 
Let me know if the same can be done in VC6 Doc/View.
Thankx
Cry | :((
 
Vikram Kashyap
Sr. Software Engineer
TechBooks International
R&D Division
GeneralNice Article!!! But............memberKoundinya24-Jun-04 19:26 
Hi Rob,
 
This is a nice Article but how can I implement the same in Dialog Based application.
 
Thanks
Sudhakar
GeneralRe: Nice Article!!! But............memberyuhaian9-Mar-05 13:34 
There is a CHTMLCtrl class. do a search on CHTMLCtrl on microsoft.com in google.com and you can find it.
 
---
Herbert Yu
Are you sure the speed of computer industry is proper? Are you sure the software you released is a bug free one?
GeneralFull HTML edit control fo VC++ 6.0memberIrek Zielinski3-Jun-04 4:47 
If you need a full HTML edit control for VC++ 6.0 read this article:
http://www.codeproject.com/useritems/HtmlEdit.asp
 
Check out my software at: http://www.ireksoftware.com
GeneralSource ViewmemberMarcus Carey4-May-04 12:29 
How do you edit and save the html source code?
 
Marcus Carey
GeneralNice!memberCloaca27-Apr-04 10:31 
But... I should like to see a QBasic version. Could you code that up for me please?
I keeed, I keeed! Wink | ;)
This was a helpful article for me, and is much appreciated.
 
Best,
Eric
GeneralRe: Nice!memberRob Manderson27-Apr-04 11:37 
Heh Smile | :) I'm working on a version for Visual Lisp++ Smile | :)
 
Rob Manderson
 
Colin Davies wrote: I'm sure Americans could use more of it, and thus reduce the world supply faster. This of course would be good, because the faster we run out globally, the less chance of pollution there will be. (Talking about the price of petrol) The Soapbox, March 5 2004

GeneralRe: Nice!memberJubjub28-Apr-04 13:30 
Fortran.NET ?
GeneralPlatinummemberJubjub26-Apr-04 16:08 
Hey Rob,
 
good article. I noticed also that the CPians wanted proof that you could do what you were doing in V7.1, in VC6 also. Good job.
 
Shouldn't this make you Platinum now, or do you go straight from Gold to Woody? Hehe
 
Jubjub
GeneralRe: PlatinummemberRob Manderson27-Apr-04 0:33 
Jubjub wrote:
do you go straight from Gold to Woody?
 
Not at my age Smile | :)
 
Rob Manderson
 
Colin Davies wrote: I'm sure Americans could use more of it, and thus reduce the world supply faster. This of course would be good, because the faster we run out globally, the less chance of pollution there will be. (Talking about the price of petrol) The Soapbox, March 5 2004

QuestionATL/WTL version?memberYasuhiko Yoshimura26-Apr-04 15:30 
Thanks a nice article.
But I would like to see atl/wtl version;)

AnswerRe: ATL/WTL version?memberShanghaier1-May-04 21:12 
nice. very cool

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130617.1 | Last Updated 26 Apr 2004
Article Copyright 2004 by Rob Manderson
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid