WPF中去边框窗体与WebBrowser控件的兼容问题解决办法

问题产生原因:若设置窗体为AllowsTransparency="True",WindowStyle="None",内嵌的WebBrowser就无法显示了,但它加载的网页内容还能正常交互。

解决方案:

通过google,找到了如下的WPF窗体文件,并对其进行了简单修改。

1.添加一个新窗体,命名为WebBrowserOverlay;

XAML:WebBrowserOverlay.xaml

<Window x:Class="WpfUI.WebBrowserOverlay"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    WindowStyle="None" ShowInTaskbar="False" ResizeMode="NoResize">
    <WebBrowser Name="_wb">

    </WebBrowser>
</Window>
C#:WebBrowserOverlay.xaml.cs
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;


namespace WpfUI
{
    /// <summary>
    /// Displays a WebBrowser control over a given placement target element in a WPF Window.
    /// The owner window can be transparent, but not this one, due mixing DirectX and GDI drawing. 
    /// WebBrowserOverlayWF uses WinForms to avoid this limitation.
    /// </summary>
    public partial class WebBrowserOverlay : Window
    {
        FrameworkElement _placementTarget;


        public WebBrowser WebBrowser { get { return _wb; } }


        public WebBrowserOverlay(FrameworkElement placementTarget)
        {
            InitializeComponent();


            _placementTarget = placementTarget;
            Window owner = Window.GetWindow(placementTarget);
            Debug.Assert(owner != null);


            //owner.SizeChanged += delegate { OnSizeLocationChanged(); };
            owner.LocationChanged += delegate { OnSizeLocationChanged(); };
            _placementTarget.SizeChanged += delegate { OnSizeLocationChanged(); };


            if (owner.IsVisible)
            {
                Owner = owner;
                Show();
            }
            else
                owner.IsVisibleChanged += delegate
                {
                    if (owner.IsVisible)
                    {
                        Owner = owner;
                        Show();
                    }
                };


            //owner.LayoutUpdated += new EventHandler(OnOwnerLayoutUpdated);
        }


        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            base.OnClosing(e);
            if (!e.Cancel)
                // Delayed call to avoid crash due to Window bug.
                Dispatcher.BeginInvoke((Action)delegate
                {
                    Owner.Close();
                });
        }


        void OnSizeLocationChanged()
        {
            Point offset = _placementTarget.TranslatePoint(new Point(), Owner);
            Point size = new Point(_placementTarget.ActualWidth, _placementTarget.ActualHeight);
            HwndSource hwndSource = (HwndSource)HwndSource.FromVisual(Owner);
            CompositionTarget ct = hwndSource.CompositionTarget;
            offset = ct.TransformToDevice.Transform(offset);
            size = ct.TransformToDevice.Transform(size);


            Win32.POINT screenLocation = new Win32.POINT(offset);
            Win32.ClientToScreen(hwndSource.Handle, ref screenLocation);
            Win32.POINT screenSize = new Win32.POINT(size);


            Win32.MoveWindow(((HwndSource)HwndSource.FromVisual(this)).Handle, screenLocation.X, screenLocation.Y, screenSize.X, screenSize.Y, true);
        }
    }
}

2.在主窗体中加入一个关闭按钮和一个命名为BdBrowser的Border元素,再在BdBrowser中添加一个WebBrowser控件;

	<Grid Background="#FF009D99">
		<Button x:Name="BtnClose" Content="×" Margin="0" Width="30" Height="30" HorizontalAlignment="Right" VerticalAlignment="Top" FontWeight="Bold" FontSize="16" Foreground="#FFCC0000" FontFamily="Arial Black" Focusable="False" Click="BtnClose_Click">
		</Button>
		<Border x:Name="BdBrowser" Margin="0,30,0,0">
			<WebBrowser x:Name="WbBrowser"/>
		</Border>
	</Grid>

3.加载调用。

            var w = new WpfUI.WebBrowserOverlay(BdBrowser);
            var wb = w.WebBrowser;
            wb.Navigate(new System.Uri("http://www.baidu.com/"));

由于WPF中的WebBrowser功能远没有WinForm中的强大,所以我尝试着在WPF中嵌入WinForm的WebBrowser,方案如下(只贴了修改部分的代码,其他同上):

1.添加引用System.Windows.Forms和WindowsFormsIntegration;

2.在WebBrowserOverlay.xaml中嵌入WindowsFormsHost以承载WinForm的WebBrowser控件

<Window x:Class="WpfUI.WebBrowserOverlay"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:wfi ="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
    xmlns:wf ="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
    WindowStyle="None" ShowInTaskbar="False" ResizeMode="NoResize">
    <wfi:WindowsFormsHost x:Name="_wfh">
        <wf:WebBrowser x:Name="_wb"/>
    </wfi:WindowsFormsHost>
</Window>

3.WebBrowserOverlay.xaml.cs中将System.Windows.Controls.WebBrowser替换成System.Windows.Forms.WebBrowser;

        public System.Windows.Forms.WebBrowser WebBrowser { get { return _wb; } }

4.主窗体不做改变,但是我稍微改动了一下,以便后续开发。加了一个TextBox作为地址栏,一个Button作为跳转按钮,功能简略,各位看官可以跳过。

using System.Windows;

namespace WpfUI
{
	/// <summary>
	/// MainWindow.xaml 的交互逻辑
	/// </summary>
    public partial class MainWindow : Window
    {
        private WebBrowserOverlay wbo;
        private System.Windows.Forms.WebBrowser fwb;
        public MainWindow()
        {
            this.InitializeComponent();

            // 在此点下面插入创建对象所需的代码。
            wbo = new WebBrowserOverlay(BdBrowser);
            fwb = wbo.WebBrowser;
            fwb.Navigate(new System.Uri(TbAddress.Text));
        }

        private void BtnClose_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void BtnGo_Click(object sender, RoutedEventArgs e)
        {
            string add = TbAddress.Text;
            fwb.Navigate(new System.Uri(add));
        }

    }
}

源码资源下载:http://download.csdn.net/detail/danding_ge/7167399

参考资源链接:[WPF透明窗体WebBrowser兼容性解决方案](https://wenku.csdn.net/doc/47ms2m0j8r?utm_source=wenku_answer2doc_content) 在WPF开发中,由于WebBrowser控件源自于Windows Forms而不直接支持透明特性,因此需要特殊处理才能在透明窗体中使用。推荐的文章《WPF透明窗体WebBrowser兼容性解决方案》中提出了一个创新的方法,通过创建一个名为`FormsWebBrowser`的工具类,实现了WebBrowser控件WPF透明窗体中的正确显示。 具体步骤包括: 1. 创建`FormsWebBrowser`类,封装WebBrowser控件,处理兼容性问题。 2. 构造函数接收`FrameworkElement`作为WebBrowser控件的放置目标,并获取其所在的`Window`对象。 3. 初始化Windows Forms的`Form`实例,设置不显示在任务栏中,并与WPF窗口透明度同步。 4. 利用`Interop`技术将WebBrowser控件添加到Windows Forms的`Form`中,确保WebBrowser控件位置与WPF目标元素匹配。 5. 提供`WebBrowser`属性,允许开发者调用加载HTML内容等方法。 这一解决方案的关键在于独立的Windows Forms窗体作为WebBrowser控件的承载容器,并通过同步其透明度,使得在视觉上实现了与WPF窗口的透明效果一致。这个工具类在项目实战中非常有用,它不仅解决了兼容性问题,还允许开发者在保持整体设计风格的同时,在透明背景下展示网页内容。 参考资源链接:[WPF透明窗体WebBrowser兼容性解决方案](https://wenku.csdn.net/doc/47ms2m0j8r?utm_source=wenku_answer2doc_content)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

公西雒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值