0

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

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

Windows 照片查看器无法打开此图片,因为该文件似乎已损坏、损坏或太大。

该消息来自 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();
}

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

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

4

1 回答 1

0

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

我自己想出的解决方法是使用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-ed(System.Drawing.Image需要显式处理)并且我正在加载相对较大的图像,所以它似乎确实会稍微影响内存使用,最终在大型作业上会慢一些。

于 2013-06-04T14:28:17.990 回答