Back to main page

 

New and Cool in MFC 6.0

Changes to AppWizard, IE4 Controls, and a connection to DHTML make this rev worth learning By Scot Wingo

You may already be enjoying the productivity gains from great new features in Microsoft Visual C++ 6.0 like the IDE, editor, and compiler. Now that you’ve had a chance to recompile your current projects with the latest rev of Visual C++, it’s time to look at what’s new in the latest release of MFC, Version 6.0.

Fire It Up!

The fastest way to discover what’s new in MFC 6.0 is to fire up our old friend, AppWizard, and see what’s changed since Version 5.0. Go ahead and start AppWizard by selecting File/New/MFC AppWizard (EXE).

Figure 1:New AppWizard functionality

The first difference you’ll notice occurs in step 1. Figure 1 shows a new option: “Document/View architecture support?” In previous versions, everything generated by AppWizard was automatically document/view-oriented, and you had to manually remove any document/view (and document template, etc.). Now if you’re starting a project and don’t care for document/view support, this option automatically omits document/view references from the generated code for you.


For this example, accept all of the defaults and go to step 4. Figure 2 shows step 4 of the AppWizard and another new option: “How do you want your toolbars to look?” with the “Normal” and “Internet Explorer ReBars” options. Choose Internet Explorer ReBars.

Figure 3: Project style option

At the top of Step 5, shown in Figure 3, you’ll get another new question: “What style of project would you like?” The options are “MFC Standard” or “Windows Explorer.” Choose the Windows Explorer option.

Finally, Step 6 includes a new but hidden feature. Can you find it? If you select a view, you’ll notice a new CView derivative: CHtmlView. Figure 4 shows where this new option lives.


Figure 4: CHtmlView

CHtmlView is fairly sophisticated, so we’ll cover it in a separate section later. Accept the defaults in step 6 and compile and run the application. Figure 5 shows the application in action.


Figure 5: Working application

Notice that the application has a fancy new toolbar that “slides” and has grippers like the toolbar in Internet Explorer 4. Also notice that a splitter has automatically been created for us so that we can more easily create an Explorer-style application with a CTreeView in the left pane and a CListView in the right pane.

Let’s learn more about the new ReBar control by exploring the code that AppWizard generated (so you can convert existing applications to use the new toolbar) and customize the default ReBar.

 

Anatomy of a ReBar

In addition to the “sliding” and gripper functionality, the ReBar also allows you to provide many more internal control types—such as drop-down menus—than are available in CToolBar. Before we explore these features let’s look at the components of a ReBar.


Figure 6: ReBar elements

Figure 6 shows the various parts of a ReBar. Each internal toolbar in a ReBar is called a “band.” The raised edge where the user slides the band is called a gripper. Each band can also have a label as illustrated.

MFC 6.0 provides two new classes that facilitate working with ReBars:

CReBar—a high-level abstraction class that provides members for adding CToolBar and CDialogBar classes to ReBars as bands. CReBar also handles communication (such as message notifications) between the underlying control and the MFC framework.
CReBarCtrl—a low-level wrapper class that wraps the IE ReBar control. This class provides numerous members for creating and manipulating ReBars, but doesn’t provide the niceties found in CReBar. Most MFC applications use CReBar and call the member function GetReBarCtrl( ), which returns a CReBarCtrl pointer to gain access to the lower-level control on an as-needed basis.
Working with CReBar

If you open the MainFrm.h header file generated earlier by AppWizard, you’ll see the code below which declares the CReBar data member, m_ndReBar.

protected:  // control bar embedded members

	CStatusBar  m_wndStatusBar;

	CToolBar    m_wndToolBar;

	CReBar      m_wndReBar;

	CDialogBar  m_wndDlgBar;

In the MainFrm.cpp file, you can see the code that adds the toolbar and dialog bar to the CReBar:

	if (!m_wndReBar.Create(this) ||

		!m_wndReBar.AddBar(&m_wndToolBar) ||

		!m_wndReBar.AddBar(&m_wndDlgBar))

	{

		TRACE0("Failed to create rebar\n");

		return -1;      // fail to create

	}

Let’s customize the “TODO: layout dialog bar” band from the application we generated earlier with AppWizard.

First, open up the Visual C++ resource editor. Under the dialog heading you’ll find a dialog resource (for the dialog bar) with ID IDR_MAINFRAME, which contains “TODO: layout dialog bar.” Let’s follow AppWizard’s suggestion and put some real controls into the dialog bar. First, delete the static control with the “TODO” text in it. Next, place a combo box in the dialog bar and enter some default data items: “one,” “two,” “buckle,” “my,” “shoe”! Now place a button and change the button’s text to “Increment.” Next, place a progress bar with the default properties and place another button with the text “Decrement.” When you’re done laying out the dialog bar it should look similar to Figure 7.


Figure 7: Adding controls to the dialog bar

Before we can program the handlers for the “Increment” and “Decrement” buttons, we need to attach the dialog bar to a class using ClassWizard. While in the resource editor, bring up ClassWizard by double clicking on the Increment button. Choose Select an existing class. We choose this option because we want our dialog resource to be a band in the toolbar, not a separate dialog class. Choose CMainFrame from the list and select OK. ClassWizard prompts you with one last dialog. Select Yes and exit ClassWizard. You have successfully associated the IDR_MAINFRAME dialog bar with the CMainFrame class!

Finally, let’s add some behavior to the dialog bar. Bring up the IDR_MAINFRAME dialog resource in the resource editor and double click on the Increment button. ClassWizard automatically creates an OnButton1( ) handler for you—accept the default name for this function. Enter this code for the OnButton1( ) function:

void CMainFrame::OnButton1()

{

	CProgressCtrl * pProgress = 

		  (CProgressCtrl*)m_wndDlg Bar.GetDlgItem

								  (IDC_PROGRESS1);

	pProgress->StepIt();

}

The OnButton1( ) handler first gets a pointer to the progress control and then calls StepIt( ) to increment the progress control.

Now we need to add similar code to the decrement handler. Double click on the Decrement button in the resource editor, and ClassWizard will automatically create an OnButton2( ) handler. Add the following code to the OnButton2( ) member function:

void CMainFrame::OnButton2()

{

CProgressCtrl * pProgress =

	   (CProgressCtrl*)m_wndDlgBar.GetDlgItem

							(IDC_PROGRESS1);



	int nCurrentPos = pProgress->GetPos();



	pProgress->SetPos(nCurrentPos-10);

}


Figure 8: Application results

Now you’re ready to compile and run the application. Figure 8 shows the results. This example is just the tip of the ReBar functionality iceberg, but it should give you an idea of how to get started and what it’s like to work with the new class. The Visual C++ on-line documentation is a great place to learn more about ReBar’s capabilities.

Actually, the ReBar is one of several new controls that are part of the Internet Explorer SDK now supported in MFC 6.0. Let’s take a look at some of the other new controls that are supported.

IE 4 Controls

When Microsoft released Internet Explorer 4, they included a new and improved version of the COMCTL32.DLL, which houses the Windows Common Controls. Because this update to the common controls wasn’t part of an operating system release, Microsoft calls the update the “Internet Explorer 4 Common Controls.” It updates all of the existing controls and adds a variety of advanced new controls. Visual C++ 6.0 and MFC 6.0 include a great deal of support for these new controls.

Figure 9 shows a dialog with each of the new IE4 controls. You can refer to it as you read the descriptions of the controls that follow.


Figure 9: New IE4 controls

Date and Time Picker

Before the date and time picker was provided with the IE4 controls, to enter a date, you had to use a third-party control, or subclass an MFC edit control to do significant data validation to ensure the entered date was valid. Fortunately, the new date and time picker provides an advanced control that prompts the user for a date or time while offering the developer a wide variety of styles and options. For example, dates can be displayed in short (8/14/68) or long (August 14, 1968) formats. A time mode lets the user enter a time using the familiar hour:minute:second AM/PM format.

The control also lets you decide if you want the user to select the date via in-place editing, a pop-down calendar, or a spinner. A variety of selection options are available, including single and multi (a range of dates) selections and the ability to turn on and off the red-ink “circling” of the current date. The control even has a mode that lets the user select “no date” by checking a check box. In Figure 9, the first four controls on the left illustrate the variety of configurations available with this control.

The new MFC 6.0 CDateTimeCtrl class provides the MFC interface to the IE4 date and time picker common control. This class offers a variety of notifications that enhance the programmability of the control. CDateTimeCtrl provides member functions for dealing with either CTime or COleDateTime time structures.

You set the date and time in a CDateTimeCtrl using the SetTime( ) member function and retrieve the date and time via the GetTime( ) function. You can create custom formats using the SetFormat( ) member function and change a variety of other configurations using the CDateTimeCtrl interface.

Month Calendar

The large display at the bottom left of Figure 9 is a month calendar. Like the date and time picker, the month calendar lets the user choose a date; but the month calendar can also be used to implement a small “Personal Information Manager (PIM)” in your applications. You can use the month calendar to show from one to 12 months. Figure 9 uses the month calendar to show only two months.

The month calendar supports single or multiple selection and allows you to display a variety of different options such as numbered months and circled days. Notifications for the control let you specify which dates are bold. It’s up to you to decide what this represents. For example, you could use the bold feature to indicate holidays, appointments, or invalid dates. The MFC 6.0 CMonthCalCtrl class provides the implementation of this control.

To initialize CMonthCal-Ctrl, you can call the SetToday() member function. CMonthCalCtrl provides members that deal with both CTime and COleDateTime.

 

Internet Protocol Address Control

If you write an application that uses any form of Internet or TCP/IP functionality, you may need to prompt the user for an Internet Protocol (IP) address. The IE4 Common Controls include an IP address control as shown in the top right of Figure 9. In addition to allowing the user to enter a four-byte IP address, this control performs automatic validation of the entered IP address. CIPAddressCtrl provides MFC support for the IP address control.


Figure 10: IP address

An IP address consists of four “fields” as shown in Figure 10. The fields are numbered from left to right. To initialize an IP address control, call the SetAddress( ) member function in your OnInitDialog( ) function. SetAddress( ) takes a DWORD, with each byte in the DWORD representing one of the fields. In your message handlers, you can call the GetAddress( ) member function to retrieve a DWORD or a series of bytes to retrieve the various values of the four IP address fields.

Extended Combo Box

The “old fashioned” combo box was developed in the early days of Windows, and its age and inflexible design have been the source of a great deal of developer confusion. With the IE4 controls, Microsoft released a much more flexible version of the combo box, called the “extended combo box.”

The extended combo box gives you much simpler access and control over the edit control portion of the combo box. In addition, the extended combo box lets you attach an image list to the items in the combo box so you can easily display graphics in it. (Remember the old days when you had to use owner-drawn combo boxes?) Each item in the extended combo box can be associated with a selected image, an unselected image, and an overlay image. These three images can be used to provide a variety of graphical displays in the combo box. The bottom two combo boxes in Figure 9 are both extended combo boxes. The MFC CComboBoxEx class provides comprehensive extended combo box support.

CComboBoxEx can be attached to a CImageList that will automatically display graphics next to the text in the extended combo box. If you’re already familiar with CComboBox, CComboBoxEx may cause some confusion; instead of containing strings, the extended combo box contains items of type COMBOBOXEXITEM. COMBOBOXEXITEM is a structure that consists of the following fields:

UINT mask—A set of bit flags that specify which operations are to be performed using the structure. For example, set the CBEIF_IMAGE flag if the iImage field is to be set or retrieved in an operation.
int iItem—Extended combo box item number. Like the older style combo box, the extended combo box uses zero-based indexing.
LPTSTR pszText—Text of the item.
int cchTextMax—Length of the buffer available in pszText.
int iImage—Zero-based index into an associated image list.
int iSelectedImage—Index of the image in the image list to be used to represent the “selected” state.
int iOverlay—Index of the image in the image list to be used to overlay the current image.
int iIndent—Number of 10-pixel indentation spaces.
LPARAM lParam—32-bit parameter for the item.

See Bill Wagner’s article, “Build a Browser in an Afternoon Using Microsoft’s Web Browser” at www.vcdj.com/vcdj/jul98 /browser1.asp for more more information.

The last and perhaps biggest new feature in MFC 6.0 is support for Dynamic HTML in the CHTMLView class.

DHTML Support

Dynamic HTML (DHTML) is a new and exciting feature introduced as part of IE4. It provides serious benefits that could ultimately change the way we think about developing Windows applications. What’s the buzz about?

It all starts with the IE “HTML display engine,” sometimes called “Trident” in Microsoft literature. As part of the design of IE4, Microsoft made Trident its own COM component, exposing many of its internal objects used for displaying HTML pages in IE. This feature allows you to traverse the portions of an HTML page in script or code as if the HTML page was a data structure. Gone are the days of having to parse HTML or write grotesque CGI scripts to get to data in a form. The real power in DHTML doesn’t lie in the ability to access the HTML objects, but to actually change and manipulate the HTML page on-the-fly—thus, the name Dynamic HTML.

Once you understand the concept of DHTML, a million possible applications come to mind. For the Webmaster, this means that much of the logic that manipulates a page can live in scripts that are downloaded to the client. For the C++ developer, it means you can embed DHTML in your applications and use it as an embedded Web client or as a super-flexible, dynamic “form” that your application can change on-the-fly. For an example of how to leverage Web views in your applications, try some of the new Internet-enabled applications like Quicken 99 or Microsoft Money 99.

DHTML is so powerful and extensive that it would take a separate book (like Inside Dynamic HTML by Scott Isaacs) to fill you in on all of the copious details. For example, to really leverage DHTML, you need to understand the many possible elements of an HTML page, such as forms, lists, and stylesheets. Instead of covering all of the aspects of DHTML, I’ll briefly introduce you to the DHTML object model and show you how to work with it using MFC. This is all made possible by the excellent DHTML support introduced in Visual C++ 6.0.

The DHTML Object Model

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.

Where the Connection Begins

MFC’s support for DHTML starts with a new CView derivative, CHtmlView, allowing you to embed an HTML view inside of frame windows or splitter windows. With some DHTML work, CHtmlView can act as a dynamic form. Let’s use it to generate a simple application and add some DHTML manipulation code.

First, create a simple MDI application with a CHtmlView as the view. In Visual C++, select File/New/Projects and choose MFC AppWizard (EXE). Accept all the defaults up to step 6. In step 6 choose CHtmlView as the base class.

If you look in your ProjectNameView.cpp file, you’ll see this line in the CProjectNameView::OnInitialUpdate( ) function:

	Navigate2(_T("http://www.microsoft.com/visualc/"),NULL,NULL);


Figure 12: Sample application

You can edit this line to have the application load a different URL from the Visual C++ page, or a local page. Compile and run this application to see the basic CHtmlView in action. Figure 12 shows the application running.

You can obtain on www.vcdj.com a more comprehensive DHTML sample that creates a CHtmlView and a CListView separated by a splitter. It then uses DHTML to enumerate the HTML elements in the CHtmlView and displays the results in the CListView. The end result is a DHTML explorer that you can use to view the DHTML object model of any HTML file! The sample includes a README.TXT file that describes the steps used to generate the application. Figure 13 shows the MFC 6.0 sample in action.


Figure 13: MFC 6.0 sample

For more information

I hope this introduction to DHTML has started you thinking about some ways you can use this exciting new technology in your MFC-based applications. The possibilities are endless: applications that update from the Internet, completely dynamic applications, and countless others.