mono C# print persian text ubuntu - c#

I am using mono-develop under Ubuntu 14.04.
In my project I need to print Persian documents.
We are using native .net package system.drawing.
I ran the following code under Windows (mono which was installed on Windows) and
I had absolutely NO PROBLEM, but here under Ubuntu letters are not going to be joined together to create words. The output is something like this:
I know somehow it is related to my OS. Please help me to solve this.
Here is my code:
namespace printPage{
public class PrintClass
{
PrintDialog printDialog;
PrintDocument printDocument;
PageSetupDialog psd;
public PrintClass()
{
printDialog = new PrintDialog ();
printDocument = new PrintDocument();
printDialog.Document = printDocument;
printDocument.PrintPage +=
new System.Drawing.Printing.PrintPageEventHandler(CreateReceipt);
DialogResult result = printDialog.ShowDialog();
if (result == DialogResult.OK)
printDocument.Print();
}
public void CreateReceipt(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
//string to be printed out
string txt = "با سلام و خسته نباشید";
Graphics graphic = e.Graphics;
Font font = new Font("Arial unicode MS", 20, FontStyle.Regular); //must use a mono spaced font as the spaces need to line up
float fontHeight = font.GetHeight();
int startX = 100;
int startY = 100;
StringFormat sf = new StringFormat();
sf.FormatFlags = StringFormatFlags.DirectionRightToLeft;
sf.FormatFlags = StringFormatFlags.DisplayFormatControl;
int faLCID = new System.Globalization.CultureInfo("fa-IR").LCID;
sf.SetDigitSubstitution(faLCID, StringDigitSubstitute.National);
graphic.DrawString( txt, font, new SolidBrush(Color.Black), startX, startY, sf);
e.HasMorePages = false;
}
}
class MainClass
{
static void Main()
{
PrintClass p = new PrintClass ();
}
}
}

Related

Cannot print Arabic/Persian letters correctly in C#

I have problems with printing typing Arabic letters in C# using printdocument.
Here's my code:
PrintDocument pd;
PaperSize ps;
void pd_Factor(object sender, PrintPageEventArgs e)
{
Graphics g = e.Graphics;
Font vazir = new Font("Vazir Code FD", 12, FontStyle.Regular);
SolidBrush sb = new SolidBrush(Color.Black);
string a = "سلام";
g.DrawString(a, vazir, sb, 200, 330);
}
private void btnDone_Click(object sender, EventArgs e)
{
PrintDocument pd = new PrintDocument();
PaperSize ps = new PaperSize("Factor", 723, 1024);
pd.PrintPage += new PrintPageEventHandler(pd_Factor);
pd.PrintController = new StandardPrintController();
pd.DefaultPageSettings.Margins.Left = 0;
pd.DefaultPageSettings.Margins.Right = 0;
pd.DefaultPageSettings.Margins.Top = 0;
pd.DefaultPageSettings.Margins.Bottom = 0;
pd.DefaultPageSettings.PaperSize = ps;
printDialog1.Document = pd;
if (printDialog1.ShowDialog() == DialogResult.OK)
{
try
{
pd.Print();
}
catch (Exception)
{
}
}
}
Sadly, the above code prints this way:
By the way, I tried
StringFormat format = new StringFormat();
format.FormatFlags = StringFormatFlags.DirectionRightToLeft;
g.DrawString(a, vazir, sb, 200, 330, format);
It just make the position of anchor going from up-left to up-right this way:
So, I thought with myself, I should reverse it:
string a = "سلام";
string b = "";
for (int i = a.Length - 1; i > -1; i--)
{
b += Convert.ToString(a[i]);
}
And it made the text looks like this:
It still looks wrong but it goes better.
However I tried adding characters from left-to-right using character map.
And my code changed to:
string a = "ﻡﺎﻠﺳ";
And it prints correctly:
By the way, I have an input and I don't know what is the text going to be; so, I can't use character map for that.
Also it looks impossible or hard to code to replace the text; at least I need these characters:
My question is: How to print correctly?
Note: The font I'm using is this; However I tried using Tahoma too, but the problem still persists.
Seems strange, But magically Problem Solved!
I tried using another app to test called "Print2Pdf" and the text prints correctly, Maybe it's a bug of Microsoft XPS writer/reader that cannot print/read Arabic/Persian letters.
*Sorry for not providing link to Print2Pdf as I couldn't find the original website; If someone knows the original please add link; Thanks

Programmatically provide a filepath as input file for “Microsoft Print to PDF” printer

Desired result
I want to print a file to a new PDF using the Windows 10 printer "Microsoft Print to PDF" which is installed by default.
When you select this printer as your default printer and use your context menu on a file and select Print, it only asks for a save directory and name. After that, it immediately converts to PDF and saves the file.
As long as MS Office is installed, this works for Word, Excel, PowerPoint file types. But also for common image types and normal text files.
I'd like to automate this by providing a default path.
What I already tried
Stackoverflow already has this related question, but it does not address my specific problem and is rather incomplete and not working.
But I came up with this C# console program which uses the PDF printer to produce a new PDF on my desktop with "Hello World" as string
namespace PrintToPdf_Win10
{
using System;
using System.Drawing;
using System.Drawing.Printing;
class Program
{
public static void Main(string[] args)
{
PrintDocument printDoc = new PrintDocument
{
PrinterSettings = new PrinterSettings
{
PrinterName = "Microsoft Print to PDF",
PrintToFile = true,
PrintFileName = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/test.pdf"
}
};
printDoc.PrintPage += printDoc_PrintPage;
printDoc.Print();
Console.ReadKey(true);
}
static void printDoc_PrintPage(object sender, PrintPageEventArgs e)
{
e.Graphics.DrawString("Hello World", new Font("Arial", 12), Brushes.Black, 50, 50);
}
}
}
Problem
How do I set the content of - let's say a Word file - as input for my printDoc object?
Is there a generic way to set printDoc by providing only a filePath to my file I want to print from? Or do I have to create a custom function for each possible filetype families like:
Office filetypes (doc, docx, xls, xlsx, xlsm, ppt, pptx etc.)
Image filetypes (png, bmp, jpg)
text files (txt, rtf, ini)
Here is simple solution how to print image or text (it could help you with formats like png, bmp, jpg, txt, ini)
private static StreamReader streamToPrint;
static void Main(string[] args)
{
string printFormat;
printFormat = "txt";
try
{
streamToPrint = new StreamReader(#"D:\TestText.txt");
PrintDocument printDoc = new PrintDocument
{
PrinterSettings = new PrinterSettings
{
PrinterName = "Microsoft Print to PDF",
PrintToFile = true,
PrintFileName = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/test.pdf"
}
};
printDoc.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("A4", 210, 290);
printDoc.PrinterSettings.DefaultPageSettings.Landscape = false;
printDoc.PrinterSettings.DefaultPageSettings.Margins.Top = 0;
printDoc.PrinterSettings.DefaultPageSettings.Margins.Left = 0;
switch (printFormat)
{
case "jpg":
printDoc.PrintPage += printDoc_PrintImage;
break;
case "txt":
printDoc.PrintPage += printDoc_PrintText;
break;
default:
break;
}
printDoc.Print();
}
finally
{
streamToPrint.Close();
}
Console.ReadKey(true);
}
static void printDoc_PrintImage(object sender, PrintPageEventArgs e)
{
Image photo = Image.FromFile(#"D:\TestImage.jpg");
Point pPoint = new Point(0, 0);
e.Graphics.DrawImage(photo, pPoint);
}
static void printDoc_PrintText(object sender, PrintPageEventArgs e)
{
Font printFont;
printFont = new Font("Arial", 10);
float linesPerPage = 0;
// Calculate the number of lines per page.
linesPerPage = e.MarginBounds.Height / printFont.GetHeight(e.Graphics);
float yPos = 0;
int count = 0;
float leftMargin = e.MarginBounds.Left;
float topMargin = e.MarginBounds.Top;
string line = null;
while (count < linesPerPage &&
((line = streamToPrint.ReadLine()) != null))
{
yPos = topMargin + (count *
printFont.GetHeight(e.Graphics));
e.Graphics.DrawString(line, printFont, Brushes.Black,
leftMargin, yPos, new StringFormat());
count++;
}
// If more lines exist, print another page.
if (line != null)
e.HasMorePages = true;
else
e.HasMorePages = false;
}
As you know docx, xlsx are like zip files and you can unzip and get content as xml. So, it's much work to to if you want to print them

Print the entire area of the control with C#

This is not a duplicat question- the diffenece beetween my question an the others one is my Controler contail a scroller, so they are more informations can't be printed.
I have a C# application that contains a main form name MainForms. This MainForms has a control mainDisplay. I want to print the entire information what we found on the mainDisplay to the printer.
The problem is the information on the the control is too big, and I have to scroll to see all information.
Someone have any function that allow me to print this control MainDisplay with entire information in it?
This the printscreen of the area of my MainDisplay at the right you see the scrollbar:
I use this Function (Source : Printing a control)
private static void PrintControl(Control control)
{
var bitmap = new Bitmap(control.Width, control.Height);
control.DrawToBitmap(bitmap, new Rectangle(0, 0, control.Width, control.Height));
var pd = new PrintDocument();
pd.PrintPage += (s, e) => e.Graphics.DrawImage(bitmap, 100, 100);
pd.Print();
}
But my problem still can't print all the informations contain in my control, it's just print a small erea, still need print more informations which are not printed.
I find the solution. This is the steps i do :
1 - We have a mainForm, and this main form contain a control mainDisplay with a specific dimension and area, let's say this dimensions is smaller and we get scroll.
2- What i do is i make this mainDisplay Empty.
3- i create an other Control myControlToDisplay. I draw and i put all fields i want without scroll, so this one myControlToDisplay will have a big dimension.
4- on the star-up of my application, i tell to the mainDisplay to load myControlToDisplay. This time all the content of myControlToDisplay will be display on mainDisplay with a scroll. Because mainDisplay have a small area.
5- I write this functions :
Bitmap MemoryImage;
PrintDocument printDoc = new PrintDocument();
PrintDialog printDialog = new PrintDialog();
PrintPreviewDialog printDialogPreview = new PrintPreviewDialog();
Control panel = null;
public void Print(Control pnl)
{
DateTime saveNow = DateTime.Now;
string datePatt = #"yyyy-M-d_hh-mm-ss tt";
panel = pnl;
GetPrintArea(pnl);
printDialog.AllowSomePages = true;
printDoc.PrintPage += new PrintPageEventHandler(Print_Details);
printDialog.Document = printDoc;
printDialog.Document.DocumentName = "Document Name";
//printDialog.ShowDialog();
if (printDialog.ShowDialog() == DialogResult.OK)
{
printDoc.Print();
}
}
public void PrintPreview(Control pnl)
{
DateTime saveNow = DateTime.Now;
string datePatt = #"yyyy-M-d_hh-mm-ss tt";
panel = pnl;
GetPrintArea(pnl);
printDoc.PrintPage += new PrintPageEventHandler(Print_Details);
printDialogPreview.Document = printDoc;
printDialogPreview.Document.DocumentName = "Document Name";
//printDialog.ShowDialog();
if (printDialogPreview.ShowDialog() == DialogResult.OK)
{
printDoc.Print();
}
}
private void Print_Details(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
RectangleF marginBounds = e.MarginBounds;
DateTime saveNow = DateTime.Now;
string datePatt = #"M/d/yyyy hh:mm:ss tt";
//String dtString = saveNow.ToString(datePatt);
// create header and footer
string header = "Put all information you need to display on the Header";
string footer = "Print date : " + saveNow.ToString(datePatt);
Font font = new Font("times new roman", 10, System.Drawing.FontStyle.Regular);
Brush brush = new SolidBrush(Color.Black);
// measure them
SizeF headerSize = e.Graphics.MeasureString(header, font);
SizeF footerSize = e.Graphics.MeasureString(footer, font);
// draw header
RectangleF headerBounds = new RectangleF(marginBounds.Left-80, marginBounds.Top-80, marginBounds.Width, headerSize.Height);
e.Graphics.DrawString(header, font, brush, headerBounds);
// draw footer
RectangleF footerBounds = new RectangleF(marginBounds.Left-80, marginBounds.Bottom - footerSize.Height+80, marginBounds.Width, footerSize.Height);
e.Graphics.DrawString(footer, font, brush, footerBounds);
// dispose objects
font.Dispose();
brush.Dispose();
}
public void GetPrintArea(Control pnl)
{
MemoryImage = new Bitmap(pnl.Width, pnl.Height);
Rectangle rect = new Rectangle(0, 0, pnl.Width, pnl.Height);
pnl.DrawToBitmap(MemoryImage, new Rectangle(0, 0, pnl.Width, pnl.Height));
}
protected override void OnPaint(PaintEventArgs e)
{
if (MemoryImage != null)
{
e.Graphics.DrawImage(MemoryImage, 0, 0);
base.OnPaint(e);
}
}
void PrintDoc_PrintPage(object sender, PrintPageEventArgs e)
{
Rectangle pageArea = e.PageBounds;
Rectangle m = e.MarginBounds;
if ((double)MemoryImage.Width / (double)MemoryImage.Height > (double)m.Width / (double)m.Height) // image is wider
{
m.Height = (int)((double)MemoryImage.Height / (double)MemoryImage.Width * (double)m.Width);
}
else
{
m.Width = (int)((double)MemoryImage.Width / (double)MemoryImage.Height * (double)m.Height);
}
e.Graphics.DrawImage(MemoryImage, m);
}
6 -And finally we suppose that we have two buttons, one to Print and the other one to print preview.
You just have to call this function :
private void PrintButton_Click(object sender, EventArgs e)
{
try
{
Print(mainDisplay.getCurentPanel());
}
catch (Exception exp)
{
MessageBox.Show("Error: \n" + exp.Message);
}
}
private void PrintPreviewButton_Click(object sender, EventArgs e)
{
try
{
PrintPreview(mainDisplay.getCurentPanel());
}
catch (Exception exp)
{
MessageBox.Show("Error: \n" + exp.Message);
}
}
Hope it will help someone :)
good luck

PrintDocument coming up blank

I have this method that should generate what I need to print:
private void myPrintDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
e.Graphics.PageUnit = GraphicsUnit.Inch;
e.Graphics.DrawImage(makeBarcode(), 500, 1000);
e.Graphics.DrawString("Do Not Seperate", makeFont(), Brushes.Black, 100, 2);
e.Graphics.DrawString("Choking Hazard", makeFont(), Brushes.Black, 200, 2);
}
How ever when I print it, it comes up blanks and when I look at it in PrintPreviewDialog it comes up blanket. What I am missing here?
This is my constructor by the way:
public Form1()
{
InitializeComponent();
this.myPrintDocument.PrintPage += new
System.Drawing.Printing.PrintPageEventHandler
(this.myPrintDocument_PrintPage);
}
For Mark
private Image makeBarcode()
{
InventoryBLL ibll = new InventoryBLL();
Barcode b = new Barcode();
b.IncludeLabel = true;
b.Height = 35;
b.Width = 200;
b.BackColor = Color.White;
b.ForeColor = Color.Black;
b.Alignment = BarcodeLib.AlignmentPositions.CENTER;
return b.Encode(TYPE.CODE128, ibll.getFNSKU(txtASIN.Text));
}
private Font makeFont()
{
Font myFont = new Font("arial", 10);
return myFont;
}
e.Graphics.PageUnit = GraphicsUnit.Inch;
...
e.Graphics.DrawString("Choking Hazard", ..., 200, 2);
That string is going to print at 200 inches. Somewhat safe to assume that your paper isn't that big, 8 inch is about typical. You cannot see what's off the paper. Consider changing the PageUnit or using much smaller floating point print positions.

How to print a full size image in c#

I am trying to print an image in C#. It is a full 8.5x11 size tiff created by Adobe Acrobat from a PDF. When I print it with C# using the code below, it prints correct vertically, but not horizontally, where it is pushed over about a half inch. I set the origin of the image to 0,0. Am I missing something?
private FileInfo _sourceFile;
public void Print(FileInfo doc, string printer, int tray)
{
_sourceFile = doc;
PrintDocument pd = new PrintDocument();
pd.PrinterSettings.PrinterName = printer;
pd.DocumentName = _sourceFile.FullName;
using (Image img = Image.FromFile(_sourceFile.FullName)) {
if (img.Width > img.Height) {
pd.DefaultPageSettings.Landscape = true;
}
}
pd.PrintPage += PrintPage;
foreach (PaperSource ps in pd.PrinterSettings.PaperSources) {
if (ps.RawKind == tray) {
pd.DefaultPageSettings.PaperSource = ps;
}
}
pd.Print();
}
private void PrintPage(object o, PrintPageEventArgs e)
{
using (System.Drawing.Image img = System.Drawing.Image.FromFile(_sourceFile.FullName)) {
Point loc = new Point(0, 0);
e.Graphics.DrawImage(img, loc);
}
}
look at the code from this below for a good example this code is from this link below
Print Image in C#
private void PrintImage()
{
PrintDocument pd = new PrintDocument();
pd.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
pd.OriginAtMargins = false;
pd.DefaultPageSettings.Landscape = true;
pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
printPreviewDialog1.Document = pd;
printPreviewDialog1.ShowDialog();
//pd.Print();
}
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
double cmToUnits = 100 / 2.54;
e.Graphics.DrawImage(bmIm, 100, 1000, (float)(15 * cmToUnits), (float)(10 * cmToUnits));
}
private void button5_Click(object sender, EventArgs e)
{
PrintImage();
}

Categories

Resources