Solved:
The solution for this commercial app was essentially what I do when building 3D graphs and objects. I build an oversized object then multiply it by 0.1; The graph/object and various axes all become sharp and clear, no blurry characters.
For this current problem, I do not have access to the user printers or monitors. And since there are literally hundreds, I don’t want access. It’s also unacceptable to tell users that they need a printer with X DPI to get good clear output. The same goes for monitors.
So when defining a picture I expanded it by a factor of 5
Expander = 5 // expand pic by a factor of 5
Crisper = 0.2 // before displaying or printing a page, I reduce it by multiplying it by Crisper, so letters are crisp and sharp for both the monitor and printer.
PixHt = 12 // height of a line in pixels
In other words, all text becomes non-blurry before being sent to a printer or monitor.
Consider it like a photograph that you are going to scan. If the photo is blurry then the scan will be blurry. If the photo is clear and crisp then the scan will be clear and crisp. The scanner will not change the picture itself.
By using a picture, everything remains in a nice neat package that can be stored and delivered with a user friendly interface. I initialize a picture (a single page) with:
PageImage = BitmapForCaching(525*Expander, 725*Expander) // make image 5 times larger than needed
g = PageImage.Graphics
After initializing, building the picture took a little more effort since the x and y positions had to consider this size change. Statements look like:
YPos = YPos + PixHt * Expander
g.DrawString(" Proj leader: " + ProjLeader,XPos,YPos)
This new YPos advances the output one line from the last YPos. XPos was also multiplied by the Expander, but remained the same for each line. An underscore took this form:
YPos = YPos + PixHt/2 * Expander
g.DrawLine(50 * Expander,YPos,525 * Expander,YPos)
Once the page was complete I refreshed the canvas to get the Paint event to fire with this command:
g.DrawPicture(PageImage, 0, 0, PageImage.Width * Crisper * PicScale, PageImage.Height * Crisper * PicScale, XScroll, YScroll, PageImage.Width, PageImage.Height)
The Crisper eliminates the oversized pic (5x) and brings it back to a normal size. Now all the letters are sharp and ‘crisp’. The PicScale is for my zoom buttons and the scrolls allow for scrolling.
Next to the canvas I have controls for Prior page, Next page, Go to page, zoom in, zoom out, print visible page, print multiple pages, reset to original size after zooming and re-center after scrolling.
With multi-paged documents, at some point you’re going to run out of memory since each page is treated as a separate picture that cannot be discarded. For this app, it would not be unusual to have a 500 page report, outlining collected field data. The solution is to create a new database record where you can save each page in a document. With that feature I can retrieve, say, page 234 of Table 5 and display it. I don’t have to re-create the first 233 pages to produce page 234. The speed is such that the user will never know it is coming from the database.
Like everything else, this will get refined and improved over time. TJ