C# Printing overlaps after submiting the form multiple times - c#

So I have a program which I want to create as a POS Program for restaurant (practicing). The main problem is I add everything product from my program and fill out the details that I want (Name, Address etc. for delivery purposes). For the first time everything goes pretty well and it prints out a nice looking receipt but after that. The printPage method get called for the amount of times which I used it before like a queue which remembers all of the past printings and at the end it is overlapping.
Here is the code for my Printer class. Which I call from my Form1.cs
//Printer.cs
public class Printer
{
public Printer(List<Stuff> _StuffList, OtherClass _OtherClass)
{
this._StuffList = _StuffList;
this._OtherClass = _OtherClass;
}
public void printPage(object sender, PrintPageEventArgs e)
{
Graphics graphics = e.Graphics;
//The other stuff below is just receipt drawing.
}
And Here is my Form1.cs
//Form1.cs
Printer printer;
private void btn_print_Click(object sender, EventArgs e)
{
OtherClass = new _OtherClass(data_from_textbox here));
printer = new Printer(StuffList, OtherClass);
printReceipt(printer);
StuffList.Clear();
listBox.Items.Clear();
OtherClass.Clear();
//reset TextBox & Labels
label.Text = "";
textBox.Text = "";
}
private static String FILE = Environment.CurrentDirectory + #"\FILE.txt";
private void printReceipt(Printer printer)
{
FileStream fs = new FileStream(FILE, FileMode.Open);
StreamReader sr = new StreamReader(fs);
stringToPrint = sr.ReadToEnd();
//printDocument.PrinterSettings.PrinterName = "EPSON TM-T20III Receipt";
printDocument.PrinterSettings.PrinterName = "Microsoft Print to PDF";
printDocument.PrintPage += new PrintPageEventHandler(printer.printPage);
printDocument.Print();
sr.Close();
fs.Close();
}

Related

C# print document from two printers on 1 form

On 1 Form I have two buttons (one to print to PDF printer, second to normal printer). I print some bitmap image. However behaviour of the program is strange. Sometimes both buttons work as expected. Sometimes normal printer prints blank, while pdf prints proper, sometimes normal printer do not print anything while pdf printer prints some "code".
Below my code
private void printBtn_Click(object sender, EventArgs e)
{ ... BmpToPrint = new Bitmap(tmp_bmp);
tmp_bmp.Dispose();
string file = "sometext";
pdoc.PrinterSettings.PrinterName = System.Configuration.ConfigurationManager.AppSettings["Printer"];
pdoc.DocumentName = file;
pdoc.DefaultPageSettings.Landscape = false;
ppv.Document = pdoc; //printpreviewdialog ppv, printdocument pdoc
printDialog1.Document = pdoc;
if (printDialog1.PrinterSettings.IsValid) { pdoc.Print(); } }
private void printPdfBtn_Click(object sender, EventArgs e)
{... BmpToPrint = new Bitmap(tmp_bmp);
tmp_bmp.Dispose();
string file = "sometext" + ".pdf";
if (!Directory.Exists(directory)) { directory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); }
pdoc.PrinterSettings.PrinterName = System.Configuration.ConfigurationManager.AppSettings["PdfPrinter"];
pdoc.PrinterSettings.PrintToFile = true;
pdoc.DocumentName = file;
pdoc.PrinterSettings.PrintFileName = Path.Combine(directory, file);
pdoc.DefaultPageSettings.Landscape = false;
ppv.Document = pdoc;
printDialog1.Document = pdoc;
if (printDialog1.PrinterSettings.IsValid) { pdoc.Print(); } }
private void pdoc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
e.Graphics.Clear(Color.White);
Point PktWst = new Point(5, 0);
e.Graphics.DrawImage(BmpToPrint, PktWst);
e.HasMorePages = false;
}
sometimes in pdf instead of image appears this
Sometimes it works perfectly printing image both to pdf and printer while sometimes the same image as before is either not printed/blank printed/ or pdf has this artifacts instead.
Shall I reset some settings while using second printer or clean some data somehow?

C# Printing invoices from a generated, formatted string, one invoice per printer page

I've generated a single long string of invoices formatted as required. I now need to print them out on a printer with one invoice displayed per page.
I've looked at these tutorials/help as well as some code I was:
https://msdn.microsoft.com/en-us/library/cwbe712d%28v=vs.110%29.aspx
https://social.msdn.microsoft.com/Forums/en-US/93e54c4f-fd07-4b60-9922-102439292f52/c-printing-a-string-to-printer?forum=csharplanguage
I've primarily followed the second one.
What I've ended up with is (Working VS C# project with a single form with a single button):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TestPrint
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private string stringToPrint = "Hello\r\nWorld\r\n\r\n<<< Page >>>World\r\nHello";
private void button1_Click(object sender, EventArgs e)
{
// Convert string to strings
string[] seperatingChars = { "<<< Page >>>" };
string[] printString = stringToPrint.Split(seperatingChars, System.StringSplitOptions.RemoveEmptyEntries);
// Connect to the printer
PrintDocument printDocument1 = new PrintDocument(); // Stream to the printer
// Send to printer (reference: https://social.msdn.microsoft.com/Forums/en-US/93e54c4f-fd07-4b60-9922-102439292f52/c-printing-a-string-to-printer?forum=csharplanguage)
foreach (string s in printString)
{
printDocument1.PrintPage += delegate (object sender1, PrintPageEventArgs e1)
{
e1.Graphics.DrawString(s, new Font("Times New Roman", 12), new SolidBrush(Color.Black),
new RectangleF(0, 0, printDocument1.DefaultPageSettings.PrintableArea.Width,
printDocument1.DefaultPageSettings.PrintableArea.Height));
};
try
{
printDocument1.Print();
printDocument1.Dispose();
}
catch (Exception ex)
{
throw new Exception("Exception Occured While Printing", ex);
}
}
}
}
}
I break the long string into it's parts that I want printed to each individual page and then sent that to the printer. This works fine for the first invoice/page but after that it just adds each page on to image of the first (I added the printDocument1.Dispose(); to try and sort that but that didn't work).
What I want to know is how can I print the string as a single string while keeping one invoice per page.
EDIT: How do I generate the string as multi-page image for the printer?
EDIT: complete solution.
public partial class Form1 : Form
{
//string to print
private string stringToPrint = "Hello\r\nWorld\r\n\r\n<<< Page >>>World\r\nHello";
//list of strings/pages
private List<string> pageData = new List<string>();
//enumerator for iteration thru "pages"
private IEnumerator pageEnumerator;
//print document
PrintDocument printDocument1;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Connect to the printer
printDocument1 = new PrintDocument();
//handle events
printDocument1.BeginPrint += new PrintEventHandler(BeginPrint);
printDocument1.PrintPage += new PrintPageEventHandler(PrintPage);
try
{
//do print
printDocument1.Print();
printDocument1.Dispose();
}
catch (Exception ex)
{
throw new Exception("Exception Occured While Printing", ex);
}
}
void BeginPrint(object sender, PrintEventArgs e)
{
// Convert string to strings
string[] seperatingChars = { "<<< Page >>>" };
//generate some dummy strings to print
pageData = stringToPrint.Split(seperatingChars, System.StringSplitOptions.RemoveEmptyEntries).ToList();
// get enumerator for dummy strings
pageEnumerator = pageData.GetEnumerator();
//position to first string to print (i.e. first page)
pageEnumerator.MoveNext();
}
private void PrintPage(object sender, PrintPageEventArgs e)
{
//define font, brush, and print area
Font font = new Font("Times New Roman", 12);
Brush brush = Brushes.Black;
RectangleF area = new RectangleF(0, 0, printDocument1.DefaultPageSettings.PrintableArea.Width,
printDocument1.DefaultPageSettings.PrintableArea.Height);
//print current page
e.Graphics.DrawString(pageEnumerator.Current.ToString(), font, brush, area);
// advance enumerator to determine if we have more pages.
e.HasMorePages = pageEnumerator.MoveNext();
}
}
From what I can see, this line is causing the problem that you described:
printDocument1.PrintPage += delegate(object sender1,
PrintPageEventArgs e1)
Try changing it to:
printDocument1.PrintPage = delegate(object sender1,
PrintPageEventArgs e1)

C# Backgroundworker download progress in label, get bytes in label

I've created an application that patches my game servers files.
However, I've got 3 problems which I can't solve:
When downloading a new patch, it doesn't update the progressbar instantly, but refreshes it after around 30-40 seconds
I want a label to show how much mega bytes they are downloading, and how much they have so far (for example: 122Mb/750Mb
When downloading, I want a label to show ~% of how much it has downloaded so far
I am not sure how to add number 2 and 3, and the number 1 problem just seems ridiculous, because there's nothing that indicates it should refresh after 30-40 seconds in my coding (at least as far as I know)
My backgroundWorker1_DoWork:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Defines the server's update directory
string Server = "http://localhost/dl/game-updates/";
//Defines application root
string Root = AppDomain.CurrentDomain.BaseDirectory;
//Make sure version file exists
FileStream fs = null;
if (!File.Exists("version"))
{
using (fs = File.Create("version"))
{
}
using (StreamWriter sw = new StreamWriter("version"))
{
sw.Write("1.0");
}
}
//checks client version
string lclVersion;
using (StreamReader reader = new StreamReader("version"))
{
lclVersion = reader.ReadLine();
}
decimal localVersion = decimal.Parse(lclVersion);
//server's list of updates
XDocument serverXml = XDocument.Load(#Server + "Updates.xml");
//The Update Process
foreach (XElement update in serverXml.Descendants("update"))
{
string version = update.Element("version").Value;
string file = update.Element("file").Value;
decimal serverVersion = decimal.Parse(version);
string sUrlToReadFileFrom = Server + file;
string sFilePathToWriteFileTo = Root + file;
if (serverVersion > localVersion)
{
Uri url = new Uri(sUrlToReadFileFrom);
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
response.Close();
Int64 iSize = response.ContentLength;
Int64 iRunningByteTotal = 0;
using (System.Net.WebClient client = new System.Net.WebClient())
{
using (System.IO.Stream streamRemote = client.OpenRead(new Uri(sUrlToReadFileFrom)))
{
using (Stream streamLocal = new FileStream(sFilePathToWriteFileTo, FileMode.Create, FileAccess.Write, FileShare.None))
{
int iByteSize = 0;
byte[] byteBuffer = new byte[iSize];
while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
{
streamLocal.Write(byteBuffer, 0, iByteSize);
iRunningByteTotal += iByteSize;
double dIndex = (double)(iRunningByteTotal);
double dTotal = (double)byteBuffer.Length;
double dProgressPercentage = (dIndex / dTotal);
int iProgressPercentage = (int)(dProgressPercentage * 100);
backgroundWorker1.ReportProgress(iProgressPercentage);
}
streamLocal.Close();
}
streamRemote.Close();
}
}
//unzip
using (ZipFile zip = ZipFile.Read(file))
{
foreach (ZipEntry zipFiles in zip)
{
zipFiles.Extract(Root + "\\", true);
}
}
//download new version file
WebClient webClient = new WebClient();
webClient.DownloadFile(Server + "version.txt", #Root + "version");
//Delete Zip File
deleteFile(file);
}
}
}
My backgroundWorker1_ProgressChanged:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
label1.Text = "Downloading updates...";
}
And my backgroundWorker1_RunWorkerCompleted:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
settings_btn.Enabled = true;
start_btn_disabled.Enabled = false;
start_btn_disabled.Visible = false;
start_btn.Visible = true;
start_btn.Enabled = true;
progressBar1.Value = 100;
label1.Text = "Client is up to date!";
}
Also, a side note: I'm also having a bit problems of updating labels in backgroundWorker2_DoWork?
Any ideas?
Here's some working code which updates a label on Form1 using the BackgroundWorker.
Create a new Windows Form project and drop it in your code and it'll work.
It's super ugly, but it works.
After that, just plug your code into the DoWork method and calculate your value and send to ReportProgress.
Keep in mind that the work done in DoWork method is the actual Background Thread.
That means that in that method (DoWork) you cannot access UI (form) elements because they are on the UI thread.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
}
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
button1.Enabled = true;
}
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
backgroundWorker1.RunWorkerAsync();
}
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = e.ProgressPercentage.ToString();
}
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
FakeCountingWork();
}
private void FakeCountingWork()
{
int totalNumber = 100;
int progressCounter = 0;
while (progressCounter < totalNumber)
{
int fakecounter = 0;
for (int x = 0; x < 100000000; x++)
{
fakecounter++;
}
progressCounter++;
backgroundWorker1.ReportProgress(progressCounter);
}
}
}
################################## EDITED TO ADD OTHER FUNCTIONALITY
Okay, here's how you can implement a label which displays the number of bytes downloaded so far.
Add a second label named label2 to your form.
Next alter the following methods from my previous example.
Here we are going to use the UserState to pass an extra value to the ProgressChanged Event. It's very simple. You can see that I'm generating a random number and it will now appear in Label2. This is where you could show your number of bytes.
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = e.ProgressPercentage.ToString();
label2.Text = e.UserState.ToString();
}
private void FakeCountingWork()
{
int totalNumber = 100;
int progressCounter = 0;
Random rnd = new Random();
while (progressCounter < totalNumber)
{
int fakecounter = 0;
for (int x = 0; x < 100000000; x++)
{
fakecounter++;
}
progressCounter++;
updateValue = rnd.Next();
backgroundWorker1.ReportProgress(progressCounter,updateValue);
}
}
I would imagine this is because you are trying to update UI objects on a different thread. HAve you tried using the Dispatcher if using wpf? https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invoke(v=vs.110).aspx
or Invoke if using Winforms? https://msdn.microsoft.com/fr-ca/library/zyzhdc6b(v=vs.85).aspx
Edit:
As #daylight pointed out to be, the UI was being updated in the progresschanged event, which executes on the thread which created the background worker, therefore there shouldn't be an issue regarding threading. See https://msdn.microsoft.com/en-us/library/ka89zff4(v=vs.110).aspx for more info

ThreadStateException occurred

I seem to have a problem with two lines of code in my program.
A ThreadStateException occurs at the lines if (o.ShowDialog() == DialogResult.OK) and if(s.ShowDialog() == DialogResult.OK)
The program is supposed to interpret a made up language, but that part of code has not been made yet. Please help, I have no idea what to do!
public class meow : Form
{
TextBox meowbox = new TextBox();
private string titile;
public meow()
{
titile="Tiger goes Meow";
Size = new Size(500, 600);
Text =titile ;
meowbox.Size = new Size(450, 520);
meowbox.Multiline = true;
meowbox.ScrollBars = ScrollBars.Horizontal;
meowbox.WordWrap = true;
meowbox.Location = new Point(25, 10);
//file
MenuItem feow = new MenuItem("File Meow");
MenuItem oeow = new MenuItem("open Meow");
MenuItem seow = new MenuItem("Save Meow");
feow.MenuItems.Add(oeow);
feow.MenuItems.Add(seow);
//run
MenuItem leow = new MenuItem("Meow");
MenuItem ceow = new MenuItem("Check Meow");
MenuItem reow = new MenuItem("Run Meow");
leow.MenuItems.Add(ceow);
leow.MenuItems.Add(reow);
//menu
MainMenu beow = new MainMenu();
Menu = beow;
beow.MenuItems.Add(feow);
beow.MenuItems.Add(leow);
//put it all meow
Controls.Add(meowbox);
//handlers
oeow.Click += new EventHandler(oeow_Click);
seow.Click += new EventHandler(seow_Click);
/*ceow.Click += new EventHandler(ceow_Click);
reow.Click += new EventHandler(reow_Click);*/
}
protected void oeow_Click( object sender, EventArgs e){
Text="Oeow";
OpenFileDialog o = new OpenFileDialog();
if (o.ShowDialog() == DialogResult.OK)
{
Stream file = o.OpenFile();
StreamReader reader = new StreamReader(file);
char[] data = new char[file.Length];
reader.ReadBlock(data, 0, (int)file.Length);
meowbox.Text = new String(data);
reader.Close();
}
Text = titile;
}
protected void seow_Click(object sender, EventArgs e)
{
Text="seow";
SaveFileDialog s = new SaveFileDialog();
if(s.ShowDialog() == DialogResult.OK)
{
StreamWriter writer = new StreamWriter(s.OpenFile());
writer.Write(meowbox.Text);
writer.Close();
}
Text=titile;
}
public static void Main()
{
Application.Run(new meow());
}
}
If the code you posted is your real program, then the problem is that you aren't setting the thread's apartment state correctly. The main Winforms UI thread must be a single-threaded apartment thread.
Try:
[STAThread]
public static void Main()
{
Application.Run(new meow());
}
Note that ideally, you should just create your Winforms project using the template built into Visual Studio. It will configure the thread correctly for you.

PrintDocument and StreamReader in MVC C#

I'm using a PrintDocument to set a network printer and paper source. I have a Stream to print.
In this case, only a blank page is printed (on good printer and tray), so how bind the StreamReader to the PrintDocument in MVC4 ? Stream is well populated.
public ActionResult ImprimerEtiquettes(int patientId, int venueId, string uf)
{
//do some business logic to have a Stream with parameters
using (StreamReader sr = new StreamReader(fStream))
{
var doc = new PrintDocument();
doc.PrinterSettings.PrinterName = "\\\\imp-dsii\\PI91063";
PaperSource ps = doc.PrinterSettings.PaperSources[2];
doc.DefaultPageSettings.PaperSource = ps;
doc.PrintPage += doc_PrintPage;
doc.Print();
}
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
void doc_PrintPage(object sender, PrintPageEventArgs e)
{
}

Categories