user2055996
user2055996

Reputation: 1545

Why does multi page printing in Windows Forms work the way it does?

Since we recently learned how to print in Windows Forms, I was wondering why to print multiple pages, OnPrintPage(PrintPageEventArgs e) of your PrintDocument gets called for each page and to tell it that I have multiple pages I have to set e.HasMorePages to true. I thought of multiple other solution like a Page Object you can draw on and the OnPrintPage method returning an array of those object.

But since I would think that Microsoft had a good reason to implement it the way they did I wanted to know if anyone knows the reason the API looks the way it does.

Upvotes: 0

Views: 317

Answers (1)

Hans Passant
Hans Passant

Reputation: 942267

It just fundamentally maps to the way printing works on Windows. Which is page based, a printer driver works on one page at a time. StartDoc and EndDoc are the outer winapi functions that select the driver and shut it down. They map to the PrintDocument.BeginPrint and EndPrint events.

Then an app must call the StartPage winapi function before it starts rendering graphics into the printer's device context. Which maps to the PrintPage event, the PrintController fires it right after it called StartPage. When the app is done rendering the page then EndPage must be called. Done by the PrintController when the PrintPage event handler returns. And that adds a page to the spooler.

Setting e.MorePages = true simply tells the PrintController that it needs to stay inside the loop, again calling StartPage and firing the PrintPage event.

This can make printing a bit painful, you have to maintain state yourself between PrintPage event calls. Which necessarily needs to be done storing them in fields inside a class, they cannot be local variables of the PrintPage event handler. I've written a functional replacement for PrintDocument that doesn't have this problem, you can render an entire document in a single method. With a FormFeed() method that separates pages. You can find the code in this MSDN forum post. Also note how a C# iterator (yield return statement) can be a good general purpose solution to the problem.

Upvotes: 2

Related Questions