{"id":209,"date":"2007-05-12T17:04:14","date_gmt":"2007-05-12T15:04:14","guid":{"rendered":" http:\/\/www.nsonic.de\/blog\/2007\/05\/a-better-way-to-print-a-form\/"},"modified":"2007-05-12T17:04:16","modified_gmt":"2007-05-12T15:04:16","slug":"a-better-way-to-print-a-form","status":"publish","type":"post","link":"https:\/\/www.nsonic.de\/blog\/2007\/05\/a-better-way-to-print-a-form\/","title":{"rendered":"A Better Way To Print a Form"},"content":{"rendered":"<p>Technical Information Database<\/p>\n<p>TI1412D.txt   A Better Way To Print a Form<br \/>\nCategory   :General Programming<br \/>\nPlatform    :All<br \/>\nProduct    :Delphi  All<br \/>\nDescription:<\/p>\n<p>The following TI details a better way to print the contents of<br \/>\na form, by getting the device independent bits in 256 colors<br \/>\nfrom the form, and using those bits to print the form to the<br \/>\nprinter.<br \/>\n<!--more--><br \/>\nIn addition, a check is made to see if the screen or printer<br \/>\nis a palette device, and if so, palette handling for the device<br \/>\nis enabled. If the screen device is a palette device, an additional<br \/>\nstep is taken to fill the bitmap&#8217;s palette from the system palette,<br \/>\novercoming some buggy video drivers who don&#8217;t fill the palette in.<\/p>\n<p>Note: Since this code does a screen shot of the form, the form must<br \/>\nbe the topmost window and the whole from must be viewable when the<br \/>\nform shot is made.<\/p>\n<p>[code lang=&#8221;delphi&#8221;]unit Prntit;<\/p>\n<p>interface<\/p>\n<p>uses<br \/>\n  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics,<br \/>\n  Controls, Forms, Dialogs, StdCtrls, ExtCtrls;<\/p>\n<p>type<br \/>\n  TForm1 = class(TForm)<br \/>\n    Button1: TButton;<br \/>\n    Image1: TImage;<br \/>\n    procedure Button1Click(Sender: TObject);<br \/>\n  private<br \/>\n    { Private declarations }<br \/>\n  public<br \/>\n    { Public declarations }<br \/>\n  end;<\/p>\n<p>var<br \/>\n  Form1: TForm1;<\/p>\n<p>implementation<\/p>\n<p>{$R *.DFM}<\/p>\n<p>uses Printers;<\/p>\n<p>procedure TForm1.Button1Click(Sender: TObject);<br \/>\nvar<br \/>\n  dc: HDC;<br \/>\n  isDcPalDevice : BOOL;<br \/>\n  MemDc :hdc;<br \/>\n  MemBitmap : hBitmap;<br \/>\n  OldMemBitmap : hBitmap;<br \/>\n  hDibHeader : Thandle;<br \/>\n  pDibHeader : pointer;<br \/>\n  hBits : Thandle;<br \/>\n  pBits : pointer;<br \/>\n  ScaleX : Double;<br \/>\n  ScaleY : Double;<br \/>\n  ppal : PLOGPALETTE;<br \/>\n  pal : hPalette;<br \/>\n  Oldpal : hPalette;<br \/>\n  i : integer;<br \/>\nbegin<br \/>\n {Get the screen dc}<br \/>\n  dc := GetDc(0);<br \/>\n {Create a compatible dc}<br \/>\n  MemDc := CreateCompatibleDc(dc);<br \/>\n {create a bitmap}<br \/>\n  MemBitmap := CreateCompatibleBitmap(Dc,<br \/>\n                                      form1.width,<br \/>\n                                      form1.height);<br \/>\n {select the bitmap into the dc}<br \/>\n  OldMemBitmap := SelectObject(MemDc, MemBitmap);<\/p>\n<p> {Lets prepare to try a fixup for broken video drivers}<br \/>\n  isDcPalDevice := false;<br \/>\n  if GetDeviceCaps(dc, RASTERCAPS) and<br \/>\n     RC_PALETTE = RC_PALETTE then begin<br \/>\n    GetMem(pPal, sizeof(TLOGPALETTE) +<br \/>\n      (255 * sizeof(TPALETTEENTRY)));<br \/>\n    FillChar(pPal^, sizeof(TLOGPALETTE) +<br \/>\n      (255 * sizeof(TPALETTEENTRY)), #0);<br \/>\n    pPal^.palVersion := $300;<br \/>\n    pPal^.palNumEntries :=<br \/>\n      GetSystemPaletteEntries(dc,<br \/>\n                              0,<br \/>\n                              256,<br \/>\n                              pPal^.palPalEntry);<br \/>\n    if pPal^.PalNumEntries <> 0 then begin<br \/>\n      pal := CreatePalette(pPal^);<br \/>\n      oldPal := SelectPalette(MemDc, Pal, false);<br \/>\n      isDcPalDevice := true<br \/>\n    end else<br \/>\n    FreeMem(pPal, sizeof(TLOGPALETTE) +<br \/>\n           (255 * sizeof(TPALETTEENTRY)));<br \/>\n  end;<\/p>\n<p> {copy from the screen to the memdc\/bitmap}<br \/>\n  BitBlt(MemDc,<br \/>\n         0, 0,<br \/>\n         form1.width, form1.height,<\/p>\n<p>         Dc,<br \/>\n         form1.left, form1.top,<br \/>\n         SrcCopy);<\/p>\n<p>  if isDcPalDevice = true then begin<br \/>\n    SelectPalette(MemDc, OldPal, false);<br \/>\n    DeleteObject(Pal);<br \/>\n  end;<\/p>\n<p> {unselect the bitmap}<br \/>\n  SelectObject(MemDc, OldMemBitmap);<br \/>\n {delete the memory dc}<br \/>\n  DeleteDc(MemDc);<br \/>\n {Allocate memory for a DIB structure}<br \/>\n  hDibHeader := GlobalAlloc(GHND,<br \/>\n                            sizeof(TBITMAPINFO) +<br \/>\n                            (sizeof(TRGBQUAD) * 256));<br \/>\n {get a pointer to the alloced memory}<br \/>\n  pDibHeader := GlobalLock(hDibHeader);<\/p>\n<p> {fill in the dib structure with info on the way we want the DIB}<br \/>\n  FillChar(pDibHeader^,<br \/>\n           sizeof(TBITMAPINFO) + (sizeof(TRGBQUAD) * 256),<br \/>\n           #0);<br \/>\n  PBITMAPINFOHEADER(pDibHeader)^.biSize :=<br \/>\n    sizeof(TBITMAPINFOHEADER);<br \/>\n  PBITMAPINFOHEADER(pDibHeader)^.biPlanes := 1;<br \/>\n  PBITMAPINFOHEADER(pDibHeader)^.biBitCount := 8;<br \/>\n  PBITMAPINFOHEADER(pDibHeader)^.biWidth := form1.width;<br \/>\n  PBITMAPINFOHEADER(pDibHeader)^.biHeight := form1.height;<br \/>\n  PBITMAPINFOHEADER(pDibHeader)^.biCompression := BI_RGB;<\/p>\n<p> {find out how much memory for the bits}<\/p>\n<p>  GetDIBits(dc,<br \/>\n            MemBitmap,<br \/>\n            0,<br \/>\n            form1.height,<br \/>\n            nil,<br \/>\n            TBitmapInfo(pDibHeader^),<br \/>\n            DIB_RGB_COLORS);<\/p>\n<p> {Alloc memory for the bits}<br \/>\n  hBits := GlobalAlloc(GHND,<br \/>\n                       PBitmapInfoHeader(pDibHeader)^.BiSizeImage);<br \/>\n {Get a pointer to the bits}<br \/>\n  pBits := GlobalLock(hBits);<\/p>\n<p> {Call fn again, but this time give us the bits!}<br \/>\n  GetDIBits(dc,<br \/>\n            MemBitmap,<br \/>\n            0,<br \/>\n            form1.height,<br \/>\n            pBits,<br \/>\n            PBitmapInfo(pDibHeader)^,<br \/>\n            DIB_RGB_COLORS);<\/p>\n<p> {Lets try a fixup for broken video drivers}<br \/>\n  if isDcPalDevice = true then begin<br \/>\n    for i := 0 to (pPal^.PalNumEntries &#8211; 1) do begin<br \/>\n      PBitmapInfo(pDibHeader)^.bmiColors[i].rgbRed :=<br \/>\n        pPal^.palPalEntry[i].peRed;<br \/>\n      PBitmapInfo(pDibHeader)^.bmiColors[i].rgbGreen :=<br \/>\n        pPal^.palPalEntry[i].peGreen;<br \/>\n      PBitmapInfo(pDibHeader)^.bmiColors[i].rgbBlue :=<br \/>\n        pPal^.palPalEntry[i].peBlue;<br \/>\n    end;<br \/>\n    FreeMem(pPal, sizeof(TLOGPALETTE) +<br \/>\n           (255 * sizeof(TPALETTEENTRY)));<br \/>\n  end;<\/p>\n<p> {Release the screen dc}<br \/>\n  ReleaseDc(0, dc);<br \/>\n {Delete the bitmap}<br \/>\n  DeleteObject(MemBitmap);<\/p>\n<p> {Start print job}<br \/>\n  Printer.BeginDoc;<\/p>\n<p> {Scale print size}<br \/>\n  if Printer.PageWidth < Printer.PageHeight then begin\n   ScaleX := Printer.PageWidth;\n   ScaleY := Form1.Height * (Printer.PageWidth \/ Form1.Width);\n  end else begin\n   ScaleX := Form1.Width * (Printer.PageHeight \/ Form1.Height);\n   ScaleY := Printer.PageHeight;\n  end;\n\n\n {Just incase the printer drver is a palette device}\n  isDcPalDevice := false;\n  if GetDeviceCaps(Printer.Canvas.Handle, RASTERCAPS) and\n      RC_PALETTE = RC_PALETTE then begin\n   {Create palette from dib}\n    GetMem(pPal, sizeof(TLOGPALETTE) +\n          (255 * sizeof(TPALETTEENTRY)));\n    FillChar(pPal^, sizeof(TLOGPALETTE) + \n          (255 * sizeof(TPALETTEENTRY)), #0);\n    pPal^.palVersion := $300;\n    pPal^.palNumEntries := 256;\n    for i := 0 to (pPal^.PalNumEntries - 1) do begin\n      pPal^.palPalEntry[i].peRed := \n        PBitmapInfo(pDibHeader)^.bmiColors[i].rgbRed;\n      pPal^.palPalEntry[i].peGreen := \n        PBitmapInfo(pDibHeader)^.bmiColors[i].rgbGreen;\n      pPal^.palPalEntry[i].peBlue := \n        PBitmapInfo(pDibHeader)^.bmiColors[i].rgbBlue;\n    end;\n    pal := CreatePalette(pPal^);\n    FreeMem(pPal, sizeof(TLOGPALETTE) + \n            (255 * sizeof(TPALETTEENTRY)));\n    oldPal := SelectPalette(Printer.Canvas.Handle, Pal, false);\n    isDcPalDevice := true\n  end;\n\n {send the bits to the printer}\n  StretchDiBits(Printer.Canvas.Handle,\n                0, 0,\n                Round(scaleX), Round(scaleY),\n                0, 0,\n                Form1.Width, Form1.Height,\n                pBits,\n                PBitmapInfo(pDibHeader)^,\n                DIB_RGB_COLORS,\n                SRCCOPY);\n\n {Just incase you printer drver is a palette device}\n  if isDcPalDevice = true then begin\n    SelectPalette(Printer.Canvas.Handle, oldPal, false);\n    DeleteObject(Pal);\n  end;\n\n {Clean up allocated memory}\n  GlobalUnlock(hBits);\n  GlobalFree(hBits);\n  GlobalUnlock(hDibHeader);\n  GlobalFree(hDibHeader);\n\n\n {End the print job}\n  Printer.EndDoc;\nend;\n[\/code]\n\n[tags]Delphi, Printing, Forms[\/tags]\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Technical Information Database TI1412D.txt A Better Way To Print a Form Category :General Programming Platform :All Product :Delphi All Description: The following TI&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":""},"categories":[11],"tags":[75,100,119],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p71Tml-3n","_links":{"self":[{"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/posts\/209"}],"collection":[{"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/comments?post=209"}],"version-history":[{"count":0,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/posts\/209\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/media?parent=209"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/categories?post=209"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/tags?post=209"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}