Reputation: 2176
Can anybody explain how this should work (Delphi XE2 running on Windows10)?
In a minimalist application - a form with two buttons - with the following code:
procedure TForm2.Button1Click(Sender: TObject);
begin
Printer.BeginDoc;
Printer.Canvas.TextOut(10,10,'Hello World');
Printer.EndDoc;
end;
procedure TForm2.Button2Click(Sender: TObject);
var
MyPrinter : TPrinter;
begin
MyPrinter := Printer;
MyPrinter.BeginDoc;
MyPrinter.Canvas.TextOut(10,10,'Hello World');
MyPrinter.EndDoc;
MyPrinter.Free;
end;
If I click Button1, the program prints a 'Hello World' at my default printer, and closes normally when I close it (with the close button). If instead, I click Button2, the program prints an identical page but now when I close with the close button I get an Error 217 message.
I can't find clarification in the Delphi documentation regarding exactly how to use the Printer function and TPrinter variables. I am quite happy using a derivative of the Button1 technique to print - if it is confirmed that this is the 'bullet-proof' way to go, but would like to understand why the Button2 method doesn't work. Should I just assume that it is not my responsibility to free any TPrinter object I instantiate, or is there a clearer explanation?
Upvotes: 2
Views: 1153
Reputation: 5920
When you are running this code:
MyPrinter := Printer;
MyPrinter.BeginDoc;
MyPrinter.Canvas.TextOut(10,10,'Hello World');
MyPrinter.EndDoc;
MyPrinter.Free;
Printer
is deleted on function exit. So when appication is terminating, it tries to delete it again, and you get an error. More than that, if you try to run this code second time, it will raise as well. MyPrinter
is just a pointer to the global TPrinter
object, returned by the Printer
function. You should not delete things, that you have not created.
Documentation of the Printer
function:
Returns a global instance of TPrinter to manage interaction with the printer.
Printer creates an instance of a global TPrinter object the first time it is called. Use the Printer function to print using the TPrinter object.
Note: The global TPrinter object is freed automatically when the application shuts down. After a call to SetPrinter, the printer that is returned is not automatically freed. It is the caller's responsibility to either free the return value, or replace it using another call to SetPrinter and to free the substitute printer that the second SetPrinter call returns.
Upvotes: 6