如何打印FORM的图象?(200分)

  • 主题发起人 主题发起人 winsun
  • 开始时间 开始时间
W

winsun

Unregistered / Unconfirmed
GUEST, unregistred user!
我想在程序中打印FORM的图象,查看DELPHI的帮助说是用form的print方法。
我试了试,在我的打印机上得到的是一张白纸。在打印之前用getformimage方法也不行。
后来我又试用了windows的API函数stretchDIBits.在我的实验室里可以正确地打印出来。后来换到单位上就不行了。
我实验室的设备是HP原装166MMX(Vectra).用的是网络共享打印机(HP LaserJet 4VC)。网络服务器是HP原装机(2 processor ,200MMX).安装的是NT4。工作站安装的是win95(最早的版本),用的是delphi3C/S.
单位的机器是HP原装机。用的是网络打印服务器。
程序代码如下:
procedure PrintBitmap(Bitmap: TBitmap;
X, Y: Integer);
var
Info: PBitmapInfo;
InfoSize: Integer;
Image: Pointer;
ImageSize: Longint;
begin

with Bitmapdo

begin

GetDIBSizes(Handle, InfoSize, ImageSize);
getmem(info,InfoSize);
try
getmem(image,ImageSize);
try
GetDIB(Handle, Palette, Info^, Image^);
with Info^.bmiHeaderdo

StretchDIBits(Printer.Canvas.Handle, X, Y, Width*6,
Height*4, 0, 0, biWidth, biHeight, Image, Info^,
DIB_RGB_COLORS, SRCCOPY);
finally
FreeMem(Image, ImageSize);
end;

finally
FreeMem(Info, InfoSize);
end;

end;

end;

我的E-mail是:wangjinlong@163.net
 
试过form1.paintto(printer.canvas.handle)没有?
 
用Tprinter不行吗!
 
首先在设计阶段用File|Print试一试打印Form, 如果能够打印, 则说明是你的程序的
问题, 因为设计阶段的打印机制就是Form.Print. 如果不能, 可能是打印机设置问题
或者是其他原因(如病毒...)
 
huizhang,
我试过在设计阶段时用File/print,可以的。
在同一个实验室里,原先有一台机器是能用程序打印出Form图象的。可是后来这台机器被别的机房搬走了,整个环境都被破坏了,也不知是为了什么能打印。这台机器是实达的。其它的都是HP的。
至于用Tprinter,我也试过了,打印出来的图象简直就是面目全非,要么就是只能打一点点大的图象。
我有写一个只有几行的测试程序来测试我的打印功能,也不行。是不是delphi 的BUG?
 
winsun:
试一下这个来自Borland 的原装大程序吧。应该可以解决你的问题。http://www.inprise.com/devsupport/delphi/ti_list/TI3155.html

各位:
我惹了个QuickRep的大麻烦,请帮我。主题是:"QuickRep方面的大问题!"

Regards,
SupWang
 
上面的地址是
http://www.inprise.com/devsupport/delphi/ti_list/TI3155.html
 
我试了SupWang提供的方法,效果虽然不太好,还可以,我接受答案.
 
接受了就给Point给我啊,我在这里是第一次答问题 :-)
 
我这几天试了试Form的Print方法,我发现如果是在256色的情况下,就可以正确地打印
。我查看了Delphi的原文件,发现print用的和我上面这段程序是同一个函数。
可为什么我这段程序就是不行?
 
请参考一下Inprise的FAQ
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.}
{Wedo
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 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.rgbRed :=
lPPalEntriesArray^.peRed;
lpBitmapInfo^.bmiColors.rgbGreen :=
lPPalEntriesArray^.peGreen;
lpBitmapInfo^.bmiColors.rgbBlue :=
lPPalEntriesArray^.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.begin
Doc;
BltTBitmapAsDib(Printer.Canvas.Handle,
0,
0,
Image1.Picture.Bitmap.Width,
Image1.Picture.Bitmap.Height,
Image1.Picture.Bitmap);
Printer.EndDoc;
end;

end;


7/16/98 4:31:28 PM
 
我也曾碰到这个问题,机器的配置和你差不多,166mmx, 打印机是HP6L
激光打印机。后来修改打印机的设置600dpi为300dpi,才可以打印出
form画面,但效果不太好,你可以试一试。
 
告诉你一个笨办法,在将form的image获取前,先将form不可见,
后将form的比例放大,用Tprinter,将form可见。一定可以,我作过的。
 
接受答案了.
 

Similar threads

I
回复
0
查看
2K
import
I
I
回复
0
查看
639
import
I
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
后退
顶部