news:k46sml$8e8$1...@speranza.aioe.org...
>
> I still didn't decide about using the Printer object or the hdc returned
> by the common dialog, but I'll need an hdc before the common dialog
> is displayed because I need to measure some heights of texts that I
> need to do with:
> Call DrawText(hdc, nText, ByVal Len(nText), iRect, iAlingment
> Or DT_CALCRECT Or DT_WORDBREAK)
> I need to measure the texts in order to know where the pages break
> to be able to show the print preview . . .
> My idea is to print the full report to some DC, may be a hidden
> picturebox or a memory DC (may be all the pages in one DC or one
> DC per page), and then copy the image to the pictureboxes of the
> print preview . . . Perhaps I'll need to stretch the images with
> something better than StrechBlt, but I know there are some functions
> for scaling images with better quality . . . But now, I need to
> select the proper DC for doing that. What do you suggest? I'll call
> DrawText with DT_CALCRECT to break texts in lines, but the breaks and
> sizes must be the same of the final printing...
If you are going to display a print dialog to the user which allows him to
select the printer he wants to use and to alter its various settings and if
you want the print job to then immediately be carried out (which of course
is the normal thing to do) then you cannot really create DC in advance which
accurately reflects those print dialog DC settings because you do not know
in advance which printer he is going to choose or how he is going to set it
up. So you will need to use any suitable DC to initially create your
document and then take steps later to make sure the document outputs in
exactly the same manner to the printer DC which the user eventually creates
by virtue of his selections in the print dialog.
You can create your initial DC (perhaps against a specific printer or
against the default printer, or you could use the Printer Object's DC) and
you can use that DC for your various measurements, but the values it returns
for the height and width of any specific piece of text at a specific font
name and size might be different than the values which would be returned by
the printer and settings that are eventually chosen by the user in the print
dialog. Even very small differences can cause line wraps to occur on a
different word, and they can thereby cause a block of text (drawn using
DrawTextEx for example) to use a different total number of lines, so your
print preview generated using the values returned by the DC you have created
in advance is quite likely to be different from the actual printout. You
could of course require the user to select his printer and its properties
before you display any print previews, but that is not the normal thing to
do.
It is actually possible to create a totally accurate print preview even
before the user selects the printer and its settings in the print dialog (MS
Word for example has no problem doing it), but it is not quite as
straightforward as it might at first appear, at least not if you want it
exact. MS Word does it by creating a DC before you start typing the document
(I'm not sure whether it uses a DC from the default printer or perhaps a
sort of "stock" DC which it creates itself in memory) and it lays out the
document in accordance with that DC. MS Word of course knows that the DC
which the user eventually creates (by his choice of printer and printer
settings in the print dialog) is quite likely to return different actual
sizes for the height and width of text and so instead of drawing the text in
accordance with the target DC it draws the text in accordance with the DC it
initially created (the one which it used to lay out the document and to
produce the print preview), and it deliberately positions each character on
the page in exactly the same location that it is in the displayed document
and in the print preview. A VB RichTextBox is capable of doing something
similar, laying out its contents in accordance with a reference DC but
actually drawing them into a different target DC, but I don't think that
would suit your needs.
Doing a similar thing in VB would take a bit of work to cover all the bases
and to do it really accurately, but it can be done. For example you could
draw a text string representing a paragraph into your own created DC (which
you are currently doing with the DrawText API) and keep a record of the
words (character positions) at which each line wrapped and also a record of
the actual height of a line. (You might need to write your own wrapping code
to do this, or you could do it with a bit of judicious juggling with the
DrawTextEx function and DrawTextParams). Then when that same paragraph gets
drawn into the output printer you draw each line one at a time at the
appropriate positions. In that way the block of text will "wrap" at the same
words it wrapped in your own DC and in your print preview.
You would actually need to do a bit more than that though because the line
endings on the printout would quite likely not be in the same exact position
as they were on the "stock DC", and it is even possible that some lines
might run into some other object on the page when they did not do so in the
stock DC. So, you would really need to not only draw each specific line of
text as previously explained, but you would also need to draw every single
character of each line in exactly the same character position on the printed
page. If you look at a printout from an MS Word document for example then
you'll find that's what MS Word does. For this you would probably need to
use the ExtTextOut function which allows you to pass the string to print
together with an array of values which specify the exact required spacing
between each character and the next. All this would take a bit of work to
get right, but it can be done.
One method I have used myself in cases where I want the output on the
printer (any printer, regardless of its characteristics) to exactly match
the output on the display and also to exactly match the output in any
preview window is to draw all my stuff to an enhanced metafile DC (I think I
used one metafile for each page, it is a while ago now and I'm not quite
sure offhand). This would avoid all the above complications about logging
word wrap positions and character positions and other stuff (although of
course it introduces complications of its own because you need to get your
head around writing to a metafile, but I can help you with that). You then
just use all the normal DrawText and other methods in the normal way to
create your page(s), but you use them on the metafile DC. The metafile then
effectively contains the full contents of perhaps an A4 or US Letter Size
page. Then when the time comes to print the page (when the user makes his
various selections in the print dialog) you simply dump the metafile to the
printer (one per page) using a simple one line PaintPicture. You don't need
to worry about the stuff I have mentioned above, because the metafile will
automatically make sure that all the lines wrap at exactly the same point
and that they are all correctly spaced and it will even ensure that all the
characters on each line are exactly in the correct position, regardless of
the device you draw the metafile to. With this method a simple PaintPicture
can draw the metafile onto the user's printer page, or onto your main Form
or whatever, or into a PictureBox of any size you desire, and it will
automatically use the exact correct font sizes and line wraps and all the
other stuff, so that each page will look the same wherever you draw it.
Also, because it is a metafile (rather than a bitmap image which your
previous suggestion would produce) you always get a good quality output
because it uses the full resolution of whatever device you are drawing it
to, whether that is a 96 dpi PictureBox or a 600 dpi printer. It might not
be the way you want to go, but it is worth thinking about
Anyway, I'm sure other people have their own ways of doing these things and
that others will probably give you all sorts of other possibilities, so the
above things are just suggestions really for you to mull over and consider.
Mike