Introduction
When I was trying to create a chat UserControl
for my apps, I ran into the problem where I wanted to display text color in the RichTextBox
output box. I began Googling around and found a variety of ways (this link is one of the good ones), but those seemed to be too complicated to me because I'm not good at RTF and I don't like too much coding. In the frustration of looking for a real solution, I saw the WebBrowser
control in the ToolBox
menu of Visual Studio, and I thought of wonderful things a browser could display if I can add HTML code to it. Like most Internet addicted people who have done a lot of blogging or forum posting, HTML coding would not be a problem to me.
This article is intended for absolute beginners; therefore most often in the article, I use simple un-professional terms. I will try to make it short and clear.
Contents
- Creating User Control with
WebBrowser
as output display - Create Class property
- Append HTML code to
WebBrowser
control - Events Handling
- Tips that can save you time from writing unnecessary long code
Creating User Control
- Right click on your Project -> Add -> New Item…
- Select Visual C# Item -> Windows Forms -> User Control on the right panel. I name it
HTMLChatControl
- Add a
TableLayoutPanel
(1 col X 2 rows). Set Dock
Property: Fill
- Add a
WebBrowser
to the top cell and TextBox
to the bottom cell. Set Dock
Property: Fill
Tips: To have the two small overlaying buttons staying on the top right corner of the control form as you see in the picture, add a Panel to the top cell, before adding the WebBrowser
. Also make sure to set the Buttons' Anchor
property to Top|Right. If you add the buttons, you could also add a Font or a Color Dialog control and wire the button click event to the Font | Color ShowDialog
.
Create Properties for the User Control
In my apps, the two buttons are for setting the background color and text color.
public string Text
{
get { return textBox1.Text; }
set { textBox1.Text = value; }
}
public Color ColorBackGround
{
get { return button_BackGroundColor.BackColor; }
set { button_BackGroundColor.BackColor = value; }
}
public Color ColorText
{
get { return button_TextColor.BackColor; }
set { button_TextColor.BackColor = value; }
}
Note: I use the child controls' property values to store the host User Control property values.
Appending HTML Code
There are two ways I can think of for adding HTML code to your browser at runtime. Each way has some benefits and disadvantages compared to the other.
- Inject the HTML code to the browser using
webBrowser.Document.Body.AppendChild(HtmlElement)
- Store the HTML page in a
string
variable and then webBrowser.DocumentText = [the string]
. The main problem with this method is how to manipulate the HTML string at runtime. I think it would not be so hard seeing that HTML is just an extension of XML and we have a built-in XML assembly available in .NET Frameworks. I thought of this method first, but have not tried if it would work.
I'm using the first method for this article to append the HTML code to the WebBrowser
control.
public void AppendText(string mgs, Color c)
{
HtmlElement htmlSPAN = webBrowser1.Document.CreateElement("SPAN");
HtmlElement htmlFont = webBrowser1.Document.CreateElement("FONT");
htmlFont.SetAttribute("color", string.Format
("rgb({0},{1},{2})", c.R, c.G, c.B));
htmlFont.InnerText = mgs;
htmlSPAN.AppendChild(htmlFont);
webBrowser1.Document.Body.AppendChild(htmlSPAN);
}
Note: The Document.CreateElement("[tag]")
method does not actually add the element to the browser document.
Note: It's not necessary to create a FONT
tag. You can just set the color
using:
[HtmlElement].Style = string.Format
("background-color:rgb({0},{1},{2});", c.R, c.G, c.B);
You CANNOT set an attribute for style
. e.g.:
SetAttribute("style", [string value])
It will compile but it won't do anything.
The same thing for adding linked text with a click event:
public void AppendLinkText(string mgs, string href, Color c)
{
HtmlElement htmlA = webBrowser1.Document.CreateElement("A");
HtmlElement htmlFont = webBrowser1.Document.CreateElement("FONT");
htmlA.SetAttribute("href", href);
htmlA.Click += new HtmlElementEventHandler(htmlItem_Click);
htmlFont.SetAttribute("color", string.Format("rgb({0},{1},{2})", c.R, c.G, c.B));
htmlFont.InnerText = mgs;
htmlA.AppendChild(htmlFont);
webBrowser1.Document.Body.AppendChild(htmlA);
}
And adding a new line...
public void AppendNewLine()
{
HtmlElement htmlBR = webBrowser1.Document.CreateElement("BR");
webBrowser1.Document.Body.AppendChild(htmlBR);
}
Change the background color:
public void SetBackgroundColor(Color c)
{
webBrowser1.Document.Body.SetAttribute
("bgcolor", string.Format("rgb({0},{1},{2})", c.R, c.G, c.B));
button_BackGroundColor.BackColor = c;
}
Tips: If you try to build the app right now, it will compile without any error. However, if you try to test any of the Append
functions, you will get null reference runtime error. The reason is there is nothing in the webBrowser1.Document
!!! I will not show the trick to overcome this issue in this article. I think you can discover that yourself (I could think of 2 ways so far). If you give up, look at my source code.
Event Handling
Remember we have a click event in the AppendLinkText()
above; What do you want the click events to do? For my demo app, it will fire up a custom event and let the host windows take care of the actions. I named my custom event WebItemClick
. I will also need a custom event handler for my event.
public event WebItemClickEventHandler WebItemClick;
The Event handler also needs a custom event argument to pass the value on.
Note: I put the following code outside of the HTMLChatControl : UserControl
class bracket:
public class WebItemClickEventArgs : EventArgs
{
private string _itemValue;
public string ItemValue
{ get { return _itemValue; } set { _itemValue = value; } }
}
public delegate void WebItemClickEventHandler
(object sender, WebItemClickEventArgs e);
Note: Conventionally, you would put this code before the UserControl
class. However you will soon realize you should put this code at the bottom before you try to compile the app. Why??? Why don't you test that yourself.
Now all you have to do is to add the htmlItem_Click()
method to your chat control class.
private void htmlItem_Click(object sender, HtmlElementEventArgs e)
{
HtmlElement htmle = sender as HtmlElement;
WebItemClickEventArgs eg = new WebItemClickEventArgs();
eg.ItemValue = htmle.GetAttribute("href");
WebItemClick(this, eg);
}
Again let me summarize what I have been trying to accomplish. When I click on the link text on the WebBrowser
, it will call htmlItem_Click()
which will in turn fire the WebItemClick
event. My host Windows Form now, by registering the WebItemClick
event, can get the clicked item's value.
Tips That Can Save You Time from Writing Unnecessary Long Code
You might run into these problems at some point.
How can I catch the Enter Key when typing on the text box?
private void HtmlChatControl1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
}
}
private void HtmlChatControl1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
}
}
I try the above code on my chat control, but it is still not working.
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
this.OnKeyDown(e);
}
I disable the default right click menu of the WebBrowser
(IsWebBrowserContextMenuEnabled = false
) and add my custom ContextMenuStrip
(because the default right click menu has unwanted commands). How can I keep the copy highlighted text function?
Go here to learn more.
webBrowser1.Document.ExecCommand("Copy", false, null);
Conclusion
WebBrowser
control is a very powerful display engine that can show images, tables, etc., and can even support JavaScript. Using the WebBrowser
control, you can bring richer, more interactive elements to your application.
About Me
I'm just a newbie, a very beginner programmer compared to most veterans here on the Code Project. I just began learning about programming a few years ago and I'm still a very inexperienced coder. I'm not a software developer or anything like that. I'm working as a computer hardware technician or a computer repair guy in other words. I only write code for fun during spare times of my busy college student's life.
I understand that knowledge is power, and I appreciate those who spend their precious time writing articles sharing their power with others. I trying to be like one of them.
Please rate my post and leave your constructive comments.
History
- 10/10/2008: First release