给你个获取打印机状态的文章吧: 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;interfaceuses 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.htmltype 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;implementationprocedure 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 &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;interfaceuses 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;
可用CREATEFILE以PRN为文件名生成一个文件,检测返回值,若成功则打印机可用,否则显示打印机故障。生成关于PRN的文件句柄后,可象普通文件一样向文件写入内容,比如WRITE,写完后关闭文件。 //从并行端口读取打印机状态 function GetPrinterStatus:byte; asm MOV DX,$379; IN AL,DX; end; //获取打印机是否出错 function CheckPrinter:boolean; var temp:byte; begin temp:=GetPrinterStatus; Result:=not ( ((temp and $80)=0) //打印机忙 or ((temp and $20)<>0) //打印机缺纸 or ((temp and $10)=0) //打印机未联机 or ((temp and $08)=0) ); //打印机出错; end;
为默认打印机创建一个快捷方式后,用ShellExecute运行可以启动默认 打印机管理程序。如果不创建快捷方式,如何直接启动。 感谢http://www.experts-exchange.com/Q.10115433, 以下代码ShowPrintSpool可以实现: function ExecuteContextMenuCommand(hParent: THandle; sf: IShellFolder; childPidl: PItemIDList; verb: string = ''; propPage: string = ''; pidlCount: UInt = 1): Boolean; var cm, cm2, cm3: IContextMenu; ici: TCMInvokeCommandInfo; pop : HMenu; c: Cardinal; begin Result := False; if sf.GetUIObjectOf(hParent, pidlCount, childPidl, IID_IContextMenu,nil, Pointer(cm)) <> NOERROR then Exit; try cm2 := cm as IContextMenu2; cm := cm2; try cm3 := cm as IContextMenu3; cm := cm3; except end; except end; ZeroMemory(@ici, sizeOf(ici)); with ici do begin cbSize := sizeOf(TCMInvokeCommandInfo); fMask := CMIC_MASK_FLAG_NO_UI; hWnd := hParent; lpVerb := PChar(verb); lpParameters := PChar(propPage); //'Settings'; nShow := SW_SHOW; end; if verb <> '' then Result := cm.InvokeCommand(ici) = NOERROR else begin pop := CreatePopupMenu; try if Succeeded(cm.QueryContextMenu(pop, 0, 1, $7FFF, CMF_DEFAULTONLY)) then begin c := GetMenuDefaultItem(pop, 0, 0); if c <> 0 then begin ici.lpVerb := MakeIntResource(c - 1); Result := cm.InvokeCommand(ici) = NOERROR; end; end; finally DestroyMenu(pop) end; end end;function PidlToStr(sf: IShellFolder; childPidl: PItemIDList): string; var sr: _StrRet; begin Result := ''; if (sf = nil) or (childPidl = nil) then Exit; sr.uType := STRRET_CSTR; if sf.GetDisplayNameOf(childPidl,SHGDN_NORMAL,sr) = NOERROR then case sr.uType of STRRET_CSTR : Result := string(sr.cStr); STRRET_OFFSET : Result := string(PChar(Cardinal(childPidl) + sr.uOffset)); STRRET_WSTR : Result := string(sr.pOleStr); end; end;function DefaultPrinterDevice: string; var Device, Driver, Port: array [0..255] of Char; Mode: THandle; begin Device := ''; with Printer do if Printers.Count > 0 then GetPrinter(Device, Driver, Port, Mode); Result := Device; end;procedure ShowPrintSpool; var pidl1, pidl2: PItemIDList; sf1, sf2: IShellFolder; malloc: IMalloc; el: IEnumIDList; c: Cardinal; sDefaultPrinter: string; begin if (SHGetSpecialFolderLocation(INVALID_HANDLE_VALUE, CSIDL_PRINTERS, pidl1) = NOERROR) and (SHGetMalloc(malloc) = NOERROR) then try if (pidl1^.mkid.cb <> 0) and (SHGetDesktopFolder(sf1) = NOERROR) and (sf1.BindToObject(pidl1, nil, IID_IShellFolder, Pointer(sf2)) = NOERROR) and (sf2.EnumObjects(Application.Handle, High(Cardinal), el) = NOERROR) then begin sDefaultPrinter := DefaultPrinterDevice; el.Reset; while el.Next(1, pidl2, c) = NOERROR do begin if PidlToStr(sf2, pidl2) = sDefaultPrinter then ExecuteContextMenuCommand(Application.Handle, sf2, pidl2); malloc.Free(pidl2); end; end; finally malloc.Free(pidl1); end;
Printers是专门用来控制打印机的,可是在没有安装打印机时,却会提示I/O错误,所以必须有一个检测是否存在打印机的方法,我试过很多方法,可是I/O错误总是比我的判断早出现,所以采用以下的烂招来检测打印机。首先在uses增加Printers,再准备一个列表框ComboBox1,其属性Visible设为FALSE,然后在打印之前执行下列语句,那么就可以检测到是否存在打印机了:procedure TForm1.ButtonClick(Sender: Tobject); begin ComboBox1.Clear; ComboBox1.Items.Assign(Printer.Printers); if ComboBox1.Items.CommaText='' then Messagedlg('你需要安装打印机才能打印!',mtError,[mbOk],0); else Form1.Print; end;
打印机状态检测
可用CREATEFILE以PRN为文件名生成一个文件,检测返回值,若成功则打印机可用,否则显示打印机故障。生成关于PRN的文件句柄后,可象普通文件一样向文件写入内容,比如WRITE,写完后关闭文件。//从并行端口读取打印机状态function GetPrinterStatus:byte;asmMOV DX,$379;IN AL,DX;end;//获取打印机是否出错function CheckPrinter:boolean;vartemp:byte;begintemp:=GetPrinterStatus;Result:=not ( ((temp and $80)=0) //打印机忙or ((temp and $20)<>0) //打印机缺纸or ((temp and $10)=0) //打印机未联机or ((temp and $08)=0) ); //打印机出错;end;
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;interfaceuses
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.htmltype
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;implementationprocedure 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 &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;interfaceuses
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;
//从并行端口读取打印机状态
function GetPrinterStatus:byte;
asm
MOV DX,$379;
IN AL,DX;
end;
//获取打印机是否出错
function CheckPrinter:boolean;
var
temp:byte;
begin
temp:=GetPrinterStatus;
Result:=not ( ((temp and $80)=0) //打印机忙
or ((temp and $20)<>0) //打印机缺纸
or ((temp and $10)=0) //打印机未联机
or ((temp and $08)=0) ); //打印机出错;
end;
打印机管理程序。如果不创建快捷方式,如何直接启动。
感谢http://www.experts-exchange.com/Q.10115433, 以下代码ShowPrintSpool可以实现:
function ExecuteContextMenuCommand(hParent: THandle; sf: IShellFolder; childPidl: PItemIDList;
verb: string = ''; propPage: string = ''; pidlCount: UInt = 1): Boolean;
var
cm, cm2, cm3: IContextMenu;
ici: TCMInvokeCommandInfo;
pop : HMenu;
c: Cardinal;
begin
Result := False;
if sf.GetUIObjectOf(hParent, pidlCount, childPidl, IID_IContextMenu,nil, Pointer(cm)) <> NOERROR then Exit;
try
cm2 := cm as IContextMenu2;
cm := cm2;
try
cm3 := cm as IContextMenu3;
cm := cm3;
except
end;
except
end;
ZeroMemory(@ici, sizeOf(ici));
with ici do
begin
cbSize := sizeOf(TCMInvokeCommandInfo);
fMask := CMIC_MASK_FLAG_NO_UI;
hWnd := hParent;
lpVerb := PChar(verb);
lpParameters := PChar(propPage); //'Settings';
nShow := SW_SHOW;
end;
if verb <> '' then
Result := cm.InvokeCommand(ici) = NOERROR
else
begin
pop := CreatePopupMenu;
try
if Succeeded(cm.QueryContextMenu(pop, 0, 1, $7FFF, CMF_DEFAULTONLY)) then
begin
c := GetMenuDefaultItem(pop, 0, 0);
if c <> 0 then
begin
ici.lpVerb := MakeIntResource(c - 1);
Result := cm.InvokeCommand(ici) = NOERROR;
end;
end;
finally
DestroyMenu(pop)
end;
end
end;function PidlToStr(sf: IShellFolder; childPidl: PItemIDList): string;
var
sr: _StrRet;
begin
Result := '';
if (sf = nil) or (childPidl = nil) then Exit;
sr.uType := STRRET_CSTR;
if sf.GetDisplayNameOf(childPidl,SHGDN_NORMAL,sr) = NOERROR then
case sr.uType of
STRRET_CSTR : Result := string(sr.cStr);
STRRET_OFFSET : Result := string(PChar(Cardinal(childPidl) + sr.uOffset));
STRRET_WSTR : Result := string(sr.pOleStr);
end;
end;function DefaultPrinterDevice: string;
var
Device, Driver, Port: array [0..255] of Char;
Mode: THandle;
begin
Device := '';
with Printer do
if Printers.Count > 0 then
GetPrinter(Device, Driver, Port, Mode);
Result := Device;
end;procedure ShowPrintSpool;
var
pidl1, pidl2: PItemIDList;
sf1, sf2: IShellFolder;
malloc: IMalloc;
el: IEnumIDList;
c: Cardinal;
sDefaultPrinter: string;
begin
if (SHGetSpecialFolderLocation(INVALID_HANDLE_VALUE, CSIDL_PRINTERS, pidl1) = NOERROR) and
(SHGetMalloc(malloc) = NOERROR) then
try
if (pidl1^.mkid.cb <> 0) and (SHGetDesktopFolder(sf1) = NOERROR) and
(sf1.BindToObject(pidl1, nil, IID_IShellFolder, Pointer(sf2)) = NOERROR) and
(sf2.EnumObjects(Application.Handle, High(Cardinal), el) = NOERROR) then
begin
sDefaultPrinter := DefaultPrinterDevice;
el.Reset;
while el.Next(1, pidl2, c) = NOERROR do
begin
if PidlToStr(sf2, pidl2) = sDefaultPrinter then
ExecuteContextMenuCommand(Application.Handle, sf2, pidl2);
malloc.Free(pidl2);
end;
end;
finally
malloc.Free(pidl1);
end;
begin
ComboBox1.Clear;
ComboBox1.Items.Assign(Printer.Printers);
if ComboBox1.Items.CommaText='' then
Messagedlg('你需要安装打印机才能打印!',mtError,[mbOk],0);
else
Form1.Print;
end;
可用CREATEFILE以PRN为文件名生成一个文件,检测返回值,若成功则打印机可用,否则显示打印机故障。生成关于PRN的文件句柄后,可象普通文件一样向文件写入内容,比如WRITE,写完后关闭文件。//从并行端口读取打印机状态function GetPrinterStatus:byte;asmMOV DX,$379;IN AL,DX;end;//获取打印机是否出错function CheckPrinter:boolean;vartemp:byte;begintemp:=GetPrinterStatus;Result:=not ( ((temp and $80)=0) //打印机忙or ((temp and $20)<>0) //打印机缺纸or ((temp and $10)=0) //打印机未联机or ((temp and $08)=0) ); //打印机出错;end;