Print Documents PrintDocument-- what am I doing wrong? Must besomething stupid

R

raylopez99

I am running out of printing paper trying to debug this...it has to be
trivial, but I cannot figure it out--can you? Why am I not printing
text, but just the initial string "howdy"?

On the screen, when I open a file, the entire contents of the file is
in fact being shown...so why can't I print it later? All of this code
I am getting from a book (Chris Sells) and the net. The solution is
to be found in the fact that stringbuilder is not retaining
information outside the 'using' bracket, despite the fact I made it
'global'.

Keyword search //!!! below to see where I think the problem lies.

RL

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;


namespace MyNameSpace1
{
public partial class MyForm : Form
{
string myPrintFilename;
StringBuilder myGlobalStringBuilder; //!!! this is supposed
to be global to the form MyForm, right?

string strModified; // = String.Copy(strOriginal); //not used

public MyForm()
{
InitializeComponent();
myGlobalStringBuilder = new StringBuilder("howdy"); //!!!
the only thing that gets printed is 'howdy'!

}

private void toolStripButton1_Click(object sender, EventArgs
e)
{
Stream myStream;
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Title = "Open text file";
openFileDialog1.InitialDirectory = @"c:\";
openFileDialog1.Filter = "txt files (*.txt)|*.txt|All
files (*.*)|*.*";

if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
if ((myStream = openFileDialog1.OpenFile()) !=
null)
{
using (myStream)
{
StreamReader sr =
File.OpenText(openFileDialog1.FileName);
string s = sr.ReadLine();
StringBuilder sb = new StringBuilder();
while (s != null)
{
sb.Append(s);
s = sr.ReadLine();

myGlobalStringBuilder.Append(s); //!!! ??? Why is myGlobal not
appending here?
}
sr.Close();
textBox1.Text = sb.ToString(); //this
works, to show the file text on the screen textBox1

}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: could not read file from
disk (myStream); Err: " + ex.Message);
}
}
}

private void printToolStripButton_Click(object sender,
EventArgs e)
{
if (myPrintFilename != "")
{
this.printDocument1.DocumentName =
this.myPrintFilename;

this.printDocument1.Print();
}
}

private void printDocument1_PrintPage(object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
//p. 292 Chris Sells
//draw to the e.Graphics object that wraps the print
target

Graphics g = e.Graphics;
using (Font font = new Font("Lucida Console", 48) )
{
string mylocalstring;

mylocalstring =
myGlobalStringBuilder.ToString(); //!!! only prints "Howdy"--the
initial string--never the appended string from myGlobalStringBuilder--
why?

if (myGlobalStringBuilder.Length != 0)
{
g.DrawString(mylocalstring, font, Brushes.Blue, 0,
0);
}
}

}


}
}
 
J

J. Moreno

raylopez99 said:
I am running out of printing paper trying to debug this...it has to be
trivial, but I cannot figure it out--can you? Why am I not printing
text, but just the initial string "howdy"?

There's 4 things wrong with your code...
1. the variable myPrintFilename isn't being set to
openFileDialog1.FileName 2. You are using Append when you should be
using AppendLine 3. You have the myGlobalStringBuilder after the
sr.ReadLine instead of after the sb.Append (which should be
sb.AppendLine) 4. You're using Lucinda 48, instead of something
smaller...
 
P

Pavel Minaev

There's 4 things wrong with your code...
   1. the variable myPrintFilename isn't being set to
   openFileDialog1.FileName 2. You are using Append when you should be
   using AppendLine 3. You have the myGlobalStringBuilder after the
      sr.ReadLine instead of after the sb.Append (which should be
   sb.AppendLine) 4. You're using Lucinda 48, instead of something
   smaller...

There's one more here. This:

if ((myStream = openFileDialog1.OpenFile()) !=
null)
{
using (myStream)
{
StreamReader sr =
File.OpenText(openFileDialog1.FileName);
string s = sr.ReadLine();
StringBuilder sb = new StringBuilder();
while (s != null)
{
sb.Append(s);
s = sr.ReadLine();

myGlobalStringBuilder.Append(s); //!!! ??? Why is myGlobal not
appending here?
}
sr.Close();
textBox1.Text = sb.ToString(); //this
works, to show the file text on the screen textBox1

}
}

Note how myStream is never actually used. Also, it is pointlessly
initialized outside the using-expression.
 
F

Family Tree Mike

Set a breakpoint in printDocument1_PrintPage, at the line where
"mylocalstring" is set. I believe you will see that the value is correct for
"myStringBuilder". The lack of carriage returns will hide the fact that the
string is correct when printed. I believe it is going off the page. The
print document functions won't fix newlines, wrapping, etc. Also, you need
to worry about the next page when the text is long. Printing is very
complicated in .net, until you get the hang of it...
 
R

raylopez99

On Aug 28, 5:57 am, Family Tree Mike

No kidding FTM! Printing is indeed very complicated in .NET. In
fact, I'm giving up after this post! (assuming I don't get a reply
that fixes the below)

I just spent half a day doing various things trying to get print to
work. I finally got it to work--somewhat--but with one big caveat--
the print only prints one page! If it's more than one page of text,
you get an infinite loop (the pages just keep increasing, until you
hit cancel).

Below is the code, and where I think the infinite loop problem is--
I've keyword marked it with 'fooey' (see also // Infinite Loop? Why?)

Like I say, everything works fine, if the textbox has one page of text
in it or less.

I also tried setting up a temporary file and writing and reading from
it, but it's the same as reading from a textbox (but nevertheless I
left this code in below, commented out).

I appreciate you guys helping. Please don't spend too much time on
this--I've thrown in the towel--but I do believe the problem is in the
place marked "fooey" below--you are not 'consuming' your string
properly when using the method ".Substring" (this code was from an
example on the net--see the header)--and thus the string never
'decreases' so you always get a "e.HasMorePages = true;" condition,
rather than "= false".

If any of you pity a newbie, please upload a working example of a
simple print (no preview required) for printing from a textbox.

RL

//adapted from http://www.expresscomputeronline.com/20030915/techspace02.shtml
//main code from here
// an excellent example, too bad it doesn't work for me

// and from Chris Sells, Chapter 8, Printing in WinForms
//Chris Sells Chap 8 is very very simplistic--in retrospect I suspect
because printing is difficult and he didn't want to spend time on it
//

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;
using System.Drawing.Printing; //needed for print


namespace MyProgram1
{
public partial class MyPrintForm : Form
{
string myPrintFilename;
StringBuilder myGlobalStringBuilder;
Font f;
SolidBrush b;
StringFormat strformat;
string printstr;
int intchars, intlines;

StreamReader reader;


public MyPrintForm()
{
InitializeComponent();
myGlobalStringBuilder = new StringBuilder();
strformat = new StringFormat();
FileNotSavedYet = true; //dirty file bool indicator—not
used

}

private void printToolStripButton_Click(object sender,
EventArgs e)
{
if (myPrintFilename != "")
{

this.printDocument1.DocumentName =
this.myPrintFilename;

this.printDocument1.Print();
}

}

private void printDocument1_PrintPage(object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
////try writing textbox text to a file first! Make it
write to a temp file and read back.
////// //UPDATE: Not true,you still get an infinite loop
if you do this

//string path1 =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
//string path2 = "\\temp123454321.txt"; //temporary file
name
//string path12 = path1 + path2; //local path + file name

//try
//{
// using (FileStream fs = new FileStream(path12,
FileMode.Create)) //fs = new FileStream("test123454321.txt",
FileMode.OpenOrCreate)
// {
// using (StreamWriter myWritter = new
StreamWriter(fs, System.Text.Encoding.ASCII))
// {
// myWritter.Write(textBox1.Text);
// }
// }
//}
//catch(Exception ex)
//{
// MessageBox.Show(ex.Message);
//}



//string mylocalstring;

//try
//{
// reader = new StreamReader(path12);
//}
//catch (Exception ex)
//{
// MessageBox.Show("reader err:" + ex.Message);
//}

//mylocalstring = reader.ReadToEnd();

RectangleF myrect = new
RectangleF(e.MarginBounds.Left,e.MarginBounds.Top,
e.MarginBounds.Width,e.MarginBounds.Height);
SizeF sz = new SizeF(e.MarginBounds.Width,
e.MarginBounds.Height);

string mylocalstring = textBox1.Text; //also equivalent it
turns out--same thing!
//thus, no need to create and save a temporary file from the textBox1—
just use directly.

//mylocalstring = myGlobalStringBuilder.ToString();
e.Graphics.MeasureString(mylocalstring, f, sz, strformat,
out intchars, out intlines);

printstr = mylocalstring.Substring(0,intchars);
e.Graphics.DrawString(printstr, f, b, myrect,strformat);

if (mylocalstring.Length > intchars)
{
mylocalstring = mylocalstring.Substring(intchars);//
problem here! fooey!
// Infinite Loop? Why?

// one idea: is mylocalstring being changed? note .Substring library
method here has only one parameter
//should .Substring method not have two parameters?
// Update: tried with ‘mylocalstring =
mylocalstring.Substring(0,intchars); and still failed
// but, perhaps the first parameter should be intchar + intchar*N,
where N=0,1,2? Anybody have thoughts?

e.HasMorePages = true;
}
else
e.HasMorePages = false;


//end of relevant code--rest below is not relevant to this problem --
RL
////p. 292 Chris Sells
////draw to the e.Graphics object that wraps the print
target
//Graphics g = e.Graphics;
//using (Font font = new Font("Courier", 12))
//{
// string mylocalstring;

// // mylocalstring =
myGlobalStringBuilder.ToString(); //commented out, an earlier version
used this
// mylocalstring = textBox1.Text;
// if (myGlobalStringBuilder.Length != 0)
// {
// g.DrawString(mylocalstring, font, Brushes.Blue,
0, 0);
// }
//}
////// end of pg. 292 Chris Sells

}


// this is code that you need to open a file. Not really relevant for
the 'infinite loop' problem above, but I include for Pavel


private void openAToolStripButtun_Click(object sender,
EventArgs e)
{
Stream myStream;
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Title = "Open text file";
openFileDialog1.InitialDirectory = @"c:\";
openFileDialog1.Filter = "txt files (*.txt)|*.txt|All
files (*.*)|*.*";

if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
if ((myStream = openFileDialog1.OpenFile()) !=
null)
{
using (myStream)
{
StreamReader sr =
File.OpenText(openFileDialog1.FileName);
myPrintFilename =
openFileDialog1.FileName;
string s = sr.ReadLine();
StringBuilder sb = new StringBuilder();
while (s != null)
{
sb.Append(s);
myGlobalStringBuilder.AppendLine(s);
s = sr.ReadLine();
myGlobalStringBuilder.AppendLine(s);
Debug.WriteLine("Hi");

}
sr.Close();
textBox1.Text = sb.ToString();
//
myGlobalStringBuilder.Append(sb.ToString()); //wrong

}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: could not read file from
disk (myStream); Err: " + ex.Message);
}
}
}

// // this is code that you need to save a file. Not really relevant
for the 'infinite loop' problem above, but I include for Pavel

private void saveToolStripButton_Click(object sender,
EventArgs e)
{

// SaveFileDialog saveFileDialog1 = new SaveFileDialog(); //
not needed
SaveFileDialog MySaveFileDialog = new SaveFileDialog();
MySaveFileDialog.Filter = "txt files (*.txt)|*.txt|All
files (*.*)|*.*";
MySaveFileDialog.DefaultExt = "txt";
MySaveFileDialog.FilterIndex = 2;
MySaveFileDialog.RestoreDirectory = true;



if (MySaveFileDialog.ShowDialog() == DialogResult.OK)
{
using (Stream myStream = MySaveFileDialog.OpenFile())
{
if (myStream != null)
{
using (StreamWriter myWritter = new
StreamWriter(myStream, System.Text.Encoding.ASCII))
{
myWritter.Write(textBox1.Text);
}
}
}

}
}

private void printDocument1_BeginPrint(object sender,
System.Drawing.Printing.PrintEventArgs e)
{
//can go here to avoid having to do this for every page
(since same for every page)
////Hence we have created the Font, SolidBrush and
StringFormat objects in the handler for the BeginPrint event. Note
that we could have done this in the handler of the PrintPage event as
well but then these objects would have been created for each page

f = new Font("Arial", 12, FontStyle.Regular);
b = new SolidBrush(Color.Black);
strformat.Trimming = StringTrimming.Word;
}

private void printDocument1_QueryPageSettings(object sender,
System.Drawing.Printing.QueryPageSettingsEventArgs e)
{
//set margins to 0.5" all around p. 305 Chris Sells
// e.PageSettings.Margins = new Margins(50, 50, 50, 50); //
does not really help much it seems, but does not hurt either
}

}
}
 
R

raylopez99

Note how myStream is never actually used. Also, it is pointlessly
initialized outside the using-expression.

Privet Pavel!

I thank you for your time. Now since I've seen so many ways to open/
close read/write a text file, I would appreciate the 'right' way.
Even experts (on the net) have disagreed about this.

So, in my last post (the long one, in this thread, from a few minutes
ago), I include a comment: "// this is code that you need to open a
file. Not really relevant for the 'infinite loop' problem above, but
I include for Pavel"

If you can please tell me what parts of this code is not needed to
safely open/close read/write a text file, I would be thankful. This
way, I can put the 'proper' code into my library, and for future
reference not have to worry about it.

I also have done this for binary files, but for now text file is more
important, for this example. My binary files seem to be working (so
are my text files, but I don't like using code that is superfluous or
not needed, as you say).

Spasibo

RL
 
J

J.B. Moreno

raylopez99 said:
Privet Pavel!

I thank you for your time. Now since I've seen so many ways to open/
close read/write a text file, I would appreciate the 'right' way.
Even experts (on the net) have disagreed about this.

This really has nothing to do with the "right" way to open a file, but
rather an unused variable.


myStream can be left out entirely without changing how the program
works.

But if you want to use the "using" statement, and don't want to use
myStream for anything, then replace


using (myStream)
{
StreamReader sr = File.OpenText(openFileDialog1.FileName);
}

With

using (StreamReader sr = File.OpenText(openFileDialog1.FileName))
{
}

And then delete the if where mystream is assigned.
 
F

Family Tree Mike

It appears you get the value from the textbox and put it into mylocalstring
within the printDocument1_PrintPage routine, but you never reset the textbox
to what is left. This means, the textbox remains the same throughout the
printing and thus there is always more than one page left to print.

On Aug 28, 5:57 am, Family Tree Mike

No kidding FTM! Printing is indeed very complicated in .NET. In
fact, I'm giving up after this post! (assuming I don't get a reply
that fixes the below)

I just spent half a day doing various things trying to get print to
work. I finally got it to work--somewhat--but with one big caveat--
the print only prints one page! If it's more than one page of text,
you get an infinite loop (the pages just keep increasing, until you
hit cancel).

Below is the code, and where I think the infinite loop problem is--
I've keyword marked it with 'fooey' (see also // Infinite Loop? Why?)

Like I say, everything works fine, if the textbox has one page of text
in it or less.

I also tried setting up a temporary file and writing and reading from
it, but it's the same as reading from a textbox (but nevertheless I
left this code in below, commented out).

I appreciate you guys helping. Please don't spend too much time on
this--I've thrown in the towel--but I do believe the problem is in the
place marked "fooey" below--you are not 'consuming' your string
properly when using the method ".Substring" (this code was from an
example on the net--see the header)--and thus the string never
'decreases' so you always get a "e.HasMorePages = true;" condition,
rather than "= false".

If any of you pity a newbie, please upload a working example of a
simple print (no preview required) for printing from a textbox.

RL

//adapted from
http://www.expresscomputeronline.com/20030915/techspace02.shtml
//main code from here
// an excellent example, too bad it doesn't work for me

// and from Chris Sells, Chapter 8, Printing in WinForms
//Chris Sells Chap 8 is very very simplistic--in retrospect I suspect
because printing is difficult and he didn't want to spend time on it
//

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;
using System.Drawing.Printing; //needed for print


namespace MyProgram1
{
public partial class MyPrintForm : Form
{
string myPrintFilename;
StringBuilder myGlobalStringBuilder;
Font f;
SolidBrush b;
StringFormat strformat;
string printstr;
int intchars, intlines;

StreamReader reader;


public MyPrintForm()
{
InitializeComponent();
myGlobalStringBuilder = new StringBuilder();
strformat = new StringFormat();
FileNotSavedYet = true; //dirty file bool indicator—not
used

}

private void printToolStripButton_Click(object sender,
EventArgs e)
{
if (myPrintFilename != "")
{

this.printDocument1.DocumentName =
this.myPrintFilename;

this.printDocument1.Print();
}

}

private void printDocument1_PrintPage(object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
////try writing textbox text to a file first! Make it
write to a temp file and read back.
////// //UPDATE: Not true,you still get an infinite loop
if you do this

//string path1 =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
//string path2 = "\\temp123454321.txt"; //temporary file
name
//string path12 = path1 + path2; //local path + file name

//try
//{
// using (FileStream fs = new FileStream(path12,
FileMode.Create)) //fs = new FileStream("test123454321.txt",
FileMode.OpenOrCreate)
// {
// using (StreamWriter myWritter = new
StreamWriter(fs, System.Text.Encoding.ASCII))
// {
// myWritter.Write(textBox1.Text);
// }
// }
//}
//catch(Exception ex)
//{
// MessageBox.Show(ex.Message);
//}



//string mylocalstring;

//try
//{
// reader = new StreamReader(path12);
//}
//catch (Exception ex)
//{
// MessageBox.Show("reader err:" + ex.Message);
//}

//mylocalstring = reader.ReadToEnd();

RectangleF myrect = new
RectangleF(e.MarginBounds.Left,e.MarginBounds.Top,
e.MarginBounds.Width,e.MarginBounds.Height);
SizeF sz = new SizeF(e.MarginBounds.Width,
e.MarginBounds.Height);

string mylocalstring = textBox1.Text; //also equivalent it
turns out--same thing!
//thus, no need to create and save a temporary file from the textBox1—
just use directly.

//mylocalstring = myGlobalStringBuilder.ToString();
e.Graphics.MeasureString(mylocalstring, f, sz, strformat,
out intchars, out intlines);

printstr = mylocalstring.Substring(0,intchars);
e.Graphics.DrawString(printstr, f, b, myrect,strformat);

if (mylocalstring.Length > intchars)
{
mylocalstring = mylocalstring.Substring(intchars);//
problem here! fooey!
// Infinite Loop? Why?

// one idea: is mylocalstring being changed? note .Substring library
method here has only one parameter
//should .Substring method not have two parameters?
// Update: tried with ‘mylocalstring =
mylocalstring.Substring(0,intchars); and still failed
// but, perhaps the first parameter should be intchar + intchar*N,
where N=0,1,2? Anybody have thoughts?

e.HasMorePages = true;
}
else
e.HasMorePages = false;


//end of relevant code--rest below is not relevant to this problem --
RL
////p. 292 Chris Sells
////draw to the e.Graphics object that wraps the print
target
//Graphics g = e.Graphics;
//using (Font font = new Font("Courier", 12))
//{
// string mylocalstring;

// // mylocalstring =
myGlobalStringBuilder.ToString(); //commented out, an earlier version
used this
// mylocalstring = textBox1.Text;
// if (myGlobalStringBuilder.Length != 0)
// {
// g.DrawString(mylocalstring, font, Brushes.Blue,
0, 0);
// }
//}
////// end of pg. 292 Chris Sells

}


// this is code that you need to open a file. Not really relevant for
the 'infinite loop' problem above, but I include for Pavel


private void openAToolStripButtun_Click(object sender,
EventArgs e)
{
Stream myStream;
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Title = "Open text file";
openFileDialog1.InitialDirectory = @"c:\";
openFileDialog1.Filter = "txt files (*.txt)|*.txt|All
files (*.*)|*.*";

if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
if ((myStream = openFileDialog1.OpenFile()) !=
null)
{
using (myStream)
{
StreamReader sr =
File.OpenText(openFileDialog1.FileName);
myPrintFilename =
openFileDialog1.FileName;
string s = sr.ReadLine();
StringBuilder sb = new StringBuilder();
while (s != null)
{
sb.Append(s);
myGlobalStringBuilder.AppendLine(s);
s = sr.ReadLine();
myGlobalStringBuilder.AppendLine(s);
Debug.WriteLine("Hi");

}
sr.Close();
textBox1.Text = sb.ToString();
//
myGlobalStringBuilder.Append(sb.ToString()); //wrong

}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: could not read file from
disk (myStream); Err: " + ex.Message);
}
}
}

// // this is code that you need to save a file. Not really relevant
for the 'infinite loop' problem above, but I include for Pavel

private void saveToolStripButton_Click(object sender,
EventArgs e)
{

// SaveFileDialog saveFileDialog1 = new SaveFileDialog(); //
not needed
SaveFileDialog MySaveFileDialog = new SaveFileDialog();
MySaveFileDialog.Filter = "txt files (*.txt)|*.txt|All
files (*.*)|*.*";
MySaveFileDialog.DefaultExt = "txt";
MySaveFileDialog.FilterIndex = 2;
MySaveFileDialog.RestoreDirectory = true;



if (MySaveFileDialog.ShowDialog() == DialogResult.OK)
{
using (Stream myStream = MySaveFileDialog.OpenFile())
{
if (myStream != null)
{
using (StreamWriter myWritter = new
StreamWriter(myStream, System.Text.Encoding.ASCII))
{
myWritter.Write(textBox1.Text);
}
}
}

}
}

private void printDocument1_BeginPrint(object sender,
System.Drawing.Printing.PrintEventArgs e)
{
//can go here to avoid having to do this for every page
(since same for every page)
////Hence we have created the Font, SolidBrush and
StringFormat objects in the handler for the BeginPrint event. Note
that we could have done this in the handler of the PrintPage event as
well but then these objects would have been created for each page

f = new Font("Arial", 12, FontStyle.Regular);
b = new SolidBrush(Color.Black);
strformat.Trimming = StringTrimming.Word;
}

private void printDocument1_QueryPageSettings(object sender,
System.Drawing.Printing.QueryPageSettingsEventArgs e)
{
//set margins to 0.5" all around p. 305 Chris Sells
// e.PageSettings.Margins = new Margins(50, 50, 50, 50); //
does not really help much it seems, but does not hurt either
}

}
}
 
R

raylopez99

FTM you da man!

I did what you suggested, tinkered around with it, and finally it
works but with two minor but important changes:

1/ first and foremost, you must place this line: textBox1.Text =
printstr;

Here:
/////////////////////////
e.Graphics.MeasureString(mylocalstring, f, sz, strformat,
out intchars, out intlines);

printstr = mylocalstring.Substring(0,intchars);

textBox1.Text = printstr;
//IMPORTANT! DO NOT LEAVE OUT--GET INFINITE LOOP WHEN MORE THAN ONE
PAGE OF TEXT PRESENT

e.Graphics.DrawString(printstr, f, b, myrect,strformat);

if (mylocalstring.Length > intchars)
{
/////////////////////////

2/ A minor point but makes the page look decent, since you don't
print close to the edge: set the "OriginAtMargins" property of the
printDocument1 icon (at the Wizard, I could not figure out how to set
it programically) to "FALSE" (not true).

Now the code works flawlessly.


Thanks FTM!

RL
 
R

raylopez99

J.B. Moreno--I did what you suggested and it appears the code works
fine, but, I take it you are sure that this is as 'safe' as before--
what if somebody is reading from the floppy drive and the drive fails
because the floppy disk is taken out of the slot? But I trust you've
thought through this problem. Anyway I wrapped the 'using' with a try/
catch block just to be safer.

I will update my library with your suggestion in mind.

Thanks,

RL
 
R

raylopez99

Spoke too soon! I tried printing more than two pages, and found that
the code is truncated after two pages. So my optimism was premature.

Now I'm stuck again...how to make this code work for printing more
than two pages of text?

If you have a sample print method you can upload for future reference
I would be greatful.

Tx,

RL
 
F

Family Tree Mike

These controls would be on the form: FileLabel, ChooseFileButton,
PrintFileButton, QuitButton, and ContentsTextBox. The control types are
hopefully obvious...

This is quick code, and I know one issue is the text lines are not checked
if they go off the right side of the page. You will note that I am working
with the text lines, not the contents of the text box.

Hopefully this is helpfull to you or others....

Mike

================================================

public partial class MyPrintAppUI : Form
{
private string TextFileName { get; set; }
private string[] TextLines { get; set; }

public MyPrintAppUI()
{
InitializeComponent();

TextFileName = "Unknown.txt";
FileLabel.Text = TextFileName;

ChooseFileButton.Click += new EventHandler(ChooseFileButton_Click);
PrintFileButton.Click += new EventHandler(PrintFileButton_Click);
QuitButton.Click += delegate { Close(); };
}

private void ChooseFileButton_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() == DialogResult.OK)
{
TextFileName = ofd.FileName;
FileLabel.Text = TextFileName;
TextLines = File.ReadAllLines(TextFileName);
ContentsTextBox.Text = File.ReadAllText(TextFileName);
}
}
}

private void PrintFileButton_Click(object sender, EventArgs e)
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
pd.Print();
}

private int LineIndex = 0;

private void pd_PrintPage(object sender, PrintPageEventArgs e)
{
int LinesPerPage = 0, y = 0, count = 0;
int LeftMargin = e.MarginBounds.Left;
int TopMargin = e.MarginBounds.Top;

using (Font printFont = new Font("Arial", 10))
{
LinesPerPage = (int)(e.MarginBounds.Height /
printFont.GetHeight(e.Graphics));
while ((count < LinesPerPage) && (LineIndex < TextLines.Length))
{
y = (int) (TopMargin + (count * printFont.GetHeight(e.Graphics)));
e.Graphics.DrawString(TextLines[LineIndex], printFont, Brushes.Black,
LeftMargin, y, new StringFormat());
++count;
++LineIndex;
}
}

e.HasMorePages = LineIndex < TextLines.Length;
}
}




================================================
 
J

J.B. Moreno

raylopez99 said:
J.B. Moreno--I did what you suggested and it appears the code works
fine, but, I take it you are sure that this is as 'safe' as before--
what if somebody is reading from the floppy drive and the drive fails
because the floppy disk is taken out of the slot? But I trust you've
thought through this problem. Anyway I wrapped the 'using' with a try/
catch block just to be safer.

-snip-

Try/Catch blocks by themselves don't make your code safer, it just
keeps the program from crashing -- that can in fact make it /less/
safe. The same thing applies to the using statement.

The using statement doesn't prevent exceptions, it just disposes of the
object created whether or not there is an exception.

Take a look at this pseudo-code....

bool eraseFile = true;

try {

using (StreamReader sr) {
throw exception;
eraseFile= false;
}
} catch (Exception ex) {
MessageBox.Show("There was a problem");
}

if (eraseFile) {
//code to delete the file...
}

There's a using statement, there's a try/catch block -- is it safer?
 
R

raylopez99

There's a using statement, there's a try/catch block -- is it safer?

I assume you're asking a rhetorical question, but to show my level of
competence, or lack thereof, it's not obvious to me that the code you
posted is not safer. So I would vote yes, it is safer.

Anyway, thanks for your input.

RL
 
R

raylopez99

Hopefully this is helpfull to you or others....
================================================

Thanks FTM. I will go over this code and if I have any questions or
improvements will post back. I notice though it does have a way of
breaking out of the loop by counting lines and text length that seems
more robust than the web example I originally posted and modified, so
hopefully I'll get this to work.

RL
 
R

raylopez99

Here is the complete, updated program, and it works fine, including
the margins. Don't forget to set your textbox "MaxLength" property
(found in the Designer Wizard properties tab) to something bigger than
the default 32k if you intend to print lots of pages).

The important change was here: textBox1.Text = mylocalstring; //works
now, problem solved

Making this one line change enabled the program to avoid printing an
infinite loop.

This code adapted from these two sources (mainly the first source,
which had the small bug I mention above, and did not quite work):

//adapted from http://www.expresscomputeronline.com/20030915/techspace02.shtml
//main code from here // an excellent example, too bad it doesn't work
for me the first time (without the changes made now--now it works)
// and from Chris Sells, Chapter 8, Printing in WinForms
//Chris Sells Chap 8 is very very simplistic--in retrospect I suspect
because printing is difficult and he didn't want to spend time on it

//SOF
using System;
using System.Collections.Generic;
using System.ComponentModel; //I don't think you need some of these
using directives, but I think you need .Printing for sure
using System.Data;
using System.Drawing;
using System.Linq; //not needed in this example
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;
using System.Drawing.Printing;


namespace MyNameSpace01
{
public partial class MyFormTextBox : Form
{
string myPrintFilename;
StringBuilder myGlobalString;
Font f;
SolidBrush b;
StringFormat strformat;
string printstr;
int Char_out_, Lines_out;
bool DirtyBool_not_used;
bool bool_YorN_Printed;

// StreamReader reader;


public MyFormTextBox()
{
InitializeComponent();
myGlobalString = new StringBuilder("");
strformat = new StringFormat();
DirtyBool_not_used = true;
bool_YorN_Printed = false;

}


private void myPrintButton_Click(object sender, EventArgs e)
{
if (myPrintFilename != "")
{
DirtyBool_not_used = false;
bool_YorN_Printed = false;
int length_myTextBox = myTextBox.Text.Length;
myGlobalString = new StringBuilder(length_myTextBox +
1);

myGlobalString.Append(myTextBox.Text); ////*&%
this.printDocument1.DocumentName =
this.myPrintFilename;

this.printDocument1.Print();
}
else
{
DirtyBool_not_used = true;
}

}

private void printDocument1_PrintPage(object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{


RectangleF myrect = new
RectangleF(e.MarginBounds.Left,e.MarginBounds.Top,
e.MarginBounds.Width,e.MarginBounds.Height);
SizeF sz = new SizeF(e.MarginBounds.Width,
e.MarginBounds.Height);

string string_temp = myTextBox.Text;

string mylocalstring = myTextBox.Text; //also equivalent
it turns out--same thing!//works


e.Graphics.MeasureString(mylocalstring, f, sz, strformat,
out Char_out_, out Lines_out);

printstr = mylocalstring.Substring(0,Char_out_);
// myTextBox.Text = printstr; //only prints two pages-error
e.Graphics.DrawString(printstr, f, b, myrect,strformat);

if (mylocalstring.Length > Char_out_)
{
mylocalstring = mylocalstring.Substring(Char_out_);//
problem here
myTextBox.Text = mylocalstring; //works now! problem
solved


e.HasMorePages = true;
}
else
e.HasMorePages = false;
bool_YorN_Printed = true;

}


private void openClipBoardIconButton_Click(object sender,
EventArgs e)
{
// Stream aStream;
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Title = "Open text file";
openFileDialog1.InitialDirectory = @"c:\";
openFileDialog1.Filter = "txt files (*.txt)|*.txt|All
files (*.*)|*.*";

if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
{
using (StreamReader sr =
File.OpenText(openFileDialog1.FileName))
{
//StreamReader sr =
File.OpenText(openFileDialog1.FileName);
myPrintFilename =
openFileDialog1.FileName;
string s = sr.ReadLine();
StringBuilder sb = new StringBuilder();
while (s != null)
{
sb.Append(s);

s = sr.ReadLine();

}
sr.Close();
myTextBox.Text = sb.ToString();


}

}
}
catch (Exception ex)
{
MessageBox.Show("Error: could not read file from
disk; Err: " + ex.Message);
}
}
}


private void mySaveButton_Click(object sender, EventArgs e)
{

SaveFileDialog MySaveFileDialog = new SaveFileDialog();
MySaveFileDialog.Filter = "txt files (*.txt)|*.txt|All
files (*.*)|*.*";
MySaveFileDialog.DefaultExt = "txt";
MySaveFileDialog.FilterIndex = 2;
MySaveFileDialog.RestoreDirectory = true;


if (MySaveFileDialog.ShowDialog() == DialogResult.OK)
{
using (Stream aStream = MySaveFileDialog.OpenFile())
{
if (aStream != null)
{
using (StreamWriter myWritter = new
StreamWriter(aStream, System.Text.Encoding.ASCII))
{
myWritter.Write(myTextBox.Text);
}
}
}
}
}

private void printDocument1_BeginPrint(object sender,
System.Drawing.Printing.PrintEventArgs e)
{
//can go here to avoid having to do this for every page
(since same for every page)
////Hence we have created the Font, SolidBrush and
StringFormat objects in the handler for the BeginPrint event. Note
that we could have done this in the handler of the PrintPage event as
well but then these objects would have been created for each page

f = new Font("Arial", 12, FontStyle.Regular);
b = new SolidBrush(Color.Black);
strformat.Trimming = StringTrimming.Word;
}

private void printDocument1_QueryPageSettings(object sender,
System.Drawing.Printing.QueryPageSettingsEventArgs e)
{
//set margins to 0.5" all around p. 305 Chris Sells
e.PageSettings.Margins = new Margins(50,50,50,50);
//Important! set "OriginAtMargins" property of Form
Printer to FALSE to get decent (not too close to edge) results!
}

private void myTextBox_Click(object sender, EventArgs e)
{
if (bool_YorN_Printed)
{
myTextBox.Text = myGlobalString.ToString(); //restores
textbox text after printing
bool_YorN_Printed = false;
}
}

}
}

// EOF
 
R

raylopez99

Minor 'bug' fix of sorts: replace - sb.Append(s);

with:

sb.AppendLine(s);

if you want line breaks preserved in any text you import from a file.

RL
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top