I have a form that has all sorts of controls on it from pictureboxes to flexgrids which I need to print.
But, I need to print it with the aid of the printer commondialog control which apparently the printform method doesn't allow.
Ideally the printed output is sized to suit the size of paper selected.
From other threads getting the idea that to achieve this I need to create a "data report or "crystal report". Is this right?
I don't seem to have "crystal report" installed but "Data Report" is in the component's manager.
Can someone point me in a direction on how to achieve this? I don't know the first thing about creating a report. All I know is that it appears in the component's manager.
The CommonDialog control could well be useful, it allows the user to specify which printer to use.
As you just want to print controls that are on the form, there is no need to use a reporting tool - you can simply use the Printer object. Here is a quick (untested) example:
VB Code:
Printer.CurrentX = 10 'Print text at certain location
This is really frustrating. I have found countless threads on this subject but there are no simple examples or clear explainations.
Attached is the shell project with the suggested code. Havn't bothered to started to look at stretching it to fit the page because it is taking a screenshot of my desktop as well as the form.
Does anyone have a simple example of how to print a picture that has controls in it and fit that image it to the printer.width and printer.height?
Here are the problems:
The picture is bigger than the form, and the form is bigger than the MDI form...
And you are telling it to print from the picture's Height wich is longer than the screen...
If you want to print the controls also, then they MUST be visible. The controls don't have an internal buffer that store it's image. They just print themselves on the screen ONLY when they are visible... (that's done in the Paint event), and if the control is not visible, it won't paint anything...
The only way I can think of, is to re-paint (draw) yourself all the controls in a picturebox that has AutoRedraw = True, but that is very complicated, and you can't do it with all controls, only the basic ones.
I've been slowly creating my project over two years and to find out I can't print it is a bit of a blow to put it mildly.
To list the controls in my form, I have :
ComboBoxes,
MHSFexgrids
OptionBoxes,
Textboxes,
& MartinLiss's Numberboxes.
I had the printform method printing it out fairly well but that doesn't allow me to chose a printer using the commondialog box or size the output to a papersize.
Is this a commonly known bug? Surely there's something I can do....???
Can I use the printform method to spit out an image that I can then use to resize and send to the printer?
Do you want to print what is VISIBLE on the screen, or everything (including the controls that are not visible because they are too low and don't come up on the screen until you scroll the window ?
Becasue if you want to print what you see on the screen only, then it is possible to do with the method previously shown exept you have to tell it the bowndries where to take the picture from...
I'd really want to print everything in the picture within the form even if they aren't visible.
It's just that screen sizes may vary ( form will need to be scrolled for people with smaller screens) or if the form isn't in a maximised state when it is printed.
I'd say almost all applications support this. MSWord, Adobe, Internet explorer.. Amazed this topic hasn't been done to death and it doesn't posted all the time.
Sorry, I'm sounding annoyed but it's a little frustrating at this stage.
In that case you are out of luck... it is verry difficult to do what you are asking.
One "quick trick" you can do, is to take a picture, save it in a buffer, scroll the window, take another picture, append to that buffer, and so on until you copy the whole thing, and then you print on the printer what you have accumulated in the buffer.
This will work because you are telling the control to display itself in the visible area of the screen, then you take a picture, and then you scroll more to get the other controls that were previously invisible, and so on...
The problem with this is that the user will actually see on the screen everything moving around until the process is done, if you try to hide the process, then the controls won't be visible, therefore, it will take a picture of something else (whatever is visible in that part of the screen, like when you tell it to take a picture that is bigger than the form (your previous complaint))
Edit
PS, by "a buffer" I mean: A picture box that is not visible, but with AutoRedraw = True. This will keep the image in the picture box even if it's not visible.
Last edited by CVMichael; Dec 4th, 2006 at 03:43 PM.
I'd say almost all applications support this. MSWord, Adobe, Internet explorer.. Amazed this topic hasn't been done to death and it doesn't posted all the time.
Sorry, I'm sounding annoyed but it's a little frustrating at this stage.
You are right, but there is a diference between printing your own stuff (what you draw), and printing a control where you are not drawing it...
If you were to draw the controls, then it won't be any problem... but you don't control the drawing part of each control...
Printform does exactly what I need but it sends the image to the default printer. Don't surpose there is another method that sends the image to a buffer that I can then send to the printer using the printer commondialog. I'm sure you've thought of this but I don't understand why it can't or hasn't been done.
VB is all I know and I have one sizable project written so far to let this be a shortfall in it.
In most cases, it's about asking the right question, and describing your problem in detail.
Like in your previous thread: [RESOLVED] Scrollbar thumb (slider) size.
At first I tought you wanted to scroll the picture when the form is bigger than the picture, not the other way around as you wanted.
So asking the right questions is the key to solving your problems.
Just think "how someone else whould read this ?", when you write your problem.
Why does it take about 5 seconds for the form to feed to the printer. I take it that it is taking a bitmap of the form which is a large file. Guessing that slower computers may take a lot longer.
Getting very picky here but is there a way that it can send a smaller jpg image or something?
Can ony hope I'm giving food for thought once in a blue moon as I don't think I can repay favours here for a while.
Any suggestions for the printer.zoom method to have a form fit to a page?
OK, here's how to use the zoom, but the problem is that it only works when you have to zoom-in, it gives an error when you have to zoom-out, ie, the form is bigger than the printer page...
This will auto zoom depending on the width and height, if the width is bigger then it will zoom by the width, otherwise it will zoom by the height
Getting very picky here but is there a way that it can send a smaller jpg image or something?
There are 2 reasons you can't, PrintForm does not give you control over the canvas (hDC), and even if you could, the printers' RAW data is bitmap... so even if you could convert to jpg, it will be converted back to RAW data when it's gonna send the jpg to the printer to print. So you don't have a choice there...
Programs that print fast, print directly in the printer's hDC, but in this case, you don't have access to it (I mean the PrintForm does not give you access to the hDC)
Another important difference with other programs.. they don't print a picture (which is basically what you are doing) unless it is needed, they print as text if possible. This takes much less data (basically a few bytes per character), and is therefore noticably faster.
If you use the method at the start of my example (CurrentX/CurrentY/Print) you can print a piece of text at a particular location on the page (in whatever font you like too). To print the relevant data from your controls you would just need to use that code a few times (in a loop for grids/lists/..), and you can also print pictures (as shown in my example), and draw simple graphics like lines and circles (using Printer.Line / Printer.Circle).
I thought that the printform method printed everything on the form including stuff that doesn't appear on screen. I was wrong. Back to the drawing board.
I would like to see all the additional controls drawn as they appear. Everything has been layed out already on the form and it would be nice if I don't have to redraw everything again.
Can someone have a look at this suggestion from MS's website.
I've tried applying it but what values are :
sWide = 8.5
sTall = 11 ' or 14, etc.
Should these be adjusted to match the paper size?
And why is it adjusting the form width?
Me.Width = twipFactor * sWide
Me.Height = twipFactor * sTall
Shoud it be adjusting the picture size instead?
I've had to add Me.WindowState = 0 otherwise I get an error that it can't adjust the form when it is maximised.
And even then it is not printing out the contents of picturebox3 which has a drawing in it nor the contents of the flexgrid?
If I can iron out these two issues it will solve all my printing problems.
Attached is the shell project for an example.
Picture3 and MSHFlexGrid1 contents don't want to print.
And how do I set the "sWide" and "stall" variables to suit the printer.width and printer.height properties. Ive tried and i've failed.
I have never used that method, so I don't know why it isn't doing the Picture3 and MSHFlexGrid1.. one solution is to draw them separately, like this (not perfect, but shows you the idea):
VB Code:
With MSHFlexGrid1
Picture2.PaintPicture .Picture, .Left, .Top
End With
You shouldn't use the .width and .height properties of the printer, as those are the measurements for the outside of the paper, not the printable area (which varies by printer and other factors). Instead you should use ScaleWidth/ScaleHeight.
The annoying thing is that these could be in a variety of measurement scales (Twips/Points/Inches, ...), so you need to find it out and convert them.. luckily there are functions to do that:
..although to be honest I dont see the point of using twipFactor, you may as well just read the sizes as Twips instead of Inches and avoid the extra step (and potential loss of accuracy).
Works well for the Flexgrid put but i'm stumped on why picture3 doesn't want to do the same. Tried all sorts of options but... when I don't know what I'm doing it is a little difficult.
Do you know anything about the method they have used to paste picture1 on picture 2 for printing.
I have never seen that method before.. all I can suggest (to continue in that manner) is to use another picturebox to paint them into, then use PaintPicture to position them within the main 'temporary' one.
The best way to print a form that is larger than the screen size or window size is to use the attached code. Most controls print fine except for a couple. In my case it was the mhsflexgrids and additional pictureboxes. Unless someone can advise me otherwise there are still a few glitches as I see it.
Without an automatic resizer control you will have to draw all the controls on the form to a picture size that matches a scaled papersize.
Haven't dabbled with autoresizers but here's a link to one if you want to use one. Free but costs without limitations. http://www.vbgold.com/ I'm not even sure if this would do what I want it to do. I'd want it to stretch the form to the scaled papersize and not stretch things to the form size. Anyway....
Flexgrids can be painted seperately to the main invisible picturebox without any problems but additional pictureboxes within the form have to be painted seperately.
For every picturebox you have on the form you need to create an additional invisible picturebox. Set picturebox.visible=false. Size doesn't matter as you resize the invisible picturebox to match the picturebox you want to print.
The attached should explain the rest hopefully. Right click on them and sendtoback if you want them out of the way.
If someone can help me further...
When I print it to a pdf and I open the pdf in Adobe, why do I have to zoom way out to see the full image?
I've just started trying to apply the code to my own project. Any explainations why i get the runtime error "480" Cannot create AutoRedraw image on the line
The auto-redraw error means that memory cannot be allocated.. perhaps because your application is already using too much from all those other pictureboxes, or perhaps because you have used the wrong ScaleMode on the pictureboxes (Twips is what you want).
I haven't tested it, but I think due to the "Picture2.Picture = Picture2.Image" line, you may not actually need AutoRedraw turned on anyway.
Originally Posted by sgrya1
The best way to print a form that is larger than the screen size or window size is to use the attached code.
That seems like a lot of work to me... I'll stick to using the normal printer methods, and print just the relevant text/graphics instead of the whole form!
When I print it to a pdf and I open the pdf in Adobe, why do I have to zoom way out to see the full image?
if this can help you
• Capture the entire contents of a form.
• Capture the client area of a form.
• Capture the entire screen.
• Capture the active window on the screen.
• Capture any portion of any window given a handle to it.
• Create a Picture object from a bitmap and a palette.
• Print a Picture object as large as possible on the page.
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Feels like a lot of work at the moment. When I'm done I should understand the whole procedure and be able to explain it a bit better.
Hoping for a little more help though.
I want to print be able to print the form as is and not have to manually draw tables and controls in a print method. Everything is there already and I'd like to print the form as the user sees it.
Thanks Westconn1 but that code turns out to be much the same as the printform method. Unfortunately it only captures what is visible on screen. It does help for scaling picture size to suit the printer.width and printer.height size for printing.
Here's where I'm at. The main form has picture1 which has all the controls in it. I paintpicture picture1 to picture2. Using the PrintPictureToFitPage subroutine the picture is painted to the size of the printer. Feels like there is a step there that I shouldn't need but that seems to be the way.
I have to repeat the same process for each additional smaller picturebox in the form because they don't seem to get painted to picture2.
Here lies the problem....I don't want the smaller pictureboxes to be printed to the full size of the printer page.
I made the PrintSmallPictureToFitPage subroutine to find the size and location to match the page size.
The routine does not pass picture.left and picture.top properties so im stuck now. Any suggestions?