使用 .NET 的 WebBrowser 控件创建自定义 Web 浏览器






4.66/5 (13投票s)
如何在您的应用程序中使用 .NET 的 WebBrowser 控件为 Windows 操作系统创建自定义 Web 浏览器
引言
本文介绍了 WPF (Windows Presentation Foundation) 的 WebBrowser
控件(不要与 Windows Forms 的 WebBrowser
控件混淆,它们不相同),以及在您的软件中创建基本的 Web 浏览器应用程序的常用用法。
背景
在我开始学习软件开发时,我曾尝试查看一个浏览器应用程序的示例,但由于代码过于混乱且我无法理解,因此未能成功。
两个月前,发生了同样的事情,另一位开发者正在寻找开发可在 Windows 操作系统上运行的 Web 浏览器的相同内容,因此我尝试编写该应用程序并在网上分享,以便其他人也能理解如何编写一个简单的 C# 程序来创建 Web 浏览器。
环境要求
该项目使用 .NET Framework 4.5 和 Visual Studio 2013 开发。您需要安装 Visual Studio 2013。您可以从 Microsoft 获取 Visual Studio 副本,可以选择试用版或购买正式版。
您可以从 Microsoft 的 MSDN 库的下载选项卡中免费获取 Visual Studio 的 Express 版本。
完成上述操作后,您可以继续下载项目并使用您的 Visual Studio 进行构建。
理解 WPF
WPF 是 Microsoft 的一种模型,您可以在其中专注于 C# 代码和逻辑,而无需过多关注 UI 代码,从而简化在 Windows Forms 甚至 C++ 的 Win32 应用程序中必须处理的 UI 和其他代码。
MSDN 关于 WPF 的一段引述如下:
Windows Presentation Foundation (WPF) 为开发人员提供了一个统一的编程模型,用于构建丰富的 Windows 智能客户端用户体验,其中包括 UI、媒体和文档。
WPF 包含一套 UI 控件,您可以在 Windows 软件中使用它们,并且可以通过后端 C# 代码来控制它们。您可以在 MSDN 上找到可用的控件列表,其中提供了关于控件的基本信息、方法和属性。
WPF 是在 Windows Forms 之后开发的,旨在最大程度地减少开发人员在 Windows Forms 中遇到的问题,并且是 Microsoft 提供的最新编程平台。
http://msdn.microsoft.com/en-us/library/ms754130(v=vs.110).aspx
WPF 允许您设计布局、控制数据绑定以及更多功能,您可以在此处学习:
Windows Forms 仍在使用,但如今 WPF 更受推荐。
理解 WebBrowser 控件
Windows Forms 的 WebBrowser
控件与 WPF 的 WebBrowser
控件之间存在差异。WebBrowser
控件中移除了一些方法和属性,并添加了一些新的、更优化的属性,这些属性的合并使其体积更小但功能更强大。
您可以在 System.System.Controls.WebBrowser
命名空间
中找到本文档中使用的 WebBrowser
控件的文档。请勿与 System.Windows.Forms.WebBrowser
命名空间
混淆。
这种歧义可能会让您感到困惑,不明白为什么某些控件、函数和属性找不到,并且 Visual Studio 会抱怨缺少某个程序集。Visual Studio 会尝试在您源代码顶部已添加的 命名空间
类中查找控件属性,如下所示:
using System.Windows.Controls;
...现在,当您使用以下构造函数访问它时:
WebBrowser myBrowser = new WebBrowser();
...它将为您提供 WPF WebBrowser
的浏览器实例,而不是 Windows Forms WebBrowser
的实例,因为您没有使用该 命名空间
,并且该 WebBrowser
中的函数在此实例中找不到。这就是为什么 Visual Studio 会抱怨找不到以下函数,等等。
因此,请记住,您在软件中访问的每一个对象都来自某个 命名空间
,或者是由您自己创建的。它们执行的功能也来自它们所属的同一来源。
为应用程序编写代码
您可以创建一个简单的 Visual C# 程序,并向其中编写代码,使其成为您自己的 Web 浏览器应用程序。该代码最多使用 WebBrowser
类对象,并仅更新 UI。其余部分由 WebBrowser
控件本身处理,因此您无需处理文档中的每个子对象等。
创建 WebBrowser 对象 (XAML)
一旦您在 XAML 中创建了 WebBrowser
对象,您只需要担心它之外的内容,而无需担心它内部的内容。我们使用的 WebBrowser
的 XAML 代码如下:
<WebBrowser Name="myBrowser"
Height="530"
Margin="0, 55, 0, 0"
KeyDown="myBrowser_KeyDown"
Navigating="myBrowser_Navigating"
Navigated="myBrowser_Navigated"
LoadCompleted="myBrowser_LoadCompleted"
/>
此 WebBrowser
控件附加了一些事件,我们将在接下来的段落中讨论。
MainWindow 构造函数
与其他所有程序一样,我们的 Main
函数是创建 MainWindow
实例,在我们的软件中,其构造函数如下:
// MainWindow class constructor
public MainWindow()
{
InitializeComponent();
myBrowser.Navigate("http://www.google.com");
myUrl.Text = "http://www.google.com";
ChangeUserAgent("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)");
uri = "http://www.google.com";
this.setView();
this.navigationKeys();
}
在构造函数中,我正在更改浏览器的 User-Agent,以使网站认为请求数据的浏览器是 IE9(实际上并非如此)。在此之后,在构造函数内部,我调用了两个需要在启动时调用的其他函数,以设置导航键和浏览器视图。上面的代码只是应用程序启动时执行的代码,您可以将其他方法附加到此构造函数,以便在应用程序启动时立即执行它们。
导航键处理程序事件
// The navigation keys settings
private void navigationKeys()
{
// if browser has a forward page
if (!myBrowser.CanGoForward)
{
// enable button
BrowserGoForward.IsEnabled = false;
}
else
{
// disable it
BrowserGoForward.IsEnabled = true;
}
// if browser has a back page
if (!myBrowser.CanGoBack)
{
// enable button
BrowserGoBack.IsEnabled = false;
}
else
{
// disable button
BrowserGoBack.IsEnabled = true;
}
}
上述控件按钮来自 XAML,它们在那里编写,我调用此代码来启用或禁用它们。
视图设置事件处理程序
如构造函数中所述,视图设置事件编写如下:
private void setView()
{
// this code sets the height and the width of the WebBrowser element.
myBrowser.Width = this.Width;
myBrowser.Height = (this.Height - 59);
}
这是一小段代码,您只需看一眼即可理解。它根据 MainWindow
相对设置了浏览器控件的宽度和高度。在此代码中,this
指的是 MainWindow
类。
处理浏览器内的按键事件
每个浏览器都有一些定义的键盘功能,用户可以使用它们来执行任务而无需使用鼠标。大多数浏览器具有不同的功能,但大多数功能都相似,并在浏览器中定义以由软件处理。
我们的浏览器有一些功能,例如当用户按下退格键时会发生什么,当用户在提供的 TextBox
中输入 URL 时按下回车键会发生什么。为此,在 WebBrowser
中,我们为 KeyDown
定义了一个函数,在 C# 代码中,我们可以轻松处理它。
private void myUrl_KeyDown(object sender, KeyEventArgs e)
{
TextBox textBox = sender as TextBox;
string url = textBox.Text;
// get if the key is ENTER key and then navigate
if (e.Key == Key.Enter)
{
try
{
myBrowser.Navigate(url);
}
catch (Exception er)
{
// there was an error in the URI, complete it!
if (url.IndexOf("http://") == -1 || url.IndexOf("https://") == -1)
{
// there was no URI indicator, append it to string!
url = "http://" + url;
myBrowser.Focus();
try
{
myBrowser.Navigate(url.Replace("..", "."));
}
catch (Exception ex)
{
MessageBox.Show("The URL you provided is not correct, check it twice.");
}
myUrl.Text = myBrowser.Source.ToString();
}
}
}
}
上面的代码处理浏览器中触发 KeyDown
事件的所有事件,但仅在条件满足时才尝试处理它们。您可以这样考虑 BACKSPACE 键事件:
private void myBrowser_KeyDown(object sender, KeyEventArgs e)
{
// get the web browser
WebBrowser myBrowser = sender as WebBrowser;
// get if the key is BACKSPACE then go back!
if (e.Key == Key.Back)
{
if (myBrowser.CanGoBack)
{
myBrowser.GoBack();
}
}
}
这样,您就可以最大限度地减少因没有上一页而导致异常的可能性。您会检查上一页,如果浏览器可以返回,则返回,否则忽略该事件。
您可以添加更多类似的条件来为这个浏览器对象添加更多功能。
前进和后退按钮
每个浏览器都有一组按钮,用于处理浏览器的历史记录,以及向前或向后浏览历史记录。我们的浏览器具有处理此功能的原生按钮,并且我们在 navigationKeys
处理程序事件中对其进行了覆盖。但要查看它们是如何实际工作的,我们可以使用此代码:
// Back button handler, loads previous page in history (if present)
private void BrowserGoBack_Click(object sender, RoutedEventArgs e)
{
if (myBrowser.CanGoBack)
{
myBrowser.GoBack();
}
}
// Forward button handler, loads next page in history (if present)
private void BrowserGoForward_Click(object sender, RoutedEventArgs e)
{
if (myBrowser.CanGoForward)
{
myBrowser.GoForward();
}
}
您可以轻松理解此代码的功能。如果历史记录中有任何网页,它会向前或向后导航,依此类推。这是创建这些按钮所需的最少代码,并且它会检查条件,不会抛出任何类型的错误,因为我们只在有可供用户浏览的网页时进行导航,否则将什么也不做。在 navigationKeys
事件中,为这些按钮添加了一个额外的安全层,如果历史记录中没有用户可以浏览的网页,则会禁用这些按钮。
刷新 Web 浏览器(页面)
您也可以为浏览器添加刷新页面功能,它也只需一行代码,但值得注意的是,几乎所有浏览器都必须具备这些功能。并非所有用户都知道键盘快捷键,因此他们使用 UI 与软件应用程序进行交互。因此,我们在这里也将做同样的事情,刷新代码如下:
// Reload the current page function.
private void BrowserRefresh_Click(object sender, RoutedEventArgs e)
{
myBrowser.Refresh();
myUrl.Text = myBrowser.Source.ToString();
}
只需第一行代码即可,第二行代码仅更新 URL 栏的值。
使用软件进行测试
现在您可以使用该软件来测试 Web 浏览器应用程序,您会注意到我所说的更改,并且您会注意到 WebBrowser
控件能够自行处理。
运行软件
这取决于您是创建软件然后运行它,还是对其进行调试。
您将看到的第一个页面是主页(主页),已设置为 Google 的主页。
WebBrowser 中的事件
WebBrowser
中的事件由 Control
本身处理,您无需担心它们。
您可以看到,您根本不必担心对象本身的事件,它们会自动处理。您只需要编写关于软件应用程序的代码。
导航到另一个网页
与其他所有 Web 浏览器一样,我们的 Web 浏览器有一个 URL 栏,用户可以在其中输入他们想要跳转到的 URL。但请注意,在实际代码中,您需要将 URI 写成:“http://www.example.com”,简单的“example.com”将不起作用。但在本浏览器中,我捕获了这个错误,并允许用户只输入域名。
我导航到了 Facebook 网站,结果如下:
浏览器最大化视图如上所示,您可以使用这两种视图,但请记住,始终捕获事件然后进行调整。您可以在我使用的代码中看到事件,并了解我如何在每次 WindowResize
事件中更改 WebBrowser
的视图。
关注点
我了解到,在每个 命名空间
中,每个对象的名称都可以不同,但是其他 命名空间
中的类对象名称可能与它们匹配。您必须调用对象的准确名称,然后才能使用附加到它的属性和函数。否则,您的软件将无法正常工作。
历史
- 2014 年 8 月 16 日:帖子的第一个版本