Home All Groups Group Topic Archive Search About

Printing contents of a picture box

Author
30 Jun 2009 8:45 PM
John Simpson
OK, I'm stuck!

I found the following code on the net. What it does is display the value of
TXT in
hollow block letters. This works fine.

Now what I want to do is to print the contents of the picture box, as drawn,
using the printer
object.

VB6 with Vista (ugh!)

Can anyone help me with this??


Private Declare Function BeginPath Lib "gdi32" (ByVal hdc As Long) As Long

Private Declare Function EndPath Lib "gdi32" (ByVal hdc As Long) As Long

Private Declare Function StrokePath Lib "gdi32" (ByVal hdc As Long) As Long

Dim p As VB.Printer
'
'
Private Sub Form_Load()
    Me.Show

    For Each p In VB.Printers
        If p.DeviceName = "ml490-usb" Then         ' set the printer
            Set Printer = p
        End If
    Next

End Sub
'
'
'
Private Sub cmdPrintText_Click()
    Const TXT = "TEMPLATE"

    Pic1.AutoRedraw = True
    Pic1.Font.Name = "Courier New"
    Pic1.Font.Bold = True
    Pic1.Font.Size = 75
    Pic1.Width = Pic1.TextWidth(TXT)
    Pic1.Height = Pic1.TextHeight(TXT)

    ' Make the clipping path.
    BeginPath Pic1.hdc
    Pic1.CurrentX = 0
    Pic1.CurrentY = 0
    Pic1.Print TXT
    EndPath Pic1.hdc
    ' Draw the path.
    StrokePath Pic1.hdc

'    Printer.Print ?????????     ' here's my problem
    Printer.EndDoc

End Sub

Thanks!

John

Author
30 Jun 2009 9:54 PM
Larry Serflaten
"John Simpson" <jas***@earthlink.net> wrote

> Can anyone help me with this??
>
> '    Printer.Print ?????????     ' here's my problem
>     Printer.EndDoc

Try

Printer.PaintPicture Pic1, 0, 0

LFS
Are all your drivers up to date? click for free checkup

Author
1 Jul 2009 4:28 PM
John Simpson
Show quote Hide quote
"Larry Serflaten" <serfla***@usinternet.com> wrote in message
news:endeS0c%23JHA.5780@TK2MSFTNGP03.phx.gbl...
>
> "John Simpson" <jas***@earthlink.net> wrote
>
>> Can anyone help me with this??
>>
>> '    Printer.Print ?????????     ' here's my problem
>>     Printer.EndDoc
>
> Try
>
> Printer.PaintPicture Pic1, 0, 0
>
> LFS
>
>

Thanks Larry.
Author
1 Jul 2009 10:22 AM
Mike Williams
"John Simpson" <jas***@earthlink.net> wrote in message
news:uuKVpOc%23JHA.4360@TK2MSFTNGP04.phx.gbl...

> OK, I'm stuck!
> ' resize Pic1 code omitted for brevity
> BeginPath Pic1.hdc
> Pic1.CurrentX = 0
> Pic1.CurrentY = 0
> Pic1.Print TXT
> EndPath Pic1.hdc
> StrokePath Pic1.hdc
> Printer.Print ?????????     ' here's my problem

It is easily possible to print the picturebox contents to the printer,
although the output quality would not be very good because you are
effectively "stretching" a low resolution screen bitmap (96 dpi) so that it
appears at a suitable size on a high resolution perhaps 600 dpi printer. The
text outline on the printed page would therefore look fairly "blocky" on
close inspection, partly because of the "pixel stretching" I mentioned and
partly because the StrokePath API function does not use the text smoothing
that standard characters use. So, the best way to draw the Path you have
created to the Printer is to actually create it against the Printer.hdc and
to use StrokePath Printer.hdc to print it, controlling the thickness of the
outline with a Printer.DrawWidth statement if you want the outline to be
greater than one printer pixel in thickness (which you in many cases would
do because printer pixels are very small). However, because there are other
issues with your existing PictureBox method in the code you have posted, and
because some of those issues would also affect the "Stroke Path to Printer"
method, I will deal here with the answer to the specific question you have
asked (how to transfer the PictureBox drawn contents to the printer).

The drawing created by your existing code ends up as a bitmap in the Image
property of the PictureBox. You can print the Image property bitmap to the
printer using Printer.PaintPicture pic1.Image but if you do it that way
(without specifying a source size and without making any other modifications
to your code) you may end up printing a bitmap that is larger than the
current size of the PictureBox. That's because the bitmap contained in the
Image property of a PictureBox still retains its previous pixel size even
after you have resized the PictureBox unless the previous size was smaller
than the "resized" size and the Image bitmap can therefore end up larger
than the PictureBox that is displaying it, so if the PictureBox was
originally larger than the size your code has resized it to then the bitmap
in its Image property, and therefore the bitmap that gets printed, will be
larger than you are expecting. You won't see the extra of course if the
background is white, but you will if it is some other colour or if it
contained a background of some kind. There are ways to overcome this problem
using the various PaintPicture statement parameters but generally it is wise
to resize the bitmap properly, especially if you ever wish to save the Image
using SavePicture. There are all sorts of ways of forcing a PictureBox to
reliably resize its bitmap Image and all of them are very simple. For
example with your own code as posted you could simply move the Autoredraw
statement to after the resize, or you could use a Cls method after the
resize, there are all sorts of different ways. Personally in your own code I
would suggest using Pic1.Cls immediately after the Pic1.Width and
Pic1.Height statements. Then after you have finished your Picture Box
drawing (after the StrokePath statement) use:

    Printer.PaintPicture pic1.Image, 0, 0

Having said all that, there are are few other things about your code that I
would like to comment on. Firstly you are setting the Width and Height of
the PictureBox to the desired size of the bitmap you intend it to contain.
If the PictureBox has a border then the actual size of the bitmap it
contains will be less than its overall width and height. So with a
PictureBox that has a border you really need to be setting its Width and
Height to a slightly greater value so that the size of the bitmap it
contains is correct. This often (but not always) won't be a problem when the
bitmap is just a string of text because in many cases there is some "white
space" around the character cells anyway and so the characters themselves
will probably still all be fully displayed, but it is wise not make that
assumption and to size it properly. There are various ways of accounting for
the border thicknesses to fix this problem but a simple "native VB code"
method would be something like:

    Dim xBorder As Single, yBorder As Single
    pic1.ScaleMode = pic1.Container.ScaleMode
    xBorder = pic1.Width - pic1.ScaleWidth
    yBorder = pic1.Height - pic1.ScaleHeight
    pic1.Width = pic1.TextWidth(TXT) + xBorder
    pic1.Height = pic1.TextHeight(TXT) + yBorder

As I've said, there are all sorts of different ways of doing the above but
the important thing, whichever way you choose, is that you actually do it.
The above code will reliably set the picbox overall size correctly so that
its contained bitmap size (the client area) is the size you require but when
dealing with the size of fonts there are also other things you need to take
into consideration. That's because the VB TextWidth function and the
alternative API GetTextExtentPoint32 function do NOT tell you the actual
displayed width of the string of characters. They in fact tell you the width
of the character cells in which the characters "live". This is often okay
because many character glyphs in many fonts (the actual printed character
shapes) live entirely within their cells, but in many cases it is not okay
because some character glyphs overhang the border of their character cell at
the left side or the right side or sometimes both sides. In fact in some
cases some characters overhang the bottom of the character cell as well.

To see what I mean first run your code as it currently exists (with or
without the amendments I have mentioned) and you should see the word
"TEMPLATE" entirely visible in the PictureBox. Now change the font to "Times
New Roman" and add the line Pic1.Font.Italic = True and change the TXT
variable from "TEMPLATE" to "fluff" and try it again. This time you should
see that the text is not entirely visible, with the "f" characters in the
word "fluff" overhanging the left side and the right side and the bottom
edge of their cells. This is not a characteristic of the StrokePath function
or of anything else in your code, but rather it is a characteristic of fonts
in general and the same thing will happen if you use a standard Print
statement or any other statement that prints text.

As I've already mentioned, the problem arises because the TextWidth function
(and the equivalent API GetTextExtent function) return the width of the
string of text without taking into account any characters ate the left or
right end of the string that might overhang their cells. Similarly the
TextHeight function (and the equivalent API GetTextExtent function) do not
take account of any characters that overhang the bottom of their cells. To
calculate the correct size you need to get the width returned by the
TextWidth (or the alternative GetTextExtent32) function and then add to that
the amount by which the leftmost character overhangs the left edge of its
cell and also the amount by which the rightmost character overhangs the
right edge of its cell. Then when you have set the bitmap (the PictureBox
client area or whatever) to the calculated width you need to position the x
coordinate of the print statement to a positive value equal to the amount by
which the leftmost character overhangs the left edge of its cell.

If in any specific case you need to know only the left and right edge
overhangs of a character then you can use the very simple GetCharABCWidths
API function but if you want to also know the bottom edge overhang (not as
common as left and right overhangs) then you'll need to use a something
else, for example the slightly more complicated GetGlyphOutline API function
which can get both the size and the position within the character cell of
the "black box" (the black box is the smallest solid rectangle that would
completely cover the actual character glyph).

By the way, while on the subject of printing characters at a very large font
size as you are doing you might also want to look at kerning, which is the
amount of space that the designer of the font decided was the best between
each specific pair of characters. When printing very large text, especially
when it consists mainly of uppercase characters, it always looks best when
it is properly kerned. For example, try the following:

    Me.Font.Name = "Times New Roman"
    Me.Font.Size = 100
    Me.Print "AVERAGE"

If you look at the output it appears as though the leading "A" is stuck out
there on its own, with the "VERAGE" appearing to be a separate word. Also
there is clearly too much white space between the second "A" and the "G".
Positioning the characters in accordance with the spacing that the designer
of the font decided upon makes it look much better. The optimal spacing
between glyphs depends on the shape of the glyph and the glyph immediately
following it and the spacing therefore needs to take into account both
characters. The GetKerningPairs API function will tell you what spacing the
font designer decided on for all specific pairs of characters in a specific
font and size, and you can then use that information to space out your
characters appropriately.

This response is already quite long and in any case I'm not sure how far you
want to take this stuff. Perhaps you might be happy to simply "add a bit
extra" to account for the overhangs I have mentioned and perhaps you don't
wish to bother with the added complication of kerning, but if you do want
details of how to use the functions I have mentioned then post again.

Mike
Author
1 Jul 2009 4:42 PM
John Simpson
Show quote Hide quote
"Mike Williams" <M***@WhiskyAndCoke.com> wrote in message
news:%23jqmQXj%23JHA.5040@TK2MSFTNGP04.phx.gbl...
> "John Simpson" <jas***@earthlink.net> wrote in message
> news:uuKVpOc%23JHA.4360@TK2MSFTNGP04.phx.gbl...
>
>> OK, I'm stuck!
>> ' resize Pic1 code omitted for brevity
>> BeginPath Pic1.hdc
>> Pic1.CurrentX = 0
>> Pic1.CurrentY = 0
>> Pic1.Print TXT
>> EndPath Pic1.hdc
>> StrokePath Pic1.hdc
>> Printer.Print ?????????     ' here's my problem
>
> It is easily possible to print the picturebox contents to the printer,
> although the output quality would not be very good because you are
> effectively "stretching" a low resolution screen bitmap (96 dpi) so that
> it appears at a suitable size on a high resolution perhaps 600 dpi
> printer. The text outline on the printed page would therefore look fairly
> "blocky" on close inspection, partly because of the "pixel stretching" I
> mentioned and partly because the StrokePath API function does not use the
> text smoothing that standard characters use. So, the best way to draw the
> Path you have created to the Printer is to actually create it against the
> Printer.hdc and to use StrokePath Printer.hdc to print it, controlling the
> thickness of the outline with a Printer.DrawWidth statement if you want
> the outline to be greater than one printer pixel in thickness (which you
> in many cases would do because printer pixels are very small). However,
> because there are other issues with your existing PictureBox method in the
> code you have posted, and because some of those issues would also affect
> the "Stroke Path to Printer" method, I will deal here with the answer to
> the specific question you have asked (how to transfer the PictureBox drawn
> contents to the printer).
>
> The drawing created by your existing code ends up as a bitmap in the Image
> property of the PictureBox. You can print the Image property bitmap to the
> printer using Printer.PaintPicture pic1.Image but if you do it that way
> (without specifying a source size and without making any other
> modifications to your code) you may end up printing a bitmap that is
> larger than the current size of the PictureBox. That's because the bitmap
> contained in the Image property of a PictureBox still retains its previous
> pixel size even after you have resized the PictureBox unless the previous
> size was smaller than the "resized" size and the Image bitmap can
> therefore end up larger than the PictureBox that is displaying it, so if
> the PictureBox was originally larger than the size your code has resized
> it to then the bitmap in its Image property, and therefore the bitmap that
> gets printed, will be larger than you are expecting. You won't see the
> extra of course if the background is white, but you will if it is some
> other colour or if it contained a background of some kind. There are ways
> to overcome this problem using the various PaintPicture statement
> parameters but generally it is wise to resize the bitmap properly,
> especially if you ever wish to save the Image using SavePicture. There are
> all sorts of ways of forcing a PictureBox to reliably resize its bitmap
> Image and all of them are very simple. For example with your own code as
> posted you could simply move the Autoredraw statement to after the resize,
> or you could use a Cls method after the resize, there are all sorts of
> different ways. Personally in your own code I would suggest using Pic1.Cls
> immediately after the Pic1.Width and Pic1.Height statements. Then after
> you have finished your Picture Box drawing (after the StrokePath
> statement) use:
>
>    Printer.PaintPicture pic1.Image, 0, 0
>
> Having said all that, there are are few other things about your code that
> I would like to comment on. Firstly you are setting the Width and Height
> of the PictureBox to the desired size of the bitmap you intend it to
> contain. If the PictureBox has a border then the actual size of the bitmap
> it contains will be less than its overall width and height. So with a
> PictureBox that has a border you really need to be setting its Width and
> Height to a slightly greater value so that the size of the bitmap it
> contains is correct. This often (but not always) won't be a problem when
> the bitmap is just a string of text because in many cases there is some
> "white space" around the character cells anyway and so the characters
> themselves will probably still all be fully displayed, but it is wise not
> make that assumption and to size it properly. There are various ways of
> accounting for the border thicknesses to fix this problem but a simple
> "native VB code" method would be something like:
>
>    Dim xBorder As Single, yBorder As Single
>    pic1.ScaleMode = pic1.Container.ScaleMode
>    xBorder = pic1.Width - pic1.ScaleWidth
>    yBorder = pic1.Height - pic1.ScaleHeight
>    pic1.Width = pic1.TextWidth(TXT) + xBorder
>    pic1.Height = pic1.TextHeight(TXT) + yBorder
>
> As I've said, there are all sorts of different ways of doing the above but
> the important thing, whichever way you choose, is that you actually do it.
> The above code will reliably set the picbox overall size correctly so that
> its contained bitmap size (the client area) is the size you require but
> when dealing with the size of fonts there are also other things you need
> to take into consideration. That's because the VB TextWidth function and
> the alternative API GetTextExtentPoint32 function do NOT tell you the
> actual displayed width of the string of characters. They in fact tell you
> the width of the character cells in which the characters "live". This is
> often okay because many character glyphs in many fonts (the actual printed
> character shapes) live entirely within their cells, but in many cases it
> is not okay because some character glyphs overhang the border of their
> character cell at the left side or the right side or sometimes both sides.
> In fact in some cases some characters overhang the bottom of the character
> cell as well.
>
> To see what I mean first run your code as it currently exists (with or
> without the amendments I have mentioned) and you should see the word
> "TEMPLATE" entirely visible in the PictureBox. Now change the font to
> "Times New Roman" and add the line Pic1.Font.Italic = True and change the
> TXT variable from "TEMPLATE" to "fluff" and try it again. This time you
> should see that the text is not entirely visible, with the "f" characters
> in the word "fluff" overhanging the left side and the right side and the
> bottom edge of their cells. This is not a characteristic of the StrokePath
> function or of anything else in your code, but rather it is a
> characteristic of fonts in general and the same thing will happen if you
> use a standard Print statement or any other statement that prints text.
>
> As I've already mentioned, the problem arises because the TextWidth
> function (and the equivalent API GetTextExtent function) return the width
> of the string of text without taking into account any characters ate the
> left or right end of the string that might overhang their cells. Similarly
> the TextHeight function (and the equivalent API GetTextExtent function) do
> not take account of any characters that overhang the bottom of their
> cells. To calculate the correct size you need to get the width returned by
> the TextWidth (or the alternative GetTextExtent32) function and then add
> to that the amount by which the leftmost character overhangs the left edge
> of its cell and also the amount by which the rightmost character overhangs
> the right edge of its cell. Then when you have set the bitmap (the
> PictureBox client area or whatever) to the calculated width you need to
> position the x coordinate of the print statement to a positive value equal
> to the amount by which the leftmost character overhangs the left edge of
> its cell.
>
> If in any specific case you need to know only the left and right edge
> overhangs of a character then you can use the very simple GetCharABCWidths
> API function but if you want to also know the bottom edge overhang (not as
> common as left and right overhangs) then you'll need to use a something
> else, for example the slightly more complicated GetGlyphOutline API
> function which can get both the size and the position within the character
> cell of the "black box" (the black box is the smallest solid rectangle
> that would completely cover the actual character glyph).
>
> By the way, while on the subject of printing characters at a very large
> font size as you are doing you might also want to look at kerning, which
> is the amount of space that the designer of the font decided was the best
> between each specific pair of characters. When printing very large text,
> especially when it consists mainly of uppercase characters, it always
> looks best when it is properly kerned. For example, try the following:
>
>    Me.Font.Name = "Times New Roman"
>    Me.Font.Size = 100
>    Me.Print "AVERAGE"
>
> If you look at the output it appears as though the leading "A" is stuck
> out there on its own, with the "VERAGE" appearing to be a separate word.
> Also there is clearly too much white space between the second "A" and the
> "G". Positioning the characters in accordance with the spacing that the
> designer of the font decided upon makes it look much better. The optimal
> spacing between glyphs depends on the shape of the glyph and the glyph
> immediately following it and the spacing therefore needs to take into
> account both characters. The GetKerningPairs API function will tell you
> what spacing the font designer decided on for all specific pairs of
> characters in a specific font and size, and you can then use that
> information to space out your characters appropriately.
>
> This response is already quite long and in any case I'm not sure how far
> you want to take this stuff. Perhaps you might be happy to simply "add a
> bit extra" to account for the overhangs I have mentioned and perhaps you
> don't wish to bother with the added complication of kerning, but if you do
> want details of how to use the functions I have mentioned then post again.
>
> Mike
>
>
>

Mike,

Thanks for taking the time to write a tutorial. It was very informative, and
my senior citizen's brain could easily absorb it.

As it turns out, I won't be able to go this route. I was going to print it
as a
transparent 'overlay' on some Purchase Order forms that the client didn't
want
processed, but the white space in the picture box blocks some of the form.
I'm just going to go with straight, big text. Not as cute, but it gets the
point
across. But I learned something today!

Thanks again.

John
Author
1 Jul 2009 6:08 PM
Larry Serflaten
Show quote Hide quote
"John Simpson" <jas***@earthlink.net> wrote

> >> OK, I'm stuck!

> Mike,
>
> Thanks for taking the time to write a tutorial. It was very informative, and
> my senior citizen's brain could easily absorb it.
>
> As it turns out, I won't be able to go this route. I was going to print it  as a
> transparent 'overlay' on some Purchase Order forms that the client didn't want
> processed, but the white space in the picture box blocks some of the form.
> I'm just going to go with straight, big text. Not as cute, but it gets the point
> across. But I learned something today!


Hey John...

You are missing a piece of the puzzle.  With judicious use of the last parameter
to PaintPicture, you can overlay one image on another.  That last parameter
determines how the individual bits of the source and destination get combined.

If you tell it to copy the image, it will copy it, overwriting whatever was there.
If you want an overlay you have to combine the image that is already there,
with the image you want overlayed.

For an example add 2 Pictureboxes to a new form and paste in the code
below.  Running the program will show the overlay (SAMPLE) and
an image it overlays onto.  Clicking on the overlay image will add the
overlay to the destination.  Clicking on the destination will remove the
overlay.

Most of the code simply draws the images.  The important stuff is in the
Click events.  Try it and see if that is what you had in mind....

LFS



Option Explicit

Private OverLay As PictureBox
Private Page As PictureBox


Private Sub Form_Load()
Dim X, Y, Z
  Set OverLay = Picture1
  Set Page = Picture2

  ' Draw the SAMPLE overlay
  With OverLay
    .Move 0, 0, 4000, 1000
    .AutoRedraw = True
    .BackColor = vbWhite
    .Font.Name = "Arial"
    .Font.Size = 48
    .Font.Bold = True

    '.ForeColor = RGB(240, 240, 240)   ' Lighter
    .ForeColor = RGB(224, 224, 224)   ' Darker
    '.ForeColor = RGB(192, 192, 192)   ' Darkest

  End With
  OverLay.Print "SAMPLE"
  Set OverLay.Picture = OverLay.Image

  ' Drawing the destination image ...
  With Page
    .Move 0, 1100, 4600, 4000
    .AutoRedraw = True
    .BackColor = vbWhite
  End With
  ' Draw some colored lines
  Page.Line (1220, 20)-Step(580, 4000), vbYellow, BF
  Page.Line (620, 20)-Step(580, 4000), RGB(128, 196, 255), BF
  ' Draw a circle
  Page.FillStyle = vbSolid
  Page.FillColor = vbRed
  Page.Circle (3000, 2000), 1500
  Page.FillColor = vbWhite
  Page.Circle (3000, 2000), 1000
  ' Draw some text
  For Y = 1200 To 2800 Step 180
  Page.CurrentX = 30
  Page.CurrentY = Y
  For X = 0 To 250
    Z = Int(Rnd * 60)
    If Z > 25 Then
      Page.Print " ";
    Else
      Page.Print Chr(Z + 65);
    End If
  Next
    Page.Print
  Next
  ' This helps the demo work, you wouldn't need this
  Page.AutoRedraw = False

End Sub

Private Sub Picture1_Click()
Dim X, Y, Z
  ' Combine source with destination bits using AND
  For Y = 240 To 4000 Step 1300
  For X = Z To 4600 Step 4600
    Page.PaintPicture OverLay, X, Y, , , , , , , vbSrcAnd
  Next
  Z = Z - 2700
  Next
End Sub

Private Sub Picture2_Click()
  ' Remove overlay
  Page.Cls
End Sub
Author
1 Jul 2009 7:59 PM
Mike Williams
"John Simpson" <jas***@earthlink.net> wrote in message
news:OUjg5rm%23JHA.4944@TK2MSFTNGP02.phx.gbl...

> Mike, Thanks for taking the time to write a tutorial. It was very
> informative, and my senior citizen's brain could easily absorb it.

You're very welcome. The fact that your senior citizen's brain could easily
absorb it is probably down to the fact that I am a senior citizen myself,
and I wrote it :-)

> As it turns out, I won't be able to go this route.

Yes you will!

> I was going to print it as a transparent 'overlay' on some
> Purchase Order forms that the client didn't want processed,
> but the white space in the picture box blocks some of the form.

That's not a problem, John. There are all sorts of ways of printing bitmaps
over backgrounds so that one specific colour (white, for example) is
transparent and only the "not white" pixels are printed. In fact I see that
Larry Serflaten has already posted such a solution. I haven't had time to
check out Larry's code but he is a regular here and he is extremely good at
what he does so I assume that his code will work okay.

However, perhaps you didn't fully read the first part of my previous
response in which I said that you can create and draw the path directly to
the Printer. You can also draw it directly to the Form if you wish. Here is
an extract of the relevant part of my previous response:

    "So, the best way to draw the Path you have
    created to the Printer is to actually create it
    against the Printer.hdc and to use StrokePath
    Printer.hdc to print it, controlling the thickness
    of the outline with a Printer.DrawWidth statement"

As a simple example, consider a Printer page (or a VB Form) with a
background image or some other background stuff over which you wish to draw
some large outline characters. In this example I'll use the Printer,
although the same basic principles apply to a Form. Let's assume that you
want some text on the page (or perhaps some text and some images) and you
want to overlay some large outline text over all of it. Here is how you can
do it (see code at end of this response). In this specific example it simply
prints some lines of text to almost fill the page and it then prints some
large point size outline text over the top of it. The same sort of thing
will work whether you are printing over background text or images or grids
or boxes or whatever. Also (although I haven't done it in this simple
example) it is possible with just a bit more code to print the outline text
at any angle you desire, for example diagonally so that it overlays the
whole page in a diagonal fashion. Anyway, here is some simple example code.
Let me know how you get on with it:

Mike

Option Explicit
Private Declare Function BeginPath Lib "gdi32" _
  (ByVal hdc As Long) As Long
Private Declare Function EndPath Lib "gdi32" _
  (ByVal hdc As Long) As Long
Private Declare Function StrokePath Lib "gdi32" _
  (ByVal hdc As Long) As Long

Private Sub Command1_Click()
Dim n As Long
Printer.ScaleMode = vbInches
Printer.Font.Name = "Times New Roman"
Printer.Font.Size = 16
Printer.Font.Bold = False
For n = 1 To 40
Printer.Print "This is some text over which we are " _
      & "going to draw some outline text for testing."
Next n
Printer.Font.Name = "Arial"
Printer.Font.Size = 80
Printer.Font.Bold = True
Printer.ForeColor = vbRed
Printer.DrawWidth = Printer.ScaleX(0.025, vbInches, vbPixels)
BeginPath Printer.hdc
  Printer.CurrentX = 0
  Printer.CurrentY = 3
  Printer.Print "CANCELLED"
EndPath Printer.hdc
StrokePath Printer.hdc
Printer.EndDoc
End Sub
Author
2 Jul 2009 7:28 AM
Mike Williams
"John Simpson" <jas***@earthlink.net> wrote in message
news:OUjg5rm%23JHA.4944@TK2MSFTNGP02.phx.gbl...

> StrokePath Pic1.hdc
> Printer.Print ?????????     ' here's my problem

Further to my previous response here is a modified example which might be of
more general use to you because I've added some code (the RotatedText Sub)
that can print both normal and outline text at any desired angle of rotation
into a Form or a PictureBox or a Printer page. Paste the example into a Form
containing a Command Button. I wrote it fairly quickly and I haven't yet had
time to fully test it under all conditions so let me know if you come across
any problems with it.

Mike

Option Explicit
Private Declare Function CreateFontIndirect Lib "gdi32" _
  Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long
Private Declare Function SelectObject Lib "gdi32" _
  (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" _
  (ByVal hObject As Long) As Long
Private Declare Function TextOut Lib "gdi32" Alias _
  "TextOutA" (ByVal hdc As Long, ByVal x As Long, ByVal _
  y As Long, ByVal lpString As String, ByVal nCount _
  As Long) As Long
Private Declare Function BeginPath Lib "gdi32" _
  (ByVal hdc As Long) As Long
Private Declare Function EndPath Lib "gdi32" _
  (ByVal hdc As Long) As Long
Private Declare Function StrokePath Lib "gdi32" _
  (ByVal hdc As Long) As Long
Private Const LF_FACESIZE = 32
Private Const OUT_OUTLINE_PRECIS = 8
Private Type LOGFONT
  lfHeight As Long
  lfWidth As Long
  lfEscapement As Long
  lfOrientation As Long
  lfWeight As Long
  lfItalic As Byte
  lfUnderline As Byte
  lfStrikeOut As Byte
  lfCharSet As Byte
  lfOutPrecision As Byte
  lfClipPrecision As Byte
  lfQuality As Byte
  lfPitchAndFamily As Byte
  lfFaceName As String * LF_FACESIZE
End Type

Private Sub RotatedText(p1 As Object, s1 As String, _
                angle As Long, outline As Boolean)
' Prints rotated text to a Form or PicBox or Printer at
' the current x and y coordinates at any specified angle
' (in tenths of a degree in an anti clockwise direction with
' zero being normal text). The font used must be a TrueType
' or Open Type or similar font and NOT a screen bitmap font
' The outline variable should be True for outline text or
' False for solid text
Dim MyHdc As Long, MyFont As LOGFONT
Dim xpix As Long, ypix As Long
Dim NewFont As Long, OldFont As Long
With p1
  xpix = .ScaleX(.CurrentX - .ScaleLeft, .ScaleMode, vbPixels)
  ypix = .ScaleY(.CurrentY - .ScaleTop, .ScaleMode, vbPixels)
  MyHdc = .hdc
End With
With MyFont
.lfEscapement = angle
.lfHeight = -(p1.ScaleY(p1.Font.Size, vbPoints, vbPixels))
.lfFaceName = p1.Font.Name & vbNullChar
If p1.Font.Bold = True Then
  .lfWeight = 700
Else
  .lfWeight = 400
End If
  .lfItalic = p1.Font.Italic
  .lfUnderline = p1.Font.Underline
  .lfOutPrecision = OUT_OUTLINE_PRECIS ' True Type
End With
NewFont = CreateFontIndirect(MyFont)
OldFont = SelectObject(MyHdc, NewFont)
If outline = True Then
  BeginPath MyHdc
  TextOut MyHdc, xpix, ypix, s1, Len(s1)
  EndPath MyHdc
  StrokePath MyHdc
Else
  TextOut MyHdc, xpix, ypix, s1, Len(s1)
End If
SelectObject MyHdc, OldFont
DeleteObject NewFont
End Sub

Private Sub Command1_Click()
Dim n As Long, s1 As String
s1 = "This is some sample normal text over which we are " _
      & "going to draw some outline text for testing purposes."
Printer.Print ' always start a print job with this
With Printer
  .ScaleMode = vbInches
  .Font.Name = "Times New Roman"
  .Font.Bold = False
  .Font.Size = 12
  .ForeColor = vbBlack
  .CurrentX = 0
  .CurrentY = 0
  For n = 1 To 47
    Printer.Print s1
  Next n
  .Font.Name = "Courier New"
  .Font.Bold = True
  .Font.Size = 120
  .CurrentX = 0.5
  .CurrentY = 7.5
  .DrawWidth = Printer.ScaleX(0.01, vbInches, vbPixels)
  .ForeColor = vbRed
  ' set last parameter of following to True for
  ' outline text or to False for solid text
   RotatedText Printer, "TEMPLATE", 600, True ' 60 degrees
End With
Printer.EndDoc
End Sub
Author
8 Jul 2009 8:33 PM
John Simpson
Been on vacation. I really appreciate the help from you guys. Once I get my
act back together
I'll play a little. I really did want to do the overlay thing. Now there's
hope!

John

<snip>

Bookmark and Share