|
code
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Printing contents of a picture boxI 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 "John Simpson" <jas***@earthlink.net> wrote Try> Can anyone help me with this?? > > ' Printer.Print ????????? ' here's my problem > Printer.EndDoc Printer.PaintPicture Pic1, 0, 0 LFS
Show quote
Hide quote
"Larry Serflaten" <serfla***@usinternet.com> wrote in message Thanks Larry.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 > > "John Simpson" <jas***@earthlink.net> wrote in message It is easily possible to print the picturebox contents to the printer, 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 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
Show quote
Hide quote
"Mike Williams" <M***@WhiskyAndCoke.com> wrote in message Mike,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 > > > 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
Show quote
Hide quote
"John Simpson" <jas***@earthlink.net> wrote Hey John...> >> 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! 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 "John Simpson" <jas***@earthlink.net> wrote in message You're very welcome. The fact that your senior citizen's brain could easily 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. 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 That's not a problem, John. There are all sorts of ways of printing bitmaps > Purchase Order forms that the client didn't want processed, > but the white space in the picture box blocks some of the form. 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 "John Simpson" <jas***@earthlink.net> wrote in message Further to my previous response here is a modified example which might be of news:OUjg5rm%23JHA.4944@TK2MSFTNGP02.phx.gbl... > StrokePath Pic1.hdc > Printer.Print ????????? ' here's my problem 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 |
|||||||||||||||||||||||