将控件保存为图片

原文: 将控件保存为图片

                                        将控件保存为图片

                                                 周银辉

这里分别提供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, 
0 0 , w, h, dc1,  0 0 , 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( 0 0 , 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;
        }

猜你喜欢

转载自www.cnblogs.com/lonelyxmas/p/9292394.html