From: Zach on 12 Jun 2010 20:23 Say I have PrintDocument pd = new PrintDocument(); Say I have a file c:\trialk.txt How do I associate the two in order to privide input for ptinting? Thanks, Zach
From: Peter Duniho on 13 Jun 2010 00:40 Zach wrote: > Say I have PrintDocument pd = new PrintDocument(); > Say I have a file c:\trialk.txt > How do I associate the two in order to privide input for ptinting? What kind of association are you looking for? If you want to print the text found in the file, you need to do that yourself. Use the File class, or FileStream, or StreamReader, or whatever to read the text from the file. Once you have a string or strings from the file representing the text found in the file, then you need to handle the Print event for the document and draw the text to the page using the Graphics.DrawString() method or similar. Pete
From: Zach on 13 Jun 2010 03:13 "Peter Duniho" <NpOeStPeAdM(a)NnOwSlPiAnMk.com> wrote in message news:bNydnSYxqcio_InRnZ2dnUVZ_q2dnZ2d(a)posted.palinacquisition... > Zach wrote: >> Say I have PrintDocument pd = new PrintDocument(); >> Say I have a file c:\trialk.txt >> How do I associate the two in order to privide input for ptinting? > > What kind of association are you looking for? > > If you want to print the text found in the file, you need to do that > yourself. Use the File class, or FileStream, or StreamReader, or whatever > to read the text from the file. Once you have a string or strings from > the file representing the text found in the file, then you need to handle > the Print event for the document and draw the text to the page using the > Graphics.DrawString() method or similar. > > Pete Pete, could you pls look through the code below for me. It works but that might not mean that it is ok. using System.ComponentModel; using System.Drawing; using System.Drawing.Printing; using System.IO; using System.Windows.Forms; namespace InfraStructure { public class Print:Form { Font printFont; StreamReader streamToPrint; public Print(out bool result) { result = execute(); } bool execute() { // select file OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Open a file"; ofd.InitialDirectory = "c:\\"; ofd.Filter = "txt files (*.txt)|*.txt"; if (DialogResult.OK == ofd.ShowDialog(this)) { streamToPrint = new StreamReader(ofd.FileName); } else return false; // font dialog FontDialog font = new FontDialog(); if (DialogResult.OK == font.ShowDialog(this)) { printFont = font.Font; } else return false; //setting margins PageSetupDialog setup = new PageSetupDialog(); PrintDocument document = new PrintDocument(); setup.Document = document; setup.ShowDialog(); //select printer PrintDialog select_printer = new PrintDialog(); select_printer.Document = document; if (select_printer.ShowDialog() == DialogResult.OK) { try { document.PrintPage += new PrintPageEventHandler(document_PrintPage); document.Print(); streamToPrint.Close(); } catch { return false; } } else return false; return true; } void document_PrintPage(object sender, PrintPageEventArgs ev) { float linesPerPage = 0; float yPos = 0; int count = 0; float leftMargin = ev.MarginBounds.Left; float topMargin = ev.MarginBounds.Top; string line = null; linesPerPage = ev.MarginBounds.Height / printFont.GetHeight(ev.Graphics); while (count < linesPerPage && ((line = streamToPrint.ReadLine()) != null)) { yPos = topMargin + (count * printFont.GetHeight(ev.Graphics)); ev.Graphics.DrawString(line, printFont, Brushes.Black, leftMargin, yPos, new StringFormat()); count++; } if (line != null) ev.HasMorePages = true; else ev.HasMorePages = false; } } }
From: Peter Duniho on 13 Jun 2010 03:39 Zach wrote: > Pete, could you pls look through the code below for me. It works > but that might not mean that it is ok. Well, after a quick glance, I only see one real problem in terms of obtaining exactly the output you expect, and that one being relatively minor. That is, it appears to me that the code will potentially print a blank page at the end. If the number of lines of text in the file is exactly a multiple of the lines you can print on a page, then your code will incorrectly report it has additional text to print, when in fact there's none, causing one last blank page to be printed. In general, my approach is to create a "print status" class that persists the state of printing between pages. This would allow you to pre-fetch a line of text even if you've reached the end of the page, so that you can detect the end of the stream even in that case. The class would then contain that line of text that was read, so that it's not lost before you continue on to the next page. Such a class could also store pagination information, such as text height and the font, along with the input stream, etc. (lines per page may still need to be recalculated, if you are using per-page print settings, but otherwise that could be cached as well). You also have several places in your code where you present a dialog and then return a failure if the user cancels the dialog. Not a problem per se, but my preference, rather than code that looks like this (as yours does): if (dialog.ShowDialog() == DialogResult.OK) { // do something } else { return false; } to instead just write it like this: if (dialog.ShowDialog() != DialogResult.OK) { return false; } // do something That is, just make the failure case return, and the success case be the main flow through the method. IMHO this makes the method more readable. A somewhat more significant problem is that you are failing to dispose a number of disposable objects. Most never get disposed at all (dialogs, and your font), but even the StreamReader is disposed only on success. You should use "using" statements liberally to address this problem. Finally, you should not be catching all exceptions around your call to Print(). You should limit your "catch" clause to only those exceptions that are expected and don't represent a terminal failure. Catching any and all exceptions and just ignoring them can lead to very hard-to-reproduce problems and subtle data corruption bugs. This sort of problem is very rare, but when it happens it's very hard to figure out if the code is simply silently catching all exceptions, even those that were not anticipated at the time the code was written. It's much better to just write the code more robustly in the first place. Pete
From: Zach on 13 Jun 2010 04:22
"Peter Duniho" <NpOeStPeAdM(a)NnOwSlPiAnMk.com> wrote in message news:maadnQA5To3cFonRnZ2dnUVZ_rOdnZ2d(a)posted.palinacquisition... > Zach wrote: >> Pete, could you pls look through the code below for me. It works >> but that might not mean that it is ok. > > Well, after a quick glance, I only see one real problem in terms of > obtaining exactly the output you expect, and that one being relatively > minor. That is, it appears to me that the code will potentially print a > blank page at the end. If the number of lines of text in the file is > exactly a multiple of the lines you can print on a page, then your code > will incorrectly report it has additional text to print, when in fact > there's none, causing one last blank page to be printed. > > In general, my approach is to create a "print status" class that persists > the state of printing between pages. This would allow you to pre-fetch a > line of text even if you've reached the end of the page, so that you can > detect the end of the stream even in that case. The class would then > contain that line of text that was read, so that it's not lost before you > continue on to the next page. > > Such a class could also store pagination information, such as text height > and the font, along with the input stream, etc. (lines per page may still > need to be recalculated, if you are using per-page print settings, but > otherwise that could be cached as well). > > You also have several places in your code where you present a dialog and > then return a failure if the user cancels the dialog. Not a problem per > se, but my preference, rather than code that looks like this (as yours > does): > > if (dialog.ShowDialog() == DialogResult.OK) > { > // do something > } > else > { > return false; > } > > to instead just write it like this: > > if (dialog.ShowDialog() != DialogResult.OK) > { > return false; > } > > // do something > > That is, just make the failure case return, and the success case be the > main flow through the method. IMHO this makes the method more readable. > > A somewhat more significant problem is that you are failing to dispose a > number of disposable objects. Most never get disposed at all (dialogs, > and your font), but even the StreamReader is disposed only on success. > > You should use "using" statements liberally to address this problem. > > Finally, you should not be catching all exceptions around your call to > Print(). You should limit your "catch" clause to only those exceptions > that are expected and don't represent a terminal failure. Catching any > and all exceptions and just ignoring them can lead to very > hard-to-reproduce problems and subtle data corruption bugs. > > This sort of problem is very rare, but when it happens it's very hard to > figure out if the code is simply silently catching all exceptions, even > those that were not anticipated at the time the code was written. It's > much better to just write the code more robustly in the first place. > > Pete ------------------------------------------------------------------------------- Hi Pete, Thank you very much. I think I can make changes to allow for your comment, however, I might find your "print status" suggestion a difficult one to realize. I might like to get back on that one, after trying myself first, if I may. Many thanks, Zach. |