Appreciate if anybody could help me with my printing problem. I am
trying to print a bitmap (using stretchblt) from a VB picturebox.
I have done this successfully. However I find that if I set the
resolution higher (e.g. 1200 dpi) or lower (180dpi) on a printer, the
picture will shrink or become lower respectively.
Thanks in advance.
Attached below is the VB code.
Justin.
Code
-------
Private Sub printPicture(ByVal printDC As Long, _
ByVal totalPhysicalHeight As Long, _
ByVal bottomMarginLength As Long, _
ByVal totalPhysicalWidth As Long, _
ByVal rightMarginLength As Long)
Const srcCopy = &HCC0020
Const newFrame = 1
Const pixel = 3
Dim hMemoryDc, hOldBitMap, apiError, result As Long
Dim pixelX, pixelY, x, timesEnlarge As Single
Dim positionX, positionY As Long
Dim bottomMarginStartPoint, rightMarginStartPoint, _
pictureStartPointHeight, pictureStartPointWidth As Long
pixelX = 1 / Printer.TwipsPerPixelX
pixelY = 1 / Printer.TwipsPerPixelY
dummyForm.Picture1.Picture = dummyForm.Picture1.Image
dummyForm.Picture1.ScaleMode = pixel
timesEnlarge = 2
bottomMarginStartPoint = (Printer.Height * pixelY) -
bottomMarginLength pictureStartPointHeight = bottomMarginStartPoint
- ((dummyForm.Picture1.ScaleHeight * timesEnlarge) * 1.25)
rightMarginStartPoint = (Printer.Width * pixelX) - rightMarginLength
pictureStartPointWidth = rightMarginStartPoint - ((dummyForm.
Picture1.ScaleWidth * timesEnlarge) * 1.25)
' Display Hour glass
MousePointer = 11
Printer.ScaleMode = 3
hMemoryDc = CreateCompatibleDC(dummyForm.Picture1.hdc)
hOldBitMap = SelectObject(hMemoryDc, dummyForm.Picture1.Picture)
positionX = Printer.ScaleWidth / 2
positionY = pictureStartPointHeight
apiError = StretchBlt(printDC, pictureStartPointWidth,
pictureStartPointHeight, _
dummyForm.Picture1.ScaleWidth * timesEnlarge,
_ dummyForm.Picture1.ScaleHeight *
timesEnlarge, hMemoryDc, 0, 0, _ dummyForm.
Picture1.ScaleWidth, _ dummyForm.Picture1.
ScaleHeight, srcCopy)
hOldBitMap = SelectObject(hMemoryDc, hOldBitMap)
apiError = DeleteDC(hMemoryDc)
MousePointer = 1
End Sub
dummyForm.Picture1.ScaleWidth * timesEnlarge, _
dummyForm.Picture1.ScaleHeight * timesEnlarge, _
The destination nWidth and nHeight variables in the StretchBlt API are in
the logical units of the destination DC, which for a printer are in pixels,
so for any specific picture box size the actual size of the printed output
(measured in inches) will depend on how large each printer pixels actually
is. If (as is the usual case) you want to specify the printed output size in
inches (so that it prints at the same on all printers at all settings) then
you need to take into account the number of pixels per inch the printer is
currently using. For example, if you want a picture that is printed at a
size of 2 inches by 3 inches then you need to do something like:
StretchBlt (Printer.hDC, 0, 0, _
Printer.ScaleX (2, vbInches, vbPixels) _
Printer.ScaleY (3, vbinches, vbPixels) _
hMemoryDC, _
. . . etc
. . . etc
By the way, you should have a look at your Dim statements. VB does *not*
work in the "old fashioned way", where you could specify the Type of a group
of variables "in one go". You need to specify each type individually. For
example:
Dim j, k as Long
will result in j having the Type of Long and k having the default Type of
Variant!
You need to do:
Dim j as Long, k as Long
Mike
"Justin" <ta...@no-spam.hotmail.com> wrote in message
news:Usenet.sbbsmnes@localhost...
Mike
"Mike Williams" <Mi...@BrandyandCoke.fsnet.co.uk> wrote in message
news:b7uggo$d6a$1...@newsg1.svr.pol.co.uk...
Also thanks for pointing out my DIM error.
Just a few more addedum to my earlier post:-
a. the parameters I passed in (assuming height is longer part of the A4
paper):-
printDC : Device Context for the printer
totalPhysicalHeight : Height of the Paper (including unprintable)
totalPhysicalWidth : Width of Paper (including unprintable)
bottomMarginLength : The unprintable area of paper's bottom
rightMarginLength : The unprintable area located in the right of the
paper.
b. What I am trying to do.
I am trying to place a picture (fixed size) on bottom right of the
paper. Naturally, I would want the picture to be place starting at
X(totalPhysicalHeight - bottomMarginLength - height of picture),
Y(totalPhysicalWidth - rightMarginLength - width of picture).
Hope it might eliminate any confusions.
Therefore I had to resort to creating a HDC from scratch, using Logfont
and selectObject.
Windows API isn't for the faint-hearted. I had to do alot of research
before being able to print anything. I found the most helpful resource
is a book called 'Print Programming in Windows' by Jeff Potts [ISBN 0-
87930-585-1]. It puts everything into perspective although he neglected
to mention the Printing pixels problem :)
Dim myfont as LOGFONT
With myfont
' set up the rotated font parameters
End With
TextOut Printer.hdc, x, y, textstring, Len(textstring)
. . . you instead have to do:
Dim myfont as LOGFONT, mydc as Long
mydc = Printer.hdc
With myfont
' set up the rotated font parameters
End With
TextOut mydc, x, y, textstring, Len(textstring)
Using the above method your rotated font will print correctly and, since you
are using the standard VB Printer object, you will be able to use all of the
standard VB Printer object methods (Print, PaintPicture, Line, Circle, etc)
on the same page as your rotated text.
In your other message you mention that you are trying to print a picture at
the bottom right corner of the page, and that you are passing your routine
some parameters that include the sizes of the "unprintable margins". You
haven't shown the code that you are using to get those values, so I can only
presume that you know that you can easily get them using the API
GetDeviceCaps function. If you don't already know this then post again and
I'll tell you more about it. In any case, from your description where you
say "Naturally, I would want the picture to be place starting at
X(totalPhysicalHeight - bottomMarginLength - height of picture), Y
(totalPhysicalWidth - rightMarginLength - width of picture)" it would appear
that you are doing it wrong anyway. You need to be aware that coordinate (0,
0) points to the top left corner of the "printable area" and *not* the top
left corner of the physical page. This applies whether you are using the VB
Printer object methods or the API methods. The "printable area", of course,
is a rectangle that is smaller than the physical page, and which is
positioned on the page at a point which varies from one printer to the next,
but is typically a small fraction of an inch from the top and about 0.13
inches from the left of the physical page (for A4 paper). The height of the
printable area is the ScaleHeigth of the printer and the width is the
ScaleWidth. Since the height and width of the printable area are both
usually about half an inch or more less than the physical height and width
of the page there is an area all around the printable area which is a "no
go" area for your output and it is physically impossible for your VB program
(or for any other application, for that matter) to get the printer to
deposit ink in these "unprintable margins". You can, however, accurately
position stuff on the page by using GetDeviceCaps to "read" the values of
the top and left offsets of the printable area and then adjusting the
Printer's ScaleLeft and ScaleTop properties accordingly. This will cause
location (0, 0) to point to the top left corner of the physical page (rather
than the top left corner of the printable area). Post again if you need help
with that.
In the meantime, you can print your picture at exactly the bottom right
corner of the printable area with very little code. For example, to print a
picture at a size of two inches by two inches so that the bottom right
corner of the picture is exactly at the bottom right corner of the printable
area you just need to do:
Printer.ScaleMode = vbInches
Printer.PaintPicture Picture1.Picture, _
Printer.ScaleWidth - 2, Printer.ScaleHeight - 2, 2, 2
Have fun!
Mike
"Justin" <ta...@no-spam.hotmail.com> wrote in message
news:Usenet.cjridoci@localhost...