İlk önce Microsoft ile ilgili bir hata olduğunu belirtmek isterim ancak bu noktada düzeltmeyi istemiyorlar. Aradığım şey, müşterimizin bu kadar önemli bir konu olduğunu düşündüğüm şeyi yapmaya çalışmanın bir geçici çözümü veya daha iyi bir yoludur.XPS dosyasında yazdırılan görüntülerin kopyalanması
kod
MainWindow.xaml
<Grid x:Name="mainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox ItemsSource="{Binding Images}">
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="Print to file" Grid.Row="1" Click="PrintToFile_Click"/>
<Button Content="Print to device" Grid.Row="2" Click="PrintToDevice_Click"/>
</Grid>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public IList<byte[]> Images { get; set; }
public MainWindow()
{
InitializeComponent();
Assembly currentAssembly = Assembly.GetExecutingAssembly();
this.Images = new List<byte[]>
{
ReadToEnd(currentAssembly.GetManifestResourceStream("PrintingInvestigation.Images.Chrysanthemum.jpg")),
ReadToEnd(currentAssembly.GetManifestResourceStream("PrintingInvestigation.Images.Desert.jpg")),
ReadToEnd(currentAssembly.GetManifestResourceStream("PrintingInvestigation.Images.Hydrangeas.jpg")),
};
this.DataContext = this;
}
public static byte[] ReadToEnd(System.IO.Stream stream)
{
long originalPosition = 0;
if (stream.CanSeek)
{
originalPosition = stream.Position;
stream.Position = 0;
}
try
{
byte[] readBuffer = new byte[4096];
int totalBytesRead = 0;
int bytesRead;
while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
{
totalBytesRead += bytesRead;
if (totalBytesRead == readBuffer.Length)
{
int nextByte = stream.ReadByte();
if (nextByte != -1)
{
byte[] temp = new byte[readBuffer.Length * 2];
Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
readBuffer = temp;
totalBytesRead++;
}
}
}
byte[] buffer = readBuffer;
if (readBuffer.Length != totalBytesRead)
{
buffer = new byte[totalBytesRead];
Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
}
return buffer;
}
finally
{
if (stream.CanSeek)
{
stream.Position = originalPosition;
}
}
}
private void PrintToDevice_Click(object sender, RoutedEventArgs e)
{
PrintDialog dialog = new PrintDialog();
if (dialog.ShowDialog() == true)
{
Thickness pageMargins;
if (dialog.PrintTicket.PageBorderless.HasValue == true)
{
if (dialog.PrintTicket.PageBorderless.Value == PageBorderless.Borderless)
{
pageMargins = new Thickness(0, 0, 0, 0);
}
else
{
pageMargins = new Thickness(20, 20, 20, 20);
}
}
else
{
pageMargins = new Thickness(20, 20, 20, 20);
}
int dpiX = 300;
int dpiY = 300;
if (dialog.PrintTicket.PageResolution != null &&
dialog.PrintTicket.PageResolution.X.HasValue &&
dialog.PrintTicket.PageResolution.Y.HasValue)
{
dpiX = dialog.PrintTicket.PageResolution.X.Value;
dpiY = dialog.PrintTicket.PageResolution.Y.Value;
}
else
{
dialog.PrintTicket.PageResolution = new PageResolution(dpiX, dpiY);
}
VisualDocumentPaginator paginator = new VisualDocumentPaginator(this.mainGrid, this.mainGrid.ActualWidth);
paginator.PageSize = new Size(dialog.PrintableAreaWidth, dialog.PrintableAreaHeight);
dialog.PrintDocument(paginator, "My first print");
GC.Collect();
}
}
private void PrintToFile_Click(object sender, RoutedEventArgs e)
{
string filePath = this.PrintToFile(null, this.mainGrid, "My first print", this.mainGrid.ActualHeight, this.mainGrid.ActualWidth);
Process.Start(filePath);
}
public string PrintToFile(Visual titleVisual, Visual contentVisual, string title, double bottomMost, double rightMost)
{
string printedFilePath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), string.Format(CultureInfo.InvariantCulture, "{0}.xps", title));
XpsDocument printedDocument = new XpsDocument(printedFilePath, FileAccess.Write, System.IO.Packaging.CompressionOption.SuperFast);
VisualDocumentPaginator paginator = new VisualDocumentPaginator(contentVisual as FrameworkElement, rightMost);
paginator.PageSize = new Size(793.7, 1122.5);
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(printedDocument);
writer.Write(paginator, new PrintTicket
{
Collation = Collation.Collated,
CopyCount = 1,
DeviceFontSubstitution = DeviceFontSubstitution.On,
Duplexing = Duplexing.OneSided,
InputBin = InputBin.AutoSelect,
OutputColor = OutputColor.Color,
OutputQuality = OutputQuality.High,
PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOA4),
PageOrientation = PageOrientation.Portrait,
PageResolution = new PageResolution(PageQualitativeResolution.High),
PagesPerSheet = 1,
TrueTypeFontMode = TrueTypeFontMode.Automatic
});
printedDocument.Close();
return printedFilePath;
}
}
VisualDocumentPaginator.cs
public class VisualDocumentPaginator : DocumentPaginator
{
#region Fields
private double desiredWidth;
private FrameworkElement element;
#endregion
#region Properties
public int Columns
{
get
{
return 1;// (int)Math.Ceiling(Element.ActualWidth/PageSize.Width);
}
}
public int Rows
{
get
{
return (int)Math.Ceiling(element.ActualHeight/PageSize.Height);
}
}
#endregion
#region Constructors
public VisualDocumentPaginator(FrameworkElement element, double desiredWidth)
{
this.desiredWidth = desiredWidth;
this.element = element;
}
#endregion
#region DocumentPaginator Members
public override DocumentPage GetPage(int pageNumber)
{
TransformGroup transforms = new TransformGroup();
double scaleRatio = this.PageSize.Width/this.desiredWidth;
int row = (pageNumber/Columns);
double pageHeight = -PageSize.Height * row/scaleRatio;
double pageWidth = -PageSize.Width * (pageNumber % Columns);
transforms.Children.Add(new TranslateTransform(pageWidth, pageHeight));
// Make sure the control is stretched to fit the page size.
if (scaleRatio != double.NaN)
{
ScaleTransform st = new ScaleTransform(scaleRatio, scaleRatio);
transforms.Children.Add(st);
}
element.RenderTransform = transforms;
Size elementSize = new Size(this.desiredWidth, element.ActualHeight);
element.Measure(elementSize);
element.Arrange(new Rect(new Point(0, 0), elementSize));
var page = new DocumentPage(element, this.PageSize, new Rect(), new Rect());
element.RenderTransform = null;
return page;
}
public override bool IsPageCountValid
{
get { return true; }
}
public override int PageCount
{
get
{
return Columns * Rows;
}
}
public override Size PageSize { set; get; }
public override IDocumentPaginatorSource Source
{
get { return null; }
}
#endregion
}
tüm kodu yazabilmek için Özürler ama ben konuyu görüyorum ki bütün alanları kapsamaktadır. Burada yardımcı olursa, sorunun yeniden üretilebileceği bir örnek projeye sahip olan Microsoft bug report.
"yazdır cihaza" butonuna ardından tıklandığında doğru görüntüler yazdırılır ise, sadece ilk görüntü 3 kez basılır bir XPS dosyası yazarken
sorun yalnızca görülür sorunu.
Bir bayt [] ile bağlandığımın nedeni, görüntüleri yerel bir SQL CE veritabanında ısrar etmemin nedeni. Bunları bir DB'de saklıyoruz, çünkü her biri yalnızca 2 ~ 2KB değerindedir ve kullanıcıların kendi Simgelerini sisteme aktarmalarına izin veriyoruz ve yanlışlıkla silinmeyeceklerini garanti etmek için bir mekanizma istedik.
NOT
ben byte bağlamak yoksa [] yukarıda belirtildiği gibi o zaman sorunu görmüyorum fark etmiş. Sistemin görüntülerin bir DB'de saklanması yaklaşımıyla çalıştığı göz önüne alındığında, geçici bir çözüm varsa onunla uğraşmayı tercih ederim, ancak bu görüntüler için depolama mekanizmasının yerini tamamen almamaktayım.
bunun için teşekkürler. Soruna oldukça hızlı bir çözüm bulmayı umuyordum, ancak müşteri şimdi XPS desteğini düşürmek ve PDF'ye geçmek istediğine karar verdiğinden, kullandığımız baskı mantığını yeniden yazacağımızı düşünüyorum. Ben kesinlikle System.Drawing.Printing içine bakacağız. – Bijington