April 28, 2008
One of the most powerful development tools I’ve come across is using a dynamic
HTML type user interface for my C# applications. Not for the entire application
(like Microsoft Money), but frequently rich mixed content needs to be delivered
to the user and an embedded web browser is powerful.
Embedding just a web browser into an app is okay, but to use it as a responsive
user interface to your C# application is where the real power lies.
Note: Don’t get overwhelmed by the number of steps here. Each step is built upon
the previous but made so you can stop anywere and use what you’ve got up to that point.
Step 1: Get Internet Explorer Into Your App
- Create a new Windows Form
- Add the SHDocVw Web Browser COM Custom Control to your “Windows Forms”
- Right Click on the Toolbox
- Choose “Customize Toolbox…”
- Select and Add “Microsoft Web Browser”
- Draw the new control onto your form (Global icon)
These steps are necessary as the OCX control requires state information that
VS.NET automatically handles and includes in the projects resource file.
Step 2: Using the Web Browser
Since the Web Browser object is compatible with IE 3 to IE 6 and is based on
COM, it is a bit more complicated to use than a .NET component. Here is some
code on how to navigate.
Note: I will call my axWebBrowser control on a form “webMain”.
private void Navigate(string url)
{
object o = System.Reflection.Missing.Value;
webMain.Navigate(url, ref o, ref o, ref o, ref o);
}
|
The System.Reflection.Missing.Value object provides a null reference for an
optional/missing parameter. Much like in VB you can make passing some parameters
optional. Ex: Function MyFunc(url as String, Optional OtherInfo as String)
Handling the Web Browsers events requires knowing what to look for. Here is an
example of the status text change event:
using AxSHDocVw;
webMain.StatusTextChange += new DWebBrowserEvents2_StatusTextChangeEventHandler(webMain_StatusTextChange);
private void webMain_StatusTextChange(object sender, DWebBrowserEvents2_StatusTextChangeEvent e)
{
Console.WriteLine(”webMain Status Text: ” + e.text);
}
|
This is all that is need just to use the browser to navigate to a web site.
Step 3: Access the IE Document Object Module (DOM)
Knowledge of Internet Explorer’s Document Object Model (IE DOM) from here
on is very useful.
Now my favorite part is in creating DHTML (Dynamic HTML) at run time and feeding
this to the browser control to make my own custom UI and display rich dynamic
content. We need access to the Microsoft HTML object library then know which
properties to line up.
- Right Click on References in the Solutions View
- Choose “Add Reference…”
- Go to the COM Tab
- Select and add “Microsoft HTML Object Library”
Note: There are a lot of items avalible in the mshtml library. Use the
references below to get more info on them.
Now let’s get the body of the web document.
using mshtml;
private HTMLDocument document
{get {return (HTMLDocument) webMain.Document;}}
private HTMLBody body
{get {return (HTMLBody) document.body;}}
|
Note: The web browser is a generic content container and by default is
not initialized to an HTML container so you must first load some HTML content
before attempting to access the document or body properties. The easiest way to
do this is:
private void Form1_Load(object sender, System.EventArgs e)
{
Navigate(”about:blank”);
while (body == null) Application.DoEvents();
Step 4: Trapping IE DOM Events
Okay so now we have a Web Browser control showing our custom content. How do we
interact with the content we’re showing to the use? We need to trap
the HTML events.
using System.Runtime.InteropServices;
private void Form1_Load(object sender, System.EventArgs e)
{
document.onclick = this;
document.onmouseover = this;
document.onmouseout = this;
}
[DispId(0)]
public void DefaultMethod()
{
HTMLWindow2 win = (HTMLWindow2) document.parentWindow; Step 5: Putting it All Together - Make a Wrapper Custom Control
Okay, we now have all the tools we need to make everything work together.
I highly recommend making your own web browser custom control wrapper to make
working with the browser easier. Here is the basic wrapper that I made and use
on everything. This is great for spiffy message boxes, rich content on your
forms, etc. Be sure to have the correct references.
Note: You will have to remove/delete the Web Browser control off the custom
control, put it back on manually, and rename it to webMain in order for VS.NET to
include the correct OCX state and licensing.
When put on a form, this custom control can appear and act much like a regular
label. It defaults to the basic color and font of other controls. Have fun!
using System;
using mshtml;
using System.Windows.Forms;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace CoadTools
{
#region Delegates
public delegate void WebBrowserElementEventHandler(object sender, mshtml.IHTMLEventObj e);
#endregion
public class WebBrowser : System.Windows.Forms.UserControl
{
#region Control Components
private System.Windows.Forms.Panel pnlWeb;
private AxSHDocVw.AxWebBrowser webMain;
private System.ComponentModel.Container components = null;
#endregion
#region Enumerators
public enum ieScrollBars {None, Always, Auto};
#endregion
#region Event Handler Declarations
public event WebBrowserElementEventHandler WebBrowserElementEvent;
#endregion
#region Constructor(s)
public WebBrowser()
{
InitializeComponent();
Navigate(”about:blank”, true);
while (body == null) {Application.DoEvents();}
pnlWeb.BorderStyle = BorderStyle.None;
this.Text = “”;
this.HTML = “”;
body.style.font = “8.25pt Microsoft Sans Serif, 10pt Verdana”;
body.style.margin = “0″;
body.style.borderStyle = “none”;
body.style.background = “buttonface”;
ScrollBars = ieScrollBars.None;
}
#endregion
#region Component Designer generated code
protected override void Dispose( bool disposing )
{
if (disposing) if (components != null) components.Dispose();
base.Dispose(disposing);
}
private void InitializeComponent()
{
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(WebBrowser));
this.pnlWeb = new System.Windows.Forms.Panel();
this.webMain = new AxSHDocVw.AxWebBrowser();
this.pnlWeb.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.webMain)).BeginInit();
this.SuspendLayout();
this.pnlWeb.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.pnlWeb.Controls.AddRange(new System.Windows.Forms.Control[] {
this.webMain});
this.pnlWeb.Dock = System.Windows.Forms.DockStyle.Fill;
this.pnlWeb.Name = “pnlWeb”;
this.pnlWeb.Size = new System.Drawing.Size(150, 150);
this.pnlWeb.TabIndex = 1;
this.webMain.ContainingControl = this;
this.webMain.Dock = System.Windows.Forms.DockStyle.Fill;
this.webMain.Enabled = true;
this.webMain.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject(”webMain.OcxState”)));
this.webMain.Size = new System.Drawing.Size(146, 146);
this.webMain.TabIndex = 0;
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.pnlWeb});
this.Name = “WebBrowser”;
this.pnlWeb.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.webMain)).EndInit();
this.ResumeLayout(false);
}
#endregion
#region Public Control Properties
[DefaultValue(ieScrollBars.None)]
[Description("Internet Explorer's BODY.Scroll Property")]
public ieScrollBars ScrollBars
{
get
{
if (body.scroll.Equals(”yes”)) return ieScrollBars.Always;
if (body.scroll.Equals(”auto”)) return ieScrollBars.Auto;
return ieScrollBars.None;
}
set
{
if (value == ieScrollBars.Auto) body.scroll = “auto”;
if (value == ieScrollBars.None) body.scroll = “no”;
if (value == ieScrollBars.Always) body.scroll = “yes”;
}
}
[DefaultValue(BorderStyle.None)]
public BorderStyle BorderStyle
{
get {return pnlWeb.BorderStyle;}
set {pnlWeb.BorderStyle = value;}
}
#endregion
#region Public HTML Properties
[Browsable(false)]
public HTMLDocument document
{ get {return (HTMLDocument) webMain.Document;} }
[Browsable(false)]
public HTMLBody body
{ get {return (HTMLBody) document.body;} }
[DefaultValue("")]
[Browsable(true)]
[Description("Internet Explorer's BODY.innerText Property")]
public override string Text
{
get {return body.innerText;}
set {body.innerText = value;}
}
[DefaultValue("")]
[Description("Internet Explorer's BODY.innerHTML Property")]
public string HTML
{
get {return body.innerHTML;}
set {body.innerHTML = value;}
}
#endregion
#region COM Event Handler for WebBrowser HTML Elements
[DispId(0)]
public void DefaultMethod()
{
WebBrowserElementEvent(this, document.parentWindow.@event);
}
#endregion
#region Public Methods
public void Navigate(string url)
{ Navigate(url, true); }
public void Navigate(string url, bool wait)
{
object o = System.Reflection.Missing.Value;
if (wait) webMain.Navigate(null, ref o, ref o, ref o, ref o);
if (wait) while (document != null) {Application.DoEvents();}
webMain.Navigate(url, ref o, ref o, ref o, ref o);
if (wait) while (document.body == null) {Application.DoEvents();}
}
#endregion
}
}
|
Step 6: Using the Custom Web Browser Control
Here is a simple form and way to use the control above. Enjoy!
using System;
using mshtml;
using CoadTools;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WebBrowserTutorial
{
public class frmWebTest : System.Windows.Forms.Form
{
private CoadTools.WebBrowser webMain;
private System.ComponentModel.Container components = null;
public frmWebTest()
{ InitializeComponent(); }
protected override void Dispose( bool disposing )
{
if (disposing) if (components != null) components.Dispose();
base.Dispose(disposing);
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.webMain = new CoadTools.WebBrowser();
this.SuspendLayout();
this.webMain.Dock = System.Windows.Forms.DockStyle.Fill;
this.webMain.HTML = “webBrowser1″;
this.webMain.Name = “webMain”;
this.webMain.Size = new System.Drawing.Size(234, 102);
this.webMain.TabIndex = 0;
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(234, 102);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.webMain});
this.Name = “frmWebTest”;
this.Text = “Web Browser Test”;
this.Load += new System.EventHandler(this.frmWebTest_Load);
this.ResumeLayout(false);
}
#endregion
[STAThread]
static void Main()
{ Application.Run(new frmWebTest()); }
private void frmWebTest_Load(object sender, System.EventArgs e)
{
webMain.WebBrowserElementEvent += new WebBrowserElementEventHandler(webMain_HTMLEvent);
webMain.HTML = “<br><br><center><span style=’font: bold 10pt verdana; color: darkgreen;’>Hello World</span></center>”;
webMain.document.onclick = webMain;
}
private void webMain_HTMLEvent(object sender, mshtml.IHTMLEventObj e)
{
Console.WriteLine(”HTML Object: ” + e.srcElement + “, Type: ” + e.type);
}
}
}
|
This concludes the test form for experimenting with the above Web Browser control.
Console.WriteLine(”Object: ” + win.@event.srcElement + “, Type: ” + win.@event.type);
}
|
body.innerText = “Hello World”;
}
|
Entry Filed under: c-sharp. Tags: C# Application, Web Browser.
Trackback this post | Subscribe to the comments via RSS Feed