1. 程式人生 > 實用技巧 >基於CefSharp開發(二)自定義瀏覽器窗體

基於CefSharp開發(二)自定義瀏覽器窗體

上一篇https://www.cnblogs.com/mchao/p/13914726.html簡單瞭解了CefSharp引用配置但頁面光禿禿的,這一篇著手開發簡單瀏覽器窗體

一、Edge瀏覽器窗體分析

如上圖所示可先將瀏覽器窗體分為兩大部分,Header及Body部分,Header暫時分為Tab展示及搜尋部分 每個Tab頁有一個搜尋及ChromiumWebBrowser

此時我們需要一個帶關閉按鈕的TabControl

二、自定義TabControl

修改TabItemControlTemplate增加Button,關於TabControl分析請參考Cys_Control(四) MTabControl

<Button Grid.Column="1" Style="{StaticResource TabCloseButton}"
                                            Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MTabControl}},Path=TabItemRemoveCommand}"
                                            CommandParameter
="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabItem}}}" />

CommandParamenter 引數傳當前 TabItem

在cs檔案中新增依賴屬性TabItemRemoveCommand

        public static readonly DependencyProperty TabItemRemoveCommandProperty = DependencyProperty.Register("TabItemRemoveCommand", typeof
(ICommand), typeof(MTabControl), new PropertyMetadata(null)); public ICommand TabItemRemoveCommand { get => (ICommand)GetValue(TabItemRemoveCommandProperty); set => SetValue(TabItemRemoveCommandProperty, value); }

併為TabItemRemoveCommand新增移除方法

 private void TabItemRemove(object obj)
 {
    if (obj is TabItem item)
    {
       this.Items.Remove(item);
    }
}

有了移除還需要有新增

在 TabControl中新增 Button,原理同移除

<Button Grid.Column="1" Style="{StaticResource TabAddButton}" HorizontalAlignment="Left"
       Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MTabControl}},Path=TabItemAddCommand}"/>


三、新增搜尋框

由圖可知 Edge 搜尋框由 三部分組成即(左右按鈕及中間文字),相當於TextBox中增加了倆按鈕,因此我們對TextBox做個擴充套件

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="auto"/>
    </Grid.ColumnDefinitions>
    <Grid Grid.Column="0">
        <Button Style="{DynamicResource Button.NavigationSearch}" Margin="2,0"/>
    </Grid>
    <Grid Grid.Column="1">
        <ScrollViewer x:Name="PART_ContentHost" FontSize="{TemplateBinding FontSize}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" BorderThickness="0" IsTabStop="False"
                                          HorizontalAlignment="{TemplateBinding HorizontalAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="4,0"/>
        <!--水印-->
        <TextBlock x:Name="Part_Watermark" Text="{TemplateBinding Watermark}" FontSize="{TemplateBinding FontSize}" Visibility="Hidden" HorizontalAlignment="Left"
                                   Foreground="{DynamicResource ColorBrush.FontWatermarkColor}" IsHitTestVisible="False" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="5,0"/>
    </Grid>
    <Grid Grid.Column="2">
        <ToggleButton Style="{DynamicResource ToggleButton.NavigationCollection}" Margin="2,0"/>
    </Grid>
</Grid>

文字框中左邊增加Button,右邊增加ToggleButton來區分是否網頁已收藏(注:本次不加入業務處理

關於TextBox水印及其他處理 請參照Cys_Control(三) MTextBox

四、調整佈局

增加前進回退重新整理等按鈕用於佔位並調整搜尋框

<Grid Grid.Row="0" Background="{DynamicResource WebBrowserBrushes.TabHeaderIsSelectedBackground}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <StackPanel Grid.Column="0" Orientation="Horizontal">
        <Button Style="{DynamicResource Button.NavigationBack}"/>
        <Button Style="{DynamicResource Button.NavigationForward}"/>
        <Button Style="{DynamicResource Button.NavigationRefresh}"/>
    </StackPanel>
    <controls:MTextBox Grid.Column="1" Watermark="搜尋或輸入Web地址" x:Name="SearchText"/>
    <Grid Grid.Column="2" MinWidth="150">

    </Grid>
</Grid>

此時從頁面上看已經有些像瀏覽器了,跑起來。。。

此時發現點選網頁連結和預想的開啟新Tab頁有些差距

五、新Tab頁開啟連結

Cef的Popup處理定義在ILifeSpanHandler介面中,若要阻止彈窗並使用自己的Tab頁則應該自定義LifeSpanHandler

新增CustomLifeSpanHandler類並實現ILifeSpanHandler介面

public class CustomLifeSpanHandler : ILifeSpanHandler
    {
        public bool OnBeforePopup(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl,
            string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures,
            IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser)
        {
            if (chromiumWebBrowser is CustomWebBrowser webBrowser)
            {
                webBrowser.OpenNewTab(targetUrl);
            }
            newBrowser = null;
            return true;
        }

        public void OnAfterCreated(IWebBrowser chromiumWebBrowser, IBrowser browser)
        {
           
        }

        public bool DoClose(IWebBrowser chromiumWebBrowser, IBrowser browser)
        {
            return false;
        }

        public void OnBeforeClose(IWebBrowser chromiumWebBrowser, IBrowser browser)
        {
           
        }
    }

OnBeforePopup方法中可以取到targetUrl也就是點選的<a>標籤中的連結

此時我們需要將targetUrl傳遞到WebBrowser中,由於我們需要開啟Tab頁,需要增加一個方法OpenNewTab(targetUrl),

ChromiumWebBrowser類並不能滿足我們的使用場景,故擴充套件ChromiumWebBrowser類,新增CustomWebBrowser繼承於ChromiumWebBrowser

並新增OpenNewTab方法

public void OpenNewTab(string url)
{
    Dispatcher.Invoke(() =>
    {
        var tabControl = ControlHelper.FindVisualParent<MTabControl>(this);
        tabControl?.TabItemAddCommand?.Execute(url);
    });
}

該方法用於新增一個Tab頁。

執行看效果

六、原始碼地址

gitee地址:https://gitee.com/sirius_machao/mweb-browser