0

I've made a program for my brother's restaurant, that sends a .txt file to the Thermal printer. The problem that I am having (or at least, what I am thinking of) is in the file's length.

This is the code that I used for the printing procedure (It's from Help needed about printing text file with delphi)

procedure TForm1.PrintTextFile(const FileName: string; const Numbering: boolean = true);
const
  FONT_NAME = 'Times New Roman';
  FONT_SIZE = 14;
var
  MARGIN: integer;
  sl1: TStringList;
  i, h: Integer;
  r, rFooter: TRect;
  s: string;
  DocEnd: integer;
begin
  with TPrintDialog.Create(nil) do
    try
      if not Execute then
        Exit;
    finally
      Free;
    end;
  sl1 := TStringList.Create;
  try
    sl1.LoadFromFile(FileName);
    Printer.BeginDoc;
    Printer.Title := FileName; // or application name or sth else
    Printer.Canvas.Font.Name := FONT_NAME;
    Printer.Canvas.Font.Size := FONT_SIZE;
    MARGIN := 1*Printer.Canvas.TextWidth('M');
    DocEnd := Printer.PageHeight - MARGIN;
    if Numbering then
    begin
      dec(DocEnd, 2*Printer.Canvas.TextHeight('8'));
      rFooter := Rect(0, DocEnd, Printer.PageWidth, Printer.PageHeight - MARGIN);
      DrawText(Printer.Canvas.Handle,
        PChar(IntToStr(Printer.PageNumber)),
        length(IntToStr(Printer.PageNumber)),
        rFooter,
        DT_SINGLELINE or DT_CENTER or DT_BOTTOM);
    end;
    r.Left := MARGIN;
    r.Top := MARGIN;
    for i := 0 to sl1.Count - 1 do
    begin
      r.Right := Printer.PageWidth - MARGIN;
      r.Bottom := DocEnd;
      s := sl1.Strings[i];
      if s = '' then s := ' ';
      h := DrawText(Printer.Canvas.Handle, // Height of paragraph on paper
        PChar(s),
        length(s),
        r,
        DT_LEFT or DT_TOP or DT_WORDBREAK or DT_CALCRECT);
      if r.Top + h >= DocEnd then
      begin
        Printer.NewPage;
        if Numbering then
          DrawText(Printer.Canvas.Handle,
            PChar(IntToStr(Printer.PageNumber)),
            length(IntToStr(Printer.PageNumber)),
            rFooter,
            DT_SINGLELINE or DT_CENTER or DT_BOTTOM);
        r.Top := MARGIN;
        r.Bottom := DocEnd;
      end;
      if h > Printer.PageHeight - 2*MARGIN then
        raise Exception.Create('Line too long to fit on single page.');
      DrawText(Printer.Canvas.Handle,
        PChar(s),
        length(s),
        r,
        DT_LEFT or DT_TOP or DT_WORDBREAK);
      inc(r.Top, h);
    end;
    Printer.EndDoc;
  finally
    sl1.Free;
  end;
end;

This is the .txt file that is sent to the thermal printer:

Prt sc of the txt file

And this is how it is being printed out:

Long ticket

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • When you step through the code in the debugger, what value does `Printer.PageHeight` have? Is there any reason why you don't set any value to that property? I see it is an Epson printer, but what is the model? Usually point-of-sales printers are controlled with so called ESC/POS commands. If you have the documentation for the printer, look for those commands. Else look for "esc/pos commands" on the net. You will also find hundreds of Q/A here on Stack Overflow. – Tom Brunberg Nov 01 '22 at 09:42

2 Answers2

0

I think you need to review your printer's driver settings before doing anything. In driver settings you can set the maximum paper height. You can also use Notepad to print the file to printer and compare the results with your program results. I have some notes about your code as you are printing to thermal printer:

  1. It is not a good idea to use paper height in your calculation.
  2. You don't add new page because this will make the printer to cut the paper.
  3. If you are using Windows and want to know the printer margins you can use something like the following function GetActualMargins.


    //This function works on the current printer
    //Dpi : Dot per inch
        procedure GetActualMargins(var DpiX, DpiY : Integer;  var LeftMargin, TopMargin: Single);
        begin
          try
            DpiX := GetDeviceCaps(Printer.Handle, LOGPIXELSX);
            DpiY := GetDeviceCaps(Printer.Handle, LOGPIXELSY);
            LeftMargin := Round((25.4 * GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX)) / DpiX );
            TopMargin := Round((25.4 * GetDeviceCaps(Printer.Handle, PHYSICALOFFSETY)) / DpiY );
          except
          //you can raise Exception here
          end;
        end;

Ehab
  • 284
  • 1
  • 9
0

I have been using thermal printers for some years but I prefer to use EPOS Commands.

I would suggest you test this;-

procedure TForm1.btnprint(Sender: TObject);
Var F:TextFile;
begin
try
  AssignFile(F,<printer port>);// e.g LPT1,LPT2,COM1,COM2...
Except
Begin
ShowMessage('Error in assigning printer.');
End;
End;

Rewrite(F);
Writeln(F,'Test printer');
Writeln(F, chr(29)+chr(86)+chr(65));//Cut and feed paper
CloseFile(F);       
End;
birgen
  • 1
  • 2
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 16 '22 at 00:37