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