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

github地址:https://github.com/sirius-chao/MWebBrowser

项目邀请:如对该项目有兴趣,欢迎联系我共同开发!!!

posted @ 2020-11-04 17:02  咸鱼翻身?  阅读(2556)  评论(6编辑  收藏  举报