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

news2024/11/16 2:25:02

最近有小伙伴需要在不规则窗体上放置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控件。

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

WebBrowser control on transparent WPF window | Microsoft Learn

Technology Regions Overview - WPF .NET Framework | Microsoft Learn

这里提供三个解决办法

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上的一个老哥,链接如下:

xaml - How do I work around the ActiveX WebBrowser flaw in a WPF Window that AllowsTransparency=true - Stack Overflow

  • 首先我们新建一个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即可。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2130312.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【CTF Web】BUUCTF BUU UPLOAD COURSE 1 Writeup(文件上传+PHP+文件包含漏洞)

BUU UPLOAD COURSE 1 1 上课用~ 点击启动靶机。 解法 疑似存在文件包含漏洞。 http://15a5666e-1796-4f76-b892-0b69cf97df8e.node5.buuoj.cn:81/index.php?fileupload.php查看网页源代码。判断是后端检查。 <!DOCTYPE html> <html lang"zh-cn"> &…

区块链Dapp开发:质押挖矿的各模式开发详解

质押挖矿是区块链去中心化金融&#xff08;DeFi&#xff09;生态系统中的核心部分&#xff0c;吸引了大量用户参与。随着Dapp&#xff08;去中心化应用&#xff09;的普及&#xff0c;质押挖矿的模式多样化发展&#xff0c;不同模式各有其优点和风险。本文将介绍质押挖矿的基本…

SpringBoot快速接入OpenAI大模型(JDK8)

使用AI4J快速接入OpenAI大模型 本博文给大家介绍一下如何使用AI4J快速接入OpenAI大模型&#xff0c;并且如何实现流式与非流式的输出&#xff0c;以及对函数调用的使用。 介绍 由于SpringAI需要使用JDK17和Spring Boot3&#xff0c;但是目前很多应用依旧使用的JDK8版本&…

计算机毕业设计选题推荐-校园车辆管理系统-Java/Python项目实战(亮点:数据可视化分析、账号锁定)

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

最新版微服务项目搭建

一&#xff0c;项目总体介绍 在本项目中&#xff0c;我将使用alibabba的 nacos 作为项目的注册中心&#xff0c;使用 spring cloud gateway 做为项目的网关&#xff0c;用 openfeign 作为服务间的调用组件。 项目总体架构图如下&#xff1a; 注意&#xff1a;我的Java环境是17…

C语言-数据结构 弗洛伊德算法(Floyd)邻接矩阵存储

弗洛伊德算法相比迪杰斯特拉相似的地方都是遍历邻接矩阵不断调整最短路径的信息&#xff0c;并且两种算法面对多源最短路径的时间复杂度都是O(n^3)&#xff0c;Floyd采用的是动态规划而Dijkstra是采用贪心的思想。在Floyd中我们将创建两个数组进行辅助&#xff0c;一个path二维…

swift qwen2-vl推理及加载lora使用案例

参考: https://swift.readthedocs.io/zh-cn/latest/Instruction/LLM%E5%BE%AE%E8%B0%83%E6%96%87%E6%A1%A3.html#%E5%BE%AE%E8%B0%83%E5%90%8E%E6%A8%A1%E5%9E%8B https://blog.csdn.net/weixin_42357472/article/details/142150209 SWIFT支持300+ LLM和50+ MLLM(多模态大模型…

MySQL主从同步延时高问题排查

文章目录 背景数据库性能指标1、sysbench工具安装1.1、yum方式在线安装1.2、离线安装1.3、sysbench简介 2、主从延时过高问题排查流程2.1、登录从库查看从库状态、事务及相关进程2.2、查看服务器磁盘、cpu等信息2.3、使用fio命令压测数据盘性能2.3.1、安装fio工具2.3.2、执行磁…

element-plus组件问题汇总

element-plus组件问题汇总 一、el-select 1. 下拉选项实现添加全部 问题描述&#xff1a;value为空时&#xff0c;select框中不显示全部选项&#xff0c;但是下拉列表中全部显示是勾选状态 图片&#xff1a; 解决办法&#xff1a;添加 :empty-values“[null, undefined]” …

基于Java+Mysql实现(WEB)宿舍管理系统

数据库实践课程之宿舍管理系统 一、系统需求分析 1.1 系统描述 随着社会的发展以及教育水平的提高&#xff0c;当今社会在校生的数量越来越庞大&#xff0c;使用传统的方式对学生的信息进行管理效率非常低下。在互联网技术高度发达的今天&#xff0c;使用数据库技术对学生的…

Golang | Leetcode Golang题解之第400题第N位数字

题目&#xff1a; 题解&#xff1a; func findNthDigit(n int) int {d : 1for count : 9; n > d*count; count * 10 {n - d * countd}index : n - 1start : int(math.Pow10(d - 1))num : start index/ddigitIndex : index % dreturn num / int(math.Pow10(d-digitIndex-1)…

Redis高可用,Redis性能管理

文章目录 一&#xff0c;Redis高可用&#xff0c;Redis性能管理二&#xff0c;Redis持久化1.RDB持久化1.1触发条件&#xff08;1&#xff09;手动触发&#xff08;2&#xff09;自动触发 1.2 Redis 的 RDB 持久化配置1.3 RDB执行流程(1) 判断是否有其他持久化操作在执行(2) 父进…

Unity开发一个FPS游戏之五

这个系列的前几篇文章介绍了如何从头开始用Unity开发一个FPS游戏&#xff0c;感兴趣的朋友可以回顾一下。这个系列的文章如下&#xff1a; Unity开发一个FPS游戏_unity 模仿开发fps 游戏-CSDN博客 Unity开发一个FPS游戏之二_unity 模仿开发fps 游戏-CSDN博客 Unity开发一个F…

828华为云征文|华为云Flexus X服务器centos挂载新增的磁盘教程

华为云Flexus X服务器推荐公司、企事业单位及生产环境使用&#xff0c;特别注重安全和稳定性 &#x1f680;【828华为云盛典&#xff0c;Flexus X引领算力新纪元&#xff01;】&#x1f680; 在数字化转型的征途中&#xff0c;数据安全是企业最坚实的后盾。华为云Flexus X实例…

中关村科金推出得助音视频鸿蒙SDK,助力金融业务系统鸿蒙化提速

鸿蒙生态大势所趋&#xff0c;各种应用适配加速 近日&#xff0c;华为纯血鸿蒙系统&#xff08;HarmonyOS NEXT&#xff09;再度引发市场高度关注。据媒体消息&#xff0c;鸿蒙NEXT Beta版将在9月24日对Mate 60系列、X5系列、Pura70系列等16款旗舰机型进行推送&#xff0c;这已…

春招审核流程优化:Spring Boot系统设计

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理大学生入学审核系统的相关信息成为必然。开…

Arcgis实现面空间位置从东至西从南至北排序

效果 背景 工作项目中经常会遇到需要对网格进行编号,而编号是有一定原则的,比如空间位置从上到下从左到右,或者其它原则,那么都可以通过下面的方式来实现 1、准备数据 点shp文件,查看初始FID字段标注,目前是一个无序的状态 2、排序 字段选择空间字段,空间排序方法…

业务流程建模(BPM)的重要性及其应用

什么是业务流程建模&#xff08;BPM&#xff09;&#xff1f; 业务流程建模&#xff08;BPM&#xff09;是对企业内各项业务流程进行图形化描述的一种方法。它旨在通过可视化的方式帮助企业理解和分析现有的业务流程&#xff0c;从而发现潜在的问题并进行改进。BPM通常采用流程…

Linux学习-Docker文件系统

Overlayfs Overlayfs 是一种类似 aufs 的一种堆叠文件系统&#xff0c;于 2014 年正式合入 Linux-3.18 主线内核&#xff0c;目前其功能已经基本稳定&#xff08;虽然还存在一些特性尚未实现&#xff09;且被逐渐推广。 Overlayfs 是一种堆叠文件系统&#xff0c;它依赖并建立…

stm32 IIC总线busy解决方法

参考博客&#xff1a; https://blog.csdn.net/PP_hui/article/details/112229696 1------这是IIC的初始化代码&#xff1a; #include "i2c.h"/* USER CODE BEGIN 0 */ // #define __HAL_AFIO_REMAP_I2C1_ENABLE() AFIO_REMAP_ENABLE(AFIO_MAPR_I2C1_REMAP) /* USE…