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

来源:互联网 发布:网络安全管理考试试题 编辑:程序博客网 时间:2024/06/06 09:29

问题产生原因:若设置窗体为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

1 0