Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Stretch To Print ?

Posted on 2000-02-17
15
Medium Priority
?
571 Views
Last Modified: 2010-05-18
I'm using this to print a panel to printer:

           Printer.BeginDoc;
           Try
            SetMapMode(Printer.Canvas.Handle, MM_ANISOTROPIC);
            SetWindowExtEx(Printer.Canvas.Handle,
                           GetDeviceCaps(Canvas.Handle, LOGPIXELSX),
                           GetDeviceCaps(Canvas.Handle, LOGPIXELSY),
                           Nil);
            SetViewportExtEx(Printer.Canvas.Handle,
                             GetDeviceCaps(Printer.Canvas.Handle, LOGPIXELSX),
                             GetDeviceCaps(Printer.Canvas.Handle, LOGPIXELSY),
                             Nil);
            ChildPanel.PaintTo(Printer.Canvas.Handle, 0, 0);
           Finally
            Printer.EndDoc;
           End;

Is there any way to stretch it so to fit to the whole page ? (eg. When printing the Panel using Landscape orientation i want to fill the whole
A4 Page)

Thanx
0
Comment
Question by:k6__
  • 6
  • 5
  • 4
15 Comments
 
LVL 8

Expert Comment

by:ZifNab
ID: 2533163
Hi k6,

You can paint it first to an image and then use stretchdraw :

Image1 := TImage.Create;
try
ChildPanel.Paintto(Image1.Canvas.Handle,0,0);
Printer.BeginDoc;
Printer.Canvas.StretchDraw(Rect(0, 0, Printer.PageWidth,
Printer.PageHeight), Image1.Picture.Bitmap);
Printer.EndDoc;
finally
 Image1.Free;
end;

Haven't tried the code, but should normally work.

Regards, Zif
0
 
LVL 6

Expert Comment

by:edey
ID: 2533361
or stretch it directly using stretchBlt


GL
Mike
0
 
LVL 2

Author Comment

by:k6__
ID: 2533389
Hehe.. it stretch it too much! =)
It get's full page but it also zooms
the panel by 500%!
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 6

Expert Comment

by:edey
ID: 2533534
and is that why you rejected the answer?  c'mon all it takes is a little thought to see that:

Printer.Canvas.StretchDraw(Rect(0, 0, Printer.PageWidth,
Printer.PageHeight), Image1.Picture.Bitmap);


*could* be:

with printer do
begin
Printer.Canvas.StretchDraw(Rect(pageWidth div 4, pageheight div 4, PageWidth-(pageWidth div 4),
PageHeight-(pageheight div 4)), Image1.Picture.Bitmap);

or even:

Printer.Canvas.StretchDraw(Rect(0, 0, 1,1), Image1.Picture.Bitmap);


I think 'ol zif deserves a little better 'n that.

0
 
LVL 8

Expert Comment

by:ZifNab
ID: 2534123
? where is the problem, doesn't works ?
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 2534645
k6, do you still have problems?
0
 
LVL 2

Author Comment

by:k6__
ID: 2537424
let me try but i think it could cause
problems...
0
 
LVL 2

Author Comment

by:k6__
ID: 2537571
ok.. tried with edey comments
and still it doesn't stretchs right...
=(
0
 
LVL 6

Expert Comment

by:edey
ID: 2537624
Could you be a little more descriptive?  Perhaps explaining exactly how you want it stretched (and how the current example fails to achieve that goal), would be a good place to begin


GL
Mike
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 2538133
well I can imagine that the stretch doesn't streches in correct ratio. But that shouldn't be a problem to incoporate, you got all the variables to get the H/W ratio. Of course when you use a ratio, you don't get a full A4 printed.
0
 
LVL 2

Author Comment

by:k6__
ID: 2538376
I have a panel ok ? when i print this
panel in Landscape mode(using the above
code) it doesn't fill the whole A4
paper. Now With ZifNabs code it filled
the Whole A4 Paper but it also Zoomed
the Panel... I want to Stretch the
panel to fit to A4 Page. I'll play
with Zifnab code... if you have any
corrections please post them =)
0
 
LVL 2

Author Comment

by:k6__
ID: 2540422
i didn't find a way to make it work =(
0
 
LVL 6

Expert Comment

by:edey
ID: 2540740
I'm not sure how you're going to "stretch" a panel without "zomming" it. As zif asked, are you looking to perserve the panel's aspect ratio? or something else?


GL
Mike
0
 
LVL 2

Author Comment

by:k6__
ID: 2543975
edey yes!... imagine you have a TImage
with the Picture is at: 100 height & 
100 width and your TImage component
has 200 Height & 135 Width.. if you
activate the "Stretch property" it will
fit your bitmap "100x100" to
the "200x135" of TImage.

Now can i do this with the panel ?
can i put it into a Virtual TImage
get the Width & Height of the Printer's
page and the activate the Stretch
property and the paint back to Printer
Canvas ? =)

Thanx
0
 
LVL 8

Accepted Solution

by:
ZifNab earned 150 total points
ID: 2545429
k6,

here is another method (from Borlands FAQ), much better, but also more code :-)

Article #16211: Sending an image to the printer

 Question and Answer Database

FAQ1211D.txt   Sending an image to the printer
Category   :Miscellaneous
Platform    :All
Product    :All 32 bit  

Question:
How can I reliably print an image to the printer?

Answer:
Sending a bitmap based on the screen to the printer is an
invalid operation that will usually fail, unless the print
driver has been designed to detect this error condition and
compensate for the error. This means you should use the VCL
canvas methods Draw, StretchDraw,CopyRect, BrushCopy, and
the like to transfer a bitmap to the printer, since the
underlying bitmap is based on the screen, and is device
dependent. The only way to reliably print an image is to
use DIBs (Device Independent Bitmaps). Getting a valid DIB can
be difficult, as there are many Windows API functions that must
be used correctly. Further, many video drivers incorrectly fill
in the DIB structure in regards to the color table in the DIB.

The following example demonstrates an attempt to overcome
some of these problems and limitations. The example should
compile successfully under all versions of Delphi/C++ Builder.

The core function in the example, BltTBitmapAsDib(), accepts
a handle to a device to image to, the x and y coordinates you
wish the bitmap to be imaged at, the width and height you wish
the image to be (stretching and shrinking is acceptable), and
the TBitmap you wish to image.
                                 
Example:

uses Printers;

type
  PPalEntriesArray = ^TPalEntriesArray; {for palette re-construction}
  TPalEntriesArray = array[0..0] of TPaletteEntry;

procedure BltTBitmapAsDib(DestDc : hdc;   {Handle of where to blt}
                          x : word;       {Bit at x}
                          y : word;       {Blt at y}
                          Width : word;   {Width to stretch}
                          Height : word;  {Height to stretch}
                          bm : TBitmap);  {the TBitmap to Blt}
var
  OriginalWidth :LongInt;               {width of BM}
  dc : hdc;                             {screen dc}
  IsPaletteDevice : bool;               {if the device uses palettes}
  IsDestPaletteDevice : bool;           {if the device uses palettes}
  BitmapInfoSize : integer;             {sizeof the bitmapinfoheader}
  lpBitmapInfo : PBitmapInfo;           {the bitmap info header}
  hBm : hBitmap;                        {handle to the bitmap}
  hPal : hPalette;                      {handle to the palette}
  OldPal : hPalette;                    {temp palette}
  hBits : THandle;                      {handle to the DIB bits}
  pBits : pointer;                      {pointer to the DIB bits}
  lPPalEntriesArray : PPalEntriesArray; {palette entry array}
  NumPalEntries : integer;              {number of palette entries}
  i : integer;                          {looping variable}
begin
{If range checking is on - lets turn it off for now}
{we will remember if range checking was on by defining}
{a define called CKRANGE if range checking is on.}
{We do this to access array members past the arrays}
{defined index range without causing a range check}
{error at runtime. To satisfy the compiler, we must}
{also access the indexes with a variable. ie: if we}
{have an array defined as a: array[0..0] of byte,}
{and an integer i, we can now access a[3] by setting}
{i := 3; and then accessing a[i] without error}
{$IFOPT R+}
  {$DEFINE CKRANGE}
  {$R-}
{$ENDIF}

 {Save the original width of the bitmap}
  OriginalWidth := bm.Width;

 {Get the screen's dc to use since memory dc's are not reliable}
  dc := GetDc(0);
 {Are we a palette device?}
  IsPaletteDevice :=
    GetDeviceCaps(dc, RASTERCAPS) and RC_PALETTE = RC_PALETTE;
 {Give back the screen dc}
  dc := ReleaseDc(0, dc);

 {Allocate the BitmapInfo structure}
  if IsPaletteDevice then
    BitmapInfoSize := sizeof(TBitmapInfo) + (sizeof(TRGBQUAD) * 255)
  else
    BitmapInfoSize := sizeof(TBitmapInfo);
  GetMem(lpBitmapInfo, BitmapInfoSize);

 {Zero out the BitmapInfo structure}
  FillChar(lpBitmapInfo^, BitmapInfoSize, #0);

 {Fill in the BitmapInfo structure}
  lpBitmapInfo^.bmiHeader.biSize := sizeof(TBitmapInfoHeader);
  lpBitmapInfo^.bmiHeader.biWidth := OriginalWidth;
  lpBitmapInfo^.bmiHeader.biHeight := bm.Height;
  lpBitmapInfo^.bmiHeader.biPlanes := 1;
  if IsPaletteDevice then
    lpBitmapInfo^.bmiHeader.biBitCount := 8
  else
    lpBitmapInfo^.bmiHeader.biBitCount := 24;
  lpBitmapInfo^.bmiHeader.biCompression := BI_RGB;
  lpBitmapInfo^.bmiHeader.biSizeImage :=
    ((lpBitmapInfo^.bmiHeader.biWidth *
      longint(lpBitmapInfo^.bmiHeader.biBitCount)) div 8) *
      lpBitmapInfo^.bmiHeader.biHeight;
  lpBitmapInfo^.bmiHeader.biXPelsPerMeter := 0;
  lpBitmapInfo^.bmiHeader.biYPelsPerMeter := 0;
  if IsPaletteDevice then begin
    lpBitmapInfo^.bmiHeader.biClrUsed := 256;
    lpBitmapInfo^.bmiHeader.biClrImportant := 256;
  end else begin
    lpBitmapInfo^.bmiHeader.biClrUsed := 0;
    lpBitmapInfo^.bmiHeader.biClrImportant := 0;
  end;

 {Take ownership of the bitmap handle and palette}
  hBm := bm.ReleaseHandle;
  hPal := bm.ReleasePalette;

 {Get the screen's dc to use since memory dc's are not reliable}
  dc := GetDc(0);

  if IsPaletteDevice then begin
   {If we are using a palette, it must be}
   {selected into the dc during the conversion}
    OldPal := SelectPalette(dc, hPal, TRUE);
   {Realize the palette}
    RealizePalette(dc);
  end;
 {Tell GetDiBits to fill in the rest of the bitmap info structure}
  GetDiBits(dc,
            hBm,
            0,
            lpBitmapInfo^.bmiHeader.biHeight,
            nil,
            TBitmapInfo(lpBitmapInfo^),
            DIB_RGB_COLORS);

 {Allocate memory for the Bits}
  hBits := GlobalAlloc(GMEM_MOVEABLE,
                       lpBitmapInfo^.bmiHeader.biSizeImage);
  pBits := GlobalLock(hBits);
 {Get the bits}
  GetDiBits(dc,
            hBm,
            0,
            lpBitmapInfo^.bmiHeader.biHeight,
            pBits,
            TBitmapInfo(lpBitmapInfo^),
            DIB_RGB_COLORS);


  if IsPaletteDevice then begin
   {Lets fix up the color table for buggy video drivers}
    GetMem(lPPalEntriesArray, sizeof(TPaletteEntry) * 256);
   {$IFDEF VER100}
      NumPalEntries := GetPaletteEntries(hPal,
                                         0,
                                         256,
                                         lPPalEntriesArray^);
   {$ELSE}
      NumPalEntries := GetSystemPaletteEntries(dc,
                                               0,
                                               256,
                                               lPPalEntriesArray^);
   {$ENDIF}
    for i := 0 to (NumPalEntries - 1) do begin
      lpBitmapInfo^.bmiColors[i].rgbRed :=
        lPPalEntriesArray^[i].peRed;
      lpBitmapInfo^.bmiColors[i].rgbGreen :=
        lPPalEntriesArray^[i].peGreen;
      lpBitmapInfo^.bmiColors[i].rgbBlue :=
        lPPalEntriesArray^[i].peBlue;
    end;
    FreeMem(lPPalEntriesArray, sizeof(TPaletteEntry) * 256);
  end;

  if IsPaletteDevice then begin
   {Select the old palette back in}
    SelectPalette(dc, OldPal, TRUE);
   {Realize the old palette}
    RealizePalette(dc);
  end;

 {Give back the screen dc}
  dc := ReleaseDc(0, dc);

 {Is the Dest dc a palette device?}
  IsDestPaletteDevice :=
    GetDeviceCaps(DestDc, RASTERCAPS) and RC_PALETTE = RC_PALETTE;


  if IsPaletteDevice then begin
   {If we are using a palette, it must be}
   {selected into the dc during the conversion}
    OldPal := SelectPalette(DestDc, hPal, TRUE);
   {Realize the palette}
    RealizePalette(DestDc);
  end;

 {Do the blt}
  StretchDiBits(DestDc,
                x,
                y,
                Width,
                Height,
                0,
                0,
                OriginalWidth,
                lpBitmapInfo^.bmiHeader.biHeight,
                pBits,
                lpBitmapInfo^,
                DIB_RGB_COLORS,
                SrcCopy);

  if IsDestPaletteDevice then begin
   {Select the old palette back in}
    SelectPalette(DestDc, OldPal, TRUE);
   {Realize the old palette}
    RealizePalette(DestDc);
  end;

 {De-Allocate the Dib Bits}
  GlobalUnLock(hBits);
  GlobalFree(hBits);

 {De-Allocate the BitmapInfo}
  FreeMem(lpBitmapInfo, BitmapInfoSize);

 {Set the ownership of the bimap handles back to the bitmap}
  bm.Handle := hBm;
  bm.Palette := hPal;

  {Turn range checking back on if it was on when we started}
{$IFDEF CKRANGE}
  {$UNDEF CKRANGE}
  {$R+}
{$ENDIF}
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  if PrintDialog1.Execute then begin
    Printer.BeginDoc;
    BltTBitmapAsDib(Printer.Canvas.Handle,
                    0,
                    0,
                    Image1.Picture.Bitmap.Width,
                    Image1.Picture.Bitmap.Height,
                    Image1.Picture.Bitmap);
    Printer.EndDoc;
  end;
end;

0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Please read the paragraph below before following the instructions in the video — there are important caveats in the paragraph that I did not mention in the video. If your PaperPort 12 or PaperPort 14 is failing to start, or crashing, or hanging, …
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…
Suggested Courses

926 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question