-
[RESOLVED] Another Printform question
Hi all.
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.
-
Re: Another Printform question
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
Printer.CurrentY = 5
Printer.Print "Hello"
'Print picture at certain location
Printer.PaintPicture Picture1.Image, 20,20
'Tell it to print
Printer.EndDoc
-
Re: Another Printform question
Thanks Si,
All my controls are within the one picturebox so I guess it makes it easier rather than locating each individual control.
Do you have any further code that might help me open the commondialog box and export picture1 streached or shrunk to fit the selected page size?
-
Re: Another Printform question
To stretch it look at the help for PaintPicture - it has extra parameters to specify the size.
To use a Common Dialog, add it to the components (via "Project"->"Components") and place it on your form. An example of usage can be seen here.
-
1 Attachment(s)
Re: Another Printform question
Thanks again.
Attached is a tiny shell project. Can you explain why is it that it is just printing out blank sheets with none of the controls.
-
Re: Another Printform question
It seems you need to do a little extra work to print the controls that are in the picturebox (the actual picture [if there is one] prints fine!).
See this thread for a couple of ways to do it (especially post #8, which basically takes a screenshot and prints that).
-
1 Attachment(s)
Re: Another Printform question
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?
-
Re: Another Printform question
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.
-
Re: Another Printform question
Ouch!!!!
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?
-
Re: Another Printform question
Let me clarify one thing:
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...
-
Re: Another Printform question
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.
-
Re: Another Printform question
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.
-
Re: Another Printform question
Quote:
Originally Posted by sgrya1
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...
-
Re: Another Printform question
Last hope.
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.
-
Re: Another Printform question
Actually, from what I remember, the CommonDialog changes the default printer to what you choose in the dialog.
So theoretically, it should work if you open the printing dialog, and then you call the PrintForm.
I did not try that, I'm not 100% sure it will work.
-
Re: Another Printform question
Quote:
Originally Posted by CVMichael
I did not try that, I'm not 100% sure it will work.
Actually, I just tried it, and it works
Just do it like this:
VB Code:
CommonDialog1.ShowPrinter
Me.PrintForm
-
Re: Another Printform question
OMG!!!! Thanyou. This should almost be a sticky!!!
In repayment I will lookout for all future posts and praise you!!!
Maybe tomorrow I'll even start to search all those old posts to reply for you.
Obviously really worried there!
Thanks again!
-
Re: Another Printform question
If you can give me one more stoke of genius...
Is there a way to fit the printed form to the size of the paper?
-
Re: Another Printform question
I'm glad this solved your problem.
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.
-
Re: Another Printform question
Quote:
Originally Posted by sgrya1
If you can give me one more stoke of genius...
Is there a way to fit the printed form to the size of the paper?
I don't think so, the PrintForm does not have any parameters on resizing or anything like that...
-
Re: Another Printform question
I'm starting to tinker with it but you might likely find the answer days before I do but there is a printer.zoom method????
Would this do anything?
Edit: Yep.
-
Re: Another Printform question
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?
-
Re: Another Printform question
And one last question hopefully,
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?
-
Re: Another Printform question
Quote:
Originally Posted by sgrya1
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
VB Code:
Private Sub Command1_Click()
Dim XZoom As Single, YZoom As Single
CommonDialog1.ShowPrinter
XZoom = 100 * Printer.Width / Me.ScaleWidth
YZoom = 100 * Printer.Height / Me.ScaleHeight
If XZoom < YZoom Then
Printer.Zoom = XZoom
Else
Printer.Zoom = YZoom
End If
Me.PrintForm
End Sub
-
Re: Another Printform question
Quote:
Originally Posted by sgrya1
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)
-
Re: Another Printform question
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).
-
Re: Another Printform question
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.
http://search.support.microsoft.com/kb/230502/EN-US/
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?
-
Re: Another Printform question
Quote:
Originally Posted by sgrya1
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?
Yes.. those are sizes in inches (twipFactor is 1440, which is the number of twips per inch).
Quote:
And why is it adjusting the form width?
Simply because it is an example - you don't have to do that.
Quote:
Shoud it be adjusting the picture size instead?
It does that too. ;)
Quote:
And even then it is not printing out the contents of picturebox3 which has a drawing in it nor the contents of the flexgrid?
Are they both inside (your equivalent of) Picture1?
-
1 Attachment(s)
Re: Another Printform question
Hey again,
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.
-
Re: Another Printform question
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:
VB Code:
With Printer
sWide = .ScaleX(.ScaleWidth, .ScaleMode, vbInches)
sTall = ...
End With
..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).
-
1 Attachment(s)
Re: Another Printform question
Thanks again Si.
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.
VB Code:
Option Explicit
Private Const twipFactor = 1440
Private Const WM_PAINT = &HF
Private Const WM_PRINT = &H317
Private Const PRF_CLIENT = &H4& ' Draw the window's client area.
Private Const PRF_CHILDREN = &H10& ' Draw all visible child windows.
Private Const PRF_OWNED = &H20& ' Draw all owned windows.
Private Declare Function SendMessage Lib "user32" Alias _
"SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
It works for both the picture box and the flexgrid but I don't know how to position them as they are on the form.
VB Code:
rv = SendMessage(Picture1.hwnd, WM_PAINT, Picture2.hDC, 0)
rv = SendMessage(Picture1.hwnd, WM_PRINT, Picture2.hDC, PRF_CHILDREN + PRF_CLIENT + PRF_OWNED)
rv = SendMessage(Picture3.hwnd, WM_PAINT, Picture2.hDC, 0)
rv = SendMessage(Picture3.hwnd, WM_PRINT, Picture2.hDC, PRF_CHILDREN + PRF_CLIENT + PRF_OWNED)
rv = SendMessage(MSHFlexGrid1.hwnd, WM_PAINT, Picture2.hDC, 0)
rv = SendMessage(MSHFlexGrid1.hwnd, WM_PRINT, Picture2.hDC, PRF_CHILDREN + PRF_CLIENT + PRF_OWNED)
-
Re: Another Printform question
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.
-
Re: Another Printform question
That's my conclusion even though a little cumbersome. Try to give a step by step for others who find themselves in the same position.
Thankyou so much for your help!!!
-
1 Attachment(s)
Re: Another Printform question
OK.
I think I have this think understood.
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?
-
1 Attachment(s)
Re: Another Printform question
Sigh!
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
rv = SendMessage(Picture1.hwnd, WM_PAINT, Picture2.hDC, 0)
The line before is :
Picture2.AutoRedraw = True
-
Re: Another Printform question
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.
Quote:
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!
Quote:
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?
Change your default zoom setting (under "Edit" -> "Preferences" -> "Display").
-
Re: Another Printform question
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.
http://support.microsoft.com/default...b;en-us;161299
-
1 Attachment(s)
Re: Another Printform question
Almost there.
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?
-
Re: Another Printform question
Sorry, solved it.
Posted the code in the codeback here .
Thanks for your help CVMichael, SiTheGeek and Westconn1.