打印时动态选择打印机,能精确知道打印机是否打印完毕(100分)

  • 主题发起人 主题发起人 szloner
  • 开始时间 开始时间
S

szloner

Unregistered / Unconfirmed
GUEST, unregistred user!
我要成批打印PFD或图片,在打印时要根据不同的打印内容动态选择不同的打印机。
以下有三个问题:
1、如何取得本机的打印设备
2、如何动态选择不同打印机
3、如何知道打印的进程
 
针对打印机,有一套完善的API,可以得到各种打印的状态。
你上雅虎上查下,就会得到一个完整的列表。我以前查过。很多。
 
1。Add a message handler for it to your main form, private section:
procedure WMSpoolerstatus( var msg: TWMSpoolerstatus );
message WM_SPOOLERSTATUS;

Hit Shift-Ctrl-C to make the IDE add a implementation for the method.
Add an inherited statement. msg.JobStatus will be 0 if the spooler thinks
it is healthy and < 0 if it has an error. From the list of error codes
found in Windows.PAS (above PR_JOBSTATUS) a missing network printer may not
be seen as an error, so look at msg.JobsLeft. If this never decreases in
the messages you see the spooler cannot get rid of the jobs. Of course it is
hard to tell when enough time has passed so you might become suspicious.
You can try to use the WinSpool.EnumJobs API to query the spooler directly.
Example below. See the diverse JOB_STATUS* codes given in the help topic for
JOB_INFO_1 in win32.hlp. Note that the Status field is a bitset, it can contain
more than one of the status codes. Use expressions like
if (Status and JOB_STATUS_OFFLINE) <> 0 then
... printer offline
uses Winspool, Printers;
function GetCurrentPrinterHandle: THandle;
var
Device, Driver, Port : array[0..255] of char;
hDeviceMode: THandle;
begin
Printer.GetPrinter(Device, Driver, Port, hDeviceMode);
if not OpenPrinter(@Device, Result, nil) then
RaiseLastWin32Error;
end;

Function SavePChar( p: PChar ): PChar;
const error: PChar = 'Nil';
begin
if not assigned( p ) then
result := error
else
result := p;
end;

procedure TForm1.Button2Click(Sender: TObject);
type
TJobs = Array [0..1000] of JOB_INFO_1;
PJobs = ^TJobs;
var
hPrinter : THandle;
bytesNeeded, numJobs, i: Cardinal;
pJ: PJobs;
begin
hPrinter:= GetCurrentPrinterHandle;
try
EnumJobs( hPrinter, 0, 1000, 1, Nil, 0, bytesNeeded,
numJobs );
pJ := AllocMem( bytesNeeded );
If not EnumJobs( hPrinter, 0, 1000, 1, pJ, bytesNeeded,
bytesNeeded, numJobs )
then
RaiseLastWin32Error;
memo1.clear;
if numJobs = 0 then
memo1.lines.add('No jobs in queue')
else
For i:= 0 to Pred(numJobs)do
memo1.lines.add( Format(
'Job %s, Status (%d): %s',
[SavePChar(pJ^.pDocument), pJ^.Status, SavePChar(pJ^.pStatus)] ));
finally
ClosePrinter( hPrinter );
end;
end;

2。如果你想要改变Windows的缺省打印机,你必须在Windows的WIN.INI中改变设备键。
发送一条 WM_WININICHANGE 消息:
var
strIni: array[0..MAX_PATH] of Char;
arrWindows: array[0..64] of Char;
begin
GetWindowsDirectory(strIni, SizeOf(strIni));
StrCat(strIni, '/win.ini');
with TIniFile.Create(strIni)do
try
WriteString('windows', 'device', 'HP LaserJet 4 Plus,HPPCL5MS,LPT1:');
finally
Free;
end;

StrCopy(arrWindows, 'windows');
SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, LongInt(@arrWindows));
end;

3。比较长,你看看吧
var
pinfo: pPRINTERINFO2;
pprt,a: Cardinal;
b:PDWORD;
begin
b:=allocmem(256);
pinfo:=AllocMem(1000);
if OpenPrinter('HP DJ 200',pprt,nil) then
begin
a:=1000;
if getprinter(pprt,2,pinfo,a,b) then
showmessage(pinfo.pPrinterName+' ststus:'+inttostr(pinfo.Status));
ClosePrinter(pprt);
end;

freemem(b);
freemem(pinfo);
end;

PRINTER_INFO_2.Status :
Windows NT:
PRINTER_STATUS_PAUSED
PRINTER_STATUS_PENDING_DELETION
Windows 95:
PRINTER_STATUS_BUSY
PRINTER_STATUS_DOOR_OPEN
PRINTER_STATUS_ERROR
PRINTER_STATUS_INITIALIZING
PRINTER_STATUS_IO_ACTIVE
PRINTER_STATUS_MANUAL_FEED
PRINTER_STATUS_NO_TONER
PRINTER_STATUS_NOT_AVAILABLE
PRINTER_STATUS_OFFLINE
PRINTER_STATUS_OUT_OF_MEMORY
PRINTER_STATUS_OUTPUT_BIN_FULL
PRINTER_STATUS_PAGE_PUNT
PRINTER_STATUS_PAPER_JAM
PRINTER_STATUS_PAPER_OUT
PRINTER_STATUS_PAPER_PROBLEM
PRINTER_STATUS_PAUSED
PRINTER_STATUS_PENDING_DELETION
PRINTER_STATUS_PRINTING
PRINTER_STATUS_PROCESSING
PRINTER_STATUS_TONER_LOW
PRINTER_STATUS_UNAVAILABLE
PRINTER_STATUS_USER_INTERVENTION
PRINTER_STATUS_WAITING
PRINTER_STATUS_WARMING_UP
//////////////////////////////////////////////////////////////////
unit PrinterStatus;
interface
uses
Windows, Messages, WinProcs, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

// TPrinterstatus
// Komponente zum Abfragen des aktuellen Druckerportstatus
// Programmiert 2000 von K. Otto
// funktioniert unter Win 9x, jedoch nicht unter Win NT
// ---------------------------------
// Status: Freeware incl. Sourcecode
// ---------------------------------
// Diese Komponente beruht auf einem Beitrag von Robert Vivrette
// f黵 "The unofficial Newsletter of Delphi Users"
// http://www.undu.com/articles/990228a.html
type
TPrinterStatus = class(TComponent)
private
{ Private-Deklarationen }
fStatus : Byte;
fLPT : Integer;
Function GetTimeOut : Boolean;
Function GetIOError : Boolean;
Function GetPrinterSelected : Boolean;
Function GetOutOfPaper : Boolean;
Function GetAcknowledgement : Boolean;
Function GetPrinterBusy : Boolean;
protected
{ Protected-Deklarationen }
public
{ Public-Deklarationen }
Procedure CheckPrinterStatus;
// Liest den Druckerstatus der angegeben LPT-Schnittstelle
Constructor Create(AOwner : TComponent);
Override;
Property TimeOut : Boolean Read GetTimeOut;
Property IOError : Boolean Read GetIOError;
Property PrinterSelected : Boolean Read GetPrinterSelected;
Property OutOfPaper : Boolean Read GetOutOfPaper;
Property Acknowledgement : Boolean Read GetAcknowledgement;
Property Busy : Boolean Read GetPrinterBusy;
published
{ Published-Deklarationen }
Property LPT : Integer Read fLPT Write fLPT;
end;

procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Eigene', [TPrinterStatus]);
end;

Function TPrinterStatus.GetTimeOut : Boolean;
begin
Result:=(fStatus and $01)=$01;
end;

Function TPrinterStatus.GetIOError : Boolean;
begin
Result:=(fStatus and $08)=$08;
end;

Function TPrinterStatus.GetPrinterSelected : Boolean;
begin
Result:=(fStatus and $10)=$10;
end;

Function TPrinterStatus.GetOutOfPaper : Boolean;
begin
Result:=(fStatus and $20)=$20;
end;

Function TPrinterStatus.GetAcknowledgement : Boolean;
begin
Result:=(fStatus and $40)=$40;
end;

Function TPrinterStatus.GetPrinterBusy : Boolean;
begin
Result:=not ((fStatus and $80)=$80);
end;

Procedure TPrinterStatus.CheckPrinterStatus;
Var
Status : Byte;
CheckLPT : Word;
begin
Status:=0;
If (fLPT>=1) and (fLPT<=3) then
begin
CheckLPT:=fLPT-1;
asm
mov dx,CheckLPT;
mov al,0;
mov ah,2;
int 17h;
mov &amp;Status, ah;
end;
end;
fStatus:=Status;
end;

Constructor TPrinterStatus.Create(AOwner : TComponent);
begin
Inherited Create(AOwner);
fLPT:=1;
fStatus:=0;
end;

end.
//////////////////////////////////////////////////////
用法:
if not PrinterStatus1.PrinterReady(0) then
//0 = current printerport
ShowMessage(PrinterStatus1.StatusMsg) else
{print print print} ;
unit PrinterStatus;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TPrinterStatus = class(TComponent)
private
{ Private declarations }
FPort : Word;
FStatusStr : string;
protected
{ Protected declarations }
public
{ Public declarations }
function PrinterReady(LPT: Word): boolean;
published
{ Published declarations }
property StatusMsg: string read FStatusStr;
end;

procedure Register;
implementation
uses Printers;
procedure Register;
begin
RegisterComponents('Win95', [TPrinterStatus]);
end;

const
PrnReady = $90;
OffLine = $00;
OffLine2 = $10;
{NEW LINE}
PaperOut = $20;
PaperOut2 = $30;
{NEW LINE}
HookedButOff = $80;
{NEW LINE}
NoConnect = $B0;
{MODIFIED LINE}
{NOCONNECT = $30 FOR SOME COMPUTERS BY STU}
function TPrinterStatus.PrinterReady(LPT: Word): boolean;
var
ErrorCode, C : BYTE;
code, x : integer;
s : string;
function GetPrinterStatus (LPT: Word): Byte;
{Pass 1 in LPT for LPT1}
begin
asm
mov ah,2
mov dx,LPT
dec dx
int $17
mov @Result,ah
end;
end;
{GetPrinterStatus}

begin
result := false;
//assume not
FPort := LPT;
if FPort = 0 then
begin
{if no port specified then
try to set port to current
printer port}
{printer name}
s := Printer.Printers[Printer.PrinterIndex];
if Pos('FPort',s) <> 0 then
begin
s := Copy(s, Pos('FPort',s) +3, 1);
Val(s,x,code);
if code <> 0 then
FPort := 1 else
FPort := x;
end else
FPort := 1;
{default to LPT1}
end;

{valid LPT is 1..4}
if (FPort > 4) or (FPort < 1) then
begin
raise ERangeError.CreateFmt(
'LPT%d is not within the valid range of %d..%d',
[FPort, 1, 4]);
exit;
end;

ErrorCode := GetPrinterStatus(FPort);
ErrorCode := ErrorCode and $B0;
{NEW LINE}
C := ERRORCODE shl 6;
{ALWAYS MEANS NOTHING CONNECTED}
if C > 0 then
ERRORCODE := $B0;
{ELEMINATES NO LPT3 AND NOTHING CONNECTED}
case ErrorCode of
PrnReady : begin
FStatusStr := 'Printer Ready';
result := true;
end;
NoConnect : FStatusStr := 'Printer not connected';
Offline,OffLine2 : FStatusStr := 'Printer off line';
{Modified}
PaperOut,PaperOut2 : FStatusStr := 'Printer out of paper';
{Modified}
HookedButOff : FStatusStr := 'Printer connected but turned off';
{New}
else
FStatusStr := 'Printer error code: ' + IntToStr(ErrorCode);
end;

end;

 
接受答案了.
 
后退
顶部