Monday, 3 April 2017

Embed Html page as resource in C# Winforms

So in previous posts I have shown a Winforms WebBrowser control navigating to a local html file.  It is possible to set the WebBrowser's DocumentStream property to a System.IO.Stream.  With the following code it is possible to create a System.IO.Stream from a string


        public static System.IO.Stream GenerateStreamFromString(string s)
        {
            MemoryStream stream = new MemoryStream();
            StreamWriter writer = 
                  new StreamWriter(stream,System.Text.Encoding.Unicode);
            writer.Write(s);
            writer.Flush();
            stream.Position = 0;
            return stream;
        }


The string would be an Html string but we want to avoid files so it looks like we can add the file as an embedded resource.

I named mine HTMLPage1 and then it can be referred to in code with


            string myFile2 = WebBrowserInWinForms.Properties.Resources.HTMLPage1;

            System.IO.Stream s = GenerateStreamFromString(myFile2);


But beware, the document needs to complete loading and whilst that is happening the stream needs to kept alive so no early disposal. To solve define stream variable at class level and dispose later. So the code becomes

using System;
using System.Windows.Forms;
using System.IO;

namespace WebBrowserInWinForms
{
    public partial class Form1 : Form
    {
        Stream s = null;

        public Form1()
        {
            
            InitializeComponent();

            string myFile2 = 
               WebBrowserInWinForms.Properties.Resources.HTMLPage1;

            this.webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted;
            s = GenerateStreamFromString(myFile2);
            this.webBrowser1.DocumentStream = s;

        }

        private void webBrowser1_DocumentCompleted(object sender, 
                                   WebBrowserDocumentCompletedEventArgs e)
        {
            s.Dispose(); // finished with this now
            System.Windows.Forms.HtmlElement clickMe = 
                              this.webBrowser1.Document.Body.All["clickMe"];
            clickMe.Click += clickMe_Click;
        }

        public static Stream GenerateStreamFromString(string s)
        {
            MemoryStream stream = new MemoryStream();
            StreamWriter writer = 
                      new StreamWriter(stream,System.Text.Encoding.Unicode);
            writer.Write(s);
            writer.Flush();
            stream.Position = 0;
            return stream;
        }
        
        void clickMe_Click(object sender, HtmlElementEventArgs e)
        {
            //...
        }
    }
}

Copying the HTML string into the resource editor is clunky, the resource string editor is probably just for words and phrases when one ships an edition in a foreign language. It would be nice if in Debug environment we could use the file navigate method and then for Release we'd do a custom build step and pack the files into the embedded resources with code. We'd need conditional compilation.

The embedded resources can be found in <$SolutionDirector$>/Properties/Resources.resx which is Xml so they are entitised, this looks possible for one day.

No comments:

Post a Comment