我们公司正在使用MindFusion的WPF图表组件开发一个应用程序(WPF,针对.NET 3.5)。显然,打印和保存XPS文档会导致不同系统出现各种错误。
我将问题简化为从我们的应用程序创建的单个样本XPS Document。我将首先概述相关系统,并分别保存xps文档并使用以下方法打印图表时解决问题以下列表中的新WPF打印路径:
注意:这三个系统都安装了安装了.NET 3.5 Framework SP1的Windows XP SP3。
使用XpsDocumentWriter使用Paginator编写XPS文档:
PC 1 - XPS Viewer(使用IE 7.0)不起作用(即使在重新安装.Net 3.5之后)。 Essential Pack中的XPS Viewer打开文档,但视图完全模糊。但正如您所看到的,我们在screenshot右侧的应用程序使用DocumentViewer来测试此问题,该问题正常运行。从损坏的XPS Viewer打印产生与屏幕相同的输出,而从DocumentViewer中的集成打印功能打印(无需我们的应用程序干预)会产生模糊输出,这种输出更具可读性,但仍然不可接受。
PC 2 - IE XPS Viewer正常运行。打印输出不一致。有时,图形(形状)不完整,或者打印设备通知内存不足(使用相同的文档)。
PC 3 - IE XPS Viewer正常工作,但启动打印作业始终会导致IE本身内的exception。 注意:所有迄今为止提到的问题都已经过我们的应用程序创建的XPS Document(已在上面提到)测试过。
使用PrintDialog.PrintDocument和Paginator创建打印作业:
从我们的应用程序打印可以为所有系统提供一致的输出:文档越大(以页面媒体大小来衡量),它越模糊。不幸的是,已经省略了许多潜在的原因。 code for printing the document非常简单。
•我没有使用我们自己的Paginator,而是使用我们使用的MindFusion WPF Diagraming Components的另一个Paginator部分替换后者。我取得了同样的结果。 (对于保存为文件的XPSDocuments,此声明也是如此)。
•我使用了最新的打印驱动程序
•对PrintTicket Resolution的更改似乎不会以任何方式影响输出
•使用另一个Visual而不是图表(如我们的应用程序本身的Window)不会影响输出
由于这些不同的问题,似乎也可能有多种原因。之前的排除使我假设PrintTicket中缺少一些关键设置,或者XPS到GDI转换behnd场景发生了严重错误。除了这些假设之外,我的想法已经不多了。
注意:所有打印设备都有非XPS驱动程序。 HP Designjet 500,HP 2100
最后但并非最不重要的是,我序列化了用于XPS Document文件和打印作业的PrintTicket。 如果有人遇到类似的问题,我将感激不尽。欢迎提出任何建议。
答案 0 :(得分:0)
我目前正在使用代码,但我仍然存在对齐问题。但是打印并没有模糊我给你的代码希望它可以帮助你,我们都可以找到解决方案。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.Windows;
using System.Windows.Media;
using System.Diagnostics;
using System.Globalization;
using System.Windows.Controls;
using System.Data;
namespace VD
{
public class CustomPaginator : DocumentPaginator
{
private int _RowsPerPage;
private Size _PageSize;
private int _Rows;
public static DataTable dtToPrint;
public CustomPaginator()
{
}
public CustomPaginator(int rows, Size pageSize, DataTable dt)
{
_Rows = rows;
PageSize = pageSize;
dtToPrint = dt;
}
public override DocumentPage GetPage(int pageNumber)
{
int currentRow = _RowsPerPage * pageNumber;
var page = new PageElement(currentRow, Math.Min(_RowsPerPage, _Rows - currentRow))
{
Width = PageSize.Width,
Height = PageSize.Height,
};
page.Measure(PageSize);
page.Arrange(new Rect(new Point(0,0), PageSize));
return new DocumentPage(page);
}
public override bool IsPageCountValid
{ get { return true; } }
public override int PageCount
{ get { return (int)Math.Ceiling(_Rows / (double)_RowsPerPage); } }
public DataTable getDtProtols
{
get
{
return dtToPrint;
}
}
public override Size PageSize
{
get { return _PageSize; }
set
{
_PageSize = value;
_RowsPerPage = PageElement.RowsPerPage(PageSize.Height);
//Can't print anything if you can't fit a row on a page
Debug.Assert(_RowsPerPage > 0);
}
}
public override IDocumentPaginatorSource Source
{ get { return null; } }
}
public class PageElement : UserControl
{
private const int PageMargin = 75;
private const int HeaderHeight = 25;
private const int LineHeight = 20;
private const int ColumnWidth = 140;
private CustomPaginator objParent = new CustomPaginator();
private DataTable ProtocolsDT = null;
private int _CurrentRow;
private int _Rows;
public PageElement(int currentRow, int rows)
{
Margin = new Thickness(PageMargin);
_CurrentRow = currentRow;
_Rows = rows;
}
private static FormattedText MakeText(string text)
{
return new FormattedText(text, CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface("Tahoma"), 14, Brushes.Black);
}
public static int RowsPerPage(double height)
{
return (int)Math.Floor((height - (2 * PageMargin)
- HeaderHeight) / LineHeight);
}
protected override void OnRender(DrawingContext dc)
{
ProtocolsDT = objParent.getDtProtols;
Point curPoint = new Point(0, 0);
dc.DrawText(MakeText("Host Names"),curPoint );
curPoint.X += ColumnWidth;
for (int i = 1; i < ProtocolsDT.Columns.Count; i++)
{
dc.DrawText(MakeText(ProtocolsDT.Columns[i].ToString()), curPoint);
curPoint.X += ColumnWidth;
}
curPoint.X = 0;
curPoint.Y += LineHeight;
dc.DrawRectangle(Brushes.Black, null, new Rect(curPoint, new Size(Width, 2)));
curPoint.Y += HeaderHeight - LineHeight;
Random numberGen = new Random();
//for (int i = _CurrentRow; i < _CurrentRow + _Rows; i++)
//{
// dc.DrawText(MakeText(ProtocolsDT.Rows[i][0].ToString()), curPoint);
//curPoint.X += ColumnWidth;
for (int j = 0; j < ProtocolsDT.Rows.Count; j++)
{
for (int z = 0; z < ProtocolsDT.Rows[j].ItemArray.Length; z++)
{
dc.DrawText(MakeText(ProtocolsDT.Rows[j].ItemArray[z].ToString()), curPoint);
curPoint.X += ColumnWidth;
}
curPoint.Y += LineHeight;
curPoint.X = 0;
//dc.DrawText(MakeText(ProtocolsDT.Rows[j].ItemArray[1].ToString()), curPoint);
//curPoint.X += ColumnWidth;
//dc.DrawText(MakeText(ProtocolsDT.Rows[j].ItemArray[2].ToString()), curPoint);
//curPoint.X += ColumnWidth;
//}
//curPoint.Y += LineHeight;
//curPoint.X = 0;
}
}
}
}
Another Class
private void PrintDataTable(DataTable dt)
{
var printDialog = new PrintDialog();
if (printDialog.ShowDialog() == true)
{
var paginator = new CustomPaginator(dt.Rows.Count,
new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight),dt);
try
{
printDialog.PrintDocument(paginator, "Running Protocols Report");
}
catch (Exception ex)
{
MessageBox.Show(this, "Unable to print protocol information. Please check your printer settings.", "VD", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
}
}
}