一、网页缩放分析
缩放入口
1、Ctrl + 鼠标滑轮缩放
2、菜单中缩放子菜单缩放
3、搜索框中网页缩放按钮缩放
缩放属性及命令
ChromiumWebBrowser 提供了缩放量值、缩放级别、放大/缩小/重置命令等,如下图
二、鼠标滑轮缩放
简单缩放实现
要实现缩放,首先需捕获鼠标滚动事件,在初始化WebBrowser方法中增加
this.CefWebBrowser.PreviewMouseWheel += CefWebBrowser_PreviewMouseWheel;
并实现CefWebBrowser_PreviewMouseWheel方法,这里需要判断Ctrl是否按下,代码如下:
private void CefWebBrowser_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { if ((Keyboard.Modifiers & ModifierKeys.Control) != ModifierKeys.Control) return; try { if (e.Delta > 0) { CefWebBrowser.ZoomInCommand.Execute(null); } else if (e.Delta < 0) { CefWebBrowser.ZoomOutCommand.Execute(null); } e.Handled = true; } catch (Exception ex) { } }
其中e.Delta大于0时放大网页,小于0时缩小网页
页面重置
一般习惯Ctrl+0重置网页大小,故需要在CefWebBrowser_PreviewKeyDown中增加组合键处理,注意:0的key值包含小键盘(NumPad0),代码如下:
if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control && (e.Key == Key.D0 || e.Key == Key.NumPad0)) { CefWebBrowser.ZoomResetCommand.Execute(null); // CefWebBrowser.SetZoomLevel(0); }
ZoomResetCommand 可使缩放级别恢复到页面打开时的缩放级别(默认为100%,若有设置可能不是100%),强势重置到100%可使用注释代码 CefWebBrowser.SetZoomLevel(0);
三、增加缩放级别显示
上面内容已可以实现网页缩放,但不知具体缩放比例(级别),查看Edge缩放展示
当网页缩放时会在搜索框中显示缩放按钮,并在下方展示缩放小窗口,接下来实现如下内容
1、扩展搜索框
由于搜索框的内容将越来越多,故不能用通用的MTextBox,需新建一个搜索框便于以后内容扩展,新建CustomControl MSearchText,
并从MTextBox搬砖到MSearchText
MSearchText控件需要增加依赖属性ZoomLevelType用来判断缩放按钮是否显示、缩小、放大
此时需要个Menu类型,添加枚举类型 None不显示缩放
public enum ZoomType { None, In, Out, }
增加依赖属性
public static readonly DependencyProperty ZoomLevelTypeProperty = DependencyProperty.Register("ZoomLevelType", typeof(ZoomType), typeof(MSearchText)); /// <summary> /// ZoomLevelType 缩放类型 /// </summary> public ZoomType ZoomLevelType { get => (ZoomType)GetValue(ZoomLevelTypeProperty); set => SetValue(ZoomLevelTypeProperty, value); }
在Xaml中Search框中增加一列 ZoomButon
<Grid Grid.Column="2"> <ToggleButton x:Name="PART_ZoomButton" FontSize="16" Style="{DynamicResource ToggleButton.FontButton}" Margin="2,0"/> </Grid>
在触发器中增加显示状态控制
<Trigger Property="ZoomLevelType" Value="None"> <Setter TargetName="PART_ZoomButton" Property="Visibility" Value="Collapsed" /> </Trigger> <Trigger Property="ZoomLevelType" Value="In"> <Setter TargetName="PART_ZoomButton" Property="Content" Value="" /> </Trigger> <Trigger Property="ZoomLevelType" Value="Out"> <Setter TargetName="PART_ZoomButton" Property="Content" Value="" /> </Trigger>
2、ZoomLevelType 类型绑定
在MSearchText 中增加Binding,ViewModel这里不再赘述。
<controls:MSearchText Grid.Column="1" Watermark="搜索或输入Web地址" Text="{Binding CurrentUrl, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" ZoomLevelType="{Binding ZoomLevelType}" KeyDown="Search_OnKeyDown"/>
当页面缩放时,执行SetSearchZoomStatus方法
private void SetSearchZoomStatus() { if (CefWebBrowser.ZoomLevel < 0) { ViewModel.ZoomLevelType = ZoomType.Out; } else if (CefWebBrowser.ZoomLevel > 0) { ViewModel.ZoomLevelType = ZoomType.In; } else { ViewModel.ZoomLevelType = ZoomType.None; } }
运行效果:
3、 缩放小窗口
Edge缩放小窗口具有如下特点:
1、缩放比例实时更新
2、当点击缩放Button 弹出小窗口
3、Ctrl+鼠标滑轮放大缩小 小窗口几秒后消失
首先设计小窗口,采用Popup,继续扩展MSearchText,增加Popup弹窗,增加TextBlock用于显示缩放比例,三个Button分别为缩小、放大、重置
<Popup x:Name="PART_ZoomPopUp" PopupAnimation="Fade" Placement="Bottom" PlacementTarget="{Binding ElementName=PART_ZoomButton}" StaysOpen="{TemplateBinding ZoomStaysOpen}" AllowsTransparency="True" HorizontalOffset="-180" VerticalOffset="5" IsOpen="{TemplateBinding ZoomIsChecked}"> <Border Background="{DynamicResource WebBrowserBrushes.SearchZoomPopupBackground}" CornerRadius="5"> <DockPanel Width="251" Height="40"> <TextBlock Text="{TemplateBinding ZoomRatio}" VerticalAlignment="Center" Margin="15,0,0,0" HorizontalAlignment="Left"/> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,15,0"> <Button Content="" Style="{DynamicResource Button.FontButton}" Width="26" Height="26"/> <Button Content="" Style="{DynamicResource Button.FontButton}" Margin="10,0,0,0" Width="26" Height="26"/> <Button Content="重置" Style="{DynamicResource Button.FontButton}" Margin="10,0,0,0" Width="64" Background="{DynamicResource WebBrowserBrushes.SearchZoomPopupResetBackground}"/> </StackPanel> </DockPanel> </Border> </Popup>
Popup的 PlacementTarget指向缩放按钮。此时缩放按钮代码如下:
<ToggleButton xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x:Name="PART_ZoomButton" FontSize="16"
Style="{DynamicResource ToggleButton.FontButton}" IsChecked="{TemplateBinding ZoomIsChecked}" Margin="2,0"/>
根据特点1,需要添加依赖属性ZoomRatio用于实时刷新比例,
根据特点2 和特点3 缩放按钮的选中状态需控制,故增加依赖属性 ZoomIsChecked,
同时需要控制Popup的显示是否保持显示状态,故增加依赖属性 ZoomStaysOpen,
在ViewModel中同样需要增加上述属性(非依赖属性)
接着对MSearchText使用处建立绑定如下:
<controls:MSearchText Grid.Column="1" Watermark="搜索或输入Web地址" Text="{Binding CurrentUrl, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" ZoomLevelType="{Binding ZoomLevelType}" ZoomRatio="{Binding ZoomRatio}" ZoomIsChecked="{Binding ZoomIsChecked}" ZoomStaysOpen="{Binding ZoomStaysOpen}" KeyDown="Search_OnKeyDown"/>
4、后端代码控制
扩展SetSearchZoomStatus方法,增加对选中状态及显示比例(显示比例做了简单处理,并不完全正确)的控制
private void SetSearchZoomStatus() { if (CefWebBrowser.ZoomLevel < 0) { ViewModel.ZoomLevelType = ZoomType.Out; ViewModel.ZoomIsChecked = true; if (CefWebBrowser.ZoomLevel > -1) { ViewModel.ZoomRatio = "90%"; } else if (CefWebBrowser.ZoomLevel <= 1) { var radio = Math.Round((CefWebBrowser.ZoomLevel + 5) / 5 * 100); ViewModel.ZoomRatio = $"{radio}%"; } } else if (CefWebBrowser.ZoomLevel > 0) { ViewModel.ZoomLevelType = ZoomType.In; ViewModel.ZoomIsChecked = true; var radio = Math.Round((1 + CefWebBrowser.ZoomLevel) * 100, 2); ViewModel.ZoomRatio = $"{radio}%"; } else { ViewModel.ZoomLevelType = ZoomType.None; ViewModel.ZoomIsChecked = false; } }
接着增加定时器,在鼠标滑轮放大时启动定时器,用于判断Popup是否消失,
此处用一变量_zoomWaitingCount判断是否隐藏,如持续滚动滑动则_zoomWaitingCount重新计数
private void CefWebBrowser_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { if ((Keyboard.Modifiers & ModifierKeys.Control) != ModifierKeys.Control) { ViewModel.ZoomStaysOpen = false; return; } try { _zoomWaitingCount = 0; if (e.Delta > 0) { if (this.CefWebBrowser.ZoomLevel < 4) { CefWebBrowser.ZoomInCommand.Execute(null); } ViewModel.ZoomStaysOpen = true; } else if (e.Delta < 0) { if (this.CefWebBrowser.ZoomLevel > -4) { CefWebBrowser.ZoomOutCommand.Execute(null); } ViewModel.ZoomStaysOpen = true; } _zoomToolTimer.Elapsed -= ZoomToolTimer_Elapsed; _zoomToolTimer.Elapsed += ZoomToolTimer_Elapsed; _zoomToolTimer.AutoReset = true; _zoomToolTimer.Enabled = true; SetSearchZoomStatus(); e.Handled = true; } catch (Exception ex) { } } private void ZoomToolTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (_zoomWaitingCount > 2) { _zoomToolTimer?.Stop(); ViewModel.ZoomIsChecked = false; ViewModel.ZoomStaysOpen = false; _zoomWaitingCount = -1; return; } if (_zoomWaitingCount > -1) { _zoomWaitingCount++; } }
运行效果:
小弹窗按钮命令绑定这里不再赘述,详情请查看代码