WebBrowser 内容保存为图片

概述

最近在Winform的开发中用到了Flash动态图表FusionCharts Free,这是个开源的flash组件。商业版可以使用FusionCharts V3,免费版本的是FusionCharts Free v2.2。下载地址:http://www.fusioncharts.com/free/download/。大家可以去看看,效果还是非常炫的。商业版比免费版能够提供更多的图表,导出pdf,image,csv等功能,当然免费版这些功能大家就别指望了。

一般flash组件都是以flash的形式在网页中呈现的。因此如果要在Winform中Flash图表个人认为有两种方案。1. 利用WebBrowser控件,将url执行包含这个flash的网页。2.利用Flash的com组件shockwave Flash。第一种方式实现方式比较简单,第二种个人认为最好的是有Flex的组件作为容器,这样可以根据传递进来的参数显示不同的图表。

因为免费版没有导出pdf,image,csv等功能,所以只好自己去写了。而且是加载到WebBrowser控件,因此我对WebBrowser进行了扩展。目前常用的Flash图表都可以展示,导出pdf,image,excel,等格式。

相关图片预览

先上几张图片给大家一个直观点的认识

  

1.导出的图片


                图2.导出的pdf

遇到的问题

1.          如标题所说的关于WebBrowser.DrawToBitmap问题,因为此控件是没有这个方法的,但是你用了也不会出错,但是问题就来了,有时候可以导出图片有时候又不能,加载的网页里面不存在Ajax内容之类的。网上有不少对此问题的解决办法,但是所见之处基本都是错误的。一种普遍的做法如下:

代码
复制代码
public void WriteBmp( string bmpPath)
        {
           
while (webbrowser.ReadyState != WebBrowserReadyState.Complete)
            {
                Application.DoEvents();
            }
            System.Drawing.Rectangle r
= new System.Drawing.Rectangle(Point.Empty,
               
new Size( int .Parse(webbrowser.Document.Body.GetAttribute( " scrollWidth " )), int .Parse(webbrowser.Document.Body.GetAttribute( " scrollHeight " ))));
            Bitmap bmp
= new Bitmap(r.Width, r.Height);
            webbrowser.DrawToBitmap(bmp, r);
            bmp.Save(bmpPath);
            bmp.Dispose();
        }
复制代码

  结果就导致了时而可以时而不可以的问题。对这个问题,国外的站点有不错的解决方法:
  1.http://bytes.com/topic/c-sharp/answers/605264-taking-screenshot-webbrowser-tab
  2. http://efreedom.com/Question/1-2434156/WebBrowser-DrawToBitmap-Methods

    根据上面的方法,我将代码列出来给大家供参考,以上两种方法我用过了效果都很棒(上面的截图就是这样生成的):

代码
复制代码
[DllImport( " user32.dll " )]
       
private static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);

       
public void WriteBmp( string bmpPath)
        {

           
int screenWidth = webbrowser.Document.Body.ScrollRectangle.Width;
           
int screenHeight = webbrowser.Document.Body.ScrollRectangle.Height;

            IntPtr myIntptr
= webbrowser.Handle;
           
int hwndInt = myIntptr.ToInt32();
            IntPtr hwnd
= myIntptr;

           
// Set hdc to the bitmap

            Bitmap bm
= new Bitmap(screenWidth, screenHeight);
            Graphics g
= Graphics.FromImage(bm);
            IntPtr hdc
= g.GetHdc();

           
// Snapshot the WebBrowser

           
bool result = PrintWindow(hwnd, hdc, 0 );
            g.ReleaseHdc(hdc);
            g.Flush();

           
// Save the bitmap, if successful

           
if (result == true )
                bm.Save(bmpPath);
        }
复制代码

第2种方式:

代码
复制代码
public static class ApiConstants
    {
       
public const int SRCCOPY = 13369376 ;
    }

   
public static class Utilities
    {
       
public static Image CaptureScreen()
        {
           
return CaptureWindow(User32.GetDesktopWindow());
        }

       
public static Image CaptureWindow(IntPtr handle)
        {

            IntPtr hdcSrc
= User32.GetWindowDC(handle);

            RECT windowRect
= new RECT();
            User32.GetWindowRect(handle,
ref windowRect);

           
int width = windowRect.right - windowRect.left;
           
int height = windowRect.bottom - windowRect.top;

            IntPtr hdcDest
= Gdi32.CreateCompatibleDC(hdcSrc);
            IntPtr hBitmap
= Gdi32.CreateCompatibleBitmap(hdcSrc, width, height);

            IntPtr hOld
= Gdi32.SelectObject(hdcDest, hBitmap);
            Gdi32.BitBlt(hdcDest,
0 , 0 , width, height, hdcSrc, 0 , 0 , ApiConstants.SRCCOPY);
            Gdi32.SelectObject(hdcDest, hOld);
            Gdi32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle, hdcSrc);

            Image image
= Image.FromHbitmap(hBitmap);
            Gdi32.DeleteObject(hBitmap);

           
return image;
        }
    }

   
public static class User32
    {
        [DllImport(
" user32.dll " )]
       
public static extern IntPtr GetDesktopWindow();
        [DllImport(
" user32.dll " )]
       
public static extern IntPtr GetWindowDC(IntPtr hWnd);
        [DllImport(
" user32.dll " )]
       
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
        [DllImport(
" user32.dll " )]
       
public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
    }

   
public class Gdi32
    {
        [DllImport(
" gdi32.dll " )]
       
public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjectSource, int nXSrc, int nYSrc, int dwRop);
        [DllImport(
" gdi32.dll " )]
       
public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, int nHeight);
        [DllImport(
" gdi32.dll " )]
       
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
        [DllImport(
" gdi32.dll " )]
       
public static extern bool DeleteDC(IntPtr hDC);
        [DllImport(
" gdi32.dll " )]
       
public static extern bool DeleteObject(IntPtr hObject);
        [DllImport(
" gdi32.dll " )]
       
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
    }

    [StructLayout(LayoutKind.Sequential)]
   
public struct RECT
    {
       
public int left;
       
public int top;
       
public int right;
       
public int bottom;
    }

   
// 如果是.net的扩展方法,如果你.net库版本比较高就去掉注释
   
// public static class ControlExtensions
   
// {
   
//     public static Image DrawToImage(this Control control)
   
//     {
   
//         return Utilities.CaptureWindow(control.Handle);
   
//     }
   
// }
复制代码

2.关于导出pdf的问题,大家可以去下载itextsharp开源的组件,学习文档可以参考

  1. http://itextpdf.com/book/examples.phpjava版的

  2. http://www.cnblogs.com/islands/archive/2008/06/27/1231288.html

小结

         以上是自己在Flash动态图表开发中一点小小的心得,写出来和大家一起分享,本文的目的给遇到类似问题的朋友一种解决方案,在你搜索完google,再搜索baidu发现都不能解决你问题的时候,或许此文能给你点帮助。

作者: Jackhuclan
出处: http://jackhuclan.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值