I am printing labels with MS Report (c#/VS2013). The labels are 8 cm wide and 4 cm high. The printer sees and feeds them as portrait (no rotation) but the report viewer prints them landscape because the width is greater than the hight. Printer specific page orientation change before printing are ignored (!), so the labels are always printed in a 90° rotation against the label orientation. printer is an industial thermo transfer printer.
I don't understand why the page orientation is bound to the relation between hight and width and cannot be set indepenently! I already tried to change the orientation right before printing - this caused the labes be printed in several pieces but did not rotate them.
The only thing that helped was changing the paper size to 8 width and 8.1 height. Then the labels print correctly but this leads to a lot of empty pages (labels) and is no good solution.
The only way I see currently is redesigning all the labels rotated by 90° which is quite some effort, so I would be grateful if someone had a solution for this stange behaviour!
I solved this issue by rendering to an image and printing that through a PrintDocument object. This way I am able to send the landscape-formed label (8cm width, 4cm height) to the printer in portrait.
I am sure this can be done more elegant but due to time pressure I now go with this solution:
String tempDir = Path.GetTempFileName();
File.Delete(tempDir);
Directory.CreateDirectory(tempDir);
tempDir = Utils.addBackslash(tempDir);
ExportToPNG(tempDir);
String imageFile = Utils.FindFirstFile(tempDir, "*.png");
if (imageFile != "")
{
PrintDocument pd = new PrintDocument();
try
{
pd.DefaultPageSettings.PrinterSettings.PrinterName = DB.Instance.getSetting("label.printername");
}
catch
{
// This is just a preset, it may fail without consequences
}
pd.DefaultPageSettings.Landscape = false; // Now I can do it!
pd.PrintPage += (sender, args) =>
{
Image i = Image.FromFile(imageFile);
Point p = new Point(100, 100);
args.Graphics.DrawImage(i, 0, 0, i.Width, i.Height);
};
PrintDialog pdi = new PrintDialog();
pdi.Document = pd;
if (pdi.ShowDialog() == DialogResult.OK)
pd.Print();
pd.Dispose();
}
Related
I am trying to print a canvas to both printer and file with the help of PrintDialog. I want the canvas to fit the page. I was able to achieve it using the following code
private void Print(Visual v)
{
System.Windows.FrameworkElement e = v as System.Windows.FrameworkElement ;
if (e == null)
return;
PrintDialog pd = new PrintDialog();
if (pd.ShowDialog() == true)
{
//store original scale
Transform originalScale = e.LayoutTransform;
//get selected printer capabilities
System.Printing.PrintCapabilities capabilities = pd.PrintQueue.GetPrintCapabilities(pd.PrintTicket);
//get scale of the print wrt to screen of WPF visual
double scale = Math.Min(capabilities.PageImageableArea.ExtentWidth / e.ActualWidth, capabilities.PageImageableArea.ExtentHeight /
e.ActualHeight);
//Transform the Visual to scale
e.LayoutTransform = new ScaleTransform(scale, scale);
//get the size of the printer page
System.Windows.Size sz = new System.Windows.Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);
//update the layout of the visual to the printer page size.
e.Measure(sz);
e.Arrange(new System.Windows.Rect(new System.Windows.Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), sz));
//now print the visual to printer to fit on the one page.
pd.PrintVisual(v, "My Print");
//apply the original transform.
e.LayoutTransform = originalScale;
}
}
The above code seems to be working as expected but when I am writing it to a PDF file using a PDF writer, the canvas will be resized when the save dialog box shows up and it will be set back to normal. So there is a resizing happening in the UI as well.
This canvas is already a cloned one and this cannot be printed without showing it in the UI because there are some background operations happening to fill the elements in the canvas which can be started only after it's loaded. Hence the cloned canvas is shown as a print preview.
Does anyone know of a good solution, or perhaps improve on the existing one to solve the UI resizing issue?
I am currently trying to print the contents of a content container (it only contains datagrids with information) and an image using PrintFixedDocument. It prints flawlessly on my machine (windows 10) with full image quality and on another pc which is windows 8, the quality is the same.
However when this is done on a Windows 7 pc the image quality becomes very poor and the final result is very blurred. This is a problem as the computer cannot be updated from windows 7 for various reasons, so im wondering if anyone else has experienced this and if so is there a workaround? Also could be an issue with my GetFixedDocument method, though I cannot work out why this would work on both win 10 and 8 but not 7.
NOTE THIS IS RUNNING FROM AN INSTALLED VERSION OF THE APPLICATION ON EACH PC
ALSO BEEN TRIED ON MULTIPLE PRINTERS ON ALL 3 OPERATING SYSTEMS
Any help would be appreciated
Xaml:
<StackPanel Margin="-105,146,66,0" Height="900" VerticalAlignment="Top" x:Name="PrintImageContextMenu">
<Image Canvas.ZIndex="0" Source="{Binding Coupon.OverlayImagePath}" Margin="0,-21,-76,108" Stretch="Fill" />
<ContentControl Content="{Binding}" ContentTemplateSelector="{StaticResource DataViewerDataTemplateSelector}" />
</StackPanel>
C#:
public partial class CouponViewerView
{
public CouponViewerView()
{
InitializeComponent();
}
public void Print()
{
//Executes On Thread
Application.Current.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, (EventHandler)delegate
{
UpdateLayout();
var fixedDoc = PrintHelper.GetFixedDocument(StackPanelToPrint, new PrintDialog());
PrintHelper.ShowPrintPreview(fixedDoc);
}, null, null);
}
private void PrintCurrentForm(object sender, RoutedEventArgs e)
{
Print();
}
C# Print helper code:
public static void ShowPrintPreview(FixedDocument fixedDoc)
{
var wnd = new Window();
var viewer = new DocumentViewer();
viewer.Document = fixedDoc;
wnd.Content = viewer;
wnd.ShowDialog();
}
public static FixedDocument GetFixedDocument(FrameworkElement toPrint, PrintDialog printDialog)
{
var capabilities = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket);
var pageSize = new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight);
var visibleSize = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);
var fixedDoc = new FixedDocument();
//If the toPrint visual is not displayed on screen we neeed to measure and arrange it
toPrint.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
toPrint.Arrange(new Rect(new Point(0, 0), toPrint.DesiredSize));
//
var size = toPrint.DesiredSize;
//Will assume for simplicity the control fits horizontally on the page
double yOffset = 0;
while (yOffset < size.Height)
{
var vb = new VisualBrush(toPrint)
{
Stretch = Stretch.None,
AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Top,
ViewboxUnits = BrushMappingMode.Absolute,
TileMode = TileMode.None,
Viewbox = new Rect(0, yOffset, visibleSize.Width, visibleSize.Height)
};
var pageContent = new PageContent();
var page = new FixedPage();
((IAddChild)pageContent).AddChild(page);
fixedDoc.Pages.Add(pageContent);
page.Width = pageSize.Width;
page.Height = pageSize.Height;
var canvas = new Canvas();
FixedPage.SetLeft(canvas, capabilities.PageImageableArea.OriginWidth);
FixedPage.SetTop(canvas, capabilities.PageImageableArea.OriginHeight);
canvas.Width = visibleSize.Width;
canvas.Height = visibleSize.Height;
canvas.Background = vb;
page.Children.Add(canvas);
yOffset += visibleSize.Height;
}
return fixedDoc;
}
anyone else has experienced this and if so is there a workaround?
That's the only directly answerable question, yes, many. Keep in mind that you often substantially rescale an image on a printer, they are devices with very high dots-per-inch resolution compared to a monitor. A machine that boots Win7 often runs at 96dpi, later ones tend to have better monitors so are often run at higher dpi settings. First thing to watch out for is the source image. If it has a pixel size that's adequate for that Win7 PC then it can get very blurry when it is blown-up to 600 dpi.
Probably the most unintuitive scaling behavior in WPF is what happens when the image alignment does not perfectly match a target pixel after scaling. A problem described well in this blog post. Be sure to also read this SO question, an almost perfect fit for your usage of VisualBrush and its blurriness problem. This problem was addressed in .NET 4.0 with the added UseLayoutRounding property. You are not using it, you definitely should. Don't blindly apply the BitmapScalingMode that the dup recommends, the type of image (line-art vs photo) matters a lot.
I had a similar issue I ended up instead of directly printing to creating a PDF and having that open for the client and they could print it if they wanted just fine.
Windows 7 just seems broken with some of the WPF printing.
A few days ago I tried to print a photo from right clicking on the photo. One dialogue box showed up to select Printer, PaperSize, Quality etc. I select PaperSize = Legal. The printer could print on Legal size paper (I am using HP LaserJet 1020 plus Printer).
Now I am trying to print something from C#, setting PaperSize, but printer is not able to print Legal. Below is my code. Does anything about code wrong?
this.printDocument.PrinterSettings.PrinterName = this.printSetting.PrinterName;
PaperSize pkCustomSize1 = new PaperSize("8.5x13", 1300, 850);
this.printDocument.DefaultPageSettings.PaperSize = pkCustomSize1;
this.printDocument.DefaultPageSettings.PaperSize.RawKind = 119;
printPreviewDialog.Document = printDocument;
printDocument.Print();
private void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Graphics g = e.Graphics;
Bitmap bm = new Bitmap(300, 3000);
// Code for bm.
g.DrawImage(bm, 0, 0);
}
So the question is, what is the proper method to set PaperSize (and PrinterSetting)?
One more thing, I searched for MaximumPrintableArea of a printer. My printer has maximum A4 size, why it does print on Legal?
The PrintDocument.PrinterSettings.PaperSizes collection has all the supported paper size for the printer which you have set using PrintDocument.Printersettings.PrinterName property. The PrintDocument.PrinterSettings has all kinds of information for the printer you have set. Use them wherever its required.
Sample Code:
// do a null check of the return value of GetPaperSize. 5 represent the rawkind of Legal
printdocument.PrinterSettings.DefaultPageSettings.PaperSize = GetPaperSize(5);
private PaperSize GetPaperSize(int rawKind)
{
PaperSize papersize = null;
foreach(PaperSize item in printdocument.PrinterSettings.PaperSizes)
{
if(item.RawKind == rawKind)
{
papersize = item;
break;
}
}
return papersize;
}
To answer your other question, I think the default PaperSize of the printer is set to Legal.
Edit:
Every printer (hardware device) has its own physical limitation which is defined as HardMargins. Software printers like Adobe PDF or Cute PDF don't have such limitations. You can't print beyond this limit. Whatever papersize you set still it will print within this limit. That's why you are still able to print in Letter, Legal, A4 etc.. (paper sizes supported by printer i.e. paper size you can insert in a printer) but the maximum printable area is still same for all paper sizes.
I'm trying to print an image (QR code) from Silverlight 4 app, however the image is antialised when printed (I have tried both XPS file printer and hardware printer)image is blury, and is not readable by barcode reader.
Image from printed XPS document http://img805.imageshack.us/img805/7677/qraliasing.png
I'm using this simple code to print it:
WriteableBitmap bitmap = new WriteableBitmap(width, height);
//write bitmap pixels
Image image = new Image(){Stretch = Stretch.None};
image.Source = bitmap;
image.Width = bitmap.PixelWidth;
image.Height = bitmap.PixelHeight;
//Print
PrintDocument printDocument = new PrintDocument();
printDocument.PrintPage += (sender, args) =>
{
args.PageVisual = image;
};
printDocument.Print("QrCode");
I have found a solution.
When printing Image control in Silverlight 4, it sends to printer not a "print screen" of an image control like it looks in your UserControl but an image set in it's source property. If you generate two bitmaps of 100x100 px and 1000x1000px resolutions and put them in 100x100px size Image controls the print result will not be the same as you may expect.
So the solution is to generate high resolution image (or upscale image) and put it in Image controls of desired size.
It seems you've come across a solution as I was typing mine, but I'll submit anyway...
The reason this happens is that the PrintDocument will essentially take the UIElement (your image), which it normally blits to a 96 DPI screen, and upscale it to 600 DPI suitable for printing. Since there's no way to tell this upscale operation how to handle smoothing, what you get is that ugly blurriness.
However, if you do the upscale blit yourself, then apply an opposite RenderTransform to the image, when the PrintDocument goes to scale up the image, your high-res blit will be the result.
Once you have your high-res blit of the QR code (essentially 600 / 96 = 6.25 times as large as normal), you apply a scale transform that sizes it back down by the exact same amount:
image.RenderTransform = new ScaleTransform {
ScaleX = 96.0 / 600.0,
ScaleY = 96.0 / 600.0
};
When you print this, you should see sharp edges.
Did you try changing the smoothing mode on the graphics object?
WriteableBitmap bitmap = new WriteableBitmap(width, height);
//write bitmap pixels
Image image = new Image(){Stretch = Stretch.None};
image.Source = bitmap;
image.Width = bitmap.PixelWidth;
image.Height = bitmap.PixelHeight;
//Print
PrintDocument printDocument = new PrintDocument();
printDocument.PrintPage += (sender, args) =>
{
//**Add this**
args.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
args.PageVisual = image;
};
printDocument.Print("QrCode");
When i select Microsoft XPS Document Writer as Printer, my output is perfect but when i select my HP 1020 printer machine, the printer outputs blank copy...Following is the code....
private void printButton_Click(object sender, RoutedEventArgs e)
{
PrintInvoice pi = new PrintInvoice();
pi.DataContext = this.DataContext;
PrintDialog printDlg = new System.Windows.Controls.PrintDialog();
if (printDlg.ShowDialog() == true)
{
pi.Margin = new Thickness(30);
//now print the visual to printer to fit on the one page.
printDlg.PrintVisual(pi, "First Fit to Page WPF Print");
}
}
This could be caused by a number of different things. There are a few steps that you can add which, when performed correctly, may cause the flying men to return with goods and knowledge.
First, you should scale to the printed page (code from a2zdotnet):
System.Printing.PrintCapabilities capabilities =
printDlg.PrintQueue.GetPrintCapabilities(printDlg.PrintTicket);
//get scale of the print wrt to screen of WPF visual
double scale = Math.Min(capabilities.PageImageableArea.ExtentWidth / this.ActualWidth, capabilities.PageImageableArea.ExtentHeight /
this.ActualHeight);
//Transform the Visual to scale
this.LayoutTransform = new ScaleTransform(scale, scale);
//get the size of the printer page
Size sz = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);
//update the layout of the visual to the printer page size.
this.Measure(sz);
this.Arrange(new Rect(new Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), sz));
//now print the visual to printer to fit on the one page.
printDlg.PrintVisual(this, "Code ganked from http://www.a2zdotnet.com/View.aspx?id=66");
The cargo-cult code is in the Measure and Arrange steps. Often, if you call Measure and pass in a new Size(Double.MaxValue, Double.MaxValue) that's all you need to do.
The second ritual involves bumping the Dispatcher.
visual.DataContext = foo;
Dispatcher.Invoke((Action)()=>{;}); // bamp
// print here
Try these and see if it helps.
this XAML does the trick in some situations
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<... Name="myPrintElement" />
</ScrollViewer >