Welcome to MSDN Blogs Sign in | Join | Help

Displaying HTML using Silverlight 2

I recently researched displaying HTML from within a Silverlight 2 application. We have a huge amount of content that is currently rendered as HTML and Silverlight XAML is well suited for displaying UI elements and animations but does not have the kind of layout support we expect from HTML browsers.

Accessing the host page 

A Silverlight application is hosted in an HTML page as an OBJECT element. Silverlight 2 provides an easy way to access the host page from managed code, through the HtmlPage class. Once the Silverlight plug-in is loaded, the host page document object model (DOM) can be accessed using the static HtmlPage.Document property (in the System.Windows.Browser namespace). For example, you can place HTML controls on the page and then access these controls through the DOM, create elements, set styles, attach event handlers, etc. You can register managed code to enable it to be called from script, using HtmlPage.RegisterScriptableObject (see Calling Managed Code from Client Script). You can also call script from your Silverlight code using HtmlPage.Window.Invoke (see Calling Client Script from Managed Code). You will need to set the EnableHtmlAccess property to "true" if you want to make any changes to the DOM.

Overlaying HTML

If you are building a Silverlight application but want to display existing HTML content, you can place a DIV/IFRAME pair in the host page and position the DIV over your Silverlight application. Note that the Windowless property needs to be set to "true" on the Silverlight object. The following code shows how this would be declared in an ASP.NET page.

   <div style="height: 100%;">
    <asp:Silverlight ID="Xaml1" runat="server" EnableHtmlAccess="true" Source="/ClientBin/HtmlOverlay.xap" Version="2.0"
      Width="100%" Height="100%" Windowless="true" />
    <div id="HtmlContainer" class="contentHost">
     <iframe id="HtmlFrame" class="contentFrame" scrolling="no" frameborder="0"></iframe>
    </div>
  </div>

Once the Silverlight plug-in is loaded, you can locate the DIV/IFRAME elements and reposition them over your application. Use an XAML panel (e.g. Grid) to position the DIV according to your XAML layout.

In your panel constructor:

      this.Loaded += new RoutedEventHandler(Content_Loaded);
      this.SizeChanged += new SizeChangedEventHandler(Content_SizeChanged); 

In Content_Loaded:

      this.container = HtmlPage.Document.GetElementById("HtmlContainer");
      this.containerFrame = this.container.Children[0];

In Content_SizeChanged:

      UIElement root = Application.Current.RootVisual as UIElement;
      GeneralTransform gt = this.LayoutRoot.TransformToVisual(root);
      Point pos = gt.Transform(new Point(0, 0));
      this.container.SetStyleAttribute("left", pos.X.ToString() + "px");
      this.container.SetStyleAttribute("top", pos.Y.ToString() + "px");
      this.container.SetStyleAttribute("width", this.LayoutRoot.ActualWidth.ToString() + "px");
      this.container.SetStyleAttribute("height", this.LayoutRoot.ActualHeight.ToString() + "px");

This way, every time your panel is resized, the DIV is repositioned. To navigate the IFRAME to a web page, you'll need to access the window object:

      ScriptObject frames = (ScriptObject)HtmlPage.Window.GetProperty("frames");
      HtmlWindow wnd = frames.GetProperty(this.containerFrame.Id);

 ~or~

      HtmlElement iframe = HtmlPage.Document.GetElementById(this.containerFrame.Id);
      HtmlWindow wnd = iframe.GetProperty("contentWindow") as HtmlWindow;

Then call the Navigate method on the window object:

      wnd.Navigate(new Uri("http://www.microsoft.com/"));

To be informed when the page is loaded:

    this.containerFrame.AttachEvent("onload", new EventHandler<HtmlEventArgs>(Content_PageLoaded););

From this point, you have the same kind of control over the HTML DOM that you would have from script/DHTML. When the HTML page has loaded, you can access the document:

     HtmlDocument doc = wnd.GetProperty("document") as HtmlDocument; 

Note that the document object is only available if the IFRAME is navigated to a page in the same domain as your host page.

Game Development: XNA Game Studio Express available Aug 30

Microsoft have announced the XNA Game Studio Express beta. Based on Visual C# Express 2005, this tool will enable creation of Windows and Xbox 360 games using the XNA Framework.

This is an exciting development for all hobbyist game developers! I'm hoping that there will be a community web site where developers can connect, share knowledge and showcase their work.

The tool is free but, to create/debug games on the Xbox 360, you will need to buy an XNA "Creators' Club" subscription for $99/year. The FAQ seems to say that only Windows will be supported until later this year. It appears that in the future, you will be able to share your Xbox 360 binaries with other users - in the beta you can distribute your source/assets to someone that also has XNA Studio Express.

No support for Xbox Live or Windows Mobile/Pocket PC.

Managed DirectX 1.1 remains supported but with no new functionality. The XNA Framework will effectively replace Managed DirectX 2.0. There will be guidance provided to help migrate MDX 1.1 code to XNA.

Go to http://msdn.microsoft.com/directx/xna/ for more information!

Posted by markda | 0 Comments

Web Browser/DHTML: Access the XMLDocument property through .NET

When Internet Explorer requests an XML page from a web server, it will apply an XSL stylesheet. This can be an XSL stylesheet that is provided in the XML file, e.g.:

<?xml-styleheet href="filename.xsl" type="text/xsl" ?>

If no stylesheet is provided, Internet Explorer will use a default stylesheet, res://msxml.dll/DEFAULTSS.xsl, that displays the XML in a hierarchic view.

If you want to access the original XML document, Internet Explorer provides an XMLDocument property on the document object. It also provides an XSLDocument property that returns the XSL stylesheet that was used.

Because these properties are late-bound (also known as expandos), they do not appear in the MSHTML primary interop assembly. The answer is to use IDispatch to request the property. You can do this with the following code:

HTMLDocumentClass doc = (HTMLDocumentClass)webBrowser1.Document.DomDocument;

Type myType = doc.GetType();

IXMLDOMNode xml = (IXMLDOMNode)myType.InvokeMember( "XMLDocument", BindingFlags.GetProperty, null, doc, null );

You will need to add a reference to msxml3.

Posted by markda | 0 Comments
Filed under: ,

Rocket Commander Tutorials on Coding4Fun

The source code and tutorials for the Rocket Commander game are available in this MSDN Coding4Fun section!

Posted by markda | 0 Comments
Filed under:

Directory.GetFiles and search patterns

System.IO.Directory.GetFiles(string,string) enables you to provide a search pattern as the second argument.

I have a list of file extensions that I need to search for and discovered two issues with this method.

1. The second argument only accepts a single search pattern string, so I used the following code to resolve this:

    List<string> _searchPatternList = new List<string>();
    ...
    List<string> fileList = new List<string>();
    foreach ( string ext in _searchPatternList )
    {
        foreach ( string subFile in Directory.GetFiles( folderName, ext  )
        {
            fileList.Add( subFile );
        }
    }
    
    // Sort alpabetically
    fileList.Sort();

    // Add files to the file browser control    
    foreach ( string fileName in fileList )
    {
        ...;
    }

2. There is an 'anomaly' with search patterns. "*.htm" will match both .htm and .html files. To avoid duplicate file entries, you will need to remove all extensions that are equivalent:

   Dictionary<string,bool> extensionMap = new Dictionary<string,bool>(); // Initialized with ".htm", ".html", ".jpg", etc

   _searchPatternList.Clear();
   
   foreach ( string ext in extensionMap.Keys )
   {
       if ( ext.Length > 4 )
       {
           if ( !extensionMap.ContainsKey( ext.Substring( 0, 4 ) ) )
           { // No short version, so add to list
               _searchPatternList.Add( "*" + ext );
           }
        }
        else
        {
            _searchPatternList.Add( "*" + ext );
        }
   }

Posted by markda | 1 Comments
Filed under:

Design updates to Visual Studio 2005 beta documentation on MSDN Online

You can read more about the changes to the MSDN Visual Studio 2005 beta documentation site at http://msdn.microsoft.com/aboutmsdn/changes/msdn2/.

The Visual Studio 2005 beta documentation is available at http://msdn2.microsoft.com/library.

Don't forget to try the cool URL model, e.g. http://msdn2.microsoft.com/library/system.data

Enjoy!

Posted by markda | 2 Comments

C++ vs C#

Eric Gunnerson recently posted some reasons why C# is an improvement over C++ and some updates. This post is a good read - be sure to consider the comments.

Some of my thoughts...

Sure, with C#, I do spend less time considering memory usage (i.e. preventing memory leaks), but the issue of closure doesn't go away. I still need to deterministically release resources and to do this I'm going to need to call Dispose(). The point I'm getting at here is that, as a programmer, I still need to spend time thinking about the same problem - resource management. Using C++, it's natural to deal with memory at the same time - memory is just another resource.

Sometimes I feel that the time I save thinking about memory usage is now spent figuring out what to do with exceptions. Exceptions aren't new to C#, there just seems to be more of them. I'm convinced that I write more lines of error handling code these days, but that's probably a good thing :O)

C# is a simplified language, compared to C++. That's a good thing for developers who are used to Visual Basic or Java, but in this simplification it does miss a lot of features that are available in C++ - which is why I don't wish for a 'winner' and applaud the enhancements being made to the C++ language and tools.

While some may never miss the C++ compilation model, I really do miss being able to view the 'interface' of a class. I can look at a C++ header file for a birds-eye view of the class, though this does rely on good code guidelines and can get unstuck with patterns that hide implementation. Being forced to write inline code just doesn't work for me. At a class level, C# just isn't as readable without the use of a tool.

Templates - they're tough to learn and can promote some very obtuse code, but they sure are powerful. Generics are a good start in C#, but don't come anywhere close to providing what C++ has to offer. I think STL and Boost get a bad rap because they're difficult to use and there are multiple implementations. If you've ever needed to choose the right smart pointer, you'll know what I mean. I do think that the C++ community can learn something from the simplicity and consistency of the .Net Framework.

At the end of the day, it's about choosing the right tool for the job.

Posted by markda | 1 Comments
Filed under:

Managed DirectX - hear about it from a game developer

Marshall Belew, lead developer of the first commercial managed DirectX game - Tin Soldiers: Alexander the Great, is interviewed by the Zman.
Posted by markda | 0 Comments
Filed under:

N/Direct web site - .NET interoperability resource

The N/Direct web site is run by Mattias Sjögren, a Microsoft MVP. In his own words:

"N/Direct is a site for developers seeking information or answers about interoperability between .NET managed code and native unmanaged code."

The web site has an impressive selection of articles, samples and other resources.

Posted by markda | 0 Comments
Filed under:

New samples in October 2004 update of DirectX SDK

More cool stuff for DirectX developers in the October 2004 DirectX SDK, available from here. Also includes tool updates (PIX, Maya Exporter) and bug fixes.

New C++ Samples

  • AntiAlias - different multisampling techniques
  • Instancing - four instancing rendering techniques
  • ConfigSystem - database-driven device capabilities

New Managed Samples

  • PrtPerVertex - how to use the precomputed radiance transfer engine
  • FragmentLinker - how to link shader fragments
  • SimpleAnimation - basic skinning animation
Posted by markda | 2 Comments
Filed under:

Yes, you do have other web browsers

I was recently informed of this useful site. You can enter the URL of your web site and see what it looks like in the following web browsers on a Mac or PC:

  • Microsoft Internet Explorer 6.0 (PC)
  • Microsoft Internet Explorer 5.5 (PC)
  • Microsoft Internet Explorer 5.01 (PC)
  • Microsoft Internet Explorer 4.01 (PC)
  • Safari 1.2 (Mac)
  • Firefox 0.8 (PC)
  • Opera 7.23(PC)

Useful for verifying that your web site looks right on each of these browsers, especially your use of CSS. It doesn't support HTTPS. It does display recent requests, so don't request a URL you don't want people to know about. The site has some bandwidth limitations, so go easy on it - and the owner is asking for some hardware, so help him out if you can.

Posted by markda | 2 Comments
Filed under:

Tracking down memory leaks when linking with the CRT DLL

I recently rebuilt a C++ project to use the DLL version of the CRT and discovered that the _crtBreakAlloc variable was not visible to the Visual C++ debugger. If you don't already know, this variable is maintained by the debug CRT heap allocation code and can be used to track memory leaks, as discussed in this KnowledgeBase article.

The article also gave me a clue as to why this technique wasn't available - I need to use the code context feature when typing the debugger expression in the Watch window:

{function,module,dll}expression

Unfortunately, the KB article suggestion doesn't work for VC 7.1 (I don't know if it works for earlier versions). For Visual C++ 7.1, the following watch expression does work when linking with the DLL version of the CRT:

{,,msvcr71d.dll}_crtBreakAlloc

Posted by markda | 0 Comments
Filed under:

Visual C# 2003 "Implement Interface" feature

Just discovered a great tip for Visual C# 2003.

If you implement an interface (or event/delegate) on your class and don't want to type all the methods, just type the interface name in your class derivation list and Intellisense will display a tooltip saying “Press TAB to insert stubs for <interfacename>”. Pressing 'TAB' will insert stub method implemenations into your class. Very cool timesaver!

Thanks go to Kevin and Jason for pointing this out to me.

Posted by markda | 4 Comments
Filed under:

Help out the Interop community

If you take a walk over to http://www.pinvoke.net, you can find an active WiKi community that is documenting the PInvoke statements used to call Win32 and other unmanaged APIs from managed code. While you're there, why not add signatures and other information for any of the unmanaged APIs you've recently called? Adam Nathan, who created the WiKi site, also has contributed a PInvoke.Net Visual Studio add-in that's available on GotDotNet.
Posted by markda | 0 Comments
Filed under:

Is spyware damaging our industry?

After spending many hours removing spyware from my home family PC, I'm so pleased that the industry is taking this malicious software seriously. IMO, the deceptive behaviour used by these companies is tantamount to fraud and is damaging our industry.

Microsoft have created a new web site on this subject.

If there is one positive thing to come out this practice, it's that there's no such thing as free software. Ok, there is such a thing as free software and the developer community does an awesome job. I do wish that companies were forced to declare the real price a user pays when they download an executable, and I don't mean something hidden in the EULA.

I also wish there was a verification process when dowloading executables - something similiar to the Authenticode mechanism used for ActiveX controls. IMO, the whole process needs to be more transparent - I know this conflicts with the 'perceived' freedom and anonymity of the Internet, but something has to give.

Word of the week: hortatory

Mark Davis (MSFT)

This posting is provided "AS IS" with no warranties, and confers no rights.

Posted by markda | 5 Comments
Filed under:
More Posts Next page »
 
Page view tracker