C# 中的 Web 浏览器






4.88/5 (143投票s)
一个带有收藏夹图标、历史和收藏夹、链接栏、查看源代码、搜索和打印功能的选项卡式 Web 浏览器(C#)。
目录
引言
这是我的第一个 C# 项目。本文介绍了如何实现 Web 浏览器应用程序的一些功能,例如管理选项卡、查看特定网站的收藏夹图标、管理收藏夹网站和链接栏、查看历史记录、在 Google 或 Live Search 上搜索、在应用程序运行之间保存设置、查看网站的源代码和属性、打印页面内容等。C# 有一个 WebBrowser
控件,可以完成网页渲染的所有工作。
实现选项卡功能
在我的主窗体中,我添加了一个名为 browserTabControl
的 TabControl
控件,其中只有一个 TabPage
,代表“新建”选项卡。当用户单击“新建”选项卡时,将创建一个新选项卡。addNewTab()
方法展示了如何在您的 Web 浏览器中添加新选项卡。
private void addNewTab()
{
// create a new TabPage object
TabPage tpage = new TabPage();
tpage.BorderStyle = BorderStyle.Fixed3D;
//add the newly created TabPage
//to the tabcontrol's collection of tab pages
browserTabControl.TabPages.Insert(
browserTabControl.TabCount - 1, tpage);
//create a WebBrowser object
WebBrowser browser = new WebBrowser();
browser.Navigate(homePage);
//add the browser object to the tab page
//you created previously
tpage.Controls.Add(browser);
browser.Dock = DockStyle.Fill;
browserTabControl.SelectTab(tpage);
//add some event handlers to your browser object
browser.ProgressChanged += new
WebBrowserProgressChangedEventHandler(Form1_ProgressChanged);
browser.DocumentCompleted += new
WebBrowserDocumentCompletedEventHandler(Form1_DocumentCompleted);
browser.Navigating +=
new WebBrowserNavigatingEventHandler(Form1_Navigating);
browser.CanGoBackChanged +=
new EventHandler(browser_CanGoBackChanged);
browser.CanGoForwardChanged +=
new EventHandler(browser_CanGoForwardChanged);
}
下面的示例显示了如何获取当前选项卡
private WebBrowser getCurrentBrowser()
{
return (WebBrowser)browserTabControl.SelectedTab.Controls[0];
}
如何获取网站的收藏夹图标
收藏夹图标是与网站关联的 16x16、32x32 或 64x64 像素的正方形图标。此图标称为 favicon.ico,可以在网站的根目录中找到。为了获取特定网站的收藏夹图标,您需要向 http://websitename/favicon.ico 发出请求。您可以从响应流中获取图标并在您的应用程序中使用它。对于没有收藏夹图标的网站,我使用了一个默认图标。
public static Image favicon(String u, string file)
{
Uri url = new Uri(u);
String iconurl = "http://" + url.Host + "/favicon.ico";
WebRequest request = WebRequest.Create(iconurl);
try
{
WebResponse response = request.GetResponse();
Stream s = response.GetResponseStream();
return Image.FromStream(s);
}
catch (Exception ex)
{
//return a default icon in case
//the web site doesn`t have a favicon
return Image.FromFile(file);
}
}
链接栏
对于链接栏,我使用了一个 ToolStrip
控件。链接按钮由一个带有收藏夹图标图像的 ToolStripButton
表示,网站名称作为按钮上显示的文本。链接存储在 XML 文件中,如下所示:
<favorits>
<link url="http://www.google.ro/" >Google/<link>
<link url="https://codeproject.org.cn/">CodeProject</link>
<link url="http://www.youtube.com/edu">Youtube/Edu</link>
</favorits>
addNewLink()
方法展示了如何添加新链接。首先,打开包含链接的 XML 文件,然后添加一个新的 XmlElement
,将 url
属性设置为网站地址,并将此元素的内部文本设置为您希望此链接在链接栏上显示的名称。然后,将一个 ToolStripButton
添加到链接栏。ToolStripButton
控件有一个接受四个参数的构造函数:public ToolStripButton(string text, Image image, EventHandler onClick, string name)
。
private void addLink(String url, string name)
{
//open the xml file
XmlDocument myXml = new XmlDocument();
//and a new element to the xml file
XmlElement el = myXml.CreateElement("link");
el.SetAttribute("url", url);
el.InnerText = name;
if (!File.Exists(linksXml))
{
XmlElement root = myXml.CreateElement("links");
myXml.AppendChild(root);
root.AppendChild(el);
}
else
{
myXml.Load(linksXml);
myXml.DocumentElement.AppendChild(el);
}
//if the links bar is visible then
//you have to add a ToolStripButton
if (linkBar.Visible == true)
{
//create a new ToolStripButton object with the favicon image,
//website name the click eventhandler to
//navigate to the specific web site
ToolStripButton b =
new ToolStripButton(el.InnerText, getFavicon(url),
items_Click, el.GetAttribute("url"));
b.ToolTipText = el.GetAttribute("url");
//the MouseUp event is used
//for showing the context menu of this button
b.MouseUp += new MouseEventHandler(b_MouseUp);
linkBar.Items.Add(b);
}
myXml.Save(linksXml);
}
ToolStripButton
控件没有 ContextMenu
,所以如果您想添加上下文菜单,您需要做一些技巧。这是我解决这个问题的方法。在设计器视图中,我添加了一个名为 linkContextMenu
的 ContextMenu
控件,并在该上下文菜单中添加了一些项。当用户右键单击链接时,该上下文菜单将在鼠标所在位置显示。然后,您保留该链接(发送该事件的按钮)的网站地址和名称。为了保留最后一个地址和名称,我使用了两个变量:adress
和 name
。因此,当用户单击上下文菜单项时,您可以使用这些变量。
string adress, name;
private void b_MouseUp(object sender, MouseEventArgs e)
{
ToolStripButton b = (ToolStripButton)sender;
adress = b.ToolTipText;
name = b.Text;
if (e.Button == MouseButtons.Right)
linkContextMenu.Show(MousePosition);
}
每个上下文菜单项都有一个点击事件处理程序。下面是一个在新窗口中打开链接的示例
private void openInNewWindowToolStripMenuItem_Click(object sender, EventArgs e)
{
WBrowser new_form = new WBrowser();
new_form.Show();
new_form.getCurrentBrowser().Navigate(adress);
}
历史记录和收藏夹
我使用了两个 XML 文件来存储历史记录和收藏夹
history.xml
<history>
<item url="https://codeproject.org.cn/"
lastVisited="19.02.2010 12:58:03" times="6" />
<item url="http://www.google.ro/"
lastVisited="19.02.2010 12:52:09" times="2" />
<item url="http://msdn.microsoft.com/"
lastVisited="13.08.2009 20:22:52" times="1" />
</history>
favorites.xml
<favorites>
<favorit url="http://images.google.ro/imghp?hl=ro&tab=wi">
Google-images</favorit>
<favorit url="http://www.yahoo.com/">Yahoo!</favorit>
</favorites>
我使用了一个 TreeView
控件来显示历史记录和收藏夹。下面是一个根据网站名称显示历史记录的示例
private void showHistory()
{
historyTreeView.Nodes.Clear();
//open the xml file
XmlDocument myXml = new XmlDocument();
if (File.Exists(historyXml))
{
myXml.Load(historyXml);
DateTime now=DateTime.Now;
//....
if (comboBox1.Text.Equals("View By Site"))
{
historyTreeView.ShowRootLines = true;
foreach(XmlElement el in myXml.DocumentElement.ChildNodes)
{
Uri site=new Uri(el.GetAttribute("url"));
if(!historyTreeView.Nodes.ContainsKey(site.Host.ToString()))
historyTreeView.Nodes.Add(site.Host.ToString(),
site.Host.ToString(),0,0);
//create a new tree node
TreeNode node =new TreeNode(el.GetAttribute("url"), 3, 3);
//set some properties of the new tree node you created
node.ToolTipText = el.GetAttribute("url") +
"\nLast Visited: " +
el.GetAttribute("lastVisited") +
"\nTimes Visited: " +
el.GetAttribute("times");
node.Name = el.GetAttribute("url");
//add a context menu to this node
node.ContextMenuStrip = histContextMenu;
//add this node to the treeview control
historyTreeView.Nodes[site.Host.ToString()].Nodes.Add(node);
}
//....
}
为了将网站添加到收藏夹,我创建了一个名为 AddFovorites
的窗体,该窗体将被视为一个对话框。该类的构造函数接受一个 string
参数,代表当前的 Web 地址。当用户单击“添加到收藏夹”按钮时,将出现 AddFavorites
对话框。用户可以选择添加收藏夹还是链接。
private void toolStripButton8_Click(object sender, EventArgs e)
{
if (getCurrentBrowser().Url != null)
{ //show the AddFavorites dialog
AddFavorites dlg =
new AddFavorites(getCurrentBrowser().Url.ToString());
DialogResult res = dlg.ShowDialog();
//if the user clicks OK
if (res == DialogResult.OK)
{
if (dlg.favFile == "Favorites")
//add a favorite to xml file and in treeview
addFavorit(getCurrentBrowser().Url.ToString(),
dlg.favName);
//add a link in xml file and in links bar
//the addLink() method is listed
//in the Links Bar section of this article
else addLink(getCurrentBrowser().Url.ToString(),
dlg.favName);
}
dlg.Close();
}
}
下面列出了 addFavorit()
方法。它与 addLink
方法类似,只是它打开另一个包含收藏夹网站的 XML 文件,并在 favTreeView
中添加一个 TreeNode
。
private void addFavorit(String url, string name)
{
XmlDocument myXml = new XmlDocument();
XmlElement el = myXml.CreateElement("favorit");
el.SetAttribute("url", url);
el.InnerText = name;
if (!File.Exists(favXml))
{
XmlElement root = myXml.CreateElement("favorites");
myXml.AppendChild(root);
root.AppendChild(el);
}
else
{
myXml.Load(favXml);
myXml.DocumentElement.AppendChild(el);
}
if (favoritesPanel.Visible == true)
{
TreeNode node = new TreeNode(el.InnerText,
faviconIndex(el.GetAttribute("url")),
faviconIndex(el.GetAttribute("url")));
node.ToolTipText = el.GetAttribute("url");
node.Name = el.GetAttribute("url");
node.ContextMenuStrip = favContextMenu;
favTreeView.Nodes.Add(node);
}
myXml.Save(favXml);
}
查看源代码
WebBrowser
控件有一个 DocumentText
属性,代表控件中显示的网页的 HTML 内容。要用记事本查看网站的源代码,首先创建一个临时文件,将 HTML 内容写入该文件,然后用记事本打开该临时文件。
private void sourceToolStripMenuItem_Click(object sender, EventArgs e)
{
String source=("source.txt");
StreamWriter writer =File.CreateText(source);
writer.Write(getCurrentBrowser().DocumentText);
writer.Close();
Process.Start("notepad.exe", source);
}
搜索
在地址栏上,我有一个文本框,用户可以在其中输入他们想要搜索的关键词。这个文本框有一个 KeyDown
事件。当用户按下“Enter”键时,结果将在当前选项卡中显示。用户可以在搜索栏旁边的下拉按钮中选择Google 搜索或Live Search。
private void searchTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
if (googleSearch.Checked == true)
getCurrentBrowser().Navigate("http://" +
"google.com/search?q=" + searchTextBox.Text);
else
getCurrentBrowser().Navigate("http://search." +
"live.com/results.aspx?q="+searchTextBox.Text);
}
保存设置
有时用户希望在应用程序运行之间保存设置。为了保存诸如主页、菜单栏或链接栏的可见性等设置,我使用了一个名为“settings.xml”的 XML 文件。
<settings>
<menuBar visible="True" />
<adrBar visible="True" />
<linkBar visible="True" />
<favoritesPanel visible="True" />
<SplashScreen checked="False" />
<homepage>about:blank</homepage>
<dropdown>15</dropdown>
</settings>
当主窗体加载时,这些设置将从 XML 文件中读取。当用户更改设置时,XML 文件内容将发生更改。在窗体关闭时保存这些更改。
更改链接栏的可见性
在我的主窗体中,我有一个名为 toolBarContextMenu
的上下文菜单,其中包含下图中的项。每个项都有一个 Click
事件。当用户单击上下文菜单中的一项时,该项的可见性将被更改。
private void linksBarToolStripMenuItem_Click(object sender, EventArgs e)
{
linkBar.Visible = !linkBar.Visible;
this.linksBarToolStripMenuItem.Checked = linkBar.Visible;
//settings represents the xml file
//"settings.xml" opened when the form loads
settings.DocumentElement.ChildNodes[2].Attributes[0].Value =
linkBar.Visible.ToString();
}
更改主页
我创建了一个名为 InternetOptions
的窗体,该窗体将被视为一个对话框。用户可以更改主页、外观或地址栏中的下拉项数量。
String homePage;
InternetOption optionDialog =
new InternetOption(getCurrentBrowser().Url.ToString());
if (optionDialog.ShowDialog() == DialogResult.OK)
{
//if the user setted a home page
if (!optionDialog.homepage.Text.Equals(""))
{
homePage = optionDialog.homepage.Text;
//changing the setting in the xml file
//settings represents the xml file
//"settings.xml" opened when the form loads
settings.DocumentElement.ChildNodes[5].InnerText =
optionDialog.homepage.Text;
}
}
属性、打印、打印预览、页面设置、另存为
这里列出了一些 WebBrowser
控件的方法
public void ShowPropertiesDialog ()
: 打开当前文档的 Internet Explorer 属性对话框。
private void propertiesToolStripMenuItem_Click(object sender, EventArgs e)
{
getCurrentBrowser().ShowPropertiesDialog();
}
public void ShowPageSetupDialog ()
: 打开 Internet Explorer 页面设置对话框。private void pageSetupToolStripMenuItem_Click(object sender, EventArgs e)
{
getCurrentBrowser().ShowPageSetupDialog();
}
public void ShowPrintDialog ()
: 打开 Internet Explorer 打印对话框,而不设置页眉和页脚的值。private void printToolStripMenuItem_Click(object sender, EventArgs e)
{
getCurrentBrowser().ShowPrintDialog();
}
public void ShowPrintPreviewDialog ()
: 打开 Internet Explorer 打印预览对话框。private void printPreviewToolStripMenuItem_Click(object sender, EventArgs e)
{
getCurrentBrowser().ShowPrintPreviewDialog();
}
public void ShowSaveAsDialog ()
: 打开 Internet Explorer 另存为网页对话框,或者如果托管的文档不是 HTML 页面,则打开其另存为对话框。private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
{
getCurrentBrowser().ShowSaveAsDialog();
}
剪切、复制、粘贴、全选
WebBrowser
控件有一个 Document
属性,它获取一个 HtmlDocument
,代表当前在控件中显示的网页。在此 HtmlDocument
上,您可以执行诸如“剪切”或“复制”之类的特定命令。下面的示例展示了如何执行此操作。
//cut
private void cutToolStripMenuItem_Click(object sender, EventArgs e)
{
getCurrentBrowser().Document.ExecCommand("Cut", false, null);
}
//copy
private void copyToolStripMenuItem_Click(object sender, EventArgs e)
{
getCurrentBrowser().Document.ExecCommand("Copy", false, null);
}
//paste
private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
{
getCurrentBrowser().Document.ExecCommand("Paste", false, null);
}
//select all
private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
{
getCurrentBrowser().Document.ExecCommand("SelectAll", true, null);
}
未来还可以做什么
还有两件事情可以进一步完成:一是将收藏夹和链接的收藏夹图标保存在 XML 文件中。这样,应用程序加载时就不需要发出那么多请求了。另一件事是可以使用 App.config 来保存设置。