Mark Davis
Want to provide seamless Internet browsing from your MFC applications? You can, using the Microsoft Internet Explorer Web browser control. This article shows you how to add Internet browsing capability to your applications with the Web browser control in an MFC application using Microsoft Visual C++ 4.
MOST users navigate the Internet using their favorite browser to specify the address (URL) of each Web site they wish to visit. As you can imagine, the browser does a lot of work connecting to the Web site, downloading the specified HTML page, and then interpreting the contents. Because of the rich content available on a Web page, a browser also needs to be able to interpret an evolving set of HTML commands. HTML defines the content, layout, and style of a Web page. HTML tags specify elements such as:
URL links
frames
entry forms
images
style sheets
scripting languages such as VBScript and JScript
ActiveX controls
Java applets
It’s no wonder that writing and maintaining your own Internet browser isn’t for the faint-hearted.
With so many people accessing the Internet and so much content available, you may wonder how you can incorporate some of this technology into your own applications, without the effort of writing and maintaining your own browser. This article discusses how you can use the Microsoft Internet Explorer browser in your own application.
There are many compelling reasons why you might want users to browse the Internet from within your application. These are just a few of the reasons:
Support and advertising: Providing a quick method for your users to reach your Web site, find out about other products, and download updates.
Personal information management: Navigating to URLs stored in a Ôfavorite Web sites’ database.
Web tools: Providing Web site map and printing features.
General browsing: Rolling your own customized browser to view Web pages and the file system.
Before I talk about the Microsoft Internet Explorer Web browser control, you may want to consider alternative ways you can use the IE browser. The most basic of these is to launch the browser as a separate application. The sample application demonstrates different ways to do this, including calling the following:
The Win32 CreateProcess function, passing the Internet Explorer executable path and file name in lpApplicationName and the URL in lpCommandLine.
The Win32 ShellExecute function, passing the URL in lpFile.
The ActiveX SDK HlinkNavigateString function, or related functions, passing the URL.
These and other methods have a major drawback in that the developer has little or no control over how the browser is displayed. Once the browser is launched, it’s up to the user to close it down or switch back to your application.
Once the Microsoft Internet Explorer has been launched, two other techniques, the IWebBrowserApp OLE Automation interface and DDE, can be used to control the browser. For more information on these interfaces, please refer to the information sources at the end of this article.
The Web browser control is installed with Microsoft Internet Explorer 3.0. It provides the view you see in the main window of the Microsoft Internet Explorer and it provides the functionality for displaying Web pages containing HTML, scripting, and ActiveX control and Java applet content. The control also hosts OLE document objects, supports OLE hyperlinks, and allows users to view Windows objects such as folders and files. Because it’s an ActiveX control, it can be used in your MFC and Visual Basic applications, or any other OLE control container. Like other ActiveX controls, the browser control exposes a number of methods, properties, and events through the IWebBrowser OLE Automation interface, as described in Tables 1, 2, and 3.
Table 1. Web browser control methods.
Method | Description |
GoBack | Navigates to the previous item in the history list. |
GoForward | Navigates to the next item in the history list. |
GoHome | Navigates to the current configured home or start page. |
GoSearch | Navigates to the current configured search page. |
Navigate | Navigates to a resource identified by a URL or file path. |
Refresh | Reloads the current page. |
Refresh2 | Reloads the current page and optionally specifies the refresh level. |
Stop | Stops any pending navigation or download. |
Table 2. Web browser control properties.
Property | Description | Method |
Application | Automation object representing the containing application. | Get |
Busy | Indicates whether a download or navigation is still in progress. | Get |
Container | Container of the WebBrowser control, if any. | Get |
Document | Automation object of the active document, if any. | Get |
Height | Vertical dimension, in pixels, of the frame window that contains the WebBrowser control. | Get/Put |
Left | Distance between the internal left edge of the WebBrowser control and the left edge of its container. | Get/Put |
LocationName | Name of the resource that the WebBrowser control is currently displaying. | Get |
LocationURL | URL of the resource that the WebBrowser control is currently displaying. | Get |
Parent | Form on which the WebBrowser control is located. | Get |
Top | Distance between the internal top edge of the WebBrowser control and the top edge of its container. | Get/Put |
TopLevelContainer | Indicates whether the current object is a top level container. | Get |
Type | Type of the current contained document object. | Get |
Width | Horizontal dimension, in pixels, of the frame window that contains the WebBrowser control. | Get/Put |
Table 3. Web browser control events.
Event | Description |
BeforeNavigate | Occurs when the WebBrowser control is about to navigate to a new URL. |
CommandStateChange | Occurs when the enabled state of a command changes. |
DownloadBegin | Occurs when a navigation operation is beginning, shortly after the BeforeNavigate event. |
DownloadComplete | Occurs when a navigation operation is finished. |
FrameBeforeNavigate | Occurs when the WebBrowser control is about to navigate to a new URL in an HTML frame. |
FrameNavigateComplete | Occurs after the browser has successfully navigated to a new URL in an HTML frame. |
FrameNewWindow | Occurs when a new window is to be created for displaying a resource in an HTML frame. |
NavigateComplete | Occurs after the browser has successfully navigated to a new URL. |
NewWindow | Occurs when a new window is to be created for displaying a resource. |
ProgressChange | Occurs when the progress of a download is updated. |
PropertyChange | Occurs when the PutProperty method changes the value of a property. |
Quit | Occurs when the Internet Explorer application is ready to quit. |
StatusTextChange | Occurs when the status bar text has changed. |
TitleChange | Occurs when the title of a document in the WebBrowser control becomes available or changes. |
Using the MFC AppWizard in Visual C++ 4, create a new MFC application selecting support for OLE Controls. The sample application, which you can download from the Visual C++ Developer home page at www.pinpub.com/vcd, is an SDI application with the view based on CView. You could also base your view on CFormView or create a dialog-based application, both of which use dialog templates for arranging Windows controls.
In the Component Gallery, you’ll see the Microsoft Web Browser Control listed in the OLE Controls section. When you insert this control, the dialog box in Figure 1 is displayed, showing the default class and filenames for the control class to be generated. So what is the CWebBrowser class? Well, support for hosting an OLE control is implemented in the MFC CWnd class, from which your newly generated class is derived. The CWebBrowser class is generated by Visual C++ from the control’s type library and provides helper functions for accessing the control methods and properties though the control’s OLE Automation interface, IWebBrowser.
Figure 1. Confirm Web browser control class dialog.
Once the Web browser control has been inserted into the project, it becomes available as an additional control in the resource editor. The control can simply be dropped onto a dialog box template as you would any other Windows control. Just assign a resource ID and a control variable to access it. Because the sample application uses a view based on CView, the Web browser control will be created dynamically, a technique that has the benefit of allowing the user to resize the view. In this example, the ID_BROWSE symbol is assigned (using View É Resource Symbols) to the control. Here’s how you would dynamically create the Web browser control:
int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // Create Web browser control if ( ! m_Browse.Create( NULL, WS_CHILD| WS_VISIBLE, CRect(), this, ID_BROWSE ) ) return -1; return 0; } void CMyView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); // Resize Web browser control m_Browse.MoveWindow( 0, 0, cx, cy ); m_Browse.UpdateWindow(); }
Once the control has been created, a mechanism is needed to obtain the URL from the user and then invoke the Navigate method. In the sample application I’ve demonstrated one way to do this: Create a drop-down combo on the toolbar and handle “Enter” key press events. Having obtained the URL, a function in the view class can invoke the control’s Navigate method:
void CMyView::DoNavigate(LPCSTR pszUrl) { COleVariant varEmpty; // Default is VT_EMPTY m_Browse.Navigate( pszUrl, &varEmpty, &varEmpty, &varEmpty, &varEmpty ); }
It’s easy to wire up additional toolbar buttons for the other methods, such as Refresh and Stop. You can find an example in the sample application. With a few lines of code, the application looks and feels like an Internet browser.
Just as exposed methods are invoked, events fired by the control can be handled easily using the MFC event map framework. If the control is created by dropping it onto a dialog box resource, each event is handled by selecting the appropriate CDialog or CFormView derived class, Object ID, and Message displayed in ClassWizard Message Maps section, as shown in Figure 2.
Figure 2. Web browser control events as shown in ClassWizard.
If control was created dynamically in the sample application, you may be wondering why the control’s resource ID (such as ID_BROWSE) isn’t shown. The reason is that ClassWizard doesn’t know which class is bound to the new resource¾the symbol is used solely for referencing the control, so the following trick is required to take advantage of the MFC event map created by ClassWizard.
Here’s how to add event support for a dynamically created OLE control: Edit any dialog box resource (such as IDD_ABOUTBOX) and drop the Web browser control onto the dialog template. While in the resource editor, run ClassWizard, then select your view class in the Class Name drop-down and select the IDC_EXPLORER1 Object ID. For each event you wish to handle, select the event name from the Messages list and use Add Function to add the member function. When all event handlers have been added, modify the event sink map generated by ClassWizard so that the correct resource ID is used and then delete the unwanted control from the dialog resource.
In the sample application, I’ve handled the TitleChange and StatusTextChange events and have updated the document title and status bar accordingly. The BeforeNavigate event is handled to detect when a new URL is selected and the PropertyChange event is handled to detect when a page has been parsed. You could, for example, handle the DownloadBegin, DownloadEnd, and ProgressChange to display a Ôbusy’ animation or progress control.
The Web browser control exposes the Internet Explorer Object Model, a collection of OLE Automation objects hosted by the control when a Web page is displayed. This model is primarily intended for use by scripting languages such as VBScript or Jscript and to allow access to objects such as frames and links. The structure of the object model is shown in Figure 3.
Figure 3. Microsoft Internet Explorer Object Model. The asterisk (*) indicates a collection.
The OLE Automation objects that comprise the Internet Explorer Object Model are implemented in MSHTML.DLL, located in your Windows system folder. ClassWizard creates MFC OLE Automation client classes from the type library in this DLL. These classes are derived from the COleDispatchDriver class, which provides easy access to the methods and properties of an OLE Automation object. When ClassWizard is used to add classes from the MSHTML.DLL type library, the dialog box shown in Figure 4 is displayed.
Figure 4. Confirm Internet Explorer Object classes dialog box.
The sample application demonstrates how to access some of the Internet Explorer objects to show the URL links on the current Web page. It does this by getting the value of the Web browser control’s Document property. This property is the dispatch interface (IDispatch) for the active document and is attached to an IHTMLDocument C++ object by calling its AttachDispatch method. The IHTMLDocument Script property provides the dispatch interface for the Window object and is attached to an IOmWindow C++ object. From this point, any of the other objects shown in Figure 3 can be accessed.
The Web browser control doesn’t fire an event to notify the application when the HTML page has been parsed and the Internet Explorer objects are ready to be accessed. Fortunately, the IOmWindow object fires an OnParseComplete event. But hold on here¾these are OLE Automation objects, not controls, so how is this event being fired? Well, the Window object implements an outgoing interface, also known as a connection point, called IOmWindowEvents. These events are handled on the client side by implementing an event sink.
An event sink is implemented by creating a class derived from CCmdTarget with Automation support selected. ClassWizard generates a new GUID when this class is created, so the GUID needs to be modified to match that of the IOmWindowEvents interface. The Ole2View utility provided with Microsoft Visual C++ can be used to view the type library (in MSHTML.DLL) to obtain the IOmWindowEvents interface GUID and methods. The methods, onParseComplete, onLoad, and onUnload are added to the event sink class using the ClassWizard OLE Automation facility.
The sample application demonstrates how to inform the IOmWindowEvents connection point that our event sink wants to be notified of these events. This notification is done in the ConnectWindowEvents function, implemented in the view class, and does the work of accessing the Window object, finding the IOmWindowEvents connection point, and calling its Advise method.
I hope I’ve enabled you to get started with this exciting control. Now it’s up to you to explore this technology and determine where to apply it to future applications.
For More Information
See the Microsoft Visual C++ help for more information on the MFC implementation of OLE Controls, OLE Automation, and connection points.
See the ActiveX SDK help for more information on the Web browser control, Internet Explorer Object Model for Scripting, and URL monikers.
For a more accurate mechanism to detect when a Web page has been loaded by Internet Explorer, you may want to look at the OBJVW (BASECTRL) sample provided with the ActiveX 3.01 SDK. This sample also provides a generic event sink class.
The following are useful Web links:
ActiveX SDK |
http://www.microsoft.com/intdev/sdk |
Internet Explorer DDE interface |
http://www.microsoft.com/ie/support/docs/tech30/dde.htm |
Internet Explorer Web Browser Control |
http:// www.microsoft.com /intdev/sdk/docs/iexplore/webrowse.htm |
Internet Explorer Object Model |
http:// www.microsoft.com /intdev/sdk/docs/scriptom/omscript.htm |
URL Monikers and OLE Hyperlinks |
http:// www.microsoft.com /intdev/prog-gen/moniker.htm |
DAVIS.ZIP at www.pinpub.com/vcd
Mark Davis specializes in Microsoft Visual C++, Microsoft Foundation Classes, ActiveX, OLE, and COM. Mark lives with his supportive wife, Janine, and children, Kurt and Adam.
http://www.geocities.com/Siliconvalley/heights/1720
To find out more about Visual C++ Developer and Pinnacle Publishing, visit their website at: http://www.pinppub.com/vcd/
Note: This is not
a Microsoft Corporation website.
Microsoft is not responsible for its content.
This article is reproduced from the February 1997 issue of Visual C++ Developer. Copyright 1997, by Pinnacle Publishing, Inc., unless otherwise noted. All rights are reserved. Visual C++ Developer is an independently produced publication of Pinnacle Publishing, Inc. No part of this article may be used or reproduced in any fashion (except in brief quotations used in critical articles and reviews) without prior consent of Pinnacle Publishing, Inc. To contact Pinnacle Publishing, Inc., please call (800) 788-1900 or (206) 251-1900.