• 关于WebBrowser.DrawToBitmap


    概述

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

    一般flash组件都是以flash的形式在网页中呈现的。因此如果要在WinformFlash图表个人认为有两种方案。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, 
    00, width, height, hdcSrc, 00, 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/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    空间距离计算
    一种支持多种并行环境的栅格地理计算并行算子
    发布或重启线上服务时抖动问题解决方案
    jetty9优化的两处地方
    mysql空间扩展 VS PostGIS
    多流向算法GPU并行化
    GDAL并行I/O
    深入浅出空间索引:2
    深入浅出空间索引:为什么需要空间索引
    virtualBox中的centOS虚拟机硬盘扩容
  • 原文地址:https://www.cnblogs.com/jackhuclan/p/1909301.html
Copyright © 2020-2023  润新知