Ok, I blogged about the failed GDI+ API yesterday and complained about it. Those of you who are following me on twitter may already know that my little liaison with GDI+ is due to some printing my application has to do and the experience hasn’t been good so far.
My requirement is quite simple, print invoices and some other papers that may (or may not) span multiple pages.
So I came up with a very simple design for my printing needs that lets me reuse all printing dialogs by supplying different strategy classes that do the printing.
This has worked out so far, but I’ll have to adjust since I found out that printing multiple pages works totally different from what I expected. In my stupid little world I was thinking that going on to the next page would be as easy as calling NextPage() somewhere and the Graphics object would start drawing to the new page.
And I was so wrong.
Apparently, how it really works is by specifying in your print event that your document has multiple pages and the print event will fire as long as eventargs.HasMorePages is true. Yep, that’s right, the event will fire again!
So apparently, all code that gets called has some way of determining what stuff doesn’t fit on the page (that itself is a huge pain in the ass with graphics.MeasureString and everything) and it also has to find out what parts have already been printed to another page.
So, in a simpler world I’d have a switch statement that would branch depending on the page number like this:
private int pages = 3; private void PrintDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { switch (pages) { case 1: //print page 1 break; case 2: //... break; } pages -= 1; e.HasMorePages = pages > 0; if (pages == 0) pages = 3; }
The irony of this is that this no longer works if you can hit a new page once your string exceeds one page. You’d have to cut off the string (after heaving measured that it won’t fit), and somehow store it so that when the method gets called next time the “part” that’s not printed yet will get printed. Can it get more stupid than that?
Having multiple entries into one method just seems plain wrong and leaves me no option as to have code everywhere to determine if something has already been printed (no need to say all the hassle there is to cut off something on page A and print the overflow on page B).
This whole RectangleF/SizeF acrobatics with almost static method calls in between feels so much like last century that I am very well inclined to write some OO library in the future to save me the hassle next time.
By the way, first I was thinking that if printing from within .NET turns out to be too hard I had this fallback plan to just generate HTML, display it in a Webbrowser control and print it from there. I should have done it that way, simple things tend to work :).