Lesson 1: Working with Dynamic HTML

Hypertext Markup Language (HTML) is a system of marking up, or tagging, a document so that it can be published on the World Wide Web. Dynamic HTML (DHTML) is an extension of HTML supported by Internet Explorer 4.0 that exposes a Web page and all the elements on it as scriptable objects. In this lesson, you will learn how you can display HTML documents and work with the DHTML object model from within your Visual C++ applications.

After this lesson, you will be able to:

  • Describe some of the benefits of using DHTML as an application user interface.
  • Describe the DHTML object model and how you can access DHTML objects from within your code.
  • Describe how to use the DHTMLView class to display HTML documents in an MFC application.
  • Describe how to use the ATL HTML control to display HTML documents.
  • Describe the function of DHTML scriptlets and how they can be incorporated into a Visual C++ application.
Estimated lesson time: 50 minutes

Review of the Internet, Intranets, and HTML

The Internet is a global, distributed network of computers that use the TCP/IP protocol. An intranet is also a network of computers operating on the TCP/IP protocol, but it is not global. Generally, an intranet is restricted to a particular set of users. An organization might run an intranet to provide information to employees only, and run a separate Internet site for the general public. Employees of the company can access both, but non-employees can access only the company's Internet site.

NOTE
In this chapter, we will use the term Internet to include both the global network of computers and intranet networks.

Most people's experience of the Internet comes from browsing the World Wide Web (the Web). The Web is the portion of the Internet that uses the Hypertext Transfer Protocol (HTTP) to connect pages and resources in a way that lets you reach any page from any other page. If you are connected to the Internet, a Web browser like Internet Explorer lets you explore the Web to view pages on Web servers across the world.

The Web operates on a client/server model. The browser running on a desktop computer acts as the client, and a Web server acts as the server by providing the HTTP pages in response to a user's request.

Web pages viewed in a Web browser appear as a collection of text, pictures, sounds, digital movies; and as links to other Web pages. Web pages are created using HTML, which tags an ASCII document so that it includes formatting tags; references to graphics, sound, or animation files; and hyperlinks to Web pages or other resources.

Users of an intranet also use a Web browser to browse Web pages located on the company's Web servers. Additionally, users can use a Web browser to access resources or run applications on remote servers on your local area network (LAN), or on your desktop computer. You can use HTML to develop applications that present a rich and consistent interface and provide seamless access to resources on a desktop computer, on remote company servers, and on global Web servers.

HTML Documents

HTML defines a standard set of formatting tags that all Web browsers recognize. For example, this is the code for a simple HTML page:

<!— MyPage.htm —> <HTML> <HEAD> <TITLE> A basic HTML Page </TITLE> </HEAD> <BODY> <H1> This is some text with H1 </H1> <H3> This is some text with H3 </H3> <P>Here is a new paragraph with normal text in <B>Bold</B> and <I>Italic</I> </P> <P>Here is a <A HREF= "SecondPage.htm"> link to a local page </A> </P> </P> <P>Here is a <A HREF= "http://msdn.microsoft.com/visualc/"> link to a page on the World Wide Web </A> </P> </BODY> </HTML>

HTML formatting tags divide a document into discrete sections known as elements. The HTML document just shown is composed of two main elements enclosed by the <HEAD> and <BODY> tag pairs. The <HEAD> element contains header information that does not affect the rendering of the document, but might be of use to the browser. The <BODY> element specifies the content of the page that is displayed by the browser. Our example demonstrates some simple tags that define elements of the document. These tags specify whether text is to be displayed in one of the pre-defined heading formats such as <H1> or <H3>, or as bold or italic text. The <A> (anchor) element specifies a hypertext link.

Most of the HTML tags define attributes that are used to supply additional information about the element. In the example just shown, the elements defined within <A> tags contain HREF attributes, which are assigned strings that specify the link destination as a Uniform Resource Locator (URL) address. You can also assign the name of a local file to the HREF attribute by prefacing the path with "file:\\".

The MyPage.htm file can be found in the Chapter 12\Exercises folder that is installed from the companion CD. Double-click the MyPage.htm file so that it displays in Internet Explorer, as shown in Figure 12.1. You can experiment by following the link to the SecondPage.htm file and, if you have a live Internet connection, to the Visual C++ home page at msdn.microsoft.com/visualc/.

click to view at full size.

Figure 12.1 MyPage.htm, as displayed by Internet Explorer 5

Dynamic HTML

DHTML is an exciting technology that was introduced as part of Internet Explorer 4.0. Using DHTML, you can create dynamic, interactive Web pages, thereby presenting users of your Web site with the kind of user interface they have come to expect from desktop applications.

For example, with DHTML you can:

  • Modify the text of your Web page.
  • Modify elements of a style sheet that specify how text is displayed (the font or the text color, for example).
  • Animate text and images on your Web page.
  • Respond to user-initiated actions such as mouse movements or clicks.
  • Validate user input to a form before it is submitted to a server.

DHTML achieves these effects by automatically reformatting and redisplaying the current document to show changes. It does not need to reload the document or load a new document, nor does it require a distant server to generate new content, as HTML would require. Instead, it uses the power of the user's computer to calculate and carry out changes. This means a user does not have to wait for text and data to complete potentially time-consuming round-trips to and from a server before seeing results.

Furthermore, DHTML does not require additional support from applications or embedded controls to carry out changes. Typically, DHTML documents are self-contained, using HTML styles to specify the format and appearance of the document; and using small blocks of script to process user input and directly manipulate the HTML tags, attributes, styles, and text in the document.

The HTML elements, attributes, and styles in DHTML are based on existing HTML specifications. Microsoft is working with the World Wide Web Consortium (W3C) toward a DHTML standard. Some of the dynamic and interactive features that you add to your documents might not be fully functional when viewed with a browser that does not support DHTML. However, by following some basic guidelines, you can ensure that the content of your document will still be viewable in other browsers.

DHTML Object Model

When Internet Explorer 4.0 (or later versions) loads an HTML page, it creates an internal representation of the page that is accessible through the DHTML object model.

Using the DHTML object model, you can access and manipulate virtually anything within a document. The HTML elements in the document are available as individual objects, which means you can examine and modify an element and its attributes by reading and setting properties and by calling methods. Elements of a document are contained in collections—similar to the MFC collections or the linked lists you use in C++ programming. You can iterate across a DHTML collection to gain access to the elements it contains.

Figure 12.2 shows several sub-objects of the document object. Most of these are collections, including the all collection that contains all of the document's HTML elements.

Figure 12.2 The DHTML object model

The object model also makes user actions, such as pressing a key or clicking the mouse, available as events. You can intercept and process these and other events by creating event handler functions and routines.

As an example, consider the following simple DHTML document:

<!— MyDynPage.htm —> <HTML> <HEAD><TITLE>Welcome!</TITLE></HEAD> <SCRIPT LANGUAGE="JavaScript"> function changeMe() {      document.bgColor = "hotpink";      MyHeading.style.color = "green";      MyText.innerText = "Color effects courtesy of DHTML"; } </SCRIPT> <BODY onclick="changeMe()"> <H3 ID=MyHeading>Welcome to Dynamic HTML!</H3> <P ID=MyText>Click anywhere in this document.</P> </BODY> </HTML>

This document changes the color of the background and heading font, and also changes a line of text when the user clicks the mouse in the document. You can test this behavior by viewing the page (Chapter 12\Exercises\MyDynPage.htm) in Internet Explorer.

Note that you can identify individual elements on a page by setting the ID attribute inside the element tag. In the example, the heading is named MyHeading and the paragraph is named MyText. You can use these IDs to access the page elements, and then write scripts to get and set the element properties. Scripts are defined with the <SCRIPT> tag.

In the example, notice that the JavaScript scripting language is used to define the changeMe() handler function, which is associated with the onClick event inside the document's <BODY> tag. The function sets the bgColor property of the document object's body object to change the document's background color. The function also changes the color of the heading by setting the color property of the style object of the MyHeading element. It replaces the text in the paragraph element by setting the innerText property of the MyText element.

NOTE
The scripting examples in this chapter will use the JavaScript language. Because it is syntactically very similar to C++, it will probably be your scripting language of choice. Most browsers use JavaScript as their default language, but it is good practice to always specify the language used in the LANGUAGE attribute of the <SCRIPT> tag. In the MSDN documentation and in other books, you might see JScript used. JScript is Microsoft's version of JavaScript, and it includes some Internet Explorer-specific extensions.

It is not the intention of this book to give you more than a brief introduction to DHTML. If you would like to know more about DHTML, refer to one of the several books available on the subject, such as Inside Dynamic HTML by Scott Isaacs (Microsoft Press, 1997). This brief introduction to the capabilities of DHTML is intended to help you appreciate that HTML—a simple markup language used to render hypertext documents—is evolving into a powerful development tool capable of providing a dynamic, interactive user interface for applications.

Microsoft WebBrowser Control

To help you incorporate Web browser elements into your applications, Microsoft provides the WebBrowser ActiveX control. This control is the component of Internet Explorer that implements the Internet Explorer main window. The WebBrowser control supports Web browsing through hyperlinks and URL navigation and maintains a history list that allows the user to browse forward and backward through previously browsed sites, folders, and documents. The control also handles security and lists of "favorite" Web sites. The WebBrowser control is itself an ActiveX control container that can host any ActiveX control.

The following sections show you how you can use the MFC CHtmlView class (which encapsulates the WebBrowser control) to create a Web browser-style application that uses HTML as the primary interface. You will learn how to use ATL to create an ActiveX control that hosts the WebBrowser control.

You will also learn how you can access the DHTML object model from within your C++ code to access and manipulate elements of the HTML document displayed by your application or control.

MFC Web Browser-Style Applications

The Microsoft WebBrowser control is a standard ActiveX control, which means you can insert the control into your MFC project using the Components and Controls Gallery. Inserting the control will create the CWebBrowser2 class, which wraps the IWebBrowser2 Automation interface exposed by the WebBrowser control. You can use the CWebBrowser2 class to get and set properties and call methods using C++ types rather than Automation types.

However, the preferred method of creating a Web browser-style application is to use the MFC AppWizard and specify CHtmlView as the view class. The CHtmlView class is derived from CView and provides the functionality of the WebBrowser control within the context of MFC's document/view architecture. CHtmlView provides member functions to allow you to access the browser functionality from within your code.

Note that you must have installed Internet Explorer 4.0 (or a later version) before you can use the CHtmlView class or the WebBrowser control.

The following exercise shows you how to create a Web browser-style application using the MFC AppWizard.

  • To create the MyHtmlApp application
    1. On the File menu, click New to create a new MFC AppWizard (exe) project named MyHtmlApp.
    2. In Step 1 of the MFC AppWizard, select the Single document option.
    3. Select the default options for steps 2 through 5.
    4. In Step 6, click CHtmlView in the Base class box. Click Finish and then click OK to create the project.

    After the project is created, expand the CMyHtmlAppView class in ClassView. Double-click the OnInitialUpdate function to view the code. The code should be as follows:

    void CMyHtmlAppView::OnInitialUpdate() {      CHtmlView::OnInitialUpdate();      // TODO: This code navigates to a popular spot on the Web.      // Change the code to go where you'd like.      Navigate2(_T("msdn.microsoft.com/visualc/"),NULL,NULL); }

    The OnInitialUpdate function uses the CHtmlView::Navigate2() function to locate and display Microsoft's Visual C++ home page in the application main window. If you do not have a live Internet connection, you might want to alter the Navigate2() function call to make the application display the MyPage.htm file instead. Supposing that MyPage.htm file is located in the c:\DAVC\Chapter 12\Exercises folder, you might want to alter the line to be as follows:

    Navigate2(_T("c:\\DAVC\\Chapter 12\\Exercises\\MyPage.htm") ,NULL,NULL);

    Before you build and run the MyHtmlApp application, complete the following exercise to add Forward and Back navigation options.

  • To add navigation menu and toolbar options
    1. In ResourceView, open the IDR_MAINFRAME menu resource from the Menu folder.
    2. Delete the Edit menu, and in its place add a new menu with the caption &Go.
    3. Add two commands to this menu with the captions &Back and &Forward. Add suitable prompt strings for the options. Allow the editor to create the default IDs ID_GO_BACK and ID_GO_FORWARD.
    4. Close the menu editor. Open the IDR_MAINFRAME toolbar resource. Delete the Cut, Copy, and Paste toolbar buttons by dragging them off the toolbar.
    5. Create toolbar buttons for the ID_GO_BACK and ID_GO_FORWARD command IDs as shown in Figures 12.3 and 12.4.
    6. Figure 12.3 The ID_GO_BACK toolbar button

      Figure 12.4 The ID_GO_FORWARD toolbar button

    7. Close the toolbar editor. Open ClassWizard and click the Message Maps tab.
    8. To the CMyHtmlAppView class, add command handlers for the ID_GO_BACK and ID_GO_FORWARD command IDs, named OnGoBack() and OnGoForward(). Click Edit Code to locate the function implementations.
    9. To each of the handler functions, add the corresponding CHtmlView navigation member function, as follows:
    10. void CMyHtmlAppView::OnGoBack() {      GoBack(); } void CMyHtmlAppView::OnGoForward() {      GoForward(); }

    11. Build and run the application. Figure 12.5 shows the MyHtmlApp application displaying the Microsoft Visual C++ home page, as specified by the default implementation of the CMyHtmlAppView:: OnInitialUpdate() function.
    12. click to view at full size.

      Figure 12.5 The MyHtmlApp application

    Explore the browser features that are provided to your application by CHtmlView. Notice that the application status bar displays information about the hyperlinks, and about the progress of a page download operation. After you have moved to other pages using hyperlinks on the page, you can move through your history list by using the Go Back and Go Forward menu and toolbar options that you created.

    Accessing the DHTML Object Model

    You will remember that access to DHTML objects such as window or document is very easy when you are writing a piece of script in an HTML document. You can simply refer to objects by name, as shown in the following piece of JavaScript:

    document.bgColor = "hotpink";

    This ability is made possible by the fact that the Internet Explorer script interpreter is parsing your lines of script and converting them into calls to the Internet Explorer Automation interfaces. In C++, you access the DHTML object model by using the Automation interfaces directly.

    The DHTML object model is exposed through a set of COM interfaces with the prefix IHTML (IHTMLDocument, IHTMLWindow, IHTMLElement, and so on). The CHtmlView class provides the GetHtmlDocument() function, which returns an IDispatch pointer of the HTML document that is currently displayed. You can call QueryInterface() on this IDispatch pointer to obtain pointers to the IHTML interfaces. After you have obtained pointers to these interfaces, you can use the properties and methods they provide to manipulate the document.

    The following exercise demonstrates how you can access elements of an HTML page displayed in the MyHtmlApp application. You will write code to retrieve all of the anchor elements (links) in the current page, and display their HREF attribute values (URLs or file paths) in a dialog box. The user will be able to select a link to view in the browser.

  • To create the View Links dialog box
    1. Using the dialog editor, create the View Links dialog box as illustrated in Figure 12.6. This dialog box should be given the resource ID IDD_LINK_DIALOG, and it should contain a large list box control named IDC_LINK_ LIST as well as the standard OK and Cancel buttons. The OK button should display the caption Go to link.
    2. click to view at full size.

      Figure 12.6 The View Links dialog box

    3. From within the resource editor, press CTRL+W to create a dialog class named CLinkDialog for the View Links dialog box. On the Member Variables page of ClassWizard, add the variables listed in Table 12.1.
    4. Table 12.1 Variables for the View Links Dialog Box

      Resource ID Category Variable type Variable name
      IDC_LINK_LIST Value CString m_strLink
      IDC_LINK_LIST Control CListBox m_lbLinkList

    5. On the Message Maps tab of ClassWizard, create an overload of the OnInitDialog() function for the CLinkDialog class (to handle the WM_INITDIALOG message). Click Edit Code to locate the function implementation.
    6. Replace the stub function with the following code, which can be found in the InitLnkDlg.cpp file in the Chapter 12\Exercises folder.
    7.  BOOL CLinkDialog::OnInitDialog() {      CDialog::OnInitDialog();      // Get pointer to view      CFrameWnd * pFrame =            dynamic_cast<CFrameWnd *>(AfxGetMainWnd());      ASSERT_VALID(pFrame);      CHtmlView * pHtmlView =            dynamic_cast<CHtmlView *>(pFrame->GetActiveView());      ASSERT_VALID(pHtmlView);      // Get pointer to the document object dispatch interface      IDispatch * pDisp = pHtmlView->GetHtmlDocument();      if(pDisp != NULL)      {           // Get pointer to IHTMLDocument2 interface to           // access document object's properties and methods           IHTMLDocument2 * pHTMLDocument2;           HRESULT hr;           hr = pDisp->QueryInterface(IID_IHTMLDocument2,                (void**)&pHTMLDocument2);           if(hr == S_OK)           {                // Get pointer to the anchors collection                IHTMLElementCollection * pColl = NULL;                hr = pHTMLDocument2->get_anchors(&pColl);                if(hr == S_OK && pColl != NULL)                {                     LONG nElem;                     hr = pColl->get_length(&nElem);                     if(hr == S_OK)                     {                          // Iterate across anchors collection                          for(long i = 0; i < nElem; i++)                          {                               _variant_t vIndex(i);                               _variant_t vName = vIndex;                               IDispatch * pDisp2;                               hr = pColl->item(                                    vName, vIndex, &pDisp2);                               if(hr == S_OK)                               {                                    // Retrieve pointer to each                                     // Anchor element so that you can                                    // retrieve the URL text and add                                     // it to the list box                                    IHTMLAnchorElement * pAnchElem;                                    hr = pDisp2->QueryInterface(                                         IID_IHTMLAnchorElement,                                         (void**) &pAnchElem);                                    if(hr == S_OK)                                    {                                         BSTR bstrHref = 0;                                         pAnchElem->get_href(&bstrHref);                                         CString strLink(bstrHref);                                         if(!strLink.IsEmpty())                                              m_lbLinkList.AddString(strLink);                                         SysFreeString(bstrHref);                                         pAnchElem->Release();                                    }                                    pDisp2->Release();                               }                          }                     }                     pColl->Release();                }                pHTMLDocument2->Release();           }           pDisp->Release();      }      return TRUE; // return TRUE unless you set the focus to a control           // EXCEPTION: OCX Property Pages should return FALSE } 

      Look through this function to understand how it really works. A pointer to the HTML document's dispatch interface is obtained by calling the CHtmlView::GetHtmlDocument() function. This pointer is used to obtain an IHTMLDocument2 interface pointer, and the IHTMLDocument2:: get_anchors() function is called to get a pointer to the DHTML anchors collection. The InitDialog() function iterates across the anchors collection and, on each iteration, retrieves an IHTMLAnchorElement pointer to the current element. From this element, the value of the HREF attribute is obtained and inserted into the list box.

    8. To the top of LinkDialog.cpp, along with the other #include statements, add the following lines:
    9. #include <mshtml.h> #include <comdef.h>

      The mshtml.h file contains the definitions for the IHTML interfaces. Comdef.h contains the definition of the _variant_t COM helper class.

    10. Create a new menu command with the caption Links under the View menu. This should have the default command ID ID_VIEW_LINKS. Using ClassWizard, create a command handler function for this ID in the CMyHtmlAppView class. This function should be named OnViewLinks.
    11. To the body of the CMyHtmlAppView::OnViewLinks() function, add the following code:
    12. CLinkDialog aDlg; if(aDlg.DoModal() == IDOK)     // ("Go to link" button) {      // If a link was selected, go there!      if(!aDlg.m_strLink.IsEmpty())           Navigate2(aDlg.m_strLink, NULL, NULL); }

    13. To the top of the MyHtmlAppView.cpp file, with the other #include statements, add the following line:
    14. #include "LinkDialog.h"

    15. You can now build and run the application. Using the Web or the local HTML files, test to see that all of the links on a particular page are displayed in the dialog box when the Links option is selected from the View menu. Select a link from the list and click Go to link to check that you moved to the destination successfully. Figure 12.7 shows the View Links dialog box displaying all the URLs for links on the Microsoft Visual C++ home page.
    16. click to view at full size.

      Figure 12.7 The View Links dialog box in action

    NOTE
    You will find that URLs containing spaces, such as c:\DAVC\Chapter 12\ Exercises\MyPage.htm, will appear in the View Links dialog box with escape sequences in place of the spaces. This is because Internet Explorer uses the InternetCanonicalizeUrl() API function to convert the URLs into a safe format for resolution. You can use the InternetCanonicalizeUrl() function to decode the URLs for display purposes. See the Internet Explorer Platform SDK for more information.

    HTML Resources

    You can include HTML pages as resources in your project, just as you can include bitmaps or dialog templates. HTML resources can be stored as .htm files in your project's res subfolder, or defined inline in your project's resource script (.rc) file. In either case, you edit the HTML resource using the Visual C++ editor. Because HTML resources are compiled into your program executable, their use provides a safe and convenient way to distribute HTML pages used by your application.

    In the following exercise, you will include the MyPage.htm and SecondPage.htm files, which you saw earlier in this chapter, as resources in your application.

  • To add HTML resources to the MyHtmlApp project
    1. In ResourceView, right-click the top-level MyHtmlApp Resources folder. On the shortcut menu, click Import.
    2. Using the Import Resource dialog box, click HTML files (.htm; .html) in the Files of type box. Locate the Chapter 12\Exercises\MyPage.htm file and click Import.
    3. The HTML source opens in the editor window. Note the HTML-aware color syntax highlighting.
    4. Right-click the IDR_HTML1 resource that has been added and then click Properties.
    5. Rename the resource IDR_MYPAGE. Note the External file check box, which allows you to specify whether the resource is stored as a file in your project's res folder or in your .rc file. Leave this check box selected.
    6. Repeat the process to add the Chapter 12\Exercises\SecondPage.htm file as an application resource. Name the resource IDR_SECONDPAGE.

    To make your application display an HTML resource, use the CHtmlView:: LoadFromResource() function as shown in the following exercise.

  • To display an HTML resource
    1. Locate the CMyHtmlAppView::OnInitialUpdate() function. Comment out the following line:
    2. Navigate2(_T("msdn.microsoft.com/visualc/"),NULL,NULL);

      Beneath this line, add the following:

      LoadFromResource(IDR_TITLEPAGE);

    3. Build and run the MyHtmlApp application. Check that the IDR_TITLEPAGE HTML resource displays as expected.

    Note that what you are seeing is a compiled version of the TitlePage.htm file. This means that any changes you make to the HTML code in the TitlePage.htm file will not display unless you rebuild the application. This also means that your View Links dialog box will not be able to retrieve and display the link on this page.

    Additionally, you will notice that you are not able to follow the local page link. This is because the link is defined as follows to point to an external .htm file:

    <A HREF= "SecondPage.htm"> link to a local page </A>

    You will need to redefine this link to point to the IDR_SECONDPAGE resource. Internet Explorer provides the res: protocol, which is similar to the HTTP protocol. It allows you to define a URL to locate a resource that is bound to an executable or DLL file. The res: protocol has the following format:

    res://resource_file/[resource_type]/resource_id

    In this protocol, resource_file indicates the name of the executable or DLL file that contains the resource, and resource_type is an optional numeric value that indicates the type of the resource—two values most commonly used here are 23 (an HTML page) and 2 (a bitmap). The numeric identifier of the resource is indicated by resource_id. The winuser.h file in the Microsoft Visual Studio\Vc98\Include folder gives a complete list of resource types as a list of constants with the RT_ prefix. If you do not specify the type, the default value 23 is used.

    In the following exercise, you will amend the links on your HTML resource pages to use the res: protocol.

  • To create a link to another resource
    1. In ResourceView, right-click the MyHtmlApp resources folder. On the shortcut menu, click Resource Symbols. The Resource Symbols dialog box will appear.
    2. Write down the numeric values assigned to the IDR_MYPAGE and the IDR_SECONDPAGE resource IDs. Close the Resource Symbols dialog box.
    3. Double-click the IDR_MYPAGE resource to edit the HTML source. Replace the following hyperlink definition:
    4. <A HREF= "SecondPage.htm"> link to a local page </A>

      with the new hyperlink definition:

      <A HREF= "res://MyHtmlApp.exe/n">

      where n is the number assigned to the IDR_SECONDPAGE resource ID.

    5. Edit the IDR_SECONDPAGE resource. Replace the following hyperlink definition:
    6. <A HREF="MyPage.htm"> Here </A>

      with the new hyperlink definition:

      <A HREF="res://MyHtmlApp.exe/n"> Here </A>

      where n is the number assigned to the IDR_MYPAGE resource ID.

    7. Build and run the MyHtmlApp application. Check that you can use the links to move between the MyPage and the SecondPage pages.

    Creating HTML Controls with ATL

    Using ATL, you can create a control that is capable of displaying HTML pages. An ATL HTML control hosts the WebBrowser control and provides a pointer to the IWebBrowser2 Automation interface, which gives you access to the DHTML object model.

    As with any other control created with ATL, the HTML control provides an empty dispatch interface to which you can add methods and properties to define how your control will interact with a container. In addition, the HTML control provides another dispatch interface that is used to communicate between the C++ code and the HTML user interface. The HTML user interface calls into C++ code using this interface, enabling you to write C++ methods that are callable from script within your HTML page.

    The ATL HTML control provides an HTML resource as an example user interface for the control, and a method that demonstrates how you can write functions that are callable from the HTML user interface.

    The following exercises show you how to create a simple HTML control using ATL.

  • To create the MyHtmlControl project
    1. On the Visual C++ File menu, click New. Create an ATL COM AppWizard project named MyHtmlControl.
    2. In Step 1 of the ATL COM AppWizard, accept the default settings and click Finish. Click OK to create the project.

  • To insert an HTML control
    1. In ClassView, right-click MyHtmlControl classes and then click New ATL Object. In the ATL Object Wizard, click the Controls category and the HTML Control, as shown in Figure 12.8.
    2. click to view at full size.

      Figure 12.8 The ATL Object Wizard

    3. Click Next. On the Names page of the ATL Object Wizard Properties dialog box, type MyHtmlCtrl in the Short Name box. The other boxes will be filled automatically and will appear as shown in Figure 12.9.
    4. click to view at full size.

      Figure 12.9 The ATL Object Wizard Properties dialog box

    5. Click OK to add the HTML control to the project.
    6. In ResourceView, double-click the IDH_MYHTMLCTRL resource in the HTML resources folder to view the source code for the example HTML page that is created as the user interface for the MyHtmlCtrl control. The HTML code displays as follows:
    7. <HTML> <BODY id=theBody> <BUTTON onclick='window.external.OnClick(theBody, "red");'>Red </BUTTON> <BR> <BR> <BUTTON onclick='window.external.OnClick(theBody, "green");'>Green </BUTTON> <BR> <BR> <BUTTON onclick='window.external.OnClick(theBody, "blue");'>Blue </BUTTON> </BODY> </HTML>

      This simple piece of DHTML defines three buttons on the page that all respond to the onclick event by calling a function named OnClick(). The OnClick() function takes two parameters; the name of an element ID, and a string that specifies one of the colors in the Internet Explorer color table.

      The OnClick() function is not part of the DHTML object model. It is a method of the IMyHtmlCtrlUI interface defined for your project by the ATL Object Wizard. You define properties and methods for the IMyHtmlCtrlUI interface that are callable from your control's DHTML code via the window.external object.

      If you look in MyHtmlCtrl.h, you will find the implementation of IMyHtmlCtrlUI::OnClick() as follows:

      // Example method called by the HTML to change the <BODY>       background color STDMETHOD(OnClick)(IDispatch* pdispBody, VARIANT varColor) {      CComQIPtr<IHTMLBodyElement> spBody(pdispBody);      if (spBody != NULL)           spBody->put_bgColor(varColor);      return S_OK; }

      The OnClick() function takes the IDispatch pointer of the DHTML page element and a VARIANT that contains the color string. The function uses the ATL CComQIPtr class to obtain a smart pointer to the IHTMLBodyElement interface from the element's dispatch interface. If the IHTMLBodyElement interface pointer is obtained correctly (a BODY element has been passed as expected), then the put_bgColor() method is called to set the background color of the document body.

    8. Build the MyHtmlControl project to create the MyHtmlControl.dll and to register the MyHtmlCtrl ActiveX control. Take the steps below to test the operation of the MyHtmlCtrl control.

  • To test the MyHtmlCtrl control
    1. On the Visual C++ Tools menu, click ActiveX Control Test Container.
    2. On the Edit menu of the ActiveX Control Test Container, click Insert New Control. In the Insert Control dialog box, click MyHtmlCtrl Class and then click OK to place the control in the container.
    3. Experiment with the control buttons to see that they change the background color as expected.

    NOTE
    This control does not function properly with some versions of Internet Explorer 5. You may need to install Internet Explorer 4.0 to see the correct behavior.

    In the following exercises, you will add a button and a handler function that will move to and display a Web page in your HTML control.

  • To add the WWW button
    1. Open the IDH_MYHTMLCONTROL HTML resource in the editor.
    2. Add the following lines to the bottom of the BODY section of the document:
    3. <BR> <BR> <BUTTON onclick='window.external.GoToWeb();'>WWW</BUTTON>

  • To add the GoToWeb() method
    1. In ClassView, expand the CMyHtmlCtrl item.
    2. Right-click the IMyHtmlCtrlUI interface item that is a sub-item of the CMyHtmlCtrl item. Select Add Method.
    3. In the Add Method to Interface dialog box, add GoToWeb to the Method Name box. Leave the Parameters box blank and click OK to add the method.
    4. Expand the IMyHtmlCtrlUI interface item and double-click the GoToWeb() function to open the MyHtmlCtrl.cpp file and edit the GoToWeb() function implementation.
    5. Replace the //TODO comment in the GoToWeb() function with the following line of code:
    6. m_spBrowser->Navigate(CComBSTR("msdn.microsoft.com/visualc/"),      NULL, NULL, NULL, NULL);

      CMyHtmlCtrl::m_spBrowser is a smart pointer to the IWebBrowser2 interface, the Automation interface of the WebBrowser control. This member variable is supplied for your control class by the ATL Object Wizard.

    7. Build the MyHtmlControl project and test the MyHtmlCtrl control by loading it into the ActiveX Control Test Container. Check that when you click the WWW button, the control displays the Visual C++ home page, as illustrated in Figure 12.10.
    8. click to view at full size.

      Figure 12.10 The MyHtmlCtrl ActiveX control

    Dynamic HTML Scriptlets

    DHTML scriptlets were introduced in Internet Explorer 4.0 to allow you to develop simple user interface controls using DHTML. Scriptlets are reusable DHTML objects that expose a well-defined public interface—a list of properties and methods that are accessible to clients. Scriptlets are also capable of firing events.

    One of the most interesting features of scriptlets is that they can be used like an ActiveX control. For example, they can be placed on a Web page or on a form in a desktop application. This behavior is made possible by the fact that scriptlets are run inside the Microsoft Scriptlet Component, an ActiveX control that is installed along with Internet Explorer. Internally, the Scriptlet Component hosts an instance of the DHTML parsing engine to interpret the scriptlet code. Externally, it presents a standard ActiveX control interface to allow interaction with a control container.

    The Scriptlet Component exposes the scriptlet's public interface to the control container. It acts as a bridge so that the container application can access the public properties and methods defined in the scriptlet's DHTML code.

    The Scriptlet Component provides an internal interface, which is accessible from the scriptlet code. Scriptlet code can query the window.external object to gain run-time information about the current state of its host; and to access services of the Scriptlet Component, such as the forwarding of events fired by the scriptlet to the containing application.

    Because scriptlets run as interpreted DHTML, they execute more slowly than compiled ActiveX controls. But if all you need is a simple lightweight control, scriptlets provide you with an easy way of developing reusable components.

    Elements of a DHTML Scriptlet

    A DHTML scriptlet is a normal DHTML document that contains <BODY> and <SCRIPT> elements. The <BODY> element defines the visual interface of the control, which you create as you would for a regular Web page.

    Within the <SCRIPT> element, you define the properties, methods, and events that allow you to use the scriptlet as a control. By following certain naming conventions, you can distinguish between the public properties and methods that are exposed to clients through the control interface; and the private properties and methods that are used only internally by the scriptlet.

    Declaring Scriptlet Properties and Methods

    Within a scriptlet, all properties and methods that are not explicitly declared public are considered private. As with any other HTML document, the <SCRIPT> elements are local to the document in which they are defined.

    There are two ways of declaring public properties and methods. The first way simply involves adding the public_ prefix to the names of all public properties and methods. You can also specify properties by declaring them as functions with the public_get_ and public_put_ prefixes. This allows you finer control over the property—for example, you could make a property read-only by specifying a public_get() function and not a public_put() function.

    The following example shows a simple scriptlet containing a paragraph named p1. The script block following the paragraph exposes a property called text and another called color, which is defined using get and set functions. The scriptlet also exposes a function called animate().

    <HTML><HEAD></HEAD> <BODY> <FONT ID="f1" color="black"> <P ID="p1">This is a paragraph of text.</P> </FONT> <SCRIPT LANGUAGE="JavaScript"> var public_text = p1.innerText; function public_get_color() {      return f1.color; } function public_put_color(color) {      f1.color = color; } function public_animate() {      // Code to perform animation } </SCRIPT> </BODY></HTML>

    If a client page were to declare an instance of this scriptlet object (you will see how this is done later), naming it MyScriptlet, any of the following JavaScript operations would be legal:

    MyScriptlet.text = "Hello"; … MyScriptlet.animate(); … var OldColor = MyScriptlet.color; … MyScriptlet.color ="blue";

    The second method of defining the public interface of a scriptlet is to use the JavaScript public_description object. You create a JavaScript constructor function that declares your scriptlet's public properties and methods, and you assign this function to the scriptlet's public_description object. Properties and methods within the scriptlet document that are not declared within the constructor function are private.

    Using the public_description method, the scriptlet from our previous example would look as follows:

    <HTML><HEAD></HEAD> <BODY> <FONT ID="f1" color="black"> <P ID="p1">This is a paragraph of text.</P> </FONT> <SCRIPT LANGUAGE="JavaScript"> public_description = new CreateScriptlet(); function CreateScriptlet() { this.text = p1.innerText;     // text property this.put_color = putcolor;     // color property (write) this.get_color = getcolor;     // color property (read) this.animate = doAnimation;     // animate() method } function getcolor() {      return f1.color; } function putcolor(color) {      f1.color = color; } function doAnimation() {      // Code to perform animation } </SCRIPT> </BODY></HTML>

    The name of the constructor function (it can have any name) is assigned to the public_description object. In the example just given, the CreateScriptlet() constructor function specifies the text and color properties, assigning a value for the text property and specifying the names of the private functions getcolor() and putcolor() used to get and set the color property values. The function also specifies the animate() method and the name of the private function doAnimation() that implements the method.

    Using the public_description object is the preferred method of seasoned object-oriented software developers. This technique creates a clear distinction between interface and implementation, and it allows you to neatly define the interface of the scriptlet in a single location—usually at the beginning of a <SCRIPT> block.

    Scriptlet Events

    An application containing a scriptlet can be notified about events that occur in the scriptlet. A DHTML scriptlet can expose two types of events:

    • Standard DHTML events include the onclick event and the onkeypress event.
    • Custom events are events that you define or DHTML events not provided as standard events. For example, the scriptlet can fire an event when a property value changes.

  • Handling Standard Events
  • A DHTML scriptlet can expose any of these standard DHTML events:

    • onclick
    • ondblclick
    • onkeypress
    • onkeydown
    • onkeyup
    • onmousemove
    • onmousedown
    • onmouseup

    You will recall from our introduction to DHTML scriptlets that one of the services provided by the Scriptlet Component is to forward events fired by the scriptlet to the control container. For example, suppose a user double-clicks the mouse in the scriptlet body. The DHTML ondblclick event is intercepted by the Scriptlet Component, and it might react by passing on a corresponding event of the appropriate type to its container. However it is important to understand that it will do this only if it is specifically instructed to do so by an element of the scriptlet code.

    To pass an event from the scriptlet to the container application, you must provide an event handler for the event you want to pass, and call the bubbleEvent method from the event handler. The bubbleEvent method is provided by the Scriptlet Component, and is accessed through the window.external object.

    To continue with our example, you would handle mouse double-clicks in the scriptlet body by specifying the body as follows:

    <BODY ondblclick = passthru()> ... </BODY>

    To forward the event to the container, you would define the passthru() function as follows:

    function passthru() {      if(!window.external.frozen)           window.external.bubbleEvent(); }

    Note that before it attempts to forward the event, the routine checks the Scriptlet Component's frozen property to ensure that it is ready to handle events.

  • Creating and Handling Custom Events
  • In addition to handling the standard DHTML events, you can make your scriptlet fire custom events. You can use custom events to:

    • Send more detail about a standard event that occurred—for example, which of several buttons in the scriptlet was clicked.
    • Notify the host application about non-standard changes in the scriptlet, such as when the value of a property changes.
    • Notify the host application about DHTML events that are not among the standard events handled by the bubbleEvent method.

    You can fire custom events from anywhere in your scriptlet code by using the raiseEvent method. The following example shows how you can use a custom event to notify the container application that the scriptlet's background color has been changed:

    <SCRIPT LANGUAGE="JavaScript"> function public_put_backgroundColor(value) {      window.document.bgColor = value;      if(!window.external.frozen)      window.external.raiseEvent("onbgcolorchange",           value); } </SCRIPT>

    You will notice that the raiseEvent method takes two parameters. The first parameter specifies a name for the event so that it can provide a standard interface to its container. The Scriptlet Component routes all custom scriptlet events through a single event named onscriptletevent. You can query the name parameter to identify which event has been fired. The second parameter can be used to pass data associated with the event.

    The following code below illustrates how Internet Explorer could handle the onbgcolorchange event raised in the previous example:

    <SCRIPT LANGUAGE="JavaScript"       FOR="MyScriptlet"       EVENT="onscriptletevent (event, obj)">      if(event == "onbgcolorchange")      {           msg = "Scriptlet background changed to " + obj;           alert(msg);      } </SCRIPT>

    Scriptlet Example

    To help you understand how scriptlets work, and how you can use them in your applications, we have included the ColorSelector scriptlet—a simple control that allows you to browse through a set of colors and select one. The source code for the scriptlet is available from Chapter 12\Exercises\ColorSelector.htm on the companion CD:

    <!— ColorSelector.htm —> <HTML><HEAD></HEAD> <BODY style="border:2px solid black;      color:white; background-color:white "      ondblclick = passthru()> <DIV ID=d1 style="position:relative; border:1px solid black; top:5; left:5; width:130; height:50"> </DIV> <P ID=p1 style="position:relative; left:13"> <BUTTON ID=BackButton onclick = cycle("back")> < </BUTTON>. <BUTTON ID=ForwardButton onclick = cycle("forward")> > </BUTTON> <BUTTON ID=SelectButton onclick = doSelect()> Select </BUTTON> </P> </BODY> <SCRIPT LANGUAGE="JavaScript"> public_description = new colorselector(); var colors = new Array("white", "red", "green", "blue", "black") ; var numcolors = colors.length; var curcolor = 0; // Object description function colorselector() {      this.get_color = getcolor; } // Public property access function function getcolor() {      return colors[curcolor]; } // Events // Standard function passthru() {      if(!window.external.frozen)           window.external.bubbleEvent(); } // Custom function doSelect() {      if(!window.external.frozen)           window.external.raiseEvent("onClickSelect", colors[curcolor]); } // Private methods function cycle(direction) {      if(direction == "back")      {           curcolor — ;           if(curcolor < 0)                curcolor = numcolors-1;      }      if(direction == "forward")      {           curcolor++;           if(curcolor >= numcolors)                curcolor = 0;      }      d1.style.backgroundColor = colors[curcolor]; } </SCRIPT> </HTML>

    By examining the colorselector() function assigned to the scriptlet's public_description object, you will be able to see that the scriptlet exposes a single read-only property named color. Note that the scriptlet exposes the standard ondblclick event and raises a custom event named onClickSelect.

    Hosting Scriptlets in a Web Page

    Like regular ActiveX controls, scriptlets can be placed in a Web page by using the HTML <OBJECT> tag. Unlike regular ActiveX controls, scriplets are not identified using a ClassID. Instead, you assign the scriptlet MIME type to the TYPE attribute, and a URL that points to the scriptlet source file to the DATA attribute. MIME (Multipurpose Internet Mail Extensions) is an Internet protocol that allows a Web browser to identify the type of file that it is displaying. The b type that identifies a scriptlet is text/x-scriptlet.

    The following example shows you how to place a scriptlet defined in the MyScriptlet.htm file.

    <OBJECT ID="MyScriptlet" TYPE="text/x-scriptlet"DATA="MyScriptlet.htm"> </OBJECT>

    This code assumes that the MyScriptlet.htm file can be found in the same directory as the current file.

    With the ColorSelector scriptlet, we have included a simple HTML page that allows you to test the scriptlet. TestScriptlet.htm is located in the Chapter 12\Exercises folder and is also listed as follows:

    <!— TestScriptlet.htm —> <HTML> <HEAD> <TITLE> Scriptlet Test </TITLE> </HEAD> <BODY> <H1> Scriptlet Test </H1> <P> <OBJECT ID="MyScriptlet" TYPE="text/x-scriptlet"       DATA="ColorSelector.htm"> </OBJECT> </P> <P> <BUTTON ID="Btn1" onclick="UseScriptlet()"> Display </BUTTON> </P> </BODY> <SCRIPT LANGUAGE="JavaScript"> function UseScriptlet() {      alert(MyScriptlet.color); } </SCRIPT> <SCRIPT LANGUAGE="JavaScript"      FOR="MyScriptlet"      EVENT="onscriptletevent(event, obj)">      if(event == "onClickSelect")           document.body.bgColor = obj; </SCRIPT> <SCRIPT LANGUAGE="JavaScript"      FOR="MyScriptlet"      EVENT=ondblclick>      alert("double-clicked in scriptlet"); </SCRIPT> </HTML>

    This page tests the scriptlet functionality in the following ways:

    • The scriptlet is hosted in Internet Explorer. You can test the internal functions of the scriptlet by clicking its arrow buttons to cycle through its colors.
    • When you click the test page's Display button, the scriptlet retrieves the current value of the scriptlet's color property and displays it in an alert box.
    • When you click the scriptlet's Select button, the scriptlet fires an onClickSelect event. The event handler uses the color passed as an event parameter to set the background color of the test page.
    • The test page provides a handler to trap a standard ondblclick event from the scriptlet.

    Open the TestScriptlet.htm file in Internet Explorer and test the scriplet. Figure 12.11 shows the scriptlet in action.

    click to view at full size.

    Figure 12.11 Testing the ColorSelector scriptlet

    Hosting Scriptlets in a Visual C++ Application

    Although scriptlets can be placed on a form in a Microsoft Visual Basic application and used like a regular ActiveX control, this functionality is not yet available for Visual C++ containers such as dialog boxes. The theory is that you should use the Components and Controls gallery to insert the Scriptlet Component into the container, generating the CWebBridge class to wrap the IWebBridge interface exposed by the component. You can use this class to set the url property of the Scriptlet Component to the URL of the scriptlet's HTML document, and you can access the event property to handle custom events from the scriptlet.

    Although you can successfully insert the Scriptlet Component into the project, and generate the CWebBridge class, you are not currently able to place a control in a dialog box. If you try, you will receive the message shown in Figure 12.12.

    Figure 12.12 Scriptlet Component error message

    Users who try to use the CWebBridge class to create an instance of the Scriptlet Component control programmatically face similar difficulties, as documented in the Knowledge Base article Q190838. The article suggests that you might be able to create an instance of the Scriptlet Component by importing (with #import) the type library. Until the functionality to place the Scriptlet Component in a dialog box becomes available, you will be best off hosting scriptlets in an HTML page, and hosting the page in a CHtmlView-based application or an ATL HTML control.

    Lesson Summary

    The rapid growth of the Internet in recent years has led to many changes in the way we think about application development. Web browsers such as Internet Explorer are now used not just to view pages on the World Wide Web or on company intranets, but to access resources and run applications on your local area network servers, or on your desktop computer. You can develop Web browser-style applications that use HTML to present a rich and consistent interface; providing seamless access to resources on the desktop computer, on remote company servers, and on Web servers across the world.

    HTML is a system of marking up or tagging an ASCII document so that it includes formatting tags; references to graphics, sound, or animation files; and hyperlinks to Web pages or other resources. HTML defines a standard set of formatting tags that all Web browsers recognize. These tags divide an HTML document into discrete sections known as elements. Some elements denote a format to be applied to text within the document; others are used to include an external resource such as an image file, or to define a hyperlink to another document. Most of the HTML tags define attributes, which you can use to supply additional information about the element.

    DHTML allows you to create dynamic, interactive Web pages. For example, using DHTML, you can modify the content and style of your Web page and process user input. DHTML achieves these effects by using the user's computer to modify the current document, automatically reformatting and redisplaying the document to show changes.

    DHTML documents use HTML styles to specify the format and appearance of the document; and small blocks of script to process user input and directly manipulate the HTML tags, attributes, styles, and text in the document. Scripts in your DHTML document use the DHTML object model to access and manipulate elements of the current page.

    Microsoft provides the WebBrowser ActiveX control to help you incorporate the functionality of the Internet Explorer Web browser into your applications. The MFC class CHtmlView incorporates the WebBrowser control into MFC's document/view architecture. The CHtmlView class provides the GetHtmlDocument() function, which returns a pointer to the dispatch interface of the HTML document that is currently displayed. You can use this pointer access the Automation interfaces of the DHTML object model, and thus manipulate the document.

    Using ATL, you can create a control that is capable of displaying HTML pages. The ATL HTML control defines a dispatch interface to which you can add methods and properties to define how your control will interact with a container. The ATL HTML control defines an additional dispatch interface that is used to communicate between the C++ code and the HTML user interface. Script in the HTML page displayed by your control can access properties and methods defined for this interface via the DHTML window.external object.

    You can include HTML pages as resources in your project, just as you can include bitmaps or dialog templates. HTML resources are compiled into your program executable, and this provides a safe and convenient way to distribute HTML pages used by your application. You can use the res: protocol in a URL to locate a resource that is bound to an executable or DLL file.

    DHTML scriptlets are reusable DHTML objects that expose properties and methods that can be accessed by clients. Scriptlets can be used as ActiveX controls—for example, they can be placed in a Web page, or within a dialog box in a Visual C++ application. Scriptlets are run inside the Scriptlet Component, an ActiveX control that is installed along with Internet Explorer. The Scriptlet Component acts as a bridge so that the container application can access the public properties and methods defined in the scriptlet's DHTML code.

    The Scriptlet Component provides an internal interface, which is accessible from the scriptlet code. Scriptlet code can query the window.external object to gain run-time information about the current state of its host; and to access services of the Scriptlet Component, such as the forwarding of events fired by the scriptlet to the containing application.



    Microsoft Press - Desktop Applications with Microsoft Visual C++ 6. 0. MCSD Training Kit
    Desktop Applications with Microsoft Visual C++ 6.0 MCSD Training Kit
    ISBN: 0735607958
    EAN: 2147483647
    Year: 1999
    Pages: 95

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net