I have a WPF application in which I have 3 forms of prints. In 2 ways, I use directly a window's visual and use PrintVisual(myPanel, "Title") to print it. And in 3rd, I got to print multiple pages so I am using FlowDocument, StackPanel and finally IDocumentPaginatorSource and call PrintDocument to print.
All the code is working perfectly on my system. I can perform Print on OneNote and XPS and it works as expected. But the same app, when I try to run on other system it shows blank page for all 3 prints. PrintVisual is supported on .NET 3.0, 3.5, 4.0, 4.5, so I can't find a reason for it not to work.
I will also share my some code, for better clarity :
// 1 PRINT
public void PrintRegister()
{
PrintDialog pd = new PrintDialog();
if (pd.ShowDialog() == true)
pd.PrintVisual(this, "Register Window");
return;
}
// 2 PRINT
public static void PrintAttendanceOf(System.Data.DataRow r1) {
PrintLayoutWindowPORT plw = PrintUtility.CreatePrintLayoutWindowPORTObject(r1); // PORTRAIT
Canvas p1 = PrintUtility.CloneCanvas(plw._PrintCanvas, 5);
Grid myPanel = new Grid();
myPanel.Margin = new Thickness(10);
myPanel.Children.Add(p1);
PrintDialog pd = new PrintDialog();
pd.PageRangeSelection = PageRangeSelection.AllPages;
PrintQueue pq = pd.PrintQueue;
pq.DefaultPrintTicket.PageOrientation = PageOrientation.Portrait;
pd.PrintTicket = pq.DefaultPrintTicket;
double pageWidth = pd.PrintableAreaWidth;
double pageHeight = pd.PrintableAreaHeight;
myPanel.Measure(new Size(pageWidth, pageHeight));
//myPanel.Arrange(new Rect(new Point(1, 1), myPanel.DesiredSize));
myPanel.UpdateLayout();
if (pd.ShowDialog().GetValueOrDefault(false))
{
pd.PrintVisual(myPanel, "Attendance Chart");
}
pd = null;
plw.Close();
plw = null;
myPanel = null;
p1 = null;
return;
}
Code for the 3rd Print i.e. Multiple Pages is quiet long, hence have not added it now here. If required, can post it.
Can anyone help me know the reason for printing blank page and no contents on other system. I feel some sort of compatibility or system or resource may be required or what else?
Any help is highly appreciated.
Thanks
Related
In RichTextBox of my WPF app, following print method is creating unexpected line breaks. Question: What I may be missing here, and how can we fix the issue?
For example, when I enter the following text in the RichTextBox (RTB), the RTB looks like as shown in image 1. But when I call the following two print methods the first one does not create the unexpected line breaks, but the second method does create unexpected line breaks:
MainWindow.xaml
<StackPanel>
<RichTextBox Name="richTB" />
<Button Click="PrintCommand1">Print RTB Content</Button>
<Button Click="PrintCommand2">Print RTB Content</Button>
</StackPanel>
Method 1
private void PrintCommand1(Object sender, RoutedEventArgs args)
{
PrintDialog pd = new PrintDialog();
if ((pd.ShowDialog() == true))
{
pd.PrintVisual(richTB as Visual, "printing as visual");
}
}
Method 2
private void PrintCommand2(Object sender, RoutedEventArgs args)
{
PrintDialog pd = new PrintDialog();
if ((pd.ShowDialog() == true))
{
pd.PrintDocument((((IDocumentPaginatorSource)richTB.Document).DocumentPaginator), "printing as paginator");
}
}
The text I enter [Note: There is only one line break]
This is a test for testing purpose only. Another test: x6. Let us do some background and foreground colors.
This is a new line with formatting, as well.
Snapshot of the RichTexBox with above text
Snapshot of "Print to PDF" (on Windows 10) using Method 1 [Printed correctly with one real line break]
Snapshot of "Print to PDF" (on Windows 10) using Method 2 [Printed incorrectly with unexpected line breaks]
Because of the DocumentPaginator class takes context of the FlowDocument and split in into multiple pages to get desired result some of FlowDocument parameters should be configured before printing:
private void PrintCommand2(Object sender, RoutedEventArgs args)
{
var pd = new PrintDialog();
if (pd.ShowDialog() == true)
{
FlowDocument doc = richTB.Document;
// Save all settings that will be configured for printing.
double pageHeight = doc.PageHeight;
double pageWidth = doc.PageWidth;
double columnGap = doc.ColumnGap;
double columnWidth = doc.ColumnWidth;
// Make the FlowDocument page match the printed page.
doc.PageHeight = pd.PrintableAreaHeight;
doc.PageWidth = pd.PrintableAreaWidth;
doc.ColumnGap = 5;
// Set the minimum desired width of the column in the System.Windows.Documents.FlowDocument.
doc.ColumnWidth = doc.PageWidth - doc.ColumnGap - doc.PagePadding.Left - doc.PagePadding.Right;
pd.PrintDocument(((IDocumentPaginatorSource)doc).DocumentPaginator, "A Flow Document");
// Reapply the old settings.
doc.PageHeight = pageHeight;
doc.PageWidth = pageWidth;
doc.ColumnGap = columnGap;
doc.ColumnWidth = columnWidth;
}
}
With respect to Matthew MacDonald this way of the flow document content printing and more advanced techniques described in his book Pro WPF 4.5 in C# Windows Presentation Foundation in .NET 4.5 (Chapter 29).
I'm currently trying to print from a .NET Core 3.1 Console App on a Brother QL-570 Label Printer on Linux.
My Code is the following:
class Program
{
static void Main(string[] args)
{
var printer = args.Length > 0 ? args[0] : "Brother QL-570";
using (PrintDocument pd = new PrintDocument())
{
var s = new PaperSize("Custom", 244, 300);
s.RawKind = 256;
pd.PrinterSettings.PrinterName = printer;
pd.DefaultPageSettings.PaperSize = s;
pd.DefaultPageSettings.Margins = new Margins(12, 12, 12, 12);
pd.DefaultPageSettings.Landscape = false;
pd.OriginAtMargins = true;
pd.DocumentName = "Label";
pd.OriginAtMargins = true;
Console.WriteLine(pd.DefaultPageSettings.PaperSize);
Console.ReadLine();
pd.PrintPage += Pd_PrintPage;
if (!pd.PrinterSettings.IsValid)
{
Console.WriteLine("Invalid printer settings.");
return;
}
pd.Print();
}
Console.ReadLine();
}
private static void Pd_PrintPage(object sender, PrintPageEventArgs e)
{
Console.WriteLine($"Res: {e.PageSettings.PrinterResolution}");
Console.WriteLine($"pa: {e.PageSettings.PrintableArea}");
Console.WriteLine($"bounds: {e.PageBounds}");
Console.WriteLine($"mb: {e.MarginBounds}");
Console.WriteLine(e.PageSettings.PaperSize);
e.HasMorePages = false;
var b = e.MarginBounds;
e.Graphics.PageUnit = GraphicsUnit.Display;
e.Graphics.DrawRectangle(new Pen(Brushes.Black, 12), b.X, b.Y, b.Width, b.Height);
}
}
(When trying to run, pass your printer name as first command line argument)
The aim is to print a 62mm wide and 3 inches (76,2mm) long label on a 62mm endless roll. On this label, the outer print margins shall be drawn with a rectangle in black.
Situation:
When executed on Windows, everything works fine. Even when connecting Windows to a Label Printer which is running on CUPS on my Raspberry PI, the label comes out fine, the output is as expected.
When on Linux, things just do not work. The Printer blinks red, no label is printed. Interestingly, in the PrintPage-Event, the PrintMargins are empty on Linux (X=Y=Width=Height=0), whereas on Windows the correct values are filled in. The same applies for the hard margin properties.
I'm using the printer-drivers-ptouch package on my Raspberry PI as driver for the brother P-Touch QL-570. In .NET Core I use the System.Drawing.Common package to use the PrintDocument APIs.
Can you provide me with more information or details on the following?
Is this probably more a driver issue or a C# issue?
Is my way of specifying the custom paper size valid for Linux, too?
I had the same issue turns out that you need to open /etc/cups/ppd/Brother-(YOUR VERSION).ppd then add the custom feed you want to use to that file.. I wanted to use 29x90 and edited the file to read..
*PageSize 29x90/29mmx90(1.1"x3.5):
after that I went to the printer settings and selected the correct page setting then application worked..
I am trying to print text to display vertical in Windows Forms Host. The label is printing with report viewer in WPF. Here is my code:
// boolean is based on true or false, when printing labels
private bool _isReportViewerLoaded;
// method to display data in .rdlc
private void ReportViewer_Load(object sender, EventArgs e)
{
// if equal false run this code isReportViewerLoaded
if (!_isReportViewerLoaded)
{
// get the lot based on the parameter Id
Lot lot = BottleLotRespository.GetLotById(this.Parameter);
// settings the page settings
PageSettings pg = new PageSettings();
pg.PrinterSettings
.DefaultPageSettings
.Margins = new Margins(0, 0, 0, 0);
pg.Landscape = false;
PaperSize size = new PaperSize("110.0 x 74.0", 433, 100);
BottleLotDataSet bottleLotDataSet = new BottleLotDataSet();
DataTable reportDataTable = bottleLotDataSet.LotDataTable;
DataRow lotRow = reportDataTable.NewRow();
lotRow["Id"] = lot.Id;
lotRow["Number"] = lot.Number.ToString();
reportDataTable.Rows
.Add(lotRow);
bottleLotDataSet.BeginInit();
this._reportViewer.SetPageSettings(pg);
this.reportDataSource.Name = "DataSet1";
this.reportDataSource.Value = reportDataTable;
this._reportViewer
.LocalReport
.DataSources
.Add(this.reportDataSource);
this._reportViewer
.LocalReport
.ReportEmbeddedResource = "BottleLotWPF.View.Report1.rdlc";
bottleLotDataSet.EndInit();
_reportViewer.RefreshReport();
_isReportViewerLoaded = true;
}
}
My problem is that the Report1.rdlc is not allowing me to rotate the text and there is no settings for it. Is there away of adding a setting to it to rotate the text?
In RDLC we have the option to print vertically it seems.
please take look at the existing thread here and see if it helps.
display-text-vertically-start-
I'm using PrintDocument to print out multiple pages that each have one control on. So far I'm able to print them all out on individual sheets as desired, however I'm unable to center the controls in the middle of the pages and it always shows in the top corner of the page. I'll post my code below.
var dialog = new PrintDialog();
var queue = GetPrinterQueue(pPrinterId);
if (queue == null)
return;
dialog.PrintQueue = queue;
dialog.PrintTicket.PageOrientation = paperOrientation
? PageOrientation.Portrait
: PageOrientation.Landscape;
var document = new FixedDocument();
var fixedPage = new FixedPage();
fixedPage.Children.Add(front);
//fixedPage.Measure(size);
//fixedPage.Arrange(new Rect());
//fixedPage.UpdateLayout();
var pageContent = new PageContent();
((IAddChild)pageContent).AddChild(fixedPage);
document.Pages.Add(pageContent);
dialog.PrintDocument(document.DocumentPaginator, "Badge");
That is the bare minimum to make it print out a control per sheet, to make it simpler I have taken out the parts that print to different pages, for the sake of this it only needs to print one.
I've tried changing what is passed into .Arrange() and it makes no difference, what am I missing?
Thanks
Below is the process I worked in Windows forms for printing.
I used PrintDocument class. It contains PrintPage event and I used that to draw the graphics of what I need to print and obtained the result successfully as I expected.
Below is the code:
public PrintDocument Printing
{
m_printDocument = new PrintDocument();
m_printDocument.PrintPage += new PrintPageEventHandler(OnPrintPage);
}
The code for OnPrintPage as follows:
protected virtual void OnPrintPage(object sender, PrintPageEventArgs e)
{
//Image img = I have the things to be printing in the form of image.
e.Graphics.DrawImage(img, new Point(0,0));
}
In WPF:
I am working with Fixed document and by using the below code I can print
PrintDialog print = new PrintDialog();
print.PrintDocument(FixedDocument.DocumentPaginator, "Print") //Where Fixed document contains the data to be printed.
This results is insufficient memory to continue the execution of the program.
But I got Fixed document without any problem.
Any solutions ...?
I hope the similar thing as like Windows form would be there in WPF too...
I used to get this when my pages contained lots of visual elements (drawings/images/ complex diagrams). Instead of printing the complete document at once (which can lead to out of memory)
print.PrintDocument(FixedDocument.DocumentPaginator, "Print")
I printed one of its page.
PrintQueue selectedPrntQueue = printDialog.PrintQueue;
XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(selectedPrntQueue);
SerializerWriterCollator collator = writer.CreateVisualsCollator();
collator.BeginBatchWrite();
var paginator = FixedDocument.DocumentPaginator;
FixedPage fixedPage = paginator.GetFixedPage(printedPageCount)
ContainerVisual newPage = new ContainerVisual();
Size sz = new Size(pageSize.Height.Value, pageSize.Width.Value);
fixedPage.Measure(sz);
fixedPage.Arrange(new Rect(new Point(), sz));
fixedPage.UpdateLayout();
newPage.Children.Add(fixedPage);
collator.Write(newPage);
I had to do GC after printing few pages (my magic number was 10).
You may need to tweak the this up to your requirement.