|
code
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Printing PictureBox ContentsUnfortunately, the printout is not the complete PictureBox content. It appears that the picturebox contents is much larger than the printed page. What I need to happen is for the printout to be the complete content of the picturebox. This means that the content needs to be 'shrunk' to fit the landscape printed page. How do I do this? Here is my current code: Public Sub PrintPictureBox(box As PictureBox, Optional x As Single = 0, Optional y As Single = 0) Dim rv As Long Dim ar As Boolean On Error GoTo Exit_Sub With box 'Save ReDraw value ar = .AutoRedraw 'Set persistance .AutoRedraw = True 'Wake up printer Printer.Print 'Draw controls to picture box rv = SendMessage(.hWnd, WM_PAINT, .hdc, 0) rv = SendMessage(.hWnd, WM_PRINT, .hdc, _ PRF_CHILDREN Or PRF_CLIENT Or PRF_OWNED) 'Refresh image to picture property .Picture = .Image 'Copy picture to Printer Printer.PaintPicture .Picture, x, y Printer.CurrentX = 0 Printer.CurrentY = 0 Printer.Print frmChart.Caption Printer.EndDoc 'Restore backcolor (Re-load picture if picture was used) box.Line (0, 0)-(.ScaleWidth, .ScaleHeight), .BackColor, BF 'Restore ReDraw .AutoRedraw = ar End With Exit_Sub: If Err.number Then MsgBox Err.description, vbOKOnly, "Printer Error!" End Sub Thanks! Webbiz "Webbiz" <nospam@formethanks.com> wrote in message PaintPicture is capable of stretching or shrinking the image it paints. At news:6mipl.69457$fM1.68327@newsfe14.iad... > What I need to happen is for the printout to be the complete > content of the picturebox. This means that the content needs > to be 'shrunk' to fit the landscape printed page. How do I do this? the moment you've got: Printer.PaintPicture .Picture, x, y This causes the PictureBox to be printed out at its full logical size. If you wish to change this then all you need to do is change the above code to the following (where wide and high specify the desired size of the printed output): Printer.PaintPicture .Picture, x, y, wide, high It would be best to set the ScaleMode of both the PictureBox and the Printer to the same logical units, perhaps vbInches or vbCentimeters or whatever you are most comfortable with (anything except vbPixels). Then your code will be easily able to compare the ScaleWidth and ScaleHeight of both the PictureBox and the Printer page in order to determine the most appropriate page orientation and whether either the width or height of the printout needs to be reduced. Personally I'm not a great believer in printing out what are effectively low resolution screen dumps of a Form or a PictureBox to a high resolution device such as a printer because of the limitation in quality, and I certainly would not advise either expanding or shrinking the output, which will reduce the quality even further. However, that is up to you of course and if it suits your needs then that's fine. By the way, I take it you have already come across the various limitations of the WM_PRINT and WM_PAINT method you are using, for example the fact that with a PictureBox (or Form) that has a border some things (standard Controls such as Command Buttons and TextBoxes) will be offset to the right and left of where they should be on the printout whereas other things, such as Label Controls, will not. Fixing the misalignment of standard Controls by using a different DC (the DC of the window rather than the DC of the client area) is not a solution because whereas it fixes the aligment of those controls it messes up the alignment of Labels, etc, which were previously okay. The easy way to fix the problem though is to simply make sure that you are using a Borderless PixtureBox. Also, I imagine that you have come across the other main problem with this method in that certain content of various controls (I think it was Picure properties or Autoredraw bitmaps) and certain content of controls in the PictureBox that are themselves acting as containers do not get printed at all, so I assume that in your own specific layout those things are not a problem for you. Mike Hi Mike.
> Somethings not working right.> PaintPicture is capable of stretching or shrinking the image it paints. At > the moment you've got: > > Printer.PaintPicture .Picture, x, y > > This causes the PictureBox to be printed out at its full logical size. If > you wish to change this then all you need to do is change the above code > to the following (where wide and high specify the desired size of the > printed output): > > Printer.PaintPicture .Picture, x, y, wide, high > What I want is to print the complete content of the picturebox onto a sheet of paper. I'd like it to fit on the paper. Originally, I simply left off the x, y. You state above that this should print out the "full logical size". Yet, my problem persists. I also set the picturebox and printer to vbInches like you suggested. That didn't change my output. It still isn't shrinking the content to fit on the paper. I'm lost. Help...pweasze? > It would be best to set the ScaleMode of both the PictureBox and the Did that. And I assume I'm suppose to set the picturebox scalemode back to > Printer to the same logical units, perhaps vbInches or vbCentimeters or > whatever you are most comfortable with (anything except vbPixels). what it was originally before exiting my print routine. So that's done also. Then your code will be Show quoteHide quote > easily able to compare the ScaleWidth and ScaleHeight of both the No, I didn't notice any problems in this regard because I'm only trying to > PictureBox and the Printer page in order to determine the most appropriate > page orientation and whether either the width or height of the printout > needs to be reduced. Personally I'm not a great believer in printing out > what are effectively low resolution screen dumps of a Form or a PictureBox > to a high resolution device such as a printer because of the limitation in > quality, and I certainly would not advise either expanding or shrinking > the output, which will reduce the quality even further. However, that is > up to you of course and if it suits your needs then that's fine. > > By the way, I take it you have already come across the various limitations > of the WM_PRINT and WM_PAINT method you are using, for example the fact > that with a PictureBox (or Form) that has a border some things (standard > Controls such as Command Buttons and TextBoxes) will be offset to the > right and left print out my price chart of lines and such. Thanks Mike. Webbiz "Webbiz" <nospam@formethanks.com> wrote I just want to reiterate a point Mike already stated.> The following code is what I use to print out the contents of my PictureBox. > > Unfortunately, the printout is not the complete PictureBox content. It > appears that the picturebox contents is much larger than the printed page. - Copying a low rez. image to a hi rez. printer yields a low rez result. The jaggies which seem normal on the screen will be very noticable in a printout. The code your using to print the picturebox is used to copy the contents of the picturebox, controls and all. If your picutrebox is all drawn graphics you don't need that routine, just use the picturebox's image: Printer.PaintPicture picChart.Image, 0, 0, Printer.ScaleWidth, Printer.ScaleHeight But, you'd get far better results if you drew your graphics to the Printer rather than copying a screen image. LFS That one line of code actually worked for me. And it made clear what Mike
was trying to tell me. I did not realize that we were talking about the "Printers" .scalewidth and .scalemode. I thought that was the pictureboxes I was suppose to pass. Oh brother. Thanks Larry. It works great. BTW, what is the difference between... ..Printer = .Image Printer.PaintPicture .Printer, 0, 0, Printer.ScaleWidth, Printer.ScaleHeight ....and Printer.PaintPicture .Image, 0, 0, Printer.ScaleWidth, Printer.ScaleHeight ? Cheers! Webbiz Show quoteHide quote "Larry Serflaten" <serfla***@usinternet.com> wrote in message news:eqKiL15lJHA.1248@TK2MSFTNGP03.phx.gbl... > > The code your using to print the picturebox is used to copy the contents > of the picturebox, controls and all. If your picutrebox is all drawn > graphics > you don't need that routine, just use the picturebox's image: > > Printer.PaintPicture picChart.Image, 0, 0, Printer.ScaleWidth, > Printer.ScaleHeight > > But, you'd get far better results if you drew your graphics to the > Printer rather than copying a screen image. > > LFS > "Webbiz" <nospam@formethanks.com> wrote Woohoo! Except, I have to wonder, are you happy with> Thanks Larry. It works great. the output? Or, does it look too course (low rez) ? > BTW, what is the difference between... One obvious difference is that one will compile, and the other> > .Printer = .Image > Printer.PaintPicture .Printer, 0, 0, Printer.ScaleWidth, Printer.ScaleHeight > > ...and > > Printer.PaintPicture .Image, 0, 0, Printer.ScaleWidth, Printer.ScaleHeight won't. If you really meant that .Printer should have been .Picture then that first one would compile. If that is the case, then what you end up doing is copying the .Image property to the .Picture property before printing the .Picture. Using .Image alone avoids that step. LFS Yes, I mean .Picture, not .Printer. Ooops!
Thanks! Webbiz Show quoteHide quote "Larry Serflaten" <serfla***@usinternet.com> wrote in message news:uVC4ghUmJHA.1388@TK2MSFTNGP06.phx.gbl... > > "Webbiz" <nospam@formethanks.com> wrote > >> Thanks Larry. It works great. > > Woohoo! Except, I have to wonder, are you happy with > the output? Or, does it look too course (low rez) ? > > >> BTW, what is the difference between... >> >> .Printer = .Image >> Printer.PaintPicture .Printer, 0, 0, Printer.ScaleWidth, >> Printer.ScaleHeight >> >> ...and >> >> Printer.PaintPicture .Image, 0, 0, Printer.ScaleWidth, >> Printer.ScaleHeight > > One obvious difference is that one will compile, and the other > won't. If you really meant that .Printer should have been .Picture > then that first one would compile. If that is the case, then what you > end up doing is copying the .Image property to the .Picture property > before printing the .Picture. Using .Image alone avoids that step. > > LFS > > Here is a quick comparision between copying and drawing
to the printer. Add a command button to a new form and run the program. Then carefully inspect the output of both methods.... HTH LFS Private Sub Command1_Click() Move Left, Top, 4500, 4500 Command1.Visible = False AutoRedraw = True BackColor = vbWhite Me.PSet (1800, 2100), vbWhite Me.Print "COPY" Me.Circle (2100, 2100), 2000, vbBlack ' Copied picture Printer.Print Printer.PaintPicture Me.Image, 0, 0 ' Direct draw Printer.PSet (1800, 7000), vbWhite Printer.Print "DRAWN" Printer.DrawWidth = 2 Printer.Circle (2100, 7000), 2000, vbBlack Printer.EndDoc Command1.Visible = True End Sub Wow. That example pretty much sums it up.
Drawing directly to the printer object is obviously the way to go for Hi-Res. Fortunately I don't need Hi-Res for printing a simple bar chart. However, when I can find the time, I'll look into reproducing the code that currently draws to the picbox to draw to the printer. Thanks Larry. Webbiz Show quoteHide quote "Larry Serflaten" <serfla***@usinternet.com> wrote in message news:ussO%23sUmJHA.3876@TK2MSFTNGP02.phx.gbl... > > Here is a quick comparision between copying and drawing > to the printer. Add a command button to a new form and > run the program. Then carefully inspect the output of > both methods.... > > HTH > LFS > > > Private Sub Command1_Click() > > Move Left, Top, 4500, 4500 > Command1.Visible = False > AutoRedraw = True > BackColor = vbWhite > > Me.PSet (1800, 2100), vbWhite > Me.Print "COPY" > Me.Circle (2100, 2100), 2000, vbBlack > > ' Copied picture > Printer.Print > Printer.PaintPicture Me.Image, 0, 0 > > ' Direct draw > Printer.PSet (1800, 7000), vbWhite > Printer.Print "DRAWN" > Printer.DrawWidth = 2 > Printer.Circle (2100, 7000), 2000, vbBlack > > Printer.EndDoc > Command1.Visible = True > > End Sub > > "Webbiz" <nospam@formethanks.com> wrote in message Looking back at my original response I suppose I did skip rather quickly news:cP_pl.25110$Si4.21185@newsfe22.iad... > That one line of code actually worked for me. And it made > clear what Mike was trying to tell me. I did not realize that > we were talking about the "Printers" .scalewidth and > .scalemode. I thought that was the pictureboxes I was > suppose to pass. Oh brother. Thanks Larry. It works great. over that part of the explanation. I was concentrating mainly on the quality and the Control misalignment aspects (if your PictureBox has a border) of the method you are using and I just assumed that you would know that I was talking about the desired *Printer* output size for the parameters wide and high in the PaintPicture line I posted. Incidentally, I would be very interested in your answer to the question posed by Larry asking whether you are happy with the quality of the output? Normally the quality of screen dumps is quite poor anyway, even if you print the "screen dump bitmap" of the PictureBox and its drawn content and Controls at full logical size, but it is usually very much worse once you either reduce or stretch the size of the output. Are you happy with the quality? Personally I would prefer to draw all output directly to the Printer using the normal Printer Object drawing methods, but if you are happy with the existing quality then that's okay of course. Unless you are dumping a bitmap copy to the printer as an example of a displayed window perhaps for a "How to use Windows" tutorial or something then the printed output of the data represented by a Form (or a PictureBox) does not necessarily need to be exactly the same as its screen representation. In fact in many cases it is actually best if it is not the same. Forms are designed primarily (although not of course totally) for user interaction whereas printed pages are not, and a layout and design which suits one does not necessarily suit the other. By the way, I vaguely recall reading a post from someone who wanted to draw a very large PictureBox and its contents at its full logical size across a number of separate printed A4 pages, so that the pages could be formed into a large poster or something, but I can't recall whether he got an answer or not (I've been on holiday a few times recently and I have often "skip read" various posts to catch up). Was it you who posted that question? If so then you can very easily achieve that using your existing code and the Printer.PaintPicture method. Post again if that is what you want. Mike Hello Mike.
"Mike Williams" <M***@WhiskyAndCoke.com> wrote in message I mentioned it in my reply to Larry's code example, but will also do so here news:OkL1CgYmJHA.6060@TK2MSFTNGP05.phx.gbl... > "Webbiz" <nospam@formethanks.com> wrote in message > news:cP_pl.25110$Si4.21185@newsfe22.iad... > > Incidentally, I would be very interested in your answer to the question > posed by Larry asking whether you are happy with the quality of the > output? directly to yours. The quality of printing the .image from the picbox to printer works satisfactory for now. It is just a series of vertical lines (price bars) and the occasional line drawing. So nothing that is needing to be Hi-Res. With that said, however, I would rather have it Hi-Res eventually. The code that currently draws on the picbox is from several modules. There is one that will draw the chart, and can be one or more that draw some tools onto the chart as part of a redraw. So somehow diverting this code to the printer rather than the picbox is something I'm going to have to give a lot of thought to. Perhaps I can add some kind of boolean flag variable that is set when PRINT is selected, and then I can run the DrawChart routine again. Hmmm, that might do it. > Nope. That was not me. First time I've heard of it, and can't think if any > By the way, I vaguely recall reading a post from someone who wanted to > draw a very large PictureBox and its contents at its full logical size > across a number of separate printed A4 pages, so that the pages could be > formed into a large poster or something, but I can't recall whether he got > an answer or not (I've been on holiday a few times recently and I have > often "skip read" various posts to catch up). Was it you who posted that > question? use for that function personally. Thanks Mike. Webbiz "Webbiz" <nospam@formethanks.com> wrote Yes, you'd need a way to make the transition only when needed, however> The code that currently draws on the picbox is from several modules. There > is one that will draw the chart, and can be one or more that draw some tools > onto the chart as part of a redraw. So somehow diverting this code to the > printer rather than the picbox is something I'm going to have to give a lot > of thought to. coding it up would be fairly simple. One way to do that is having a global variable holding the drawing surface object: (in a BAS module somewhere) Public SurfaceObject As Object Then all your drawing commands would use that object. (Since most or all of the commands are in one sub, the change would be minimal) Something like: Public Sub Draw() Dim obj As Object ' As Form Set obj = SurfaceObject obj.Line (0, 0)-(1000, 1000), vbBlack, B ' ... etc End Sub To get Intellisense to show as you write the code you could declare obj as Form, or as Picturebox, but then change it to Object when you have finished writing the code. Then when your main form loads, you set SurfaceObject to your Picturebox and when its time to Print you swap it out: Sub PrintChart() Set SurfaceObject = Printer Printer.Print Printer.Scale (L, T)-(R, B) ' As desired.... DrawChart ' ... Draw other tools as needed Printer.EndDoc Set SurfaceObject = picChart End Sub HTH LFS Now that's a pretty cool idea Larry.
One thing though. Isn't this bringing us back to the issue of "Late Binding"? Thx. Webbiz Show quoteHide quote "Larry Serflaten" <serfla***@usinternet.com> wrote in message news:udNrJLtmJHA.1252@TK2MSFTNGP03.phx.gbl... > > "Webbiz" <nospam@formethanks.com> wrote > >> The code that currently draws on the picbox is from several modules. >> There >> is one that will draw the chart, and can be one or more that draw some >> tools >> onto the chart as part of a redraw. So somehow diverting this code to the >> printer rather than the picbox is something I'm going to have to give a >> lot >> of thought to. > > Yes, you'd need a way to make the transition only when needed, however > coding it up would be fairly simple. > > One way to do that is having a global variable holding the drawing surface > object: (in a BAS module somewhere) > > Public SurfaceObject As Object > > Then all your drawing commands would use that object. (Since most > or all of the commands are in one sub, the change would be minimal) > Something like: > > Public Sub Draw() > Dim obj As Object ' As Form > Set obj = SurfaceObject > obj.Line (0, 0)-(1000, 1000), vbBlack, B > ' ... etc > End Sub > > > To get Intellisense to show as you write the code you could declare > obj as Form, or as Picturebox, but then change it to Object when you > have finished writing the code. > > Then when your main form loads, you set SurfaceObject to your > Picturebox and when its time to Print you swap it out: > > Sub PrintChart() > Set SurfaceObject = Printer > Printer.Print > Printer.Scale (L, T)-(R, B) ' As desired.... > DrawChart > ' ... Draw other tools as needed > Printer.EndDoc > Set SurfaceObject = picChart > End Sub > > HTH > LFS > > "Webbiz" <nospam@formethanks.com> wrote My, how observant! Yes, using Object does bring late binding> Now that's a pretty cool idea Larry. > > One thing though. Isn't this bringing us back to the issue of "Late > Binding"? into the picture (catch the pun?) but VB's drawing routines are pretty quick so for most applications you would hardly notice a difference. Therefore the ease of programming (being able to swap out the surface) may outweight the desire for early bound calls. (Its your call...) For an example, here is a routine that draws over 400 circles and 400 lines on every Resize operation. An added checkbox decides if the operation uses early or late binding. See if you can notice a difference: LFS Private Sub Form_Load() Check1.Caption = "Late" AutoRedraw = True End Sub Private Sub Form_Resize() Dim X#, Y# Dim obj Cls Me.Scale (-10, -10)-(110, 110) If Check1.Value = vbChecked Then Set obj = Me For Y = 0 To 100 Step 5 For X = 0 To 100 Step 5 obj.Circle (X, Y), 3, vbBlack obj.Line (X, Y)-Step(2, 0), vbBlack Next X, Y Else For Y = 0 To 100 Step 5 For X = 0 To 100 Step 5 Me.Circle (X, Y), 3, vbBlack Me.Line (X, Y)-Step(2, 0), vbBlack Next X, Y End If End Sub "Larry Serflaten" <serfla***@usinternet.com> wrote in message Thanks. And you probably thought I wasn't paying attention to your lessons. news:%23zSOck6mJHA.4372@TK2MSFTNGP02.phx.gbl... > > "Webbiz" <nospam@formethanks.com> wrote >> Now that's a pretty cool idea Larry. >> >> One thing though. Isn't this bringing us back to the issue of "Late >> Binding"? > > My, how observant! ;^) Show quoteHide quote >Yes, using Object does bring late binding Nope. Couldn't really tell.> into the picture (catch the pun?) but VB's drawing routines are > pretty quick so for most applications you would hardly notice > a difference. Therefore the ease of programming (being able > to swap out the surface) may outweight the desire for early > bound calls. (Its your call...) > > For an example, here is a routine that draws over 400 circles > and 400 lines on every Resize operation. An added checkbox > decides if the operation uses early or late binding. > > See if you can notice a difference: > > LFS Thanks Larry. Webbiz "Webbiz" <nospam@formethanks.com> wrote in message As you've indicated, vertical and horizontal lines and bars and rectangles news:0_Cql.78690$fM1.76011@newsfe14.iad... > The quality of printing the .image from the picbox to printer > works satisfactory for now. It is just a series of vertical lines > (price bars) and the occasional line drawing. So nothing that > is needing to be Hi-Res. With that said, however, I would > rather have it Hi-Res eventually. of course will usually look fine when dumped to the printer as a bitmap. It's mainly irregular lines and line drawings and text items that will not. But if you are not using much text then it's fine for the time being to leave your code as it is. If you do ever decide to increase the quality though by drawing stuff either to the display or to the printer as appropriate, as in the code you are following with the help of Larry, then you should notice a significant difference, especially with text and irregular graphics. You can still have problems of a different kind with text items though when using the "draw to either the screen or the printer" method, with such problems being related to the slightly different font sizes and characters widths you will get on the two different devices because of their widely different resolutions. This usually isn't a problem though unless you are drawing wrapped blocks of text, in which case it does often become a problem because of the different line wrapping points (and consequently the possible different total number of lines in the block) on the two devices, so you'll need to add some extra complexity to your program to solve that problem. But if you are not drawing wrapped blocks of text then you can usually ignore the slight differences in the length of individual lines of text on the different devices. Mike Points taken.
Thank you Mike. :-) Webbiz Show quoteHide quote "Mike Williams" <M***@WhiskyAndCoke.com> wrote in message news:%23kBhAP9mJHA.1292@TK2MSFTNGP02.phx.gbl... > "Webbiz" <nospam@formethanks.com> wrote in message > news:0_Cql.78690$fM1.76011@newsfe14.iad... > > > The quality of printing the .image from the picbox to printer >> works satisfactory for now. It is just a series of vertical lines >> (price bars) and the occasional line drawing. So nothing that >> is needing to be Hi-Res. With that said, however, I would >> rather have it Hi-Res eventually. > > As you've indicated, vertical and horizontal lines and bars and rectangles > of course will usually look fine when dumped to the printer as a bitmap. > It's mainly irregular lines and line drawings and text items that will > not. But if you are not using much text then it's fine for the time being > to leave your code as it is. If you do ever decide to increase the quality > though by drawing stuff either to the display or to the printer as > appropriate, as in the code you are following with the help of Larry, then > you should notice a significant difference, especially with text and > irregular graphics. You can still have problems of a different kind with > text items though when using the "draw to either the screen or the > printer" method, with such problems being related to the slightly > different font sizes and characters widths you will get on the two > different devices because of their widely different resolutions. This > usually isn't a problem though unless you are drawing wrapped blocks of > text, in which case it does often become a problem because of the > different line wrapping points (and consequently the possible different > total number of lines in the block) on the two devices, so you'll need to > add some extra complexity to your program to solve that problem. But if > you are not drawing wrapped blocks of text then you can usually ignore the > slight differences in the length of individual lines of text on the > different devices. > > Mike > > >
Stupid Format$ Question
OT: Win 3.1 IE menu extension Should Reg-free COM still utilise an installation procedure? Save Picture Q Office 2003 installer pops up when loading a project Gradient Windows Update KB960715 blocks MSFLXGRD.OCX!!!!! Any solution ? Reading Stack from VB6 Unsigned C long to signed VB5 Long query. |
|||||||||||||||||||||||