65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 中的 Web 浏览器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (143投票s)

2010年2月20日

CPOL

6分钟阅读

viewsIcon

1155824

downloadIcon

90652

一个带有收藏夹图标、历史和收藏夹、链接栏、查看源代码、搜索和打印功能的选项卡式 Web 浏览器(C#)。

WBrowser.png

目录

引言

这是我的第一个 C# 项目。本文介绍了如何实现 Web 浏览器应用程序的一些功能,例如管理选项卡、查看特定网站的收藏夹图标、管理收藏夹网站和链接栏、查看历史记录、在 Google 或 Live Search 上搜索、在应用程序运行之间保存设置、查看网站的源代码和属性、打印页面内容等。C# 有一个 WebBrowser 控件,可以完成网页渲染的所有工作。

实现选项卡功能

在我的主窗体中,我添加了一个名为 browserTabControlTabControl 控件,其中只有一个 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,所以如果您想添加上下文菜单,您需要做一些技巧。这是我解决这个问题的方法。在设计器视图中,我添加了一个名为 linkContextMenuContextMenu 控件,并在该上下文菜单中添加了一些项。当用户右键单击链接时,该上下文菜单将在鼠标所在位置显示。然后,您保留该链接(发送该事件的按钮)的网站地址和名称。为了保留最后一个地址和名称,我使用了两个变量:adressname。因此,当用户单击上下文菜单项时,您可以使用这些变量。

linkcontextmenu.png

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 对话框。用户可以选择添加收藏夹还是链接。

addfavorit.PNG

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 事件。当用户单击上下文菜单中的一项时,该项的可见性将被更改。

toolbarcontextmenu.PNG

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 的窗体,该窗体将被视为一个对话框。用户可以更改主页、外观或地址栏中的下拉项数量。

options.PNG

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 来保存设置。

© . All rights reserved.