From: Shotgun Thom on
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
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
"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
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
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)