One of the things I have been steadfastly avoiding is writing code to print stuff. Most of what I want to print is from withing apps like Outlook or Word that already provide that functionality. But I finally ended up having to bite the bullet. What I ended up with was not pretty but it is (except for one flaw noted in the comments) adequate. I present it here for comments. Perhaps it will be of use to someone else.
In a nutshell, printing requires that you "draw" each item on the page, be it text or graphics. As such, you can't just stream text to the page. You must calculate the position of each string. When you print a document, the PrintPage event gets fired until there are no more pages to print. As long as you set e.HasMorePages to True before you exit the PrintPage handler the PrintPage event will continue to fire.
As I quickly learned by starting with a Microsoft example, if you try to print a line that is too long to fit on the page, it will just get truncated. You must provide the word wrap functionality by determining what parts of the line will fit on the page and what will not. The sample code does this by tokenizing each line of text and rendering each token separately. If a token will not fit in the remaining line then it is saved for the next line.
This is my first attempt at printing so I expect that there are improvements to be had. All comments and suggestions are welcome.
pd is a PrintDocument control. The only other control on the form is a button.