Export (0) Print
Expand All

Access Code to the Web

As of December 2011, this topic has been archived. As a result, it is no longer actively maintained. For more information, see Archived Content. For information, recommendations, and guidance regarding the current version of Internet Explorer, see Internet Explorer Developer Center.

Mark Davis, Heidi Housten, Dan Mohr, and Kusuma Vellanki
Microsoft Corporation

May 7, 2001

We are having a sense of déjà vu on the team, or at least Heidi is. She couldn't take our playful little jokes and has transferred to Microsoft Consulting Services in Sweden. We were just kidding, really Heidi! She has been enjoying a second spring in Stockholm, which by her accounts is stunning. The really good news is it means we, the Web Team, are now on duty 16 hours a day—all the better to handle your questions.

This month we expose agents, get to the source, get our calls crossed, and do some framing. We just love the danger and excitement of working on this team; we don't even ask for danger pay!

Hmmm, now, who can we get rid of next?!

Contents

Dynamic HTAs—showing secure frames on the fly
Straight to XML—retrieving the XML source
Crossed Calls—calling cross script functions
Microsoft Agents to the Rescue—a talking Web page

Web Team in Short

Dynamic HTAs

Dear Web Team:

I am converting my intranet over to a HTML Application (HTA). There is one issue, though. One of the features is opening URLs within the site, using Jscript to generate an IFRAME tag and DHTML to manipulate. I am using cross frame scripting. When I place the code within an HTA, it fails. According to the documentation, the APPLICATION="yes" attribute should be present in order to work. Thus I added it to the Jscript function, and yet it still does not work. I then copied the entire IFRAME function output into an HTA, and that worked fine. Further testing indicates that dynamically generated IFRAME tags within HTA's do not process the APPLICATION attributes. Am I missing a step? Or is there another attribute that needs to be set in order for this to be recognized?

J. Wolfgang Goerlich

The Web Team replies:

You have run into a design limitation in Internet Explorer 5.x. The security decisions for frames are made only once and that is when the document is initially being parsed. Any frames added dynamically after the document has finished loading will have a default value of "no" for the APPLICATION attribute.

There are a couple of ways you can work around this issue.

  1. If it is possible in your Web application framework to determine what frames you want to display while the document is being parsed, you can use document.write to write the IFRAMES dynamically and the APPLICATION attribute set on the frames at that time will be honored.
  2. If the decision can be made only after the document has been loaded, then you can have hidden IFRAMES in your page and use/reuse each of those in turn to display and position the content you need.

Here are some sample files to illustrate the above workarounds.

Parent.hta

<HTML>
<HEAD>
<SCRIPT>
function SayHello()
{
   alert("Hello there!");
}
function SetIframeSrc()
{
// ***** Replace all occurences of localhost2 with a different domain 
// ***** in this file
document.all.ifrm1.src='http://localhost2/iframe.htm'; 
document.all.ifrm1.style.display='block';
}
</SCRIPT>
</HEAD>
<BODY>
This is the parent HTA. It contains a function that will be invoked by the 
child IFRAMES. Save this HTA in one domain and save the IFRAME document in 
a different domain. Change the occurences of http://localhost2 in this HTA 
to your second domain for testing.

<BR><BR> Click the button in the child IFRAMES to see if you can invoke 
the function in the parent document.
<BR><BR><HR>
The following is a <B>dynamic</B> IFRAME with APPLICATION=YES and from a 
different domain written using <B>document.write</B>
<BR><BR>
<SCRIPT>
document.write("<IFRAME SRC='http://localhost2/iframe.htm' 
APPLICATION='yes'></IFRAME>");
</SCRIPT>
<BR><BR><HR>
Clicking on the button below will mimic  dynamic IFRAMES by setting IFRAME 
src of a hidden IFRAME and changing its display style from none to block.
<BR><BR>
<INPUT type=button value="Display hidden IFRAME and set a new SRC" 
onclick=SetIframeSrc()>
<BR><BR>
<IFRAME id=ifrm1 SRC='about:blank' APPLICATION='yes' 
STYLE='display:none'></IFRAME>
</BODY>
</HTML>

Iframe.htm

<HTML>
<BODY>
This is a test page which invokes a function in the parent
<BR><BR>
<INPUT type=button value="Invoke parent function" onclick="parent.SayHello()">
</BODY>
</HTML>

Straight to XML

Dear Web Team:

Hi, I have a Microsoft Visual Basic application that uses the Microsoft Internet Explorer WebBrowser control (Microsoft Internet Controls). When I navigate to an XML page and view the source I can view the original XML, but when I access the document object, I get HTML.

How do I access the original XML from the WebBrowser control?

Umashankar

The Web Team replies:

What you're seeing here is the default behavior of Internet Explorer. When you navigate to an XML document, Internet Explorer transforms the contents using the default XSL style sheet. When accessing the document object that is part of the Dynamic HTML object model, your application will receive an object representing the generated HTML.

Conveniently, as well as transforming your XML into a collapsible hierarchy display, Internet Explorer also adds an XMLDocument expando property to the document object that provides access to the original XML. See the MSDN Online reference for more information.

Expando properties enable a Dynamic HTML author to add properties to an existing object, thereby extending the object model, and are commonly used by script programmers to store additional information on HTML elements and objects. This property is available to your Visual Basic® application, as shown below.

Private Sub Form_Load()
    WebBrowser1.navigate " test.xml"
End Sub

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
    If (pDisp Is WebBrowser1.Object) Then
        Dim doc As Object
        Set doc = WebBrowser1.document.XMLDocument
        MsgBox doc.documentElement.childNodes.length
    End If
End Sub

If you're a C++ programmer, you don't have the convenience that Visual Basic offers. If you want to access the XMLDocument expando property from a C++ application, you can do this directly by using the IDispatchEx interface. As you probably already know, the IDispatch interface provides support for exposing object methods and properties and is used extensively by Internet Explorer to provide a rich object model. The IDispatchEx interface extends IDispatch by providing features that allow an object model to be dynamic. It is this interface that provides the powerful dynamic language features offered by Microsoft scripting languages, including expando properties.

The following code demonstrates how a C++ programmer would access the XMLDocument expando property in a Microsoft Foundation Class (MFC) application that uses a CHtmlView-derived view class. Note that the sample code makes use of Microsoft Visual C++ COM complier support and that DocumentComplete is an overridden function.

void CAView::DocumentComplete(LPDISPATCH pDisp, VARIANT* URL)
{
IDispatchPtr   spDisp;
HRESULT         hr;

   hr = m_pBrowserApp->QueryInterface(IID_IDispatch, (void**) &spDisp);
   // Is the IDispatch* passed to us for the top-level window ?
   if (pDisp == spDisp)
   {
   IHTMLDocument2Ptr spDoc;

      // Get the active document
      spDoc = GetHtmlDocument();
      if ( spDoc )
      {
      IHTMLWindow2Ptr spWin;

         // Get the top-level window
         spDisp = spDoc->Script;
         spWin = spDisp;
         if ( spWin )
         {
            // Get the document
            spDoc = spWin->document;
            if ( spDoc )
            {
            IDispatchExPtr spDispEx;

               // Get the document's IDispatchEx
               spDoc->QueryInterface( IID_IDispatchEx,
                                      (void**)&spDispEx );
               if ( spDispEx )
               {
               _bstr_t   bstrName("XMLDocument");
               DISPID dispid;

                  // Get the XMLDocument expando property
                  spDispEx->GetDispID( bstrName,
                                       fdexNameCaseSensitive,
                                       &dispid );
                  if ( SUCCEEDED(hr) && dispid != DISPID_UNKNOWN )
                  {
                  VARIANT var;
                  DISPPARAMS dpNoArgs = {NULL, NULL, 0, 0};

                     // Get the XMLDocument value
                     hr = spDispEx->Invoke( dispid,
                                       IID_NULL,
                                       LOCALE_USER_DEFAULT,
                                       DISPATCH_PROPERTYGET,
                                       &dpNoArgs,
                                       &var,
                                       NULL,
                                       NULL );
                     if ( SUCCEEDED(hr) && var.vt == VT_DISPATCH )
                     {
                     IXMLDOMDocument* pXMLDoc=NULL;

                        // Get the IXMLDOMDocument interface
                        var.pdispVal->QueryInterface(
                                       IID_IXMLDOMDocument,
                                       (void**)&pXMLDoc );
                        VariantClear( &var );
                        if ( pXMLDoc )
                        {
                        // Get the root element
                        IXMLDOMElement* pXMLElem=NULL;

                           pXMLDoc->get_documentElement( &pXMLElem );
                           if ( pXMLElem )
                           {
                           BSTR bstr;
                           USES_CONVERSION;

                              // Get/display the tag name
                              pXMLElem->get_tagName( &bstr );
                              AfxMessageBox( OLE2T(bstr) );
                              pXMLElem->Release();
                           }
                           pXMLDoc->Release();
                        }
                     }
                  }
               }
            }
         }
      }
   }
}

Crossed Calls

Dear Web Team:

I was writing a VBScript routine that needed to un-URLEncode a string. I couldn't find a VBScript function that did that but I found that there was the "unescape" function in JScript. I really didn't want to convert my routine to Jscript so I tried using the "unescape" function in VBS. And it worked!

Is this normal? Do other Jscript functions work in VBScript?

Thanks,
Ray Messinger

The Web Team replies:

VBScript does in fact implement the escape and unescape functions, but they are not documented. The reason? Web developers often turn to these functions for encoding and decoding URIs, but this is not what the functions were meant for in practice. For example, you will notice that the colon character in http://www.microsoft.com is escaped when using the escape function which is undesirable. To resolve this, URI encoding/decoding functions were added to ECMAScript and developers at Microsoft busied themselves to implement the following handy-dandy functions to do just that—proper URI encoding and decoding. You should use these functions rather than escape and unescape for your needs:

  • encodeURI
  • encodeURIComponent
  • decodeURI
  • decodeURIComponent

Note that these functions are available only in JScript®. How does all of this help you? The good news is that you don't need to convert your whole routine to JScript. You were correct in your guess. You can still call any of the global JScript functions or any user defined JScript functions directly in your VBScript code. Refer to the JScript documentation for a list of all the built-in functions that you can call from within your VBScript. The scripting documentation can be found at our Scripting site. Since these functions are available only when the JScript engine is loaded, you will need to have at least one statement or a script block using Jscript on your page. This can even be an empty script block like below.

<SCRIPT LANGUAGE=JScript> </SCRIPT> 
OR
<INPUT TYPE=button VALUE="Say hello" ONCLICK="JavaScript:alert('Hello')">

Microsoft Agents to the Rescue!

Dear Web Team:

Hi! I was wondering if there is a way, or a plug-in, for voice-enabling Microsoft Internet Explorer 5? I am looking to have voice commands, plus have the browser "read" text aloud.

Rebecca Robertson

Does Microsoft intend to support (i.e., update and improve) the Microsoft Agent technology? That stuff is pretty fun, and I love Mr. Peedy in particular, but according to the download certificate, he seems to be at least two years old now, and I am concerned that he may not be optimized or fully compatible with advancing versions of Internet Explorer. Please don't clip Mr. Peedy's wings!

David Hua

The Web Team replies:

If you've ever had the chance to play with the Microsoft Agent control, you'll know that it's a really useful technology—and fun! We'll talk more about Microsoft Agent in a moment, after answering the first question, regarding accessibility.

Microsoft has been involved in accessibility issues for many years and has provided many features to improve the accessibility of programs and operating systems. More detailed information about these efforts, features, and products is available at the Microsoft Accessibility site. One feature, Narrator, is a text-to-speech (TTS) utility that is provided with Microsoft Windows 2000. The accessibility features provided with Internet Explorer 5 are described at http://www.microsoft.com/enable/products/IE5/.

Internet Explorer, version 4.01 and later, is one of many products to support Microsoft Active Accessibility, a developer technology that improves the way programs work with accessibility aids. For more information on the Active Accessibility support in Internet Explorer, take at look at Microsoft Active Accessibility. Internet Explorer provides accessibility information about the user interface and also the HTML elements on the Web page being viewed by the user. An accessibility aid can make use of this information to provide navigation, visual and text-to-speech aids.

Microsoft Agent is alive and well! It's a fun technology that enables applications and Web pages to display an animated character that can provide text and speech, as well as accepting speech input. Such a character can act as a guide or assistant to your application, similar to the Microsoft Office assistant, Clippy. When Agent first came out we dabbled with a Web page that used Agent characters to read aloud Shakespeare plays that had been converted into XML. The use of this technology is only limited by your imagination!

The characters provided with Agent are Peedy the parrot, Robby the robot, Genie, and Merlin, and each has an extensive list of gestures. You can also use the Microsoft Agent Character Editor to create your own characters! There are many programming features available, such as character synchronization and events, and the technology is available as an ActiveX® control and programmable object. For more information, please read the developer information on the Microsoft Agent Web site. This site provides downloads of the Microsoft Agent technology, developer documentation, and example code.

Finally, we'll leave this article with some Microsoft Foundation Class (MFC) sample code that demonstrates how you might develop a custom browser that uses Agent to provide a simple text-to-speech feature to read aloud the Web page title. You could take this example further to read the entire Web page, read selected text, or even accept speech input commands to control your user's Web browsing.

The following steps assume that the Agent technology and Peedy character are installed, and is based on a standard MFC application created using the Microsoft Visual C++® 6.0 AppWizard. In the final wizard page, select the CHtmlView view class, which implements an Internet Explorer WebBrowser view. Once created, select the Add To Project Components and Controls menu item on the Visual C++ Project menu and insert the Microsoft Agent Control 2.0 classes into your project.

  1. In your view class header file, add the following includes, generated when you inserted the Agent control into your project:
    #include "agentctlex.h"
    #include "agentctlcharacters.h"
    #include "agentctlcharacterex.h"
    #include "agentctlrequest.h"
    
  2. Inside the view class definition, add the following class data members and method declaration:
       CAgentCtlEx            m_AgentCtl;
       CAgentCtlCharacters      m_AgentCharacters;
       CAgentCtlCharacterEx   m_AgentCharacter;
       void DocumentComplete(LPDISPATCH lpDisp,VARIANT FAR* URL);
    
  3. In your view class OnInitialUpdate() override, add the following highlighted code to initialize the Agent control:
    void CMyView::OnInitialUpdate()
    {
       CHtmlView::OnInitialUpdate();
    
       // Create the Microsoft Agent control
       m_AgentCtl.Create( "msagent", WS_VISIBLE, CRect(), this, ID_AGENT );
       m_AgentCharacters = m_AgentCtl.GetCharacters();
    
       // Load the Peedy character
       m_AgentCharacters.Load( "peedy", _variant_t("peedy.acs") );
       m_AgentCharacter = m_AgentCharacters.Character( "peedy" );
    
       // Show Peedy
       m_AgentCharacter.Show( _variant_t() );
    
       // TODO: This code navigates to a popular spot on the web.
       //  change the code to go where you'd like.
       Navigate2(_T("http://www.microsoft.com/visualc/"),NULL,NULL);
    }
    
  4. Override the CHtmlView::DocumentComplete() method to handle the OnDocumentComplete event:
    void CMyView::DocumentComplete(LPDISPATCH lpDisp,VARIANT FAR* URL)
    {
    IUnknown*   pUnk;
    IDispatch*   lpWBDisp;
    BSTR         bstrTitle;
    HRESULT      hr;
    
       hr = m_pBrowserApp->QueryInterface( IID_IUnknown,
                                           (void**)&pUnk );
       hr = pUnk->QueryInterface( IID_IDispatch,
                                  (void**)&lpWBDisp );
    
       if ( lpDisp == lpWBDisp )
       {
       IDispatch*      lpDocDisp;
       IHTMLDocument2*   lpDoc;
    
          // Top-level Window object, so document has been loaded
          lpDocDisp = GetHtmlDocument();
          hr = lpDocDisp->QueryInterface( IID_IHTMLDocument2,
                                          (void**)&lpDoc );
          lpDoc->get_title( &bstrTitle );
    
          // Play the "greet" gesture
          m_AgentCharacter.Play( "Greet" );
          // Ask to Peedy to speak the web page title
          m_AgentCharacter.Speak( _variant_t( bstrTitle ), _variant_t() );
    
          lpDoc->Release();
          lpDocDisp->Release();
       }
    
       lpWBDisp->Release();
       pUnk->Release();
    }
    

Web Team in Short

XML/XSL and Microsoft.com

Q: Russ Darroch is hunting for the MSDN article about rebuilding www.microsoft.com using XML and XSL.

A: Have a gander at the Extreme XML article.

Behavior Parameters

Q: Phil Jones wanted to know if you can make DHTML behavior parameters optional.

A: You can do it in JScript by examining the arguments property inside the function, but not in VBScript.

WebBrowser Control and Script Functions

Q: Dax Westerman is looking for a way to call script functions in the WebBrowser control from Visual C++.

A: Check out Q185127 - HOWTO: Call a Script Function from a VC WebBrowser Application for details.

Display Updating and Long Running Script Calls

Q: Bo is wondering how he can get the display to update when making long script calls.

A: Dave Massy tackled this question in his February edition of DHTML Dude.

The Web Team

Mark Davis is a software design engineer on the Internet Explorer SDK team. Mark originates from England and is currently training to climb the major summits in the Northwest.

Heidi Housten is on the MSDN Architectural Samples team. She came to MSDN from the Internet Client team at Microsoft Developer Support. She is convinced that her 14 years of living and working in England were just preparation for the gray and drizzle of Seattle.

Dan Mohr, an engineer with Microsoft Developer Support's Internet Client team, spends his free minutes recording bands in his basement, programming his Commodore 64, and extolling the virtues of late '70s punk rock.

Kusuma Vellanki is one of the few people who likes winters in Washington better than summers. When not working as a developer for the Internet Client team, she can be found skiing down the slopes of Washington.

The Web Team's Greatest Hits

List of Web Team Topics


  
Show:
© 2014 Microsoft