If you’ve been heads-down on a Visual C++ project and haven’t had time to peek at HTML, it’s an ASCII mark-up language format. Here’s a very basic look at a simplistic HTML page:
<html>
<head>
<title>
This is an example of a very basic HTML page!
</title>
</head>
<body>
<h1>This is some text with H1!
</h1>
<h3>
This is some text with H3!
</h3>
</body>
</html>
This basic HTML “document” is composed of several “elements.” The head (or header) contains the title: “This is an example of a very basic HTML page!” Next, the body of the document contains two elements. The first element has a style of heading 1 (h1) and reads:
“This is some text with H1!” The last element includes text with style heading 3 (h3) that reads: “This is some text with H3!”
Figure 11: DHTML object model hierarchy
Graphic from Inside Dynamic HTML by Scott Isaacs. Reproduced by permission of Microsoft Press. All rights reserved.
When IE loads this HTML page, it creates an internal representation that you can traverse, read, and manipulate through the DHTML object model. Figure 11 shows the basic hierarchy of the DHTML object model.
At the root of the object model is the window object. This object can be used from a script to do something like pop-up a dialog box. Here’s an example of some script that accesses the window object:
<SCRIPT LANGUAGE="JavaScript">
function about() {
window.showModalDialog("about.htm","", "dialogWidth:25em;dialogHeight13em") }
</SCRIPT>
When the about script is called, it in turn calls the showModalDialog( ) function in the window DHTML object to display a dialog. This example also illustrates how scripts access the object model—through globally accessible objects that map directly to the corresponding object in the DHTML object model.
The window object has several “sub” objects that further allow you to manipulate portions of IE4. The document object is what you’ll spend most of your time on when writing DHTML code, because it gives you programmatic access to the various elements of the HTML
document currently loaded. The following script shows how to create basic dynamic content that changes the document object:
<HTML>
<HEAD>
<TITLE>Welcome!</TITLE>
<SCRIPT LANGUAGE="JScript">
function changeMe() {
document.all.MyHeading.outerHTML = "<H1
ID=MyHeading>Dynamic HTML is magic!</H1>";
document.all.MyHeading.style.color = "green";
document.all.MyText.innerText = "Presto Change-o! ";
document.all.MyText.align = "center";
document.body.insertAdjacentHTML("BeforeEnd", "<P ALIGN=\"center\">Open Sesame!</P>");
}
</SCRIPT>
<BODY onclick="changeMe()">
<H3 ID=MyHeading> Dynamic HTML demo!</H3>
<P ID=MyText>Click anywhere to see the power of DHTML!</P>
</BODY>
</HTML>
This script changes the MyHeading and MyText objects in the HTML documents on-the-fly.
Not only does it change the text, but it also changes attributes of the elements such as the color and alignment. This script is included with this article on www.vcdj.com.
Before we further decompose the DHTML object model, you need to understand the DHTML concept of a “collection.” Collections in DHTML are logically equivalent to C++ data
structures such as linked lists. In fact, access to the DHTML object model is largely
performed by iterating through collections searching for a particular HTML element and then potentially iterating through another sub-collection to get to yet another element. Elements contain several methods such as “contains” and “length,” which you use to traverse through the elements.
For example, one of the sub-elements of the document object is a collection called “all” that contains all of the document’s elements. In fact, most of the sub-objects of the document
object are collections. The following script shows how to iterate through the “all” collection and lists the various items of a document.
<HTML>
<HEAD><TITLE>Iterating through the all collection.</TITLE>
<SCRIPT LANGUAGE="JScript">
function listAllElements() { var tag_names = "";
for (i=0; i<document.all.length; i++) tag_names = tag_names +
document.all(i).tagName + " ";
alert("This document contains: " + tag_names);
}
</SCRIPT>
</HEAD>
<BODY onload="listAllElements()">
<H1>DHTML Rocks!</H1>
<P>This document is <B>very</B> short.
</BODY>
</HTML>
Notice how easy it is to retrieve items with script (using parentheses similar to how we access an array in C++)? Also notice that each element in an HTML document has properties such as “tagName” that allow you to search programmatically for various elements. For example, if you wanted to write a script that filtered out all bold items, you would scan the all collection for an element with tagName “B.”
Now that we’ve covered the basics of the DHTML object model and how to access them through scripts from the Web master’s perspective, let’s look at how MFC 6.0 lets us work with DHTML from an application developer’s perspective.
MFC 6.0 and the DHTML Connection
MFC 6.0’s CHTMLView gives you complete access to the DHTML object model. However,
access to the object model from languages like C++ is done through OLE Automation (IDispatch) and in many cases isn’t as cut-and-dried as some of the scripts we looked at earlier. The DHTML object model gets exposed through a set of COM objects with the prefix
“IHTML” (as in IHTMLDoc-ument, IHTMLWindow, IHTMLElement, and IHTMLBody-Element). In C++, once you’ve obtained the document interface, you can use any of the IHTMLDocument2 interfaces to obtain or modify the document’s properties.
You can access the all collection by calling the IHTMLDoc-ument2::get_all( ) method. This method returns an IHTML-ElementCollection collection interface that contains all the
elements in the document. You can then iterate through the collection using the
IHTMLElementCollection::item( ) method (similar to the parentheses in the scripts above).
The IHTMLElementCollection::item( ) method supplies you with an IDispatch pointer on which you can call QueryInterface, requesting the IID_IHTMLElement interface. This gives you an IHTMLElement interface pointer to get or set information for the HTML element.
Most elements also provide a specific interface for working with that element type. These element-specific interface names take the format of IHTMLXXXXElement, where XXXX is the name of the element (as in IHTMLBodyElement). You must call QueryInterface on the IHTMLElement object to request the element-specific interface you need. If this sounds confusing, it can be! But don’t worry, we’ll go through an example of how to use DHTML with MFC.