zoukankan      html  css  js  c++  java
  • 将控件保存为图片

                                            将控件保存为图片

                                                     周银辉

    这里分别提供win form 和 wpf 两种方式

    对于.net 2.0 我们可以简单地利用 BitBlt 函数来实现,非常简单,代码如下:

        public static class ControlToImageConverter
        {
            
    private const Int32 SRCCOPY = 0xCC0020;

            [DllImport(
    "gdi32.dll")]
            
    internal static extern bool BitBlt(
                IntPtr hdcDest, 
    // handle to destination DC
                int nXDest, // x-coord of destination upper-left corner
                int nYDest, // y-coord of destination upper-left corner
                int nWidth, // width of destination rectangle
                int nHeight, // height of destination rectangle
                IntPtr hdcSrc, // handle to source DC
                int nXSrc, // x-coordinate of source upper-left corner
                int nYSrc, // y-coordinate of source upper-left corner
                Int32 dwRop // raster operation code
                );


            
    public static Bitmap GetImageOfControl(Control control)
            {

                var w 
    = control.Size.Width;
                var h 
    = control.Size.Height;

                Graphics gOfCtrl 
    = control.CreateGraphics();
                var bmp 
    = new Bitmap(w, h, gOfCtrl);

                Graphics gOfBmp 
    = Graphics.FromImage(bmp);

                IntPtr dc1 
    = gOfCtrl.GetHdc();
                IntPtr dc2 
    = gOfBmp.GetHdc();

                BitBlt(dc2, 
    00, w, h, dc1, 00, SRCCOPY);

                gOfCtrl.ReleaseHdc(dc1);
                gOfBmp.ReleaseHdc(dc2);

                gOfCtrl.Dispose();
                gOfBmp.Dispose();


                
    return bmp;
            }

        }

    其中 SRCCOPY = 0xCC0020, 表示将源直接拷贝到目标。

    对于WPF,无法获得控件的hdc, 所以不能使用bitblt函数了,但幸运的是,其提供了一个RenderTargetBitmap的类型,可以将控件绘制到改类型的类型是示例上,比如:

    var renderBitmap = 
             
    new RenderTargetBitmap(w, h, 96d,96d, PixelFormats.Pbgra32);

    renderBitmap.Render(controlToConvert);

    其可以直接作为Image控件的源以便显示,如果要将其保存下来(保存到流中),则需要用到BitmapEncoder, 将上面的位图添加到encoder的帧中,然后调用save方法便可。

    包装好的代码如下:

    点击展开
        internal enum ImageType
        {
            Bmp,
            Gif,
            Jpeg,
            Png,
            Tiff,
            Wdp
        }

        
    internal static class ControlToImageConverter
        {

            
    /// <summary>
            
    /// Convert any control to a PngBitmapEncoder
            
    /// </summary>
            
    /// <param name="controlToConvert">The control to convert to an ImageSource</param>
            
    /// <param name="imageType">The image type will indicate the type of return bitmap encoder</param>
            
    /// <returns>The returned ImageSource of the controlToConvert</returns>
            private static BitmapEncoder GetImageFromControl(FrameworkElement controlToConvert, ImageType imageType)
            {

                var bounds 
    = controlToConvert.GetBounds(controlToConvert.Parent as Visual);

                var renderBitmap 
    = new RenderTargetBitmap((Int32)bounds.Width, (Int32)bounds.Height, 96d,
                                                          96d, PixelFormats.Pbgra32);
                renderBitmap.Render(controlToConvert);

                BitmapEncoder encoder 
    = GetBitmapEncoderByImageType(imageType);

                
    // puch rendered bitmap into it
                encoder.Frames.Add(BitmapFrame.Create(renderBitmap));

                
    return encoder;
            }

            
    private static Rect GetBounds(this FrameworkElement element, Visual from)
            {
                Rect rect 
    = Rect.Empty;

                
    try
                {
                    GeneralTransform transform 
    = element.TransformToVisual(from);
                    rect 
    = transform.TransformBounds(new Rect(00, element.ActualWidth, element.ActualHeight));
                    
    // ReSharper disable EmptyGeneralCatchClause
                }
                
    catch
                
    // ReSharper restore EmptyGeneralCatchClause
                {

                }

                
    return rect;
            }

            
    /// <summary>
            
    /// Get an encoder by a specify image type
            
    /// </summary>
            
    /// <param name="type">the image type</param>
            
    /// <returns>return an eccoder</returns>
            private static BitmapEncoder GetBitmapEncoderByImageType(ImageType type)
            {
                
    switch (type)
                {
                    
    case ImageType.Bmp:
                        
    return new BmpBitmapEncoder();
                    
    case ImageType.Gif:
                        
    return new GifBitmapEncoder();
                    
    case ImageType.Jpeg:
                        
    return new JpegBitmapEncoder();
                    
    case ImageType.Png:
                        
    return new PngBitmapEncoder();
                    
    case ImageType.Tiff:
                        
    return new TiffBitmapEncoder();
                    
    case ImageType.Wdp:
                        
    return new WmpBitmapEncoder();
                    
    default:
                        
    return new PngBitmapEncoder();
                }
            }

            
    /// <summary>
            
    /// Get the iamge type by image file name
            
    /// </summary>
            
    /// <param name="fileName">the file name of an image</param>
            
    /// <returns>the iamge type</returns>
            private static ImageType GetImageTypeByFileName(string fileName)
            {
                ImageType returnType 
    = ImageType.Png;

                var extension 
    = Path.GetExtension(fileName);
                
    if (!String.IsNullOrEmpty(extension))
                {
                    
    switch (extension.ToLower())
                    {
                        
    case ".bmp":
                            returnType 
    = ImageType.Bmp;
                            
    break;
                        
    case ".gif":
                            returnType 
    = ImageType.Gif;
                            
    break;
                        
    case ".jpeg":
                        
    case ".jpg":
                        
    case ".jpe":
                        
    case "jfif":
                            returnType 
    = ImageType.Jpeg;
                            
    break;
                        
    case ".png":
                            returnType 
    = ImageType.Png;
                            
    break;
                        
    case ".tiff":
                        
    case ".tif":
                            returnType 
    = ImageType.Tiff;
                            
    break;
                        
    case ".wdp":
                            returnType 
    = ImageType.Wdp;
                            
    break;
                        
    default:
                            returnType 
    = ImageType.Png;
                            
    break;
                    }
                }

                
    return returnType;
            }

            
    /// <summary>
            
    /// Get an ImageSource of a control
            
    /// </summary>
            
    /// <param name="controlToConvert">The control to convert to an ImageSource</param>
            
    /// <param name="imageType">the image type</param>
            
    /// <returns>The returned ImageSource of the controlToConvert</returns>
            public static BitmapSource GetImageOfControl(FrameworkElement controlToConvert, ImageType imageType)
            {
                
    // return first frame of image 
                var encoder = GetImageFromControl(controlToConvert, imageType);
                
    if (encoder != null && encoder.Frames != null && encoder.Frames.Count > 0)
                {
                    
    return encoder.Frames[0];
                }

                
    return new BitmapImage();
            }

            
    /// <summary>
            
    /// Get an ImageSource of a control(Jpeg as default type)
            
    /// </summary>
            
    /// <param name="controlToConvert">The control to convert to an ImageSource</param>
            
    /// <returns>The returned ImageSource of the controlToConvert</returns>
            public static BitmapSource GetImageOfControl(FrameworkElement controlToConvert)
            {
                
    return GetImageOfControl(controlToConvert, ImageType.Jpeg);
            }

            
    /// <summary>
            
    /// Save an image of a control
            
    /// </summary>
            
    /// <param name="controlToConvert">The control to convert to an ImageSource</param>
            
    /// <param name="fileName">The location to save the image to</param>
            
    /// <returns>The returned ImageSource of the controlToConvert</returns>
            public static Boolean SaveImageOfControl(FrameworkElement controlToConvert, String fileName)
            {
                
    try
                {
                    var imageType 
    = GetImageTypeByFileName(fileName);

                    
    using (var outStream = new FileStream(fileName, FileMode.Create))
                    {
                        var encoder 
    = GetImageFromControl(controlToConvert, imageType);
                        encoder.Save(outStream);
                    }
                }
                
    catch (Exception e)
                {
    #if DEBUG
                    Console.WriteLine(
    "Exception caught saving stream: {0}", e.Message);
    #endif
                    
    return false;
                }

                
    return true;
            }

        }

    注意到上面的GetImageOfControl方法返回的实际是BitmapFrame, 其是BitmapSource的一种,如果你更习惯使用BitmapImage的话,免费赠送如下方法:

            public static BitmapImage ToBitmapImage(this BitmapSource bitmapSource)
            {
                var encoder 
    = new JpegBitmapEncoder();
                var memoryStream 
    = new MemoryStream();

                encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
                encoder.Save(memoryStream);

                var bmp 
    = new BitmapImage();

                bmp.BeginInit();
                bmp.StreamSource 
    = new MemoryStream(memoryStream.ToArray());
                bmp.EndInit();

                memoryStream.Flush();
                memoryStream.Close();

                
    return bmp;
            }
  • 相关阅读:
    微信分享功能开发代码整理
    js 完美兼容浏览器的复制功能
    linux 搭建svn服务器
    zendStudio安装Xdebug项目断点调试
    程序员开发常用英语词汇
    简单的一个远传采集并下载远传图片存储到本地示例
    form表单中经常用到的禁用获取值问题
    记录下url拼接的多条件筛选js
    better-scroll在vue中的使用
    移动端适配,引入lib-flexible,vue开发中将px转化为rem
  • 原文地址:https://www.cnblogs.com/zhouyinhui/p/1740201.html
Copyright © 2011-2022 走看看