基於CefSharp開發(二)自定義瀏覽器窗體
上一篇https://www.cnblogs.com/mchao/p/13914726.html簡單瞭解了CefSharp引用配置但頁面光禿禿的,這一篇著手開發簡單瀏覽器窗體
一、Edge瀏覽器窗體分析
如上圖所示可先將瀏覽器窗體分為兩大部分,Header及Body部分,Header暫時分為Tab展示及搜尋部分 每個Tab頁有一個搜尋及ChromiumWebBrowser
此時我們需要一個帶關閉按鈕的TabControl
二、自定義TabControl
修改TabItemControlTemplate增加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頁。
執行看效果