65.9K
CodeProject 正在变化。 阅读更多。
Home

使用打印代码输出图形文件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (23投票s)

2005年3月22日

CPOL

3分钟阅读

viewsIcon

119478

downloadIcon

3219

将您的 PrintDocument “打印” 到常见的图形文件格式。

PrintControllerFileDemo

引言

您是否希望您的应用程序支持保存为不同的图形文件格式? 假设您已经实现了打印预览,事实证明它比您想象的要容易。 这是一篇围绕 GDI+ Image.Save 方法的小文章。

使用代码

使用该代码再简单不过了。

只需将 PrintControllerFile.cs 文件添加到您的项目中,并像这样使用它

using ( PrintDocument doc = new MyPrintDocument( ... ) )
{
    ImageFormat format = ImageFormat.Jpeg;
    float scale = 1f;
    long quality = 75L;
    string output = "Output";

    PrintController controller = 
      new PrintControllerFile( format, scale, quality, output );
    
    doc.PrintController = 
      new PrintControllerWithStatusDialog( controller, "Exporting" );

    doc.Print();
}

PrintControllerFile 构造函数的参数是

  • formatImageFormat 类中的静态格式之一。
  • scale:一个简单的缩放比例,用于控制输出的大小。
  • quality:仅由 JPEG 编码器使用。 默认值约为 75。
  • output:输出文件的基本文件路径。

瞧! 输出是图形文件的集合,每页一个文件。

工作原理

基本上,PrintControllerFile 使用 PreviewPrintController 生成元文件,然后将它们保存为输出。

此方法的优点是输出将始终与您的打印预览中的外观相同。

它也为我们节省了很多工作。 如果您在 Reflector 中查看 PreviewPrintController,您会发现它使用各种 GDI+ 方法为每页设置一个 Graphics 对象。 我们希望我们的输出与打印预览完全相同,因此让 PreviewPrintController 完成这项工作是有意义的。

因此,PrintControllerFile 派生自 PreviewPrintController,并重写了 OnEndPage 方法以在生成时保存每一页。 我本可以让 PreviewPrintController 生成所有页面,然后保存它们,但我希望在生成每一页后立即保存它们,这样如果您取消打印,您就可以获得到该点的输出。

internal class PrintControllerFile : PreviewPrintController
{
    ...
    
    public override void OnEndPage( PrintDocument document, PrintPageEventArgs e )
    {
        base.OnEndPage( document, e );

        // Get the current Metafile
        PreviewPageInfo[] ppia = GetPreviewPageInfo();
        PreviewPageInfo ppi = ppia[ ppia.Length - 1 ];
        Image image = ppi.Image;
        _Metafile = ( Metafile ) image;

        if ( _Format == ImageFormat.Emf )
          { _Metafile.Save( PagePath, _Format ); return; }
        if ( _Format == ImageFormat.Wmf )
          { _Metafile.Save( PagePath, _Format ); return; }

        SaveViaBitmap( document, e );
    }
    
    ...
}

保存增强型元文件和 Windows 元文件格式的输出就像使用所需的格式在 Metafile 实例上调用 Save 一样简单。

但是,此方法不适用于其他图形格式,因为您无法控制输出。 例如,将标准页面保存为位图会导致文件大小超过 100MB。 显然,这不是必需的。

解决方案是创建一个具有所需属性的 Bitmap 图像,将其播放到其中,然后保存 Bitmap。 这使我们能够控制我们需要的输出。

    protected void SaveViaBitmap( PrintDocument document, PrintPageEventArgs e )
    {
        int width  = e.PageBounds.Width  ;
        int height = e.PageBounds.Height ;

        using ( Bitmap bitmap = new Bitmap( ( int ) ( width * _Scale ), 
                                          ( int ) ( height * _Scale ) ) )
        using ( Graphics graphics = Graphics.FromImage( bitmap ) )
        {
            graphics.Clear( Color.White );

            if ( _Scale != 1 ) graphics.ScaleTransform( _Scale, _Scale );

            Point point = new Point( 0, 0 );
            Graphics.EnumerateMetafileProc callback = 
              new Graphics.EnumerateMetafileProc( PlayRecord );
  
            graphics.EnumerateMetafile( _Metafile, point, callback );

            Save( bitmap );
        }
    }

我需要设置 Bitmap 对象的唯一参数是 scale 参数。 输出的大小由 PrintPageEventArgsPageBounds 乘以 scale 参数设置。 实际上,您通常希望输出为标准大小,但大约从 0.5 到 2.0 的 scale 值可能很有用。 如果设置了 scale,则将 ScaleTransform 应用于 Graphics 对象,因此您的打印代码不必修改。

Bitmap 创建一个 Graphics 对象并将元文件播放到其中,然后只是样板代码。

然后,以所需的格式保存 Bitmap 很简单,除了 JPEG 格式,它需要设置 Quality 参数才能用于编码器。 此值必须在 0(最高压缩,最低质量)到 100(最低压缩,最高质量)的范围内。 默认值似乎约为 75。

    protected void Save( Bitmap bitmap )
    {
        if ( _Format == ImageFormat.Jpeg )
        {
            EncoderParameters parameters = new EncoderParameters( 1 );
            EncoderParameter parameter = 
              new EncoderParameter( Encoder.Quality, _Quality );
            parameters.Param[ 0 ] = parameter;

            bitmap.Save( PagePath, _Codec, parameters );
            return;
        }

        bitmap.Save( PagePath, _Format );
    }

主文件 PrintControllerFile.cs 只有大约 200 行长,而且非常容易理解。 如果您有兴趣,请看一看。

关注点

Image.Save 方法非常强大,但不能直接用于元文件。 创建一个中间 Bitmap,然后保存它,这让我们能够控制输出。

如果能有更多控制就好了,但如果您只想生成可以在图像编辑器中修改的图形文件,那么这就可以了。

历史

2005 年 3 月 22 日 - 版本 1.0

© . All rights reserved.