前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用WPF做一个简易浏览器

用WPF做一个简易浏览器

作者头像
乐百川
发布2018-01-09 10:59:17
3.4K0
发布2018-01-09 10:59:17
举报

微软的WPF(Windows Presentation Foundation)是目前Windows平台上最好用的图形界面框架了。如果想在Windows平台上编写图形界面程序,而且没有跨平台且性能需求比较高,而且对C#语言比较熟悉,那么WPF就是最适合你的了。

WPF虽然出来也有大概十来年了,但是它的很多设计思想还是非常先进的,配合C#这门语言的话更加顺手。WPF的界面设计和程序功能完全解耦,也就是说设计界面和编写程序功能可以互不干扰的同时进行。

好了,废话不多说,下面直接开始吧。当然需要说明,这篇文章不是讲如何实现浏览器的,而是利用WPF的一个浏览器控件,让大家了解一下WPF的一些简单功能。由于WPF组件庞大,没办法在一篇文章中详细介绍。所以如果大家通过这篇文章对WPF有了一些兴趣,那么这篇文章的目的就达到了。

先来看看效果图吧。当然功能比较简陋,只有前进、后退、刷新几个功能。当然如果太复杂,就没办法在一篇文章中说完了。

效果图
效果图

界面设计

布局

不管是什么图形界面框架,首先讨论的都是界面布局了。布局负责组织界面元素如何排列和显示。合适的界面布局可以降低我们程序界面的复杂度。如果需要了解布局的话,可以看看这篇英文文章,或者查找其他中文文章。

这里简单说一下常用的几种布局:

  • StackPanel。将部件按照垂直或水平顺序依次排列。
  • WrapPanel。和前者差不多,不过如果部件太多,会自动安排到下一行显示。
  • DockPanel。可以指定上下左右中五个方位的组件。
  • Grid。网格布局,可以按照网格形式排列组件。

现在返回来看看这个浏览器的布局。首先第一行是按钮和地址栏,第二行就是浏览器控件了。所以在这里我使用了DockPanel,第一行我指定为Top;第二行不指定,也就是充满整个剩余空间。

然后来看看第一行的布局,这里我希望前三个按钮按顺序排列,最后的地址栏充满整个剩余空间。所以第一行本身也需要使用DockPanel来实现。

最后来看看相应的XAML代码,虽然说得比较多,但是代码倒是很少。

代码语言:javascript
复制
<DockPanel>
    <DockPanel DockPanel.Dock="Top">
        <Button Name="ForwardButton" Content="前进" Click="ForwardButton_Click" />
        <Button Name="BackButton" Content="后退" Click="BackButton_Click" />
        <Button Name="RefreshButton" Content="刷新" Click="RefreshButton_Click" />
        <TextBox Name="UrlTextBox" KeyDown="UrlTextBox_KeyDown" />
    </DockPanel>
    <WebBrowser Name="BrowserControl" />
</DockPanel>

控件

其实关于控件我倒是没什么说的。不管是哪种图形界面,反正控件总是按钮、文本域、标签那些东西。这里我用到的就是按钮和文本框,当然最重要的是WPF提供的浏览器控件WebBrowser,它封装了浏览器的操作以便我们直接使用。

当然WPF还有一个非常重要的特点就是代码可以无缝引用界面控件,这一点将在后面体现。这个特点可是很多图形界面框架不提供的,比方说安卓的代码要引用界面元素的话就得使用getElementById方法。

样式

最后要说的就是样式了。WPF的样式和HTML的样式在语法上很相似,我们既可以直接在界面元素上指定它的样式,也可以在其他地方统一管理。当然如果要符合软件设计的最佳实践,样式当然需要在一个地方统一指定比较好。

当然,WPF的样式非常丰富,可以对一个控件进行深度定制,让它“重新做人”。所以我就不做介绍了,等到需要的时候在查阅就行了。这里只设置了按钮和文本框的宽度和外边距,外边距的4个值分别代表上、左、右、下外边距。如果不在这里统一设置,那么就要针对每个按钮设置一次外边距,这是件很麻烦的事情。

代码语言:javascript
复制
<Window.Resources>
    <Style TargetType="Button">
        <Setter Property="Width" Value="45" />
        <Setter Property="Margin" Value="10,10,0,10" />
    </Style>
    <Style TargetType="TextBox">
        <Setter Property="Margin" Value="10,10,10,10" />
    </Style>
</Window.Resources>

功能编写

事件处理

说完了界面的部分,下面来说说如何编写程序功能。利用强大的XAML,我们可以非常方便的将界面组件和功能代码对应起来。C#有一个特性叫做事件,WPF也利用了事件来处理程序响应。WPF的控件都包含了大量事件,可以处理鼠标、键盘、触屏等等各种事件,而且仅需要在XAML代码中添加一点代码就可以将事件和处理程序绑定起来。下面代码中的ClickKeyDown就是两个事件,用于处理单击鼠标和键盘按键。

代码语言:javascript
复制
<DockPanel>
    <DockPanel DockPanel.Dock="Top">
        <Button Name="ForwardButton" Content="前进" Click="ForwardButton_Click" />
        <Button Name="BackButton" Content="后退" Click="BackButton_Click" />
        <Button Name="RefreshButton" Content="刷新" Click="RefreshButton_Click" />
        <TextBox Name="UrlTextBox" KeyDown="UrlTextBox_KeyDown" />
    </DockPanel>
    <WebBrowser Name="BrowserControl" />
</DockPanel>

每个事件的处理函数签名都不相同,比方说单击鼠标的事件签名就是Click(object sender, RoutedEventArgs e),而按下键盘的事件签名是KeyDown(object sender, KeyEventArgs e)。在Visual Studio中我们只需要选择控件,然后点击属性中的相应事件,即可自动生成处理函数,我们只需要编写代码即可。

VS截图
VS截图

浏览器控件

说完了事件机制,下面我们来看看如何用它来搞点事情。由于WPF提供了方便的浏览器控件,所以这里的代码非常简单,只需要调用浏览器控件的相应方法即可。由于没有单独的处理按下回车的事件,所以这里用的是按下键盘的事件,然后在处理程序中判断按下的是否是回车键,如果是的话再进行下一步处理,也就是让浏览器导航到对应网址。

代码语言:javascript
复制
private void ForwardButton_Click(object sender, RoutedEventArgs e)
{
    BrowserControl.GoForward();
}
private void BackButton_Click(object sender, RoutedEventArgs e)
{
    BrowserControl.GoBack();
}
private void RefreshButton_Click(object sender, RoutedEventArgs e)
{
    BrowserControl.Refresh();
}
private void UrlTextBox_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Return)
    {
        var url = UrlTextBox.Text;
        BrowserControl.Navigate(url);
    }
}

自动补全URL

上面的代码已经基本可以使用,不过还是有一个小问题。那就是如果输入的不是URL格式(http://www.baidu.com),而是网址(www.baidu.com),那么程序就会崩掉。因为浏览器控件只能接受URL形式的字符串,如果不是合法的URL,那么BrowserControl.Navigate(url)这一句代码就会抛出异常。

那么这个问题该如何解决呢?我在这里直接使用正则表达式做一下测试,如果如果输入的不是有效的URL,那么我就手动在网址前面添加一个 http://。实现方法很简单,直接看代码就行了。

代码语言:javascript
复制
public partial class MainWindow : Window
{
    private readonly Regex _urlPattern = new Regex(@"\w*://\w*(.\w*)+");
    public MainWindow()
    {
        InitializeComponent();
    }
    //省略了那些事件处理程序
    private void UrlTextBox_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Return)
        {
            var url = UrlTextBox.Text;
            if (!_urlPattern.IsMatch(url))
            {
                url = "http://" + url;
            }
            BrowserControl.Navigate(url);
        }
    }
}

如果留心一下前面的XAML就会发现,在下面的代码中直接引用了XAML中浏览器控件的名字BrowserControl,并可以调用它的属性和方法。这也是浏览·WPF一个非常方便的特性。

更改地址栏URL

下面就剩下最后一个问题了。一般浏览器的地址栏,会随着访问网址的变化而变化。但是我们这个浏览器却没有这个功能,地址栏的地址永远是输入的那个地址。现在我们希望不论是前进、后退,还是从浏览器中点击其他链接,地址栏的地址都会跟着更新。

当然实现这个功能也很简单,查阅一下浏览器控件就可以发现,它有一个属性叫做Source,恰好就是当前页面的URL,所以利用这个属性就可以完美的实现我们的功能了。这样,只需要一行代码UrlTextBox.Text = BrowserControl.Source.ToString();就可以搞定了。

当然问题又来了,这行代码应该往哪里加呢?第一种办法是在所有处理程序中添加这行代码, 也就是说,前进、后退的处理程序都需要进行修改。这样并不是一个好办法,万一将来需求发生了变化,有好几处地方都要修改,更容易出错。解决办法还是刚才说的事件。经过一番查找,我发现了WebBrowserNavigated事件,顾名思义,这个事件会在调用了Navigate方法后触发。这样,只需要把这一行代码绑定到这个事件上就行了,代码非常优雅,酷毙了!

代码语言:javascript
复制
public MainWindow()
{
    InitializeComponent();
    BrowserControl.Navigated += BrowserControl_Navigated;
}
private void BrowserControl_Navigated(object sender, NavigationEventArgs e)
{
    UrlTextBox.Text = BrowserControl.Source.ToString();
}

这样,一个简易的浏览器就实现完毕了。代码我放在了Csdn Code,有兴趣的同学可以看看。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年06月30日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 界面设计
    • 布局
      • 控件
        • 样式
        • 功能编写
          • 事件处理
            • 浏览器控件
              • 自动补全URL
                • 更改地址栏URL
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档