Prev: Progressbar in Listview v5 ?
Next: Is there a way of fetching the date/time or size of a file on the Internet?
From: Shotgun Thom on 6 Nov 2009 21:56 On Nov 6, 6:56 pm, Webbiz <nos...(a)forme.thanks.com> wrote: Here is another way to skin this cat... use the keybd_event API to capture the active window (form with focus) to the clipboard. Then set the clipboard picture data from the clipboard to your picture box.making sure you then set the image by the command Picture1.Picture = Picture1.Image. Then print your picture box. The API declare is: Public Declare Sub keybd_event Lib "user32.dll" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long) The capture command which mimicks Alt-PrntScrn (capture active window): keybd_event vbKeySnapshot, &H1&, 0&, 0& Tom
From: Webbiz on 7 Nov 2009 00:13 On Fri, 6 Nov 2009 18:56:23 -0800 (PST), Shotgun Thom <tmoran4511(a)gmail.com> wrote: >On Nov 6, 6:56�pm, Webbiz <nos...(a)forme.thanks.com> wrote: > > >Here is another way to skin this cat... use the keybd_event API to >capture the active window (form with focus) to the clipboard. Then >set the clipboard picture data from the clipboard to your picture >box.making sure you then set the image by the command Picture1.Picture >= Picture1.Image. Then print your picture box. > >The API declare is: > >Public Declare Sub keybd_event Lib "user32.dll" (ByVal bVk As Byte, >ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long) > >The capture command which mimicks Alt-PrntScrn (capture active >window): > >keybd_event vbKeySnapshot, &H1&, 0&, 0& > >Tom > > Thanks for the suggestion Tom. :-) Webbiz
From: Mike Williams on 7 Nov 2009 11:21 "Webbiz" <nospam(a)forme.thanks.com> wrote in message news:p7m9f5p7p01tvbgor9pnnjne35ahfjdib2(a)4ax.com... > Here is my final form printing code: > [only the relevant extracts shown in responses below] Actually although it might appear to work well, there are a few things that need attention (the main problem is mentioned near the end so please read through this response even if I do tend to get a bit boring at times!): > WidthForm = frm.ScaleX(frm.Width, frm.ScaleMode, vbPixels) > HeightForm = frm.ScaleY(frm.Height, frm.ScaleMode, vbPixels) You need to change the above two lines so that they use vbTwips instead of frm.ScaleMode, because the Width and Height of a Form are always in units of twips. You won't notice the problem under most conditions because the ScaleMode is almost always in units that are larger than a twip and the overly large values calculated by the above code as it stands (on a Form with Scale units larger than a twip) will simply cause the otherwise excess drawing to be clipped at the point where the calculated values exceed the size of the PictureBox (which is being sized correctly by other parts of your code). You will however notice the problem if the code is used on a Form that has Scale units which are smaller than a twip (as would be the case with certain User scales) because it will cause the printed output to clip part of the image of the Form. To fix the problem you need to change the above two lines to: WidthForm = frm.ScaleX(frm.Width, vbTwips, vbPixels) HeightForm = frm.ScaleY(frm.Height, vbTwips, vbPixels) You also need to make sure that the PictureBox you are using does not have any borders because you are setting its overall Width and height to the desired values whereas the picture is going to be blitted into its client area, which will be smaller than its overall size if the PictureBox has a border. I assume that you have set it to borderless in the IDE, but if not then you need to set it in code before you set its size. It might also be wise to add a Cls to make sure that any previous drawing is cleared (only a problem in the case of other errors mentioned below) and also to make sure that the PictureBox always correctly resizes its Autoredraw memory bitmap just in case you ever want to save the image as a bmp file or whatever. So, that part of your code would look like: frm.Picture1.AutoRedraw = True frm.Picture1.BorderStyle = vbBSNone frm.Picture1.Move 0, 0, frm.ScaleX(frm.Width, vbTwips, . . . etc The most important problem though is something that you will not notice unless your code is run on a Windows Vista machine which is running the standard Vista Aero desktop (the semi transparent caption bars and borders). If your Form is a standard resizable Form and if you start off with it smaller than the screen (for test purposes let's say about half to two thirds as wide as the screen) and then click the button to use the code to print a copy of the Form you should get an approximnately correct printout (there might be a slight bit missing at the right edge, but not much). However, if you then manually drag out the size of the Form so that it is a different size you will definitely see a problem. If the Form is narrower than before then the right border and the right side of the caption bar and probably the caption bar buttons will be missing. If the Form is wider than before then you will see the original smaller size border with the now larger client area overwriting the right part of the border and extending way beyond its right edge. These problems are certainly not minor, and they will be extremely clear on examination of the output. Note that you will only see these problem if Widows is currently displaying its Aero desktop, so you will not see them if you are running in the VB IDE and if you have your IDE automatically turn off Aero whilst it is running (as many people do). There are other ways to tackle this problem, but one way which will not require too much modification of your code is to get the DC of the desktop (rather than the DC of your Form) and to blit just the appropriate part of the desktop into your pictureBox (see modified code at the end of this response). One other problem that will also be apparent in Vista whether it is running Aero or not (although I seem to recall it also being a problem in XP, which I don't have access to at the moment?) is that if your Form is a standard resizable Form that has been maximized then part of the Form around the edges will be missing on the printout and there may also be a thin portion of the top part of the Windows taskbar on the printout. This will be a problem both in your current code and in the modification that I have posted below to fix the other faults, but it should be fairly easy to fix (I would do it now if it were not for the fact that my wife is pestering me for the computer to make some Birthday cards or something!). To fix the problem you should be able to add the appropriate offsets into your code by examining the Left and Top properties of the Form (which will both have small negative values in the maximized condition). Anyway, if you have problems making those adjustments then post again and I'll have a look at it when I get more time (or perhaps somebody else will post the required amendments). There are of course other completely different ways to perform the task you are doing, some of which can print a copy of your Form even if it is not currently entirely visible of the display, but it would probably be best to get your current method working properly first, even if you did at some later stage decide to use a different method (which you don't really need to do in your case). Anyway, here is your existing code which I have modified to take account of the problems I have so far mentioned (apart from the last problem I mentioned, which I don't have time to deal with at the moment and which you might be able to deal with yourself). I've shown only the Sub PrintTheForm code, so you'll also need to add the GetDC and GetDeskTopWindow API declarations . . . Mike Public Sub PrintTheForm(ByVal frm As Form) Dim WidthForm As Long Dim HeightForm As Long WidthForm = frm.ScaleX(frm.Width, vbTwips, vbPixels) HeightForm = frm.ScaleY(frm.Height, vbTwips, vbPixels) frm.Picture1.Visible = False frm.Picture1.AutoRedraw = True frm.Picture1.BorderStyle = vbBSNone frm.Picture1.Move 0, 0, frm.ScaleX(frm.Width, _ vbTwips, frm.ScaleMode), frm.ScaleY(frm.Height, _ vbTwips, frm.ScaleMode) frm.Picture1.Cls Call BitBlt(frm.Picture1.hDC, 0, 0, WidthForm, _ HeightForm, GetDC(GetDesktopWindow), _ frm.ScaleX(frm.Left, vbTwips, vbPixels), _ frm.ScaleY(frm.Top, vbTwips, vbPixels), _ vbSrcCopy) Printer.Orientation = vbPRORLandscape Printer.PaintPicture frm.Picture1.Image, 0, 0 Printer.EndDoc End Sub
From: Webbiz on 7 Nov 2009 13:40 On Sat, 7 Nov 2009 16:21:01 -0000, "Mike Williams" <Mike(a)WhiskyAndCoke.com> wrote: >"Webbiz" <nospam(a)forme.thanks.com> wrote in message >news:p7m9f5p7p01tvbgor9pnnjne35ahfjdib2(a)4ax.com... > >> Here is my final form printing code: >> [only the relevant extracts shown in responses below] > >Actually although it might appear to work well, there are a few things that >need attention (the main problem is mentioned near the end so please read >through this response even if I do tend to get a bit boring at times!): > >> WidthForm = frm.ScaleX(frm.Width, frm.ScaleMode, vbPixels) >> HeightForm = frm.ScaleY(frm.Height, frm.ScaleMode, vbPixels) > >You need to change the above two lines so that they use vbTwips instead of >frm.ScaleMode, because the Width and Height of a Form are always in units of >twips. You won't notice the problem under most conditions because the >ScaleMode is almost always in units that are larger than a twip and the >overly large values calculated by the above code as it stands (on a Form >with Scale units larger than a twip) will simply cause the otherwise excess >drawing to be clipped at the point where the calculated values exceed the >size of the PictureBox (which is being sized correctly by other parts of >your code). You will however notice the problem if the code is used on a >Form that has Scale units which are smaller than a twip (as would be the >case with certain User scales) because it will cause the printed output to >clip part of the image of the Form. To fix the problem you need to change >the above two lines to: > > WidthForm = frm.ScaleX(frm.Width, vbTwips, vbPixels) > HeightForm = frm.ScaleY(frm.Height, vbTwips, vbPixels) > >You also need to make sure that the PictureBox you are using does not have >any borders because you are setting its overall Width and height to the >desired values whereas the picture is going to be blitted into its client >area, which will be smaller than its overall size if the PictureBox has a >border. I assume that you have set it to borderless in the IDE, but if not >then you need to set it in code before you set its size. It might also be >wise to add a Cls to make sure that any previous drawing is cleared (only a >problem in the case of other errors mentioned below) and also to make sure >that the PictureBox always correctly resizes its Autoredraw memory bitmap >just in case you ever want to save the image as a bmp file or whatever. So, >that part of your code would look like: > > frm.Picture1.AutoRedraw = True > frm.Picture1.BorderStyle = vbBSNone > frm.Picture1.Move 0, 0, frm.ScaleX(frm.Width, vbTwips, . . . etc > >The most important problem though is something that you will not notice >unless your code is run on a Windows Vista machine which is running the >standard Vista Aero desktop (the semi transparent caption bars and borders). >If your Form is a standard resizable Form and if you start off with it >smaller than the screen (for test purposes let's say about half to two >thirds as wide as the screen) and then click the button to use the code to >print a copy of the Form you should get an approximnately correct printout >(there might be a slight bit missing at the right edge, but not much). >However, if you then manually drag out the size of the Form so that it is a >different size you will definitely see a problem. If the Form is narrower >than before then the right border and the right side of the caption bar and >probably the caption bar buttons will be missing. If the Form is wider than >before then you will see the original smaller size border with the now >larger client area overwriting the right part of the border and extending >way beyond its right edge. These problems are certainly not minor, and they >will be extremely clear on examination of the output. Note that you will >only see these problem if Widows is currently displaying its Aero desktop, >so you will not see them if you are running in the VB IDE and if you have >your IDE automatically turn off Aero whilst it is running (as many people >do). There are other ways to tackle this problem, but one way which will not >require too much modification of your code is to get the DC of the desktop >(rather than the DC of your Form) and to blit just the appropriate part of >the desktop into your pictureBox (see modified code at the end of this >response). > >One other problem that will also be apparent in Vista whether it is running >Aero or not (although I seem to recall it also being a problem in XP, which >I don't have access to at the moment?) is that if your Form is a standard >resizable Form that has been maximized then part of the Form around the >edges will be missing on the printout and there may also be a thin portion >of the top part of the Windows taskbar on the printout. This will be a >problem both in your current code and in the modification that I have posted >below to fix the other faults, but it should be fairly easy to fix (I would >do it now if it were not for the fact that my wife is pestering me for the >computer to make some Birthday cards or something!). To fix the problem you >should be able to add the appropriate offsets into your code by examining >the Left and Top properties of the Form (which will both have small negative >values in the maximized condition). Anyway, if you have problems making >those adjustments then post again and I'll have a look at it when I get more >time (or perhaps somebody else will post the required amendments). > >There are of course other completely different ways to perform the task you >are doing, some of which can print a copy of your Form even if it is not >currently entirely visible of the display, but it would probably be best to >get your current method working properly first, even if you did at some >later stage decide to use a different method (which you don't really need to >do in your case). Anyway, here is your existing code which I have modified >to take account of the problems I have so far mentioned (apart from the last >problem I mentioned, which I don't have time to deal with at the moment and >which you might be able to deal with yourself). I've shown only the Sub >PrintTheForm code, so you'll also need to add the GetDC and GetDeskTopWindow >API declarations . . . > >Mike > >Public Sub PrintTheForm(ByVal frm As Form) >Dim WidthForm As Long >Dim HeightForm As Long >WidthForm = frm.ScaleX(frm.Width, vbTwips, vbPixels) >HeightForm = frm.ScaleY(frm.Height, vbTwips, vbPixels) >frm.Picture1.Visible = False >frm.Picture1.AutoRedraw = True >frm.Picture1.BorderStyle = vbBSNone >frm.Picture1.Move 0, 0, frm.ScaleX(frm.Width, _ > vbTwips, frm.ScaleMode), frm.ScaleY(frm.Height, _ > vbTwips, frm.ScaleMode) >frm.Picture1.Cls >Call BitBlt(frm.Picture1.hDC, 0, 0, WidthForm, _ > HeightForm, GetDC(GetDesktopWindow), _ > frm.ScaleX(frm.Left, vbTwips, vbPixels), _ > frm.ScaleY(frm.Top, vbTwips, vbPixels), _ > vbSrcCopy) >Printer.Orientation = vbPRORLandscape >Printer.PaintPicture frm.Picture1.Image, 0, 0 >Printer.EndDoc >End Sub > > > > > > Hey Mike. Thanks for the lesson and code. I learned ALOT from that explanation. Man, there are so many tiny details that can be overlooked on this. I've made the changes and tested it on various forms. Works like a charm. Even though I've not made these forms to be maximized or stretched, I may need this print module in another project someday that will have such forms, so it's good to have. Thanks again! Webbiz
From: Eduardo on 7 Nov 2009 14:54
Mike Williams escribi�: > You need to change the above two lines so that they use vbTwips instead > of frm.ScaleMode, Yeah, a mistake. > If your Form is a standard resizable Form and if you start off > with it smaller than the screen (for test purposes let's say about half > to two thirds as wide as the screen) and then click the button to use > the code to print a copy of the Form you should get an approximnately > correct printout (there might be a slight bit missing at the right edge, > but not much). However, if you then manually drag out the size of the > Form so that it is a different size you will definitely see a problem. Strange. Even releasing the DC it keep happening. I don't know why. > There are of course other completely different ways to perform the task > you are doing, *some of which can print a copy of your Form even if it is > not currently entirely visible of the display* Mike, I'm interested in knowing how (not the code, just what API to use or whatever is necessary) |