首页 > 其他分享 >WPF创建不规则窗体时WebBrowser控件不显示的问题

WPF创建不规则窗体时WebBrowser控件不显示的问题

时间:2024-09-11 15:47:00浏览次数:10  
标签:控件 Windows System WebBrowser webBrowserOverlayWindow using 窗体 TargetElement

最近有小伙伴需要在不规则窗体上放置WebBrowser控件,因为设置了WindowStyle="None" 和 AllowsTransparency="True"。

导致WebBrowser控件不显示。

 

界面代码如下所示:

 1 <Window x:Class="WebBrowserDemo.MainWindow"     
 3         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 4         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:WebBrowserDemo"
 7         mc:Ignorable="d"
 8         Height="979" Width="1259"
 9         WindowStyle="None" ResizeMode="NoResize" Background="Transparent" AllowsTransparency="True"
10         MouseLeftButtonDown="Window_MouseLeftButtonDown" Loaded="Window_Loaded">
11     <Canvas>
12         <Image Source="background.png" Stretch="Fill" Width="1259" Height="979" />
13         <WebBrowser x:Name="webBrowser" Width="521" Height="635" Canvas.Left="58" Canvas.Top="198" Address="https://www.baidu.com" HorizontalAlignment="Left" VerticalAlignment="Center"></cef:ChromiumWebBrowser>
14     </Canvas>
15 </Window>

 

预期效果如下:

 

但实际浏览器并不会显示出来。

 

导致这个问题的原因是因为空域(airspace)问题,因为WebBrowser并不是一个原生的WPF控件,而是一个Win32控件。

详细描述可以参考以下两个链接:

https://learn.microsoft.com/en-us/archive/blogs/changov/webbrowser-control-on-transparent-wpf-window

https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/technology-regions-overview?view=netframeworkdesktop-4.8&redirectedfrom=MSDN

 

这里提供三个解决办法

1、将WebBrowser控件替换为CefSharp/WebView2等控件

这种方法最简单,几乎不用修改什么代码,缺点是老版本系统可能不兼容。

 

2、使用WindowsChrome

1 <WindowChrome.WindowChrome>
2        <WindowChrome GlassFrameThickness="-1"/>
3 </WindowChrome.WindowChrome>

需要配合 ResizeMode="CanMinimize" Background="Transparent" WindowStyle="None" 使用

完整界面代码如下:

 1 <Window x:Class="WebBrowserDemo.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:WebBrowserDemo"
 7         mc:Ignorable="d"
 8         ResizeMode="CanMinimize" Background="Transparent" WindowStyle="None" Height="979" Width="1259">
 9     <WindowChrome.WindowChrome>
10         <WindowChrome GlassFrameThickness="-1"/>
11     </WindowChrome.WindowChrome>
12     <Canvas>
13         <Canvas.Background>
14             <ImageBrush ImageSource="background.png" Stretch="Uniform"></ImageBrush>
15         </Canvas.Background>
16         <WebBrowser x:Name="webBrowser" Width="527" Height="501" Canvas.Left="54" Canvas.Top="249" Source="https://bing.com" HorizontalAlignment="Center" VerticalAlignment="Top"></WebBrowser>
17     </Canvas>
18 </Window>

 

3、将WebBrowser封装到一个独立的窗口,变成独立控件

这个方法来自stackoverflow上的一个老哥,链接如下:

https://stackoverflow.com/questions/23529824/how-do-i-work-around-the-activex-webbrowser-flaw-in-a-wpf-window-that-allowstran

 

  • 首先我们新建一个Window

          WebBrowserEx.xaml

 1 <Window x:Class="WebBrowserDemo.Controls.WebBrowserEx"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:WebBrowserDemo.Controls"
 7         xmlns:winForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"     
 8         WindowStyle="None"
 9         ShowInTaskbar="False"
10         ResizeMode="NoResize"  Width="761" Height="444">
11     <WindowsFormsHost x:Name="wfh">
12         <winForms:WebBrowser x:Name="wfBrowser" />
13     </WindowsFormsHost>
14 </Window>

 

  • 后台代码如下

          WebBrowserEx.xaml.cs

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6 using System.Windows;
  7 using System.Windows.Controls;
  8 using System.Windows.Data;
  9 using System.Windows.Documents;
 10 using System.Windows.Input;
 11 using System.Windows.Media;
 12 using System.Windows.Media.Imaging;
 13 using System.Windows.Shapes;
 14 
 15 namespace WebBrowserDemo.Controls
 16 {
 17     public partial class WebBrowserEx : Window
 18     {
 19         public WebBrowserEx()
 20         {
 21             InitializeComponent();
 22         }
 23 
 24         public static readonly DependencyProperty TargetElementProperty = DependencyProperty.Register("TargetElement", typeof(FrameworkElement), typeof(WebBrowserEx), new PropertyMetadata(TargetElementPropertyChanged));
 25         public FrameworkElement TargetElement
 26         {
 27             get
 28             {
 29                 return GetValue(TargetElementProperty) as FrameworkElement;
 30             }
 31             set
 32             {
 33                 SetValue(TargetElementProperty, value);
 34             }
 35         }
 36 
 37 
 38         public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(string), typeof(WebBrowserEx), new PropertyMetadata(SourcePropertyChanged));
 39         public string Source
 40         {
 41             get
 42             {
 43                 return GetValue(SourceProperty) as string;
 44             }
 45             set
 46             {
 47                 SetValue(SourceProperty, value);
 48             }
 49         }
 50         private static void SourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
 51         {
 52             var webBrowserOverlayWindow = sender as WebBrowserEx;
 53 
 54             if (webBrowserOverlayWindow != null)
 55             {
 56                 webBrowserOverlayWindow.wfBrowser.Navigate(args.NewValue as string);
 57             }
 58         }
 59 
 60         private static void TargetElementPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
 61         {
 62             var oldTargetElement = args.OldValue as FrameworkElement;
 63             var webBrowserOverlayWindow = sender as WebBrowserEx;
 64             var mainWindow = Window.GetWindow(webBrowserOverlayWindow.TargetElement);
 65 
 66             if (webBrowserOverlayWindow != null && mainWindow != null)
 67             {
 68                 webBrowserOverlayWindow.Owner = mainWindow;
 69                 webBrowserOverlayWindow.Owner.LocationChanged += webBrowserOverlayWindow.PositionAndResize;
 70                 webBrowserOverlayWindow.TargetElement.LayoutUpdated += webBrowserOverlayWindow.PositionAndResize;
 71 
 72                 if (oldTargetElement != null)
 73                     oldTargetElement.LayoutUpdated -= webBrowserOverlayWindow.PositionAndResize;
 74 
 75                 webBrowserOverlayWindow.PositionAndResize(sender, new EventArgs());
 76 
 77                 if (webBrowserOverlayWindow.TargetElement.IsVisible && webBrowserOverlayWindow.Owner.IsVisible)
 78                 {
 79                     webBrowserOverlayWindow.Show();
 80                 }
 81 
 82                 webBrowserOverlayWindow.TargetElement.IsVisibleChanged += (x, y) =>
 83                 {
 84                     if (webBrowserOverlayWindow.TargetElement.IsVisible && webBrowserOverlayWindow.Owner.IsVisible)
 85                     {
 86                         webBrowserOverlayWindow.Show();
 87                     }
 88                     else
 89                     {
 90                         webBrowserOverlayWindow.Hide();
 91                     }
 92                 };
 93             }
 94         }
 95 
 96         protected override void OnClosed(EventArgs e)
 97         {
 98             base.OnClosed(e);
 99 
100             Owner.LocationChanged -= PositionAndResize;
101             if (TargetElement != null)
102             {
103                 TargetElement.LayoutUpdated -= PositionAndResize;
104             }
105         }
106 
107         private void PositionAndResize(object sender, EventArgs e)
108         {
109             if (TargetElement != null && TargetElement.IsVisible)
110             {
111                 var point = TargetElement.PointToScreen(new Point());
112                 Left = point.X + 396;  //这里可以控制位置
113                 Top = point.Y + 326;   //point是左上角0,0的位置
114 
115                 //Height = TargetElement.ActualHeight;  //这里可以控制宽高
116                 //Width = TargetElement.ActualWidth;
117             }
118         }
119 
120     }
121 }

 

  • 然后我们新建一个自定义控件

          CustomWebBrowser.cs

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Windows;
 7 using System.Windows.Controls;
 8 using System.Windows.Data;
 9 using System.Windows.Documents;
10 using System.Windows.Input;
11 using System.Windows.Media;
12 using System.Windows.Media.Imaging;
13 using System.Windows.Navigation;
14 using System.Windows.Shapes;
15 
16 namespace WebBrowserDemo.Controls
17 {
18     public class CustomWebBrowser : Control
19     {
20 
21         private WebBrowserEx _WebBrowserOverlayWindow;
22         public static readonly DependencyProperty TargetElementProperty = DependencyProperty.Register("TargetElement", typeof(FrameworkElement), typeof(CustomWebBrowser), new PropertyMetadata(TargetElementPropertyChanged));
23         public FrameworkElement TargetElement
24         {
25             get
26             {
27                 return GetValue(TargetElementProperty) as FrameworkElement;
28             }
29             set
30             {
31                 SetValue(TargetElementProperty, value);
32             }
33         }
34 
35         public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(string), typeof(CustomWebBrowser), new PropertyMetadata(SourcePropertyChanged));
36         public string Source
37         {
38             get
39             {
40                 return GetValue(SourceProperty) as string;
41             }
42             set
43             {
44                 SetValue(SourceProperty, value);
45             }
46         }
47 
48         private static void SourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
49         {
50             var transparentWebBrowser = sender as CustomWebBrowser;
51             if (transparentWebBrowser != null)
52             {
53                 transparentWebBrowser._WebBrowserOverlayWindow.Source = args.NewValue as string;
54             }
55         }
56 
57         private static void TargetElementPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
58         {
59             var transparentWebBrowser = sender as CustomWebBrowser;
60             if (transparentWebBrowser != null)
61             {
62                 transparentWebBrowser._WebBrowserOverlayWindow.TargetElement = args.NewValue as FrameworkElement;
63             }
64         }
65 
66         public CustomWebBrowser()
67         {
68             _WebBrowserOverlayWindow = new WebBrowserEx();
69         }
70 
71         static CustomWebBrowser()
72         {
73             DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomWebBrowser), new FrameworkPropertyMetadata(typeof(CustomWebBrowser)));
74         }
75     }
76 }

 

  • 自定义控件样式如下
 1  <Style TargetType="{x:Type local:CustomWebBrowser}">
 2      <Setter Property="Template">
 3          <Setter.Value>
 4              <ControlTemplate TargetType="{x:Type local:CustomWebBrowser}">
 5                  <Border Background="{TemplateBinding Background}"
 6                          BorderBrush="{TemplateBinding BorderBrush}"
 7                          BorderThickness="{TemplateBinding BorderThickness}">
 8                  </Border>
 9              </ControlTemplate>
10          </Setter.Value>
11      </Setter>
12  </Style>

 

  • 使用时将WebBrowser控件换成CustomWebBrowser即可。

标签:控件,Windows,System,WebBrowser,webBrowserOverlayWindow,using,窗体,TargetElement
From: https://www.cnblogs.com/zhaotianff/p/18408345

相关文章

  • python中Tkinter常用控件含义
    #python中Tkinter常用控件Button'按钮控件;在程序中显示按钮。'Canvas'画布控件;显示图形元素如线条或文本'Checkbutton'多选框控件;用于在程序中提供多项选择框'Entry'输入控件;用于显示简单的文本内容'Frame......
  • 如何用图表控件LightningChart Python实现检测应用?
    LightningChartPython是知名图表控件公司LightningChartLtd正在研发的Python图表,目前还未正式推出,感兴趣的朋友可以戳下方链接申请试用!立即申请LightningChartPython试用什么是结构健康监测(SHM)?结构健康监测(SHM)是指实施结构损伤检测策略的过程,SHM涉及使用传感器和......
  • 界面控件DevExpress中文教程:如何PDF图形对象的可见性?
    DevExpress拥有.NET开发需要的所有平台控件,包含600多个UI控件、报表平台、DevExpressDashboardeXpressApp框架、适用于VisualStudio的CodeRush等一系列辅助工具。屡获大奖的软件开发平台DevExpress近期重要版本v24.1已正式发布,该版本拥有众多新产品和数十个具有高影响力的功......
  • WPF Shape系列控件的详细使用教程
    WPF(WindowsPresentationFoundation)中的Shape控件提供了一系列用于绘制几何形状的元素,如线条、矩形、椭圆、多边形等。这些控件继承自System.Windows.Shapes.Shape基类,具有一致的属性和行为,允许开发者轻松地在应用程序中创建丰富的图形界面。本文将详细介绍WPF中的......
  • visualstudio 工具箱如何批量加载devexpress控件?
     1.DevExpress简单介绍        DevExpress是一套功能强大的‌.NET用户界面控件开发套包,广泛应用于企业内容管理、成本管控、进程监督、生产调度等领域。以下是DevExpress在不同平台和控件中的使用方法:DevExpressWinForms控件的使用方法‌TreeList控件‌:设置Dock属......
  • Winform C# 窗体应用程序简单入门
    搬运来源:https://blog.csdn.net/weixin_46262993/article/details/104169982?spm=1001.2014.3001.5502一、什么是Winform?WinForm是WindowsForm的简称,是基于.NETFramework平台的客户端(PC软件)开发技术,一般使用C#编程。C#WinForm编程需要创建「Windows窗体应用程序」项目......
  • C#学习教程12——Windows窗体应用程序
    搬运来源: https://blog.csdn.net/weixin_46003347/article/details/123327620文章目录12.Windows窗体应用程序12.1创建Windows窗体应用程序12.2窗体属性12.3窗体事件12.4窗体方法12.5McssageBox:消息框12.6控件12.7Label和LinkLabel:标签控件12.8TextBox:文本框控件12.9Bu......
  • [SDK]-菜单 和 树控件
    前言各位师傅大家好,我是qmx_07,今天给大家讲解菜单和树控件的相关知识菜单认识菜单及创建自定义菜单栏资源文件->项目名.rc->Menu这是系统提供的默认菜单,也可以往里面添加修改内容以下是自定义菜单栏:创建视图,修改菜单选项,需要绑定到注册窗口通过创建自定义视......
  • 【Qt】解决设置QPlainTextEdit控件的Tab为4个空格
    前言PyQt5是一个用于创建跨平台桌面应用程序的Python绑定集合,它提供了对Qt应用程序框架的访问。用于开发具有图形用户界面(GUI)的应用程序,以及非GUI程序。PyQt5使得Python开发者可以使用Qt的丰富功能来构建应用程序。QPlainTextEdit是Qt框架中的一个纯文本编辑器......
  • 河南省12123公安厅临牌打印如何下载打印控件
    公安交通管理综合应用平台打印控件安装失败,河南省公安厅临牌打印如何下载打印控件,12123临牌系统怎么安装打印控件?   关于“12123河南省公安厅临牌打印如何下载打印控件怎么安装打印控件”的问题,实际上,交管12123APP主要用于在线申请临时号牌、查询车辆信息、处理交通违......