上一篇 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. Java_垃圾回收机制(未掌握)

    垃圾回收机制 任何一种垃圾回收算法一般要做两件基本事情: 发现无用的对象(没有任何变量引用该对象) 回收无用对象占用的内存空间 垃圾回收相关算法: 引用计数法, 引用可达法 分代垃圾回收机制: 不同的 ...

  2. 【Kata Daily 190918】Spacify(插空)

    题目: Modify the spacify function so that it returns the given string with spaces insertedbetween each ...

  3. 利用Kotlin扩展函数实现任意View的点击处理(点击效果和防止快速点击)

    利用Kotlin扩展函数实现View的点击处理(点击效果和防止快速点击) kotlin经典写法: view?.setOnClickListener { //实现 } 项目实践证明,这种写法存在问题 例 ...

  4. tp3.2 前端截取字符串

    在Common目录中建立 function.php <?php function subtext($text, $length) { if(mb_strlen($text, 'utf8') &g ...

  5. offsetWidth与offsetHeight

    HTMLElement.offsetWidth 是一个只读属性,返回一个元素的布局宽度.一个典型的(译者注:各浏览器的offsetWidth可能有所不同)offsetWidth是测量包含元素的边框(b ...

  6. Gromacs文件-Chapter1

    Gromacs的文件非常的多,这是官方文档地址:http://manual.gromacs.org/online/files.html. 本文章部分内容来自以下网址https://zhuanlan.z ...

  7. epoll oneshot

    /* Epoll private bits inside the event mask */#define EP_PRIVATE_BITS (EPOLLWAKEUP | EPOLLONESHOT | ...

  8. NO.A.0001——day01——Java概述/进制间的转换

    一.什么是JAVA语言:        JAVA语言是美国sun公司(Stanford University Network)在1995年推出的高级编程语言.所谓编程语言,是计算机的语言,人们可以使用 ...

  9. Ceph数据盘怎样实现自动挂载

    前言 在Centos7 下,现在采用了 systemctl来控制服务,这个刚开始用起来可能不太习惯,不过这个服务比之前的服务控制要强大的多,可以做更多的控制,本节将来介绍下关于 Ceph的 osd 磁 ...

  10. 02Java写一个hello world

    新建一个.text文件 输入并保存如下代码: public class HelloWorld{ public static void main(String[] args){ System.out.p ...