我将回答您的第一个问题 - 第二个问题应移至此处的单独帖子,并作为单独问题提出。
您可以直接使用Print Spooler API(来自 WinSpool.pas 单元)将内容发送到打印机,而无需使用 BeginDoc/EndDoc。下面是一个将文件直接打印到打印机的示例(几年前由 TeamB 的 Peter Above 发布在旧 Borland/CodeGear Delphi 论坛之一):
uses
WinSpool;
procedure PrintFile(const sFileName: string);
const
BufSize = 16384;
var
Count, BytesWritten: integer;
hPrinter: THandle;
Device : array[0..255] of char;
Driver : array[0..255] of char;
Port : array[0..255] of char;
hDeviceMode: THandle;
DocInfo: TDoc_Info_1;
f: file;
Buffer: Pointer;
begin
Printer.PrinterIndex := -1;
Printer.GetPrinter(Device, Driver, Port, hDeviceMode);
if not WinSpool.OpenPrinter(@Device, hPrinter, nil) then exit;
DocInfo.pDocName := 'MyDocument';
DocInfo.pOutputFile := nil;
DocInfo.pDatatype := 'RAW';
if StartDocPrinter(hPrinter, 1, @DocInfo) = 0 then
begin
WinSpool.ClosePrinter(hPrinter);
exit;
end;
if not StartPagePrinter(hPrinter) then
begin
EndDocPrinter(hPrinter);
WinSpool.ClosePrinter(hPrinter);
exit;
end;
System.Assign(f, sFileName);
try
Reset(f, 1);
GetMem(Buffer, BufSize);
while not eof(f) do
begin
Blockread(f, Buffer^, BufSize, Count);
if Count > 0 then
begin
if not WritePrinter(hPrinter, Buffer, Count, BytesWritten) then
begin
EndPagePrinter(hPrinter);
EndDocPrinter(hPrinter);
WinSpool.ClosePrinter(hPrinter);
FreeMem(Buffer, BufSize);
exit;
end;
end;
end;
FreeMem(Buffer, BufSize);
EndDocPrinter(hPrinter);
WinSpool.ClosePrinter(hPrinter);
finally
System.Closefile( f );
end;
end;
这是一个读取我找到的打印机状态的示例(再次由 TeamB 的 Peter 下面提供)- 它在 Delphi 2007 中进行了测试,因此可能需要对某些类型进行一些小的调整以用于更高版本的 Delphi:
Uses WinSpool;
function GetCurrentPrinterStatus: DWORD;
var
hPrinter: THandle;
Device : array[0..255] of char;
Driver : array[0..255] of char;
Port : array[0..255] of char;
hDeviceMode: THandle;
bytesNeeded, bytesWritten: Cardinal;
pPI: PPrinterInfo2;
Defaults: TPrinterDefaults;
begin
Assert( Printer.PrinterIndex >= 0 );
Printer.GetPrinter(Device, Driver, Port, hDeviceMode);
FillChar( Defaults, Sizeof(Defaults), 0 );
Defaults.DesiredAccess:=
PRINTER_ACCESS_ADMINISTER or PRINTER_ACCESS_USE;
Win32Check(WinSpool.OpenPrinter(@Device, hPrinter, @Defaults ));
try
WinSpool.GetPrinter(
hPrinter,
2,
Nil, 0, @bytesNeeded );
GetMem( pPI, bytesNeeded );
try
Win32Check(WinSpool.GetPrinter(
hPrinter, 2,
pPI, bytesNeeded, @bytesNeeded ));
Result := pPI^.Status;
finally
FreeMem( pPI );
end;
finally
WinSpool.ClosePrinter( hPrinter );
end;
end;
API 文档为您提供有关PRINTER_INFO_2 及其返回标志的更多信息。您可以使用以下方式检查特定标志:
if (Status and PRINTER_STATUS_ERROR) <> 0 then
// Printer is in error status