首先先看一下效果图:
本实现是基于WPF,VS版本2008 SP1。
先说一下在Winform中的实现方法:很简单通过设置窗体的opacity来实现,或者还可以设置TransparentKey来实现某种颜色透明。但是在WPF中则如何实现呢?
通过设置窗体的opacity,那么得到结果就是webbrowser整体消失了。因为这里面涉及到WPF中“空域”的问题,相关的文章如下:
http://blogs.msdn.com/changov/archive/2009/01/19/webbrowser-control-on-transparent-wpf-window.aspx
由此看来通过直接设置透明度的方法是不行了,那么回到原来的问题,“将浏览器窗体背景成透明”,其实这里的透明只是一个视觉上的感觉,就是浏览器中网页的背景和整个窗体的背景想融合就可以。看到这里,各位看官可能已经想到了,将浏览器中页面的背景绘制成被浏览器控件所覆盖出的背景就可以了。确实,我的实现也是依照这种思路走的。
这里主要用到了两个技术:
l Mshtml操作网页中元素,通过给body标签添加行为来实现背景的绘制。
Code
[ComVisible(true), Guid("0015EC28-C85F-49a8-9B1A-DC91E6345274"),
ClassInterface(ClassInterfaceType.AutoDispatch)]
public class MyGadgetBodyBehavior : IElementBehavior, IHTMLPainter
{
public delegate void SizeChangedEventHandler(SizeChangedEventArgs e);
public event SizeChangedEventHandler onSizeChangedEvent;
private AppScreenSnapHelper snapHelper;
下面是绘制部分的代码
Code
public void Draw(RECT rcBounds, RECT rcUpdates, int lDrawFlags, IntPtr hdc, IntPtr pvDrawObject)
{
Graphics g = Graphics.FromHdc(hdc);
Bitmap buffer = new Bitmap(width, height);
Graphics gBuffer = Graphics.FromImage(buffer);
AppScreenSnapHelper.Image image = snapHelper.GetScreenSnap();
gBuffer.DrawImage(image.Bitmap, 0, 0);
image.Dispose();
string imageSrc = ((IHTMLElement2)body).currentStyle.backgroundImage;
if (!string.IsNullOrEmpty(imageSrc))
{
Match match = Regex.Match(imageSrc, @"url\(""file:///(?<path>.*)""\)");
if (match.Success)
{
imageSrc = match.Groups["path"].Value;
using (Bitmap bitmap = new Bitmap(imageSrc))
{
object obj = ((IHTMLElement2)body).currentStyle.marginLeft;
gBuffer.DrawImage(bitmap, new Rectangle(0, 0, width, height));
}
}
}
g.DrawImage(buffer, rcUpdates.left, rcUpdates.top,
new Rectangle(rcUpdates.left - rcBounds.left,
rcUpdates.top - rcBounds.top, rcUpdates.right - rcUpdates.left,
rcUpdates.bottom - rcUpdates.top), GraphicsUnit.Pixel);
buffer.Dispose();
gBuffer.Dispose();
g.Dispose();
}
l RenderTargetBitmap类用来给应用程序截图:
Code
internal Image GetScreenSnap(bool isForceRefresh)
{
if (CheckPositionAndSize() && !isForceRefresh)
{
return screenImage;
}
control.Visibility = Visibility.Hidden;
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)parentWindow.Width,
(int)parentWindow.Width, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(parentWindow);
BitmapSource bitmapSource = bitmap.CloneCurrentValue();
Bitmap newBitmap = ConvertSourceImageToBitmap(bitmapSource);
newBitmap = ClipBitmap(newBitmap, new System.Drawing.Rectangle((int)oldPoint.X, (int)oldPoint.Y,
((int)control.Width == 0 ? 1 : (int)control.Width), ((int)control.Height) == 0 ? 1 : (int)control.Height));
control.Visibility = Visibility.Visible;
screenImage = new Image(newBitmap, imagePtr);
return screenImage;
}
在截图的时候这里使用了一个技巧就是,先将控件隐藏,然后截图,最后恢复控件的显示。
最后说一下本实现的一些缺陷:
- 如果将应用程序的背景设置为透明,则浏览器的背景将呈现白色,因为本实现使用的是应用程序的背景来进行截图,如果应用程序背景被透明,则截图得到的也是一张透明的图片,绘制到页面上后并不能达到透明的效果。如果想在这种情况下实现透明,可以考虑对桌面背景进行截图。
- 如果网页过大出现滚动条,那么网页中未呈现的部分并不能透明,因为截图只能作用于已经显示的部分。所以本实现用于显示本地控制好大小的html页面有比较好的效果。
具体项目下载如下:
/Files/chinese-zmm/TransportWebBrowserDemo.rar