餐饮行业,打印池是必要的部件。
实现原理:每一台打印机都有自己的任务队列和处理任务队列的线程。
unit untPrintTask;
interface
uses
 System.SysUtils, System.Classes,
 Datasnap.DBClient, frxclass,
 System.Generics.Collections;
type
 TBillContent = record // 小票内容
 machineNo: string; // POS机号
 skyName: string; // 收款员姓名
 saleNo: string; // 小票号
 saleTime: TDateTime; // 销售时间
 amount: Currency; // 应收
 pay: Currency; // 支付
 change: Currency; // 找零
 prnData: OleVariant; // 小票明细:商品名称、单价、数量、金额。。。。。。
 deskNo:string; // 台号
 payType: string; // 支付方式
 end;
type
 TPrinterInfo = record // 打印机信息
 prnNo: Integer; // 印机编号
 prnName: string; // 印机名称
 prnType: string; // 结账、厨打
 prnWidth: Integer; // 50mm\76mm\80mm
 remark: string; // 备注
 prnModel: string; // 打印模版
 end;
type
 TOneTimePrint = record // 一次打印
 printerInfo: TPrinterInfo; // 打印机信息
 billContent: TBillContent; // 小票内容
 end;
type
 TPrintTaskThread = class(TThread) // 打印任务线程
 private
 FPrintQueue: TQueue<TOneTimePrint>; // 打印队列
 protected
 procedure Execute; override;
 public
 constructor Create; overload;
 destructor Destroy; override;
 property PrintQueue: TQueue<TOneTimePrint> read FPrintQueue
 write FPrintQueue;
 end;
var
 g_PrintTasks: TDictionary<string, TPrintTaskThread>; // <打印机名字, TPrintTask>
implementation
{ TPrintTask }
uses untFastReport, UntSysConst;
constructor TPrintTaskThread.Create;
begin
 Create(False);
 FreeOnTerminate := False;
 // 创建打印队列
 FPrintQueue := TQueue<TOneTimePrint>.Create;
end;
destructor TPrintTaskThread.Destroy;
begin
 // 释放打印队列
 FreeAndNil(FPrintQueue);
 inherited;
end;
procedure TPrintTaskThread.Execute;
var
 OneTimePrint: TOneTimePrint;
 dm: TdmFastReport;
 c: TfrxComponent;
begin
 while not Self.Terminated do
 begin
 if Assigned(FPrintQueue) and (FPrintQueue.Count > 0) then
 begin
 // 从任务队列中提取一个任务
 OneTimePrint := FPrintQueue.Dequeue;
 dm := TdmFastReport.Create(nil);
 try
 try
 // 小票明细数据
 dm.cds.Data := OneTimePrint.billContent.prnData;
 // 小票模板
 dm.report.LoadFromFile(OneTimePrint.printerInfo.prnModel);
 // 哪个打印机
 dm.report.PrintOptions.Printer := OneTimePrint.printerInfo.prnName;
 // 变量赋值
 c:=dm.report.FindObject('mmShopName');
 if c<>nil then
 TfrxMemoView(c).Memo.Text := UserInfo.ShopName;
 c := dm.report.FindObject('mmMachineNo');
 if c<>nil then
 TfrxMemoView(c).Memo.Text := OneTimePrint.billContent.machineNo;
 c:=dm.report.FindObject('mmSKY');
 if c<>nil then
 TfrxMemoView(c).Memo.Text := OneTimePrint.billContent.skyName;
 c:= dm.report.FindObject('mmBillNo');
 if c<>nil then
 TfrxMemoView(c).Memo.Text := OneTimePrint.billContent.saleNo;
 c:=dm.report.FindObject('mmSaleTime');
 if c<>nil then
 TfrxMemoView(c).Memo.Text := FormatDateTime('yyyy-mm-dd hh:nn',OneTimePrint.billContent.saleTime);
 c:= dm.report.FindObject('mmDeskNo');
 if c<>nil then
 TfrxMemoView(c).Memo.Text := OneTimePrint.billContent.deskNo; // 台号
 c:= dm.report.FindObject('mmPayType');
 if c<>nil then
 TfrxMemoView(c).Memo.Text := OneTimePrint.billContent.payType;
 c:= dm.report.FindObject('mmAmount');
 if c<> nil then
 TfrxMemoView(c).Memo.Text := FormatCurr('0.00', OneTimePrint.billContent.amount);
 c:=dm.report.FindObject('mmPay');
 if c<>nil then
 TfrxMemoView(c).Memo.Text := FormatCurr('0.00', OneTimePrint.billContent.pay);
 c:= dm.report.FindObject('mmGiveChange');
 if c<> nil then
 TfrxMemoView(c).Memo.Text := FormatCurr('0.00', OneTimePrint.billContent.change);
 // 开始打印
 dm.report.PrepareReport();
 dm.report.Print;
 except
 // 打印失败,重新加入任务队列
 Self.FPrintQueue.Enqueue(OneTimePrint);
 end;
 finally
 FreeAndNil(dm);
 end;
 end;
 Sleep(1);
 end;
end;
end.