2012-07-31 387 views
2

当访问Printer.Printers字符串列表时,如果发送QuickReport报告到选定的打印机时,出现“列表索引超出范围”等错误。打印QR报告时列表索引超出范围错误

exception class : EStringListError 
exception message : List index out of bounds (6). 

main thread ($1594c): 
00479559 skdata.exe Classes 5060 TStringList.GetObject 
004a258b skdata.exe Printers 581 TPrinter.GetPrinter 
007ca744 skdata.exe QRPrntr 3208 TPrinterSettings.ApplySettings 
007cb5bb skdata.exe QRPrntr 3995 TQRPrinter.BeginDoc 
007be227 skdata.exe QuickRpt 4645 TCustomQuickRep.CreateReport 
007be909 skdata.exe QuickRpt 4853 TCustomQuickRep.Print 
00859bc7 skdata.exe PostLst 142 TPostSpecListReport.Print 

我已经添加了日志记录,显示打印机列表(Printer.Printers)在发生错误之前已更改。我猜如果网络打印机关闭,网络关闭以及其他原因,打印机列表可能会更改。

如何处理这种情况?在Delphi中,所选打印机由Printer.PrinterIndex给出,但如果打印机列表发生更改,则此索引不再有效。

我只能想到一种解决方案,即在每次打印之前显示select-printer对话框,换句话说,不要依赖Printer.PrinterIndex从一个打印作业到下一个打印作业。但是这对用户来说可能很烦人。

理想情况下,选定的打印机应该作为GUID或按名称存储。这会使它更可靠。

我搜索了这个论坛以及Embarcadero论坛,但没有发现任何提及这类问题。所以也许这里有一些我忽略的简单东西?

我用Delphi 2007和QuickReport 5

回答

1

您可以将打印机的名称,如果你愿意,并在OnBeforePrint事件处理程序,或在报告的构造函数分配给它。如果您不想对其进行硬编码,请将其存储在注册表或ini文件中。

type 
    TMyForm = class(TForm) 
    .... 
    private 
    FPrinterName: string; 
    published 
    .... 
    end; 

implementation 

uses 
    Printers; 

procedure TMyForm.FormCreate(Sender: TObject); 
begin 
    // Set, or read from registry or ini file 
    FPrinterName := 'My LaserJet Printer'; 
end; 

procedure TMyForm.PrintReportButtonClick(Sender: Object); 
begin 
    // Create report and set up. Select stored printer, or set to default 
    // printer if none is stored 
    QuickRep1.PrinterSettings.PrinterIndex := Printers.IndexOf(FPrinterName); 
    QuickRep1.Print; 
    // Clean up - free report, etc. 
end; 
+0

如果该打印机已被删除会发生什么?我猜'Printers.IndexOf(FPrinterName)'返回-1?那会导致正在使用的默认打印机? – 2012-07-31 12:40:30

+3

是的。如果打印机在调用“IndexOf”之前被删除,则调用返回-1,这意味着“使用默认打印机”(因为Delphi 1引入了“TPrinter”)。如果在设置打印机索引和实际打印报告之间的短时间内删除打印机,则可以将分配移动到更接近实际打印过程的某个位置(如“QuickRep1BeforePrint”),或者断开保存人员的腿删除您的打印机。 :-) – 2012-07-31 12:43:31