用WPF做一個簡易瀏覽器

微軟的WPF(Windows Presentation Foundation)是目前Windows平臺上最好用的圖形界面框架了。如果想在Windows平臺上編寫圖形界面程序,而且沒有跨平臺且性能需求比較高,而且對C#語言比較熟悉,那么WPF就是最適合你的了。

WPF雖然出來也有大概十來年了,但是它的很多設(shè)計思想還是非常先進(jìn)的,配合C#這門語言的話更加順手。WPF的界面設(shè)計和程序功能完全解耦,也就是說設(shè)計界面和編寫程序功能可以互不干擾的同時進(jìn)行。

好了,廢話不多說,下面直接開始吧。當(dāng)然需要說明,這篇文章不是講如何實現(xiàn)瀏覽器的,而是利用WPF的一個瀏覽器控件,讓大家了解一下WPF的一些簡單功能。由于WPF組件龐大,沒辦法在一篇文章中詳細(xì)介紹。所以如果大家通過這篇文章對WPF有了一些興趣,那么這篇文章的目的就達(dá)到了。

先來看看效果圖吧。當(dāng)然功能比較簡陋,只有前進(jìn)、后退、刷新幾個功能。當(dāng)然如果太復(fù)雜,就沒辦法在一篇文章中說完了。

效果圖

界面設(shè)計

布局

不管是什么圖形界面框架,首先討論的都是界面布局了。布局負(fù)責(zé)組織界面元素如何排列和顯示。合適的界面布局可以降低我們程序界面的復(fù)雜度。如果需要了解布局的話,可以看看這篇英文文章,或者查找其他中文文章。

這里簡單說一下常用的幾種布局:

  • StackPanel。將部件按照垂直或水平順序依次排列。
  • WrapPanel。和前者差不多,不過如果部件太多,會自動安排到下一行顯示。
  • DockPanel??梢灾付ㄉ舷伦笥抑形鍌€方位的組件。
  • Grid。網(wǎng)格布局,可以按照網(wǎng)格形式排列組件。

現(xiàn)在返回來看看這個瀏覽器的布局。首先第一行是按鈕和地址欄,第二行就是瀏覽器控件了。所以在這里我使用了DockPanel,第一行我指定為Top;第二行不指定,也就是充滿整個剩余空間。

然后來看看第一行的布局,這里我希望前三個按鈕按順序排列,最后的地址欄充滿整個剩余空間。所以第一行本身也需要使用DockPanel來實現(xiàn)。

最后來看看相應(yīng)的XAML代碼,雖然說得比較多,但是代碼倒是很少。

<DockPanel>
    <DockPanel DockPanel.Dock="Top">
        <Button Name="ForwardButton" Content="前進(jìn)" 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>

控件

其實關(guān)于控件我倒是沒什么說的。不管是哪種圖形界面,反正控件總是按鈕、文本域、標(biāo)簽?zāi)切〇|西。這里我用到的就是按鈕和文本框,當(dāng)然最重要的是WPF提供的瀏覽器控件WebBrowser,它封裝了瀏覽器的操作以便我們直接使用。

當(dāng)然WPF還有一個非常重要的特點就是代碼可以無縫引用界面控件,這一點將在后面體現(xiàn)。這個特點可是很多圖形界面框架不提供的,比方說安卓的代碼要引用界面元素的話就得使用getElementById方法。

樣式

最后要說的就是樣式了。WPF的樣式和HTML的樣式在語法上很相似,我們既可以直接在界面元素上指定它的樣式,也可以在其他地方統(tǒng)一管理。當(dāng)然如果要符合軟件設(shè)計的最佳實踐,樣式當(dāng)然需要在一個地方統(tǒng)一指定比較好。

當(dāng)然,WPF的樣式非常豐富,可以對一個控件進(jìn)行深度定制,讓它“重新做人”。所以我就不做介紹了,等到需要的時候在查閱就行了。這里只設(shè)置了按鈕和文本框的寬度和外邊距,外邊距的4個值分別代表上、左、右、下外邊距。如果不在這里統(tǒng)一設(shè)置,那么就要針對每個按鈕設(shè)置一次外邊距,這是件很麻煩的事情。

<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>

功能編寫

事件處理

說完了界面的部分,下面來說說如何編寫程序功能。利用強(qiáng)大的XAML,我們可以非常方便的將界面組件和功能代碼對應(yīng)起來。C#有一個特性叫做事件,WPF也利用了事件來處理程序響應(yīng)。WPF的控件都包含了大量事件,可以處理鼠標(biāo)、鍵盤、觸屏等等各種事件,而且僅需要在XAML代碼中添加一點代碼就可以將事件和處理程序綁定起來。下面代碼中的ClickKeyDown就是兩個事件,用于處理單擊鼠標(biāo)和鍵盤按鍵。

<DockPanel>
    <DockPanel DockPanel.Dock="Top">
        <Button Name="ForwardButton" Content="前進(jìn)" 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>

每個事件的處理函數(shù)簽名都不相同,比方說單擊鼠標(biāo)的事件簽名就是Click(object sender, RoutedEventArgs e),而按下鍵盤的事件簽名是KeyDown(object sender, KeyEventArgs e)。在Visual Studio中我們只需要選擇控件,然后點擊屬性中的相應(yīng)事件,即可自動生成處理函數(shù),我們只需要編寫代碼即可。

VS截圖

瀏覽器控件

說完了事件機(jī)制,下面我們來看看如何用它來搞點事情。由于WPF提供了方便的瀏覽器控件,所以這里的代碼非常簡單,只需要調(diào)用瀏覽器控件的相應(yīng)方法即可。由于沒有單獨的處理按下回車的事件,所以這里用的是按下鍵盤的事件,然后在處理程序中判斷按下的是否是回車鍵,如果是的話再進(jìn)行下一步處理,也就是讓瀏覽器導(dǎo)航到對應(yīng)網(wǎng)址。

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);
    }
}

自動補(bǔ)全URL

上面的代碼已經(jīng)基本可以使用,不過還是有一個小問題。那就是如果輸入的不是URL格式(http://www.baidu.com),而是網(wǎng)址(www.baidu.com),那么程序就會崩掉。因為瀏覽器控件只能接受URL形式的字符串,如果不是合法的URL,那么BrowserControl.Navigate(url)這一句代碼就會拋出異常。

那么這個問題該如何解決呢?我在這里直接使用正則表達(dá)式做一下測試,如果如果輸入的不是有效的URL,那么我就手動在網(wǎng)址前面添加一個 http://。實現(xiàn)方法很簡單,直接看代碼就行了。

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就會發(fā)現(xiàn),在下面的代碼中直接引用了XAML中瀏覽器控件的名字BrowserControl,并可以調(diào)用它的屬性和方法。這也是瀏覽·WPF一個非常方便的特性。

更改地址欄URL

下面就剩下最后一個問題了。一般瀏覽器的地址欄,會隨著訪問網(wǎng)址的變化而變化。但是我們這個瀏覽器卻沒有這個功能,地址欄的地址永遠(yuǎn)是輸入的那個地址?,F(xiàn)在我們希望不論是前進(jìn)、后退,還是從瀏覽器中點擊其他鏈接,地址欄的地址都會跟著更新。

當(dāng)然實現(xiàn)這個功能也很簡單,查閱一下瀏覽器控件就可以發(fā)現(xiàn),它有一個屬性叫做Source,恰好就是當(dāng)前頁面的URL,所以利用這個屬性就可以完美的實現(xiàn)我們的功能了。這樣,只需要一行代碼UrlTextBox.Text = BrowserControl.Source.ToString();就可以搞定了。

當(dāng)然問題又來了,這行代碼應(yīng)該往哪里加呢?第一種辦法是在所有處理程序中添加這行代碼, 也就是說,前進(jìn)、后退的處理程序都需要進(jìn)行修改。這樣并不是一個好辦法,萬一將來需求發(fā)生了變化,有好幾處地方都要修改,更容易出錯。解決辦法還是剛才說的事件。經(jīng)過一番查找,我發(fā)現(xiàn)了WebBrowserNavigated事件,顧名思義,這個事件會在調(diào)用了Navigate方法后觸發(fā)。這樣,只需要把這一行代碼綁定到這個事件上就行了,代碼非常優(yōu)雅,酷斃了!

public MainWindow()
{
    InitializeComponent();
    BrowserControl.Navigated += BrowserControl_Navigated;
}
private void BrowserControl_Navigated(object sender, NavigationEventArgs e)
{
    UrlTextBox.Text = BrowserControl.Source.ToString();
}

這樣,一個簡易的瀏覽器就實現(xiàn)完畢了。代碼我放在了Csdn Code,有興趣的同學(xué)可以看看。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,563評論 19 139
  • 目錄 什么是WPF? WPF的歷史? 為什么要用WPF及WPF作用 WPF與winForm區(qū)別? 什么是WPF? ...
    灬52赫茲灬閱讀 6,129評論 2 11
  • ¥開啟¥ 【iAPP實現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 7,330評論 0 17
  • 鯨魚喜歡看電影,有不錯的新片上映會去電影院看,有時會叫朋友一起。好友A每次不去,總說我好浪費(fèi),明明網(wǎng)上有免費(fèi)資...
    鯨魚我愛你閱讀 160評論 2 1
  • 酒館里的人魚龍混雜,三教九流。 “別看他們,切勿惹事” “明白” 黑衣男子坐下叫了壺茶,而旁邊的女子則是一直低頭站...
    六分之一閱讀 335評論 0 0

友情鏈接更多精彩內(nèi)容