I am posting this as a small sample I worked for MCS. It demonstrate some bacic usages of .Net 2.0 WinForm WebBrowser control:
1. How we can hook up the HTML events with managed code.
2. How to get the current element being edited in the WebBrowser, either by mouse or by keyborad typing.
3. How we can identify the tags in the DOM document.
===========================Form1.cs===========================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Xsl;
using System.Runtime.InteropServices;
namespace WebBrowserSample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Holding the XML document.
private XmlDocument xdoc = new XmlDocument();
// Holding the XmlElement (e.g. <food>) from the XmlDocument being edited.
private XmlElement currentEditingXMLElement;
// Holding the HtmlElement (e.g. <div> with foodid attribute) from the HtmlDocument in the WebBrowser control.
private HtmlElement currentEditingHTMLElement;
[DllImport("user32.dll")]
public static extern bool GetCaretPos(ref Point pt);
private void button1_Click(object sender, EventArgs e)
{
// Routine work. Load the XML into the control as well as the XmlDocument.
// No need to apply XSLT further as the XML already specifies so with "xml-stylesheet".
webBrowser1.Navigate(Application.StartupPath + "\\data.xml");
xdoc.Load(Application.StartupPath + "\\data.xml");
webBrowser1.Document.Click += new HtmlElementEventHandler(Document_Click);
mshtml.IHTMLDocument2 hdoc = (mshtml.IHTMLDocument2)webBrowser1.Document.DomDocument;
hdoc.designMode = "On";
button1.Enabled = false;
webBrowser1.Document.MouseMove += new HtmlElementEventHandler(Document_MouseMove);
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
webBrowser1.Document.AttachEventHandler("onkeydown", new EventHandler(this.Document_KeyDown));
}
void Document_KeyDown(object sender, EventArgs e)
{
Point p = new Point(0, 0);
bool bResult = GetCaretPos(ref p);
HtmlElement he = webBrowser1.Document.GetElementFromPoint(p);
Console.WriteLine(he.InnerText);
}
// Holding the reference of the previous element that mouse moves over.
private HtmlElement previousMovedElement;
void Document_MouseMove(object sender, HtmlElementEventArgs e)
{
// Get the current element under mouse cursor
HtmlElement movingElement = webBrowser1.Document.GetElementFromPoint(e.MousePosition);
// Is the element the same one as we recorded previously? If yes, we just ignore it.
if (movingElement != previousMovedElement)
{
// The previous element we move over is a HTML span and now we are moving out of it.
if ((previousMovedElement != null) && (previousMovedElement.TagName.ToLower() == "span"))
{
// Restore the color for the previous span element.
mshtml.HTMLSpanElement previousSpan = (mshtml.HTMLSpanElement)previousMovedElement.DomElement;
object objColor = previousSpan.getAttribute("oldColor", 0);
string strColor = (objColor != null) ? objColor.ToString() : "";
if (!string.IsNullOrEmpty(strColor))
previousSpan.style.color = strColor;
else
previousSpan.style.removeAttribute("color", 0);
}
// We are moving to a span element.
if (movingElement.TagName.ToLower() == "span")
{
// Let's remember its current color, using an additiona attribute "oldColor":
mshtml.HTMLSpanElement span = (mshtml.HTMLSpanElement)movingElement.DomElement;
if (span.style.color != null)
span.setAttribute("oldColor", span.style.color.ToString(), 0);
else
span.setAttribute("oldColor", "",0);
span.style.color = "blue";
}
// Remember the last element we move over, no matter it is a span or not.
previousMovedElement = movingElement;
}
}
void Document_Click(object sender, HtmlElementEventArgs e)
{
// Get the element being clicked.
HtmlElement clickedElement = webBrowser1.Document.GetElementFromPoint(e.MousePosition);
string id = null;
// Go up in the hierarchy until we locate the "div" with "foodid" attribute.
// Then we can find out the details from the XML with the same ID.
while (clickedElement.Parent != null)
{
id = clickedElement.GetAttribute("foodid");
if (!string.IsNullOrEmpty(id))
{
currentEditingHTMLElement = clickedElement;
break;
}
else
clickedElement = clickedElement.Parent;
}
// Make sure that we find the id.
if (!string.IsNullOrEmpty(id))
{
// XPath query for locating the food element with same id from the XmlDocument.
currentEditingXMLElement = (XmlElement)(xdoc.SelectSingleNode("//food[@id=" + id + "]"));
// Create the wrapper class, so that we can associate it with the PropertyGrid.
FoodClass currentEditingFoodClass = new FoodClass();
currentEditingFoodClass.Description = currentEditingXMLElement.SelectSingleNode("description").InnerText;
currentEditingFoodClass.Name = currentEditingXMLElement.SelectSingleNode("name").InnerText;
currentEditingFoodClass.Price = currentEditingXMLElement.SelectSingleNode("price").InnerText;
currentEditingFoodClass.Calories = int.Parse(currentEditingXMLElement.SelectSingleNode("calories").InnerText);
currentEditingFoodClass.Id = id; //This property is unused actually.
// Associate the callback routine, so that we can update the HTML view.
currentEditingFoodClass.ContentChanged += new EventHandler(currentEditingFoodClass_ContentChanged);
propertyGrid1.SelectedObject = currentEditingFoodClass;
}
richTextBox1.Text = clickedElement.OuterHtml;
}
void currentEditingFoodClass_ContentChanged(object sender, EventArgs e)
{
ConentChangedEventArgs ce = (ConentChangedEventArgs)e;
string field = ce.Field.ToLower();
// Update the content in the XmlDocument