I'm printing to an impact printer, loaded with 8.5 x 8.5 inch paper. When I print, the printer ejects 11 inches instead of 8.5.
PageMediaSize pageSize = new PageMediaSize(PageMediaSizeName.Unknown, element.Width, element.Height);
PrintDialog dialog = new PrintDialog();
dialog.PrintTicket.PageMediaSize = pageSize;
Console.WriteLine(dialog.PrintableAreaHeight); // 816, good!
dialog.PrintQueue = myQueue; // selected from a combobox
Console.WriteLine(dialog.PrintableAreaHeight); // 1056 :(
dialog.PrintVisual(element, description);
Using "How do I convert Twips to Pixels in .NET?" I've determined that 8.5 inches is 816 pixels, which is the size of my element.Width and element.Height. I'm setting a new PageMediaSize, but this seems to have no effect, dialog.PrintableAreaHeight is still ends up at 1056 when I set the queue on the dialog.
If I do dialog.ShowDialog(), manually pick my printer, and manually find and change Paper Size in my printer's advanced settings, then dialog.PrintableAreaHeight properly reflects the change.
This page http://go4answers.webhost4life.com/Example/set-printdialogs-default-page-size-168976.aspx suggests that I can only set a PageMediaSize supported by my printer. Using the GetPrintCapabilities function on my PrintQueue, I see a list of 10 or so page sizes, none of which are 8.5 x 8.5. This is the same list I see when I go to my printer's advanced settings in windows.
Please find the code below, it sets paper size as required
var printerSettings = new PrinterSettings();
var labelPaperSize = new PaperSize { RawKind = (int)PaperKind.A6, Height = 148, Width = 105 };
printerSettings.DefaultPageSettings.PaperSize = labelPaperSize;
var labelPaperSource = new PaperSource { RawKind = (int)PaperSourceKind.Manual };
printerSettings.DefaultPageSettings.PaperSource = labelPaperSource;
if (printerSettings.CanDuplex)
{
printerSettings.Duplex = Duplex.Default;
}
Related
tl;dr: Why do I need to set an extra "magic" offset on the left side when printing with WPF, XpsDocumentWriter and FixedDocument compared to printing with WinForms and PrintDocument?
I am building a WPF app that creates a FixedDocument and prints it to a label printer via XpsDocumentWriter. It's split in two parts, as I want the printer part to be able to receive and print a FixedDocument over the network from another app.
It's for use with a point of sale system, so I do not want to show a PrintDialog for every print. Size of labels and the printer name is stored in a template file. The things to be printed is in the template file combined with some data. (In below example printer name is taken from a combobox for now and just some demo things to be printed).
I retrieve the printer queue with the given printer name, and I can print to the printer, but the margins are quite off - the print is too far to the left, outside of the label and by more than just the liner margin (distance from label edge to the roll edge). By trial'n'error I found the magic offset to be around 20 plus the liner margin, but I guess that's different on another printer.
The old version of this app (which is made with WinForms and PrintDocument) prints allright (no matter how the printer properties' paper is setup). The wish from business is that all setup is in the template file, completely disregarding printer properties setup. That is how it is functioning now in the WinForms app.
What am I forgetting to set, what's the gotchas?
Should I do it some other way?
Do I need to set the PageMediaSize and PageMediaType, and why?
I'd like to do checks on PrinterCapabilities, but not if they depend on the current printer properties like the page size set in the properties. That one I'd like to set in code.
Update 11/3
I now tried printing to both a Metapace and a Zebra labelprinter, and both is happy with the 20 unit offset on the left side. But... why is it needed? When printing to pdf/xps, I get the offset to the left plus the margin on both sides. This I do not get with the old program in Winforms?
And do I need to do Measure, Arrange and UpdateLayout?
Part one - the FixedDocument creator
var printerName = CmbPrinters.SelectedValue.ToString();
var size =
(FlexTemplate.TemplateParser.TemplateFunctions.Size)
template.Functions.First(f => f is FlexTemplate.TemplateParser.TemplateFunctions.Size);
var labelSize = new Size(size.Width.Value, size.Height.Value);
// Dimensions are 1/96th of an inch, socalled Device Independent Pixels (matches 96 DPI, which is normal?)
var linerMargin = 4.7244094488189; // 1.25 mm
var magicOffset = 20; // 5.29 mm
// The document
var doc = new FixedDocument();
doc.PrintTicket = new PrintTicket();
var printTicket = (PrintTicket) doc.PrintTicket;
printTicket.PageMediaSize = new PageMediaSize(PageMediaSizeName.Unknown, size.Width.Value, size.Height.Value);
// New page
var page = new FixedPage
{
Width = labelSize.Width + magicOffset + 2 * linerMargin,
Height = labelSize.Height,
Margin = new Thickness(magicOffset + linerMargin, 0, linerMargin, 0)
};
// Page content
var border = new Border
{
Width = labelSize.Width,
Height = labelSize.Height,
BorderBrush = Brushes.Black,
BorderThickness = new Thickness(4)
};
FixedPage.SetLeft(border, 0);
FixedPage.SetTop(border, 0);
page.Children.Add(border);
// Next item on page
var tb = new TextBlock
{
Text = "Hello World!",
FontFamily = new FontFamily("Algerian Regular"),
FontSize = 30,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top
};
var content = new Border
{
Child = tb,
BorderBrush = Brushes.Black,
BorderThickness = new Thickness(1)
};
FixedPage.SetLeft(content, 10);
FixedPage.SetTop(content, 10);
page.Children.Add(content);
// Next item on page
var tb2 = new TextBlock
{
Text = "SomethingElse",
FontFamily = new FontFamily("Segoe UI"),
FontSize = 20,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top
};
var content2 = new Border
{
Child = tb2,
BorderBrush = Brushes.Black,
BorderThickness = new Thickness(1)
};
FixedPage.SetLeft(content2, 20);
FixedPage.SetTop(content2, 55);
page.Children.Add(content2);
//// Add the page to the document
//var pc = new PageContent(); // Old way of doing it (.NET 3.5 and earlier)
//((IAddChild)pc).AddChild(page); //
//doc.Pages.Add(pc); //
var pc = new PageContent();
pc.Child = page;
doc.Pages.Add(pc);
// Send it to the printer
FlexPrinter.Print(printerName, labelSize, doc);
Part two - the FixedDocument printer
// Get XpsDocumentWriter
PrintQueue queue = new PrintServer().GetPrintQueue(printerName);
var dw = PrintQueue.CreateXpsDocumentWriter(queue);
dw.Write(document);
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();
}
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 have a simple local rdlc where the page units=in, orientation=landscape and paper size=A4 w=11.69 h=8.27
When I try to retrieve the reports papersize by using
var paperSize = report.GetDefaultPageSettigs().PaperSize;
I get the following returned {[PaperSize A4 Kind=A4 Height=1169 Width=827]}
What I am doing wrong??
You are not doing anything wrong.
As can be seen from the msdn link below:-
http://msdn.microsoft.com/en-us/library/system.drawing.printing.papersize%28v=vs.100%29.aspx
Height and Width values are returned in hundredths of an inch.
Check if PaperSize.IsLandscape return true
Dim ps As New PageSettings() 'Declare a new PageSettings for printing
ps.Landscape = True 'Set True for landscape, False for Portrait
ps.Margins = New Margins(0, 0, 0, 0) 'Set margins
'Choose paper size from the paper sizes defined in ur printer.
'Here we use Linq to quickly choose by name
ps.PaperSize = (From p In ps.PrinterSettings.PaperSizes Where p.PaperName = "A4").First()
'Alternatively you can set the paper size as custom
'ps.PaperSize = new PaperSize("MyPaperSize", 827, 1169);
ReportViewer1.SetPageSettings(ps)
ReportViewer1.SetDisplayMode(DisplayMode.PrintLayout)
'Refresh the report
Me.ReportViewer1.RefreshReport()
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 >