上一篇 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

基于CefSharp开发(二)自定义浏览器窗体的更多相关文章

  1. 基于.net开发chrome核心浏览器【二】

    原文:基于.net开发chrome核心浏览器[二] 一: 上一篇的链接: 基于.net开发chrome核心浏览器[一] 二: 相关资源介绍: chrome Frame: 让IE有一颗chrome的心, ...

  2. 基于CefSharp开发浏览器(八)浏览器收藏夹栏

    一.前言 上一篇文章 基于CefSharp开发(七)浏览器收藏夹菜单 简单实现了部分收藏夹功能 如(添加文件夹.添加收藏.删除.右键菜单部分功能) 后续代码中对MTreeViewItem进行了扩展,增 ...

  3. 基于.net开发chrome核心浏览器【七】

    这是一个系列的文章,前面六篇文章的地址如下: 基于.net开发chrome核心浏览器[六] 基于.net开发chrome核心浏览器[五] 基于.net开发chrome核心浏览器[四] 基于.net开发 ...

  4. 基于.net开发chrome核心浏览器

    本文转载自:http://www.cnblogs.com/liulun/archive/2013/04/20/3031502.html 一: 上一篇的链接: 基于.net开发chrome核心浏览器[一 ...

  5. 基于.net开发chrome核心浏览器【四】

    原文:基于.net开发chrome核心浏览器[四] 一: 上周去北京出差,给国家电网的项目做架构方案,每天都很晚睡,客户那边的副总也这样拼命工作. 累的不行了,直接导致第四篇文章没有按时发出来. 希望 ...

  6. 基于.net开发chrome核心浏览器【三】

    原文:基于.net开发chrome核心浏览器[三] 本篇我们讲解怎么用CefGlue开发一个最简单的浏览器 一: CefGlue是建立在Cef项目之上的,Cef项目是C/C++的项目:CefGlue只 ...

  7. 基于.net开发chrome核心浏览器【一】

    原文:基于.net开发chrome核心浏览器[一] 说明: 这是本系列的第一篇文章,我会尽快发后续的文章. 源起 1.加快葬送IE6浏览器的进程 世界上使用IE6浏览器最多的地方在中国 中国使用IE6 ...

  8. 基于.net开发chrome核心浏览器【五】

    一:本篇将解决的问题 本章主要为了解决一下几个问题: 1.JsDialog的按钮错位的问题 我们开发出的浏览器,在有些操系统上调用alert,confirm之类的对话框时,确定和取消按钮会出现错位的情 ...

  9. 基于CefSharp开发(五)浏览器菜单样式

    一.菜单分析 上图为Edge浏览器现有的菜单内容,菜单中即有子菜单也有组合菜单. 本章节将开发浏览器菜单样式,菜单部分功能将后期进行处理. 二.创建菜单用户控件 新建用户控件命名为WebMenuUc, ...

随机推荐

  1. wcf调用时时间参数问题,返回值中有日期格式得值得问题

    第一种情况,客户端在调用wcf后台服务时,参数对象有日期类型得属性,日期默认值不能是datetime.minvalue得值,需要设置大于1971-1-1,不然调不通服务, 第二种情况,服务连通了,并且 ...

  2. IP 层收发报文简要剖析1-ip报文的输入

    ip层数据包处理场景如下: 网络层处理数据包文时需要和路由表以及邻居系统打交道.输入数据时,提供输入接口给链路层调用,并调用传输层的输入接口将数据输入到传输层. 在输出数据时,提供输出接口给传输层,并 ...

  3. 修改ssh的默认22端口,并使用scp的方法

    修改默认的22的ssh端口只需要修改 /etc/ssh/sshd_config 中的 port 字段为你想要的端口就可以了 以后用其他机器ssh登录这台机器只需要: ssh -p (port) (ip ...

  4. BeanFactory and FactoryBean

    BeanFactory,这是Spring容器的基础实现类,它负责生产和管理Bean的一个工厂.当然BeanFactory只是一个接口,它的常用实现有XmlBeanFactory.DefaultList ...

  5. Python 调用Get接口

    import requests,jsonurl = 'http://localhost:30627/api/jobs/GetNuberId?id=2'req = requests.get(url)re ...

  6. 谈谈什么是MySQL的表空间?

    今天我要跟你分享的话题是:"大家常说的表空间到底是什么?究竟什么又是数据表?" 这其实是一个概念性的知识点,当作拓展知识.涉及到的概念大家了解一下就好,涉及的参数,留个印象就好. ...

  7. 分布式监控系统之Zabbix主动、被动及web监控

    前文我们了解了zabbix的网络发现功能,以及结合action实现自动发现主机并将主机添加到zabbix hosts中,链接指定模板进行监控:回顾请参考https://www.cnblogs.com/ ...

  8. On Starting My Blogging On CNBlogs

    About Myself I am a would-be Master of Engineering, on the last year of my student life, I'm ambitou ...

  9. pandas 生成html文档,支持可添加多个表

    如何通过pandas生成html格式?如何通过pandas生成html文件文件中包含多个表单Balance_64_data = pd.read_sql(Balance_64_sql,engine)df ...

  10. 思维导图iMindMap可以在哪些领域应用

    生活工作中你常常会遇到许多力所不能及的事情,感到无奈.茫然,这时候你急需一个帮手来帮你打破困境,思维导图就是这样的救世主,至于它有哪些力所能及的事情就是下面小编要跟你讲的. 你是否经常遇到过这样的情况 ...