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

  • 相关阅读:
    第24课 #pragma使用分析
    第23课 #error和#line使用分析
    第22课 条件编译使用分析
    第21课 宏定义与使用分析
    Codeforces Round #142 (Div. 2)B. T-primes
    SPOJ XMAX
    Uva 10036
    Timus 1009. K-based Numbers
    MBLAST
    ROADS
  • 原文地址:https://www.cnblogs.com/mchao/p/13915446.html
Copyright © 2020-2023  润新知