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


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

一、Edge瀏覽器窗體分析

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

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

二、自定義TabControl

修改TabItem ControlTemplate增加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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM