使用Win7和Vista上的PrintDocument将多个图像打印到传真虚拟打印机会导致TIFF损坏

时间:2013-04-25 17:39:10

标签: c# .net windows-7 printing windows-vista

我有一个应用程序,应用程序使用PrintDocument将多个图像作为单个打印作业打印,每页一个图像。我遇到了一个非常具体但常见的配置问题,我想知道如何纠正它。

代码在我可以访问的任何物理打印机和所有桌面Windows操作系统上的Microsoft XPS Document Writer上都可以正常运行。但是,打印到传真虚拟打印机(Windows操作系统上标准的打印机)仅适用于Windows XP和Windows 8.当我在Windows Vista或Windows 7上打印到传真打印机时,它表示打印成功;但是,如果有多个页面并且您打开了Windows照片查看器所创建的.tif图像

  

Windows Photo Viewer无法打开此图片,因为该文件似乎已损坏,已损坏或过大。

该消息是来自Windows 7的消息,Vista上的文本可能略有不同。如果只有一个图像(因此是一个页面),它可以正常工作。

如果发送传真,则会显示空白。我也尝试在GIMP中打开.tif图像并使用ImageMagick处理它,这两个图像都失败,表明它是一个坏的.tif文件。

这是产生问题的代码,已删除一些稳健性以允许更简洁的示例。

internal void Print( string printerName )
{
    PrintDocument printDocument = new PrintDocument
        {
            PrinterSettings = new PrinterSettings {PrinterName = printerName}
        };

    IEnumerable<string> filesToPrint = new[]{"File1.png", "File2.png"};

    IEnumerator<string> enumerator = filesToPrint.GetEnumerator();
    enumerator.MoveNext()

    printDocument.PrintPage += (sender, args) =>
        {
            string fileName = enumerator.Current;

            using (var img = System.Drawing.Image.FromFile(fileName))
            {
                args.Graphics.DrawImage(img, args.PageBounds);
            }

            var moveNext = enumerator.MoveNext();

            args.HasMorePages = moveNext;

            if (!moveNext)
            {
                enumerator.Dispose();
            }
        };

    printDocument.Print();
}

这仅仅是这些操作系统上传真打印机的问题,还是上述代码有问题?我该如何解决这个问题?

This Microsoft hotfix没有特别提及传真,但确实有正确的错误消息,所以我尝试应用它。它没有任何区别。

1 个答案:

答案 0 :(得分:0)

我在微软合作伙伴支持社区中追求这一点。最终的答复是他们已经确认了这个问题并且“升级工程师正在解决这个问题。”

我自己提出的解决方法是使用System.Printing而不是System.Drawing.Printing进行打印。

internal override void Print(string printerName, string baseFilePath, string baseFileName)
{
    using (var printQueue = GetPrintQueue(printerName))
    {
        XpsDocumentWriter xpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue);

        IEnumerable<string> filesToPrint = GetFilesToPrint(baseFilePath, baseFileName);

        PrintUsingCollator(xpsDocumentWriter, filesToPrint);
    }
}

private static void PrintUsingCollator(XpsDocumentWriter xpsDocumentWriter,
                                       IEnumerable<string> filesToPrint)
{
    SerializerWriterCollator collator = xpsDocumentWriter.CreateVisualsCollator();

    collator.BeginBatchWrite();

    foreach (var fileName in filesToPrint)
    {
        Image image = CreateImage(fileName);

        ArrangeElement(image);

        collator.Write(image);
    }

    collator.EndBatchWrite();
}

/// <remarks>
/// This method needs to be called in order for the element to print the right size.
/// </remarks>
private static void ArrangeElement(UIElement element)
{
    var box = new Viewbox {Child = element};

    box.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    box.Arrange(new Rect(box.DesiredSize));
}

System.Printing是基于WPF的新API。在这种特殊情况下它的缺点是它是内存使用。因为System.Windows.Controls.Image是GC编辑的(其中System.Drawing.Image需要显式处理)并且我正在加载相对较大的图像,所以它似乎会稍微破坏内存使用量,并最终在大型作业上稍慢一些。 / p>