并口打印机编程问题??????

blackfish 2001-11-08 01:04:43
我要对并口打印机发指令,自己写驱动,需要各位帮忙
1、并口打印机能取到返回状态吗? 如何取得?
2、有没有对并口直接操作得API(WriteFile和ReadFile除外)?
3、如何使用汇编编程?(中断号、状态位等)
回答其中一个或几个问题均可,也可以提供其它有效的方式,谢谢!!!
blackfish988@sohu.com
...全文
284 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
blackfish 2001-11-12
  • 打赏
  • 举报
回复
谢谢
cobi 2001-11-08
  • 打赏
  • 举报
回复
unit DosPrinter;

// Note: Only Be Ok in Win98, and the printer must be in
// lpt1, lpt2 or lpt3;
// And Be Sure your Windows does not install the printer
//
// User Guide: Just add this unit into the "uses" clause, then you may
// call LPT1.Write, LPT1.WriteLn, LTP1.WriteFmt directly to
// make output on the printer. (LPT2 is also supported).
//
// Limitation: This unit does not have error checking capabilities.

// New added Guide:
// TDosPrinter;
// Can Check whether the printer is empty of paper, or
// printer does not linked, or other errors.
//

interface

uses Classes, SysUtils, Windows, MusicSys;

type
// 并口号
TDosLptPort = ( dpLpt1, dpLpt2, dpLpt3 );

// 错误类别, ( 未联机, 缺纸, 超时 )  
TErrType = ( etLinkLost, etLackPaper, etTimeout );

// 打印错误事件
TErrMsgEvent = procedure(Sender: TObject; ErrType: TErrType;
var Retry: Boolean ) of object;

TDosPrinter = class
private
FLptPort: TDosLptPort;
FOnErr: TErrMsgEvent;
FblActive: Boolean;
protected

public
Constructor Create;

procedure BeginDoc;
procedure EndDoc;
procedure DoDoubleWidth( bl: Boolean );
procedure DoDoubleHeight( bl: Boolean );
procedure DoBold( bl: Boolean );
procedure ChineseMode;
procedure DoExpress( bl: Boolean );
procedure CR;
procedure Writeln( sLine: string );
procedure Write( sLine: string );
function WriteChar( Achar: char ): Boolean;
procedure MovePaper( iSize: integer );

property Active: Boolean read FblActive;
property LptPort: TDosLptPort read FLptPort write FLptPort;
property OnErr: TErrMsgEvent read FOnErr write FOnErr;

end;

function DosLpt1: TDosPrinter;
function DosLpt2: TDosPrinter;

implementation

var
_DosLpt1: TDosPrinter = nil;
_DosLpt2: TDosPrinter = nil;

function DosLpt1: TDosPrinter;
begin
if not Assigned( _DosLpt1 ) then
begin
_DosLpt1 := TDosPrinter.Create;
_DosLpt1.LptPort := dpLpt1;
end;
result := _DosLpt1;
end;

function DosLpt2: TDosPrinter;
begin
if not Assigned( _DosLpt2 ) then
begin
_DosLpt2 := TDosPrinter.Create;
_DosLpt2.LptPort := dpLpt2;
end;
result := _DosLpt2;
end;

{ TDosPrinter }

procedure TDosPrinter.BeginDoc;
begin
// Do nothing ...
end;

procedure TDosPrinter.ChineseMode;
begin
Write( #28 + '&' );
end;

procedure TDosPrinter.CR;
begin
Write( #13 );
end;

constructor TDosPrinter.Create;
begin
FLptPort := dpLpt1;
FblActive := True;
end;

procedure TDosPrinter.DoBold(bl: Boolean);
begin
if bl then
Write( #27 + 'E' )
else
Write( #27 + 'F' );
end;

procedure TDosPrinter.DoDoubleHeight(bl: Boolean);
begin
if bl then
Write( #27 + 'w' + #1 )
else
Write( #27 + 'w' + #0 );
end;

procedure TDosPrinter.DoDoubleWidth(bl: Boolean);
begin
if bl then
Write( #27 + 'W' + #1 )
else
Write( #27 + 'W' + #0 );
end;

procedure TDosPrinter.DoExpress(bl: Boolean);
begin
if bl then
Write( #28 + 'x' + #1 )
else
Write( #28 + 'x' + #0 );
end;

procedure TDosPrinter.EndDoc;
begin
// Do nothing ...
end;

procedure TDosPrinter.MovePaper(iSize: integer);
begin
Write( #27 + 'J' + char( iSize mod 255 ) );
end;

procedure TDosPrinter.Write(sLine: string);
var
index: longint;
begin
for Index := 1 to length( sLine ) do
if not WriteChar( sLine[Index] ) then
Break;
end;

function TDosPrinter.WriteChar( AChar: char): Boolean;
var
byteChar, byteStatus: Byte;
wordLpt: Word;
bPaperOut, bSelected, bIOError, bTimeOut, bOK: Boolean;
// below is new added by Musicwind, 2001-02-08
FErrType: TErrType;
Retry: Boolean;
dwTimeOut: DWORD;
begin
result := False;

if not mscIsWin98 then
begin
FblActive := result;
Exit;
end;

byteChar := byte( AChar );
if FLptPort = dpLpt1 then
wordLpt := 0 else
if FLptPort = dpLpt2 then
wordLpt := 1 else
if FLptPort = dpLpt3 then
wordLpt := 2
else
wordLpt := 0;
repeat
retry := False;

byteStatus := $40;
while (( byteStatus and $80 ) = 0 ) and (( byteStatus and $40 ) <> 0 ) do
asm
MOV AH, 0
MOV DX, wordLpt
MOV AL, byteChar
INT 17H
MOV byteStatus, AH
end;

bTimeOut := ( byteStatus and $01 ) <> 0;
bIOError := ( byteStatus and $08 ) <> 0;
bSelected := ( byteStatus and $10 ) <> 0;
bPaperOut := ( byteStatus and $20 ) <> 0;

if bTimeOut then
FErrType := etTimeOut
else
if bSelected and bPaperOut and bIOError then
FErrType := etLackPaper
else
if bSelected and bPaperOut or bIOError then
FErrType := etLinkLost
else
begin
// Print content
result := True;

end;

if not result then
begin
Retry := False;
if Assigned( FOnErr ) then
begin
Retry := True;
FOnErr( Self, FErrType, Retry );
end;
end;
until result or not Retry;
FblActive := result;
if not FblActive then
raise Exception.Create( '打印出错!' );
end;

procedure TDosPrinter.Writeln(sLine: string);
begin
Write( sLine + #13#10 );
end;

initialization



finalization



end.



unit LPT;

// Note: Only Be Ok in WinNt or later OS
// And Be Sure your Windows does not install the printer
//
// User Guide: Just add this unit into the "uses" clause, then you may
// call LPT1.Write, LPT1.WriteLn, LTP1.WriteFmt directly to
// make output on the printer. (LPT2 is also supported).
//
// Limitation: This unit does not have error checking capabilities.

// New added Guide:
// TEpson300K;
// added for Epson 300K , by Musicwind, at 2000-12-18
//

interface

uses Classes, SysUtils, Windows, SyncObjs;

type

TLPT = class
protected
FDeviceName: string;
FHandle: THandle;
FEvent: TSimpleEvent;
FOverlap: TOverlapped;
procedure SetActive(Value: Boolean);
procedure SetDeviceName(AName: string);
function GetActive: Boolean;
public
constructor Create; virtual;
destructor Destroy; override;
procedure Open;
procedure Close;
procedure WriteBuf(const Buf: PChar; Len: Integer);
procedure Write(const AString: string);
procedure WriteLn(const AString: string);
procedure WriteFmt(const FmtStr: string; Args: array of const);
property Active: Boolean read GetActive write SetActive;
property Handle: THandle read FHandle;
published
property DeviceName: string read FDeviceName write SetDeviceName;
end;

TLPTStream = class(TStream)
public
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
procedure WriteLn(const S: string);
end;

TEpson300K = class ( TLpt )
private
FiPageHeight: integer; // 一页的高度( 单位:英寸 )
FblChinese: Boolean; // 汉字打印模式
FblExpress: Boolean; // 高速打印模式
procedure SetFiPageHeight(const Value: integer); // 页长度, 单位( 英寸 )

public
constructor Create; override;

procedure BeginDoc; // 开始一个文档
procedure EndDoc; // 结束....
procedure BeginPage; // 开始页
procedure EndPage; // 结束页
procedure BeginBold; // 开始粗体
procedure EndBold; // 结束粗体

procedure MovePaper( iHeight: integer );
procedure DoubleHeight(bl: Boolean);
procedure DoubleWidth(bl: Boolean);


property PageHeight: integer read FiPageHeight write SetFiPageHeight;
property ChineseMode: Boolean read FblChinese write FblChinese;
property ExpressMode: Boolean read FblExpress write FblExpress;
end;

function LPT1: TLPT;
function LPT2: TLPT;

function Epson300k1: TEpson300k;
function Epson300k2: TEpson300k;


implementation // ===========================================================

var

_LPT1: TLPT = nil;
_LPT2: TLPT = nil;
_Epson300k1: TEpson300k = nil;
_Epson300k2: TEpson300k = nil;


{ TLPT }

constructor TLPT.Create;
begin
FDeviceName := 'LPT1';
FEvent := TSimpleEvent.Create;
FOverlap.hEvent := FEvent.Handle;
end;

destructor TLPT.Destroy;
begin
Active := False;
inherited;
end;

procedure TLPT.SetActive(Value: Boolean);
begin
if Value = Active then exit;
if Value then begin
FHandle := CreateFile(PChar(FDeviceName), GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
OPEN_EXISTING, FILE_FLAG_NO_BUFFERING or FILE_FLAG_OVERLAPPED, 0);
end
else begin
CloseHandle(FHandle);
FHandle := INVALID_HANDLE_VALUE;
end;
end;

procedure TLPT.SetDeviceName(AName: string);
begin
Active := False;
FDeviceName := AName;
end;

function TLPT.GetActive: Boolean;
begin
Result := FHandle <> INVALID_HANDLE_VALUE;
end;

procedure TLPT.Open;
begin
Active := True;
end;

procedure TLPT.Close;
begin
Active := False;
end;

procedure TLPT.WriteBuf(const Buf: PChar; Len: Integer);
var
Num: Integer;
begin
if Active = False then
Active := True;
if Active and (Len > 0) then
WriteFile(FHandle, Buf^, Cardinal( Len ), Cardinal( Num ), @FOverlap);
end;

procedure TLPT.Write(const AString: string);
begin
WriteBuf(PChar(AString), Length(AString));
end;

procedure TLPT.WriteLn(const AString: string);
const
CRLF: array[0..1] of Char = (#13, #10);
begin

WriteBuf(PChar(AString), Length(AString));
WriteBuf(CRLF, 2);
end;

procedure TLPT.WriteFmt(const FmtStr: string; Args: array of const);
begin
Write(Format(FmtStr, Args));
end;

function TLPTStream.Read(var Buffer; Count: Longint): Longint;
begin
Result := 0;
end;

function TLPTStream.Write(const Buffer; Count: Longint): Longint;
begin
Result := Count;
if Count > 0 then
LPT1.WriteBuf(PChar(@Buffer), Count);
end;

function TLPTStream.Seek(Offset: Longint; Origin: Word): Longint;
begin
Result := 0;
end;

procedure TLPTStream.WriteLn(const S: string);
begin
LPT1.WriteLn(S);
end;


// ==========================================================================

function LPT1: TLPT;
begin
if _LPT1 = nil then begin
_LPT1 := TLPT.Create;
_LPT1.DeviceName := 'LPT1';
_LPT1.Active := True;
end;
Result := _LPT1;
end;

function Epson300k1: TEpson300k;
begin
if _Epson300k1 = nil then
begin
_Epson300k1 := TEpson300k.Create;
_Epson300k1.DeviceName := 'LPT1';
_Epson300k1.Active := True;
end;
result := _Epson300k1;
end;

function Epson300k2: TEpson300k;
begin
if _Epson300k2 = nil then
begin
_Epson300k2 := TEpson300k.Create;
_Epson300k2.DeviceName := 'LPT2';
_Epson300k2.Active := True;
end;
result := _Epson300k2;
end;


function LPT2: TLPT;
begin
if _LPT2 = nil then begin
_LPT2 := TLPT.Create;
_LPT2.DeviceName := 'LPT2';
_LPT2.Active := True;
end;
Result := _LPT2;
end;

// ==========================================================================

{ TEpson300K }

procedure TEpson300K.BeginBold;
begin
Write( #27 + 'E' );
end;

procedure TEpson300K.DoubleWidth( bl: Boolean );
begin
if bl then
Write( #27 + 'W' + #1 )
else
Write( #27 + 'W' + #0 );
end;

procedure TEpson300K.DoubleHeight( bl: Boolean );
begin
if bl then
Write( #27 + 'w' + #1 )
else
Write( #27 + 'w' + #0 );

end;

procedure TEpson300K.BeginDoc;
begin
Active := True;
if FblChinese then
Write( #28 + '&' ) ; // 设定汉字打印模式
if FblExpress then
Write( #28 + 'x' + #1 )
else
Write( #28 + 'x' + #0 );
end;

procedure TEpson300K.BeginPage;
begin
if ( FiPageHeight >= 1 ) and ( FiPageHeight <= 22 ) then
begin
Write( #27 + 'C' + #0 + Char( FiPageHeight ) ) ;
Write( #27 + '$' + #0 + #0 ); // 设定绝对位置为 y=0, x=0
end;
end;

constructor TEpson300K.Create;
begin
inherited;
FiPageHeight := 0;
FblChinese := True;
FblExpress := False;
end;

procedure TEpson300K.EndBold;
begin
Write( #27 + 'F' );
end;

procedure TEpson300K.EndDoc;
begin
Active := False;
end;

procedure TEpson300K.EndPage;
begin
if FiPageHeight <> 0 then
Write( #12 );
end;

procedure TEpson300K.MovePaper(iHeight: integer);
begin
Writeln( #27 + 'J' + char( iHeight mod 255 ) );
end;

procedure TEpson300K.SetFiPageHeight(const Value: integer);
begin
FiPageHeight := Value mod 22;
end;

initialization
finalization
if _LPT1 <> nil then _LPT1.Free;
if _LPT2 <> nil then _LPT2.Free;

if _Epson300k1 <> nil then _Epson300k1.Free;
if _Epson300k2 <> nil then _Epson300k2.Free;

end.
cobi 2001-11-08
  • 打赏
  • 举报
回复
通过调用dos下的ECHO命令来管道输出到打印机来实现,在win9x下调用dos是command.com,而在win2000下是用CMD.EXE
可以试一下下面的语句

function SysPrnStr(sPrnStr:string):Boolean;
begin
result:=false;
Case iVer of
1: //系统为Win98
begin
WinExec(PChar(sWinDir+'COMMAND.COM /C ECHO '+sPrnStr+'>PRN'),SW_HIDE);
Sleep(150);
end;
2: //系统为2000
begin
WinExec(PChar(sSysDir+'CMD.EXE /C ECHO '+sPrnStr+'>PRN'),SW_HIDE);
Sleep(150);
end;
end;
result:=true;
end;

Sleep(150);//这句话可以不要,不过如果是在pos销售时连接扣条码机,不用这句可能会出现
打印顺序错乱的情况
cobi 2001-11-08
  • 打赏
  • 举报
回复
可用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;

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧